diff --git a/LICENSE b/LICENSE index 315dfa2..39d6442 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. BSD-3-Clause diff --git a/README.md b/README.md index bf589d8..d967513 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,52 @@ -BMI2xy Sensor API +BMI270 Sensor API -> This package contains BMI2xy sensor API +> This package contains the sensor APIs for the BMI270 sensor ## Sensor Overview -The BMI2xy is a small, low power, low noise inertial measurement unit designed for use in mobile applications like augmented reality or indoor navigation which require highly accurate, real-time sensor data. +The BMI270 is a small, low power, low noise inertial measurement unit designed for use in mobile applications like augmented reality or indoor navigation which require highly accurate, real-time sensor data. -### Features +## Applications -- Indoor navigation, pedestrian dead-reckoning, step-counting +### BMI270 (base) + +- Any motion, No motion, Significant motion detectors +- Wrist worn Step counter and Step detector (Pedometer) +- Activity change recognition + - Still + - Walking + - Running +- Wrist gestures + - Push arm down + - Pivot up + - Wrist shake jiggle + - Flick in + - Flick out +- Wrist wear wake up + +### BMI270 Context + +- Step counter and Step detector (Pedometer) +- Activity change recognition + - Still + - Walking + - Running + +### BMI270 Legacy + +- Any motion, No motion, Significant motion detector +- Orientation detector (Advanced Potrait-Landscape) +- High-G, Low-G (Freefall) detector +- Flat detector +- Tap detection (Single, Double, Triple taps) +- Smartphone Step counter and Step detector (Pedometer) +- Activity change recognition + - Still + - Walking + - Running + +### BMI270 Maximum FIFO + +- Supports a 6kB FIFO For more information refer product page [Link](https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi270.html) diff --git a/bmi2.c b/bmi2.c index 30f3203..dc538f6 100644 --- a/bmi2.c +++ b/bmi2.c @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi2.c -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -476,35 +476,9 @@ static uint8_t extract_output_feat_config(struct bmi2_feature_config *feat_outpu static int8_t get_gyro_cross_sense(int16_t *cross_sense, struct bmi2_dev *dev); /*! - * @brief This internal API gets the accelerometer data from the register. + * @brief This internal API parses the accelerometer/gyroscope data. * - * @param[out] data : Structure instance of sensor_data. - * @param[in] reg_addr : Register address where data is stored. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -static int8_t get_accel_sensor_data(struct bmi2_sens_axes_data *data, uint8_t reg_addr, struct bmi2_dev *dev); - -/*! - * @brief This internal API gets the gyroscope data from the register. - * - * @param[out] data : Structure instance of sensor_data. - * @param[in] reg_addr : Register address where data is stored. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -static int8_t get_gyro_sensor_data(struct bmi2_sens_axes_data *data, uint8_t reg_addr, struct bmi2_dev *dev); - -/*! - * @brief This internal API gets the accelerometer/gyroscope data. - * - * @param[out] data : Structure instance of sensor_data. + * @param[out] data : Structure instance of bmi2_sens_axes_data. * @param[in] reg_data : Data stored in the register. * * @return None @@ -516,7 +490,7 @@ static void get_acc_gyr_data(struct bmi2_sens_axes_data *data, const uint8_t *re /*! * @brief This internal API gets the re-mapped accelerometer/gyroscope data. * - * @param[out] data : Structure instance of sensor_data. + * @param[out] data : Structure instance of bmi2_sens_axes_data. * @param[in] dev : Structure instance of bmi2_dev. * * @return None @@ -525,19 +499,6 @@ static void get_acc_gyr_data(struct bmi2_sens_axes_data *data, const uint8_t *re */ static void get_remapped_data(struct bmi2_sens_axes_data *data, const struct bmi2_dev *dev); -/*! - * @brief This internal API reads the user-defined bytes of data from the given - * register address of auxiliary sensor in data mode. - * - * @param[out] aux_data : Pointer to the stored auxiliary data. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -static int8_t read_aux_data_mode(uint8_t *aux_data, struct bmi2_dev *dev); - /*! * @brief This internal API reads the user-defined bytes of data from the given * register address of auxiliary sensor in manual mode. @@ -621,6 +582,7 @@ static int8_t map_feat_int(uint8_t *reg_data_array, enum bmi2_hw_int_pin int_pin * * @param[out] start_idx : The start index for parsing data. * @param[out] len : Number of bytes to be parsed. + * @param[out] skip_length : Number of bytes to skip if dummy frame is obtained * @param[in] acc_count : Number of accelerometer frames to be read. * @param[in] fifo : Structure instance of bmi2_fifo_frame. * @@ -630,6 +592,7 @@ static int8_t map_feat_int(uint8_t *reg_data_array, enum bmi2_hw_int_pin int_pin */ static int8_t parse_fifo_accel_len(uint16_t *start_idx, uint16_t *len, + uint8_t *skip_length, const uint16_t *acc_count, const struct bmi2_fifo_frame *fifo); @@ -652,9 +615,80 @@ static int8_t extract_accel_header_mode(struct bmi2_sens_axes_data *acc, struct bmi2_fifo_frame *fifo, const struct bmi2_dev *dev); +/*! + * @brief This internal API is used to parse accelerometer data from the FIFO + * data in headerless mode. + * + * @param[out] acc : Structure instance of bmi2_sens_axes_data where + * the parsed accelerometer data bytes are stored. + * @param[in] accel_length : Number of accelerometer frames (x,y,z data). + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t extract_accel_headerless_mode(struct bmi2_sens_axes_data *acc, + uint16_t *accel_length, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to skip dummy frames in FIFO headerless mode + * + * @param[in] dummy_frame_header : Dummy frame header byte value in FIFO headerless mode + * + * ----------------------------------|-------------------- + * dummy_frame_header | Applicable to + * ----------------------------------|-------------------- + * BMI2_FIFO_HEADERLESS_DUMMY_ACC | ACCEL + * BMI2_FIFO_HEADERLESS_DUMMY_GYR | GYRO + * BMI2_FIFO_HEADERLESS_DUMMY_AUX | AUX + * ----------------------------------|-------------------- + * + * @param[in] data_index : Index value of number of bytes parsed. + * @param[in] skip_length : Number of bytes to skip if dummy frame is obtained + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t check_dummy_frame(uint8_t dummy_frame_header, + uint16_t *data_index, + uint8_t skip_length, + const struct bmi2_fifo_frame *fifo); + +/*! + * @brief This internal API is used to parse the accelerometer data from the + * FIFO data in header mode. It updates the current data + * byte to be parsed. + * + * @param[in,out] acc : Structure instance of bmi2_sens_axes_data where + * where the parsed data bytes are stored. + * @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] frame : Either data is enabled by user in header-less + * mode or header frame value in header mode. + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t unpack_accel_header_frame(struct bmi2_sens_axes_data *acc, + uint16_t *idx, + uint16_t *acc_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); + /*! * @brief This internal API is used to parse the accelerometer data from the - * FIFO data in both header and header-less mode. It updates the current data + * FIFO data in header-less mode. It updates the current data * byte to be parsed. * * @param[in,out] acc : Structure instance of bmi2_sens_axes_data where @@ -671,12 +705,12 @@ static int8_t extract_accel_header_mode(struct bmi2_sens_axes_data *acc, * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, - uint16_t *idx, - uint16_t *acc_idx, - uint8_t frame, - const struct bmi2_fifo_frame *fifo, - const struct bmi2_dev *dev); +static int8_t unpack_accel_headerless_frame(struct bmi2_sens_axes_data *acc, + uint16_t *idx, + uint16_t *acc_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); /*! * @brief This internal API is used to parse accelerometer data from the FIFO @@ -703,6 +737,7 @@ static void unpack_accel_data(struct bmi2_sens_axes_data *acc, * * @param[out] start_idx : The start index for parsing data. * @param[out] len : Number of bytes to be parsed. + * @param[out] skip_length : Number of bytes to skip if dummy frame is obtained * @param[in] gyr_count : Number of gyroscope frames to be read. * @param[in] frame : Either data enabled by user in header-less * mode or header frame value in header mode. @@ -713,13 +748,39 @@ static void unpack_accel_data(struct bmi2_sens_axes_data *acc, * @retval < 0 -> Fail */ static int8_t parse_fifo_gyro_len(uint16_t *start_idx, - uint16_t(*len), + uint16_t *len, + uint8_t *skip_length, const uint16_t *gyr_count, const struct bmi2_fifo_frame *fifo); /*! * @brief This internal API is used to parse the gyroscope data from the FIFO - * data in both header and header-less mode It updates the current data byte to + * data in header mode It updates the current data byte to + * be parsed. + * + * @param[in,out] gyr : Structure instance of bmi2_sens_axes_data. + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] gyr_idx : Index value of gyroscope data (x,y,z axes) + * frame to be parsed. + * @param[in] frame : Either data is enabled by user in header-less + * mode or header frame value in header mode. + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t unpack_gyro_header_frame(struct bmi2_sens_axes_data *gyr, + uint16_t *idx, + uint16_t *gyr_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to parse the gyroscope data from the FIFO + * data in header-less mode It updates the current data byte to * be parsed. * * @param[in,out] gyr : Structure instance of bmi2_sens_axes_data. @@ -735,12 +796,12 @@ static int8_t parse_fifo_gyro_len(uint16_t *start_idx, * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, - uint16_t *idx, - uint16_t *gyr_idx, - uint8_t frame, - const struct bmi2_fifo_frame *fifo, - const struct bmi2_dev *dev); +static int8_t unpack_gyro_headerless_frame(struct bmi2_sens_axes_data *gyr, + uint16_t *idx, + uint16_t *gyr_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); /*! * @brief This internal API is used to parse gyroscope data from the FIFO data. @@ -779,12 +840,32 @@ static int8_t extract_gyro_header_mode(struct bmi2_sens_axes_data *gyr, struct bmi2_fifo_frame *fifo, const struct bmi2_dev *dev); +/*! + * @brief This internal API is used to parse gyroscope data from the FIFO + * data in headerless mode. + * + * @param[out] gyr : Structure instance of bmi2_sens_axes_data where + * the parsed gyroscope data bytes are stored. + * @param[in] gyro_length : Number of gyroscope frames (x,y,z data). + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t extract_gyro_headerless_mode(struct bmi2_sens_axes_data *gyr, + uint16_t *gyro_length, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); + /*! * @brief This API computes the number of bytes of auxiliary 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[out] skip_length : Number of bytes to skip if dummy frame is obtained * @param[in] aux_count : Number of accelerometer frames to be read. * @param[in] fifo : Structure instance of bmi2_fifo_frame. * @@ -793,7 +874,8 @@ static int8_t extract_gyro_header_mode(struct bmi2_sens_axes_data *gyr, * @retval < 0 -> Fail */ static int8_t parse_fifo_aux_len(uint16_t *start_idx, - uint16_t(*len), + uint16_t *len, + uint8_t *skip_length, const uint16_t *aux_count, const struct bmi2_fifo_frame *fifo); @@ -815,6 +897,25 @@ static int8_t extract_aux_header_mode(struct bmi2_aux_fifo_data *aux, struct bmi2_fifo_frame *fifo, const struct bmi2_dev *dev); +/*! + * @brief This internal API is used to parse auxiliary data from the FIFO + * data in headerless mode. + * + * @param[out] aux : Structure instance of bmi2_sens_axes_data where + * the parsed auxiliary data bytes are stored. + * @param[in] aux_length : Number of auxiliary frames (x,y,z data). + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t extract_aux_headerless_mode(struct bmi2_aux_fifo_data *aux, + uint16_t *aux_length, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); + /*! * @brief This API is used to parse the auxiliary data from the FIFO data in * both header and header-less mode. It updates the current data byte to be @@ -1153,6 +1254,19 @@ static void unpack_virt_aux_sensor_time(struct bmi2_aux_fifo_data *aux, uint16_t *idx, const struct bmi2_fifo_frame *fifo); +/*! + * @brief This internal API clips the gyroscope cross-axis sensitivity within signed 16-bit limit + * + * @param[in] value : Gyro cross-axis sensitivity value to be saturated. + * @param[out] saturation_val : Saturation value to be clipped. + * + * @return Result of API execution status + * + * @return Result of API execution status + * @retval Saturated gyro cross-axis sensitivity value + */ +static int16_t saturate(int32_t value, uint16_t saturation_val); + /*! * @brief This internal API corrects the gyroscope cross-axis sensitivity * between the z and the x axis. @@ -1477,6 +1591,16 @@ static int8_t set_st_running(uint8_t st_status, struct bmi2_dev *dev); */ static int8_t crt_prepare_setup(struct bmi2_dev *dev); +/*! + * @brief This API is to run the crt process for both max burst length 0 and non zero condition. + * + * @param[in] gyro_st_crt : Update the gyro self-test crt enable bit + * @param[in] dev : Structure instance of bmi2_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ static int8_t do_gtrigger_test(uint8_t gyro_st_crt, struct bmi2_dev *dev); /*! @@ -1553,7 +1677,8 @@ static int8_t process_crt_download(uint8_t last_byte_flag, struct bmi2_dev *dev) /*! * @brief This api is used to enable the gyro self-test or crt. * - * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] gyro_st_crt : Update the gyro self-test crt enable bit + * @param[in] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success @@ -1564,8 +1689,8 @@ static int8_t select_self_test(uint8_t gyro_st_crt, struct bmi2_dev *dev); /*! * @brief This api is used to enable/disable abort. * - * @param[in] abort_enable : variable to enable the abort feature. - * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] abort_enable : Variable to enable the abort feature. + * @param[in] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success @@ -1588,7 +1713,7 @@ static int8_t gyro_self_test_completed(struct bmi2_gyro_self_test_status *gyro_s /*! * @brief This api is used to trigger the preparation for system for NVM programming. * - * @param[out] nvm_prep : pointer to variable to store the status of nvm_prep_prog. + * @param[out] nvm_prep : Pointer to variable to store the status of nvm_prep_prog. * @param[in] dev : Structure instance of bmi2_dev. * * @return Result of API execution status @@ -1598,127 +1723,141 @@ static int8_t gyro_self_test_completed(struct bmi2_gyro_self_test_status *gyro_s static int8_t set_nvm_prep_prog(uint8_t nvm_prep, struct bmi2_dev *dev); /*! - * @brief This api validates accel foc position as per the range + * @brief This internal api gets major and minor version for config file * - * @param[in] sens_list : Sensor type - * @param[in] accel_g_axis : accel axis to foc. NA for gyro foc - * @param[in] avg_foc_data : average value of sensor sample datas - * @param[in] dev : Structure instance of bmi2_dev. + * @param[out] config_major : Pointer to store the major version + * @param[out] config_minor : Pointer to store the minor version + * @param[in] dev : Structure instance of bmi2_dev * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t validate_foc_position(uint8_t sens_list, - const struct bmi2_accel_foc_g_value *accel_g_axis, - struct bmi2_sens_axes_data avg_foc_data, - struct bmi2_dev *dev); +static int8_t extract_config_file(uint8_t *config_major, uint8_t *config_minor, struct bmi2_dev *dev); /*! - * @brief This api validates accel foc axis given as input + * @brief This internal API is used to map the interrupts to the sensor. * - * @param[in] avg_foc_data : average value of sensor sample datas - * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] map_int : Structure instance of bmi2_map_int. + * @param[in] type : Type of feature or sensor. + * @param[in] dev : Structure instance of bmi2_dev. * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail + * @return None + * @retval None */ -static int8_t validate_foc_accel_axis(int16_t avg_foc_data, struct bmi2_dev *dev); +static void extract_feat_int_map(struct bmi2_map_int *map_int, uint8_t type, const struct bmi2_dev *dev); /*! - * @brief This api is used to verify the right position of the sensor before doing accel foc + * @brief This internal API selects the sensors/features to be enabled or + * disabled. * - * @param[in] dev : Structure instance of bmi2_dev. - * @param[in] sens_list: Sensor type - * @param[in] accel_g_axis: Accel Foc axis and sign input + * @param[in] sens_list : Pointer to select the sensor. + * @param[in] n_sens : Number of sensors selected. + * @param[out] sensor_sel : Gets the selected sensor. * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t verify_foc_position(uint8_t sens_list, - const struct bmi2_accel_foc_g_value *accel_g_axis, - struct bmi2_dev *dev); +static int8_t select_sensor(const uint8_t *sens_list, uint8_t n_sens, uint64_t *sensor_sel); /*! - * @brief This API reads and provides average for 128 samples of sensor data for foc operation - * gyro. + * @brief This internal API enables the selected sensor/features. * - * @param[in] sens_list : Sensor type. - * @param[in] bmi2_dev: Structure instance of bmi2_dev. - * @param[in] temp_foc_data: to store data samples + * @param[in] sensor_sel : Selects the desired sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t get_average_of_sensor_data(uint8_t sens_list, - struct bmi2_foc_temp_value *temp_foc_data, - struct bmi2_dev *dev); +static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev); /*! - * @brief This internal api gets major and minor version for config file + * @brief This internal API disables the selected sensor/features. * - * @param[out] config_major : Pointer to store the major version - * @param[out] config_minor : Pointer to store the minor version - * @param[in] dev : Structure instance of bmi2_dev + * @param[in] sensor_sel : Selects the desired sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t extract_config_file(uint8_t *config_major, uint8_t *config_minor, struct bmi2_dev *dev); +static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev); /*! - * @brief This internal API is used to map the interrupts to the sensor. + * @brief This internal API reads accelerometer, gyroscope and auxiliary sensor data. * - * @param[in] map_int : Structure instance of bmi2_map_int. - * @param[in] type : Type of feature or sensor. - * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] aux_len : Length of auxiliary sensor data + * @param[in] acc_len : Length of accelerometer sensor data + * @param[in] gyr_len : Length of gyroscope sensor data + * @param[out] sensor_data : Sensor data from register. + * @param[in, out] dev : Structure instance of bmi2_dev. * - * @return None - * @retval None + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail */ -static void extract_feat_int_map(struct bmi2_map_int *map_int, uint8_t type, const struct bmi2_dev *dev); +static int8_t read_sensor_data(uint8_t aux_len, + uint8_t acc_len, + uint8_t gyr_len, + uint8_t *sensor_data, + struct bmi2_dev *dev); /*! - * @brief This internal API selects the sensors/features to be enabled or - * disabled. + * @brief This internal API parses accelerometer, gyroscope and auxiliary sensor data with sensortime * - * @param[in] sens_list : Pointer to select the sensor. - * @param[in] n_sens : Number of sensors selected. - * @param[out] sensor_sel : Gets the selected sensor. + * @param[in] aux_len : Length of auxiliary sensor data + * @param[in] acc_len : Length of accelerometer sensor data + * @param[in] gyr_len : Length of gyroscope sensor data + * @param[in] data : Structure instance of bmi2_sens_data. + * @param[in] sensor_data : Sensor data from register. + * @param[in, out] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t select_sensor(const uint8_t *sens_list, uint8_t n_sens, uint64_t *sensor_sel); +static int8_t parse_data(uint8_t aux_len, + uint8_t acc_len, + uint8_t gyr_len, + struct bmi2_sens_data *data, + const uint8_t *sensor_data, + struct bmi2_dev *dev); /*! - * @brief This internal API enables the selected sensor/features. + * @brief This internal API is used to test gyro CRT. * - * @param[in] sensor_sel : Selects the desired sensor. - * @param[in, out] dev : Structure instance of bmi2_dev. + * @param[in] max_burst_length : Variable to store maximum burst length. + * @param[in] gyro_st_crt : Update the gyro self-test crt enable bit. + * @param[in, out] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev); +static int8_t gyro_crt_test(uint8_t max_burst_length, uint8_t gyro_st_crt, struct bmi2_dev *dev); /*! - * @brief This internal API disables the selected sensor/features. + * @brief This internal API is used to unpack virtual auxillary sensortime data. * - * @param[in] sensor_sel : Selects the desired sensor. - * @param[in, out] dev : Structure instance of bmi2_dev. + * @param[out] aux : Pointer to structure where the parsed auxiliary data + * bytes are stored. + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] aux_idx : Index value of auxiliary data (x,y,z axes) + * frame to be parsed + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in, out] dev : Structure instance of bmi2_dev. * * @return Result of API execution status * @retval 0 -> Success * @retval < 0 -> Fail */ -static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev); +static void unpack_virtual_aux_data(struct bmi2_aux_fifo_data *aux, + uint16_t *idx, + const uint16_t *aux_idx, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); /******************************************************************************/ /*! @name User Interface Definitions */ @@ -1745,12 +1884,17 @@ int8_t bmi2_sec_init(struct bmi2_dev *dev) /* Null-pointer check */ rslt = null_ptr_check(dev); + if (rslt == BMI2_OK) { - /* Perform soft-reset to bring all register values to their - * default values - */ - rslt = bmi2_soft_reset(dev); + /* Set APS flag as after reset, the sensor is on advance power save mode */ + dev->aps_status = BMI2_ENABLE; + + /* Performing a dummy read to bring interface back to SPI from I2C interface */ + if (dev->intf == BMI2_SPI_INTF) + { + rslt = bmi2_get_regs(BMI2_CHIP_ID_ADDR, &chip_id, 1, dev); + } if (rslt == BMI2_OK) { @@ -1772,6 +1916,11 @@ int8_t bmi2_sec_init(struct bmi2_dev *dev) * re-mapping in the device structure */ dev->remap = axes_remap; + + /* Perform soft-reset to bring all register values to their + * default values + */ + rslt = bmi2_soft_reset(dev); } else { @@ -1804,23 +1953,20 @@ int8_t bmi2_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, struct bmi2_ /* Variable to define loop */ uint16_t index = 0; + /* Variable to define temporary buffer */ + uint8_t temp_buf[BMI2_MAX_LEN]; + /* Null-pointer check */ rslt = null_ptr_check(dev); if ((rslt == BMI2_OK) && (data != NULL)) { - /* Variable to define temporary length */ - uint16_t temp_len = len + dev->dummy_byte; - - /* Variable to define temporary buffer */ - uint8_t temp_buf[temp_len]; - /* Configuring reg_addr for SPI Interface */ if (dev->intf == BMI2_SPI_INTF) { reg_addr = (reg_addr | BMI2_SPI_RD_MASK); } - dev->intf_rslt = dev->read(reg_addr, temp_buf, temp_len, dev->intf_ptr); + dev->intf_rslt = dev->read(reg_addr, temp_buf, (len + dev->dummy_byte), dev->intf_ptr); if (dev->aps_status == BMI2_ENABLE) { @@ -1884,7 +2030,7 @@ int8_t bmi2_set_regs(uint8_t reg_addr, const uint8_t *data, uint16_t len, struct dev->delay_us(2, dev->intf_ptr); } - /* updating the advance power saver flag */ + /* Updating the advance power saver flag */ if (reg_addr == BMI2_PWR_CONF_ADDR) { if (*data & BMI2_ADV_POW_EN_MASK) @@ -1933,7 +2079,7 @@ int8_t bmi2_soft_reset(struct bmi2_dev *dev) rslt = bmi2_set_regs(BMI2_CMD_REG_ADDR, &data, 1, dev); dev->delay_us(2000, dev->intf_ptr); - /* set APS flag as after soft reset the sensor is on advance power save mode */ + /* Set APS flag as after soft reset the sensor is on advance power save mode */ dev->aps_status = BMI2_ENABLE; /* Performing a dummy read to bring interface back to SPI from @@ -2534,11 +2680,9 @@ int8_t bmi2_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, } /*! - * @brief This API gets the sensor/feature data for accelerometer, gyroscope, - * auxiliary sensor, step counter, high-g, gyroscope user-gain update, - * orientation, gyroscope cross sensitivity and error status for NVM and VFRM. + * @brief This API gets the feature data gyroscope user-gain update and gyroscope cross sensitivity. */ -int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev) +int8_t bmi2_get_feature_data(struct bmi2_feat_sensor_data *feat_sensor_data, uint8_t n_sens, struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt; @@ -2551,7 +2695,7 @@ int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens /* Null-pointer check */ rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (sensor_data != NULL)) + if ((rslt == BMI2_OK) && (feat_sensor_data != NULL)) { /* Get status of advance power save mode */ aps_stat = dev->aps_status; @@ -2560,7 +2704,7 @@ int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens /* Disable Advance power save if enabled for feature * configurations */ - if (sensor_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) + if (feat_sensor_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) { if (aps_stat == BMI2_ENABLE) { @@ -2573,34 +2717,19 @@ int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens if (rslt == BMI2_OK) { - switch (sensor_data[loop].type) + switch (feat_sensor_data[loop].type) { - case BMI2_ACCEL: - - /* Get accelerometer data */ - rslt = get_accel_sensor_data(&sensor_data[loop].sens_data.acc, BMI2_ACC_X_LSB_ADDR, dev); - break; - case BMI2_GYRO: - - /* Get gyroscope data */ - rslt = get_gyro_sensor_data(&sensor_data[loop].sens_data.gyr, BMI2_GYR_X_LSB_ADDR, dev); - break; - case BMI2_AUX: - - /* Get auxiliary sensor data in data mode */ - rslt = read_aux_data_mode(sensor_data[loop].sens_data.aux_data, dev); - break; - case BMI2_GYRO_CROSS_SENSE: /* Get Gyroscope cross sense value of z axis */ - rslt = get_gyro_cross_sense(&sensor_data[loop].sens_data.correction_factor_zx, dev); + rslt = get_gyro_cross_sense(&feat_sensor_data[loop].sens_data.correction_factor_zx, dev); break; case BMI2_GYRO_GAIN_UPDATE: /* Get saturation status of gyroscope user gain update */ - rslt = get_gyro_gain_update_status(&sensor_data[loop].sens_data.gyro_user_gain_status, dev); + rslt = + get_gyro_gain_update_status(&feat_sensor_data[loop].sens_data.gyro_user_gain_status, dev); break; default: rslt = BMI2_E_INVALID_SENSOR; @@ -2632,46 +2761,105 @@ int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens } /*! - * @brief This API sets the FIFO configuration in the sensor. + * @brief This API gets the sensor data for accelerometer, gyroscope, + * auxiliary sensor with sensortime */ -int8_t bmi2_set_fifo_config(uint16_t config, uint8_t enable, struct bmi2_dev *dev) +int8_t bmi2_get_sensor_data(struct bmi2_sens_data *data, struct bmi2_dev *dev) { + /* Variable to define error */ int8_t rslt; - uint8_t data[2] = { 0 }; - uint8_t max_burst_len = 0; - /* Variable to store data of FIFO configuration register 0 */ - uint8_t fifo_config_0 = (uint8_t)(config & BMI2_FIFO_CONFIG_0_MASK); + uint8_t reg_data = 0; - /* Variable to store data of FIFO configuration register 1 */ - uint8_t fifo_config_1 = (uint8_t)((config & BMI2_FIFO_CONFIG_1_MASK) >> 8); + uint8_t aux_len = 0, acc_len = 0, gyr_len = 0; + + /* Array to define data stored in register */ + uint8_t sensor_data[BMI2_ACC_GYR_AUX_NUM_BYTES] = { 0 }; + /* Null-pointer check */ rslt = null_ptr_check(dev); - if (rslt == BMI2_OK) + if ((rslt == BMI2_OK) && (data != NULL)) { - rslt = bmi2_get_regs(BMI2_FIFO_CONFIG_0_ADDR, data, BMI2_FIFO_CONFIG_LENGTH, dev); + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + if (rslt == BMI2_OK) { - /* Get data to set FIFO configuration register 0 */ - if (fifo_config_0 > 0) + /* Update auxiliary sensor data length */ + if (reg_data & BMI2_AUX_EN_MASK) { - if (enable == BMI2_ENABLE) - { - data[0] = data[0] | fifo_config_0; - } - else - { - data[0] = data[0] & (~fifo_config_0); - } + aux_len = BMI2_AUX_NUM_BYTES; } - /* Get data to set FIFO configuration register 1 */ - if (enable == BMI2_ENABLE) + /* Update accelerometer sensor data length */ + if (reg_data & BMI2_ACC_EN_MASK) + { + acc_len = aux_len + BMI2_ACC_NUM_BYTES; + } + + /* Update gyroscope sensor data length */ + if (reg_data & BMI2_GYR_EN_MASK) + { + gyr_len = aux_len + acc_len + BMI2_GYR_NUM_BYTES; + } + + /* Read sensor data */ + rslt = read_sensor_data(aux_len, acc_len, gyr_len, sensor_data, dev); + + if (rslt == BMI2_OK) + { + /* Parse read sensor data */ + rslt = parse_data(aux_len, acc_len, gyr_len, data, sensor_data, dev); + } + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets the FIFO configuration in the sensor. + */ +int8_t bmi2_set_fifo_config(uint16_t config, uint8_t enable, struct bmi2_dev *dev) +{ + int8_t rslt; + uint8_t data[2] = { 0 }; + uint8_t max_burst_len = 0; + + /* Variable to store data of FIFO configuration register 0 */ + uint8_t fifo_config_0 = (uint8_t)(config & BMI2_FIFO_CONFIG_0_MASK); + + /* Variable to store data of FIFO configuration register 1 */ + uint8_t fifo_config_1 = (uint8_t)((config & BMI2_FIFO_CONFIG_1_MASK) >> 8); + + rslt = null_ptr_check(dev); + if (rslt == BMI2_OK) + { + rslt = bmi2_get_regs(BMI2_FIFO_CONFIG_0_ADDR, data, BMI2_FIFO_CONFIG_LENGTH, dev); + if (rslt == BMI2_OK) + { + /* Get data to set FIFO configuration register 0 */ + if (fifo_config_0 > 0) + { + if (enable == BMI2_ENABLE) + { + data[0] = data[0] | fifo_config_0; + } + else + { + data[0] = data[0] & (~fifo_config_0); + } + } + + /* Get data to set FIFO configuration register 1 */ + if (enable == BMI2_ENABLE) { data[1] = data[1] | fifo_config_1; if (dev->variant_feature & BMI2_CRT_RTOSK_ENABLE) { - /* Burst length is needed for CRT * FIFO enable will reset the default values * So configure the max burst length again. @@ -2732,6 +2920,8 @@ int8_t bmi2_get_fifo_config(uint16_t *fifo_config, struct bmi2_dev *dev) /*! * @brief This API reads the FIFO data. + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read + * must be given as part of data pointer in struct bmi2_fifo_frame */ int8_t bmi2_read_fifo_data(struct bmi2_fifo_frame *fifo, struct bmi2_dev *dev) { @@ -2751,12 +2941,33 @@ int8_t bmi2_read_fifo_data(struct bmi2_fifo_frame *fifo, struct bmi2_dev *dev) /* Clear the FIFO data structure */ reset_fifo_frame_structure(fifo, dev); + /* Configuring reg_addr for SPI Interface */ + if (dev->intf == BMI2_SPI_INTF) + { + addr = (addr | BMI2_SPI_RD_MASK); + } + /* Read FIFO data */ - rslt = bmi2_get_regs(addr, fifo->data, fifo->length, dev); + dev->intf_rslt = dev->read(addr, fifo->data, (uint32_t)fifo->length, dev->intf_ptr); - if (rslt == BMI2_OK) + /* Provide delay based on advanced power saving mode status */ + if (dev->aps_status == BMI2_ENABLE) { + dev->delay_us(450, dev->intf_ptr); + } + else + { + dev->delay_us(2, dev->intf_ptr); + } + + /* If interface read fails, update rslt variable with communication failure */ + if (dev->intf_rslt != BMI2_INTF_RET_SUCCESS) + { + rslt = BMI2_E_COM_FAIL; + } + if (rslt == BMI2_OK) + { /* Get the set FIFO frame configurations */ rslt = bmi2_get_regs(BMI2_FIFO_CONFIG_0_ADDR, config_data, 2, dev); if (rslt == BMI2_OK) @@ -2795,48 +3006,25 @@ int8_t bmi2_extract_accel(struct bmi2_sens_axes_data *accel_data, /* Variable to define error */ int8_t rslt; - /* Variable to index the bytes */ - uint16_t data_index = 0; - - /* Variable to index accelerometer frames */ - uint16_t accel_index = 0; - - /* Variable to store the number of bytes to be read */ - uint16_t data_read_length = 0; - - /* Variable to define the data enable byte */ - uint8_t data_enable = 0; - /* Null-pointer check */ rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (accel_data != NULL) && (accel_length != NULL) && (fifo != NULL)) { + /* Check if this is the first iteration of data unpacking + * if yes, then consider dummy byte on SPI + */ + if (fifo->acc_byte_start_idx == 0) + { + /* Dummy byte included */ + fifo->acc_byte_start_idx = dev->dummy_byte; + } + /* Parsing the FIFO data in header-less mode */ if (fifo->header_enable == 0) { - - /* Get the number of accelerometer bytes to be read */ - rslt = parse_fifo_accel_len(&data_index, &data_read_length, accel_length, fifo); - - /* Convert word to byte since all sensor enables are in a byte */ - data_enable = (uint8_t)(fifo->data_enable >> 8); - for (; (data_index < data_read_length) && (rslt != BMI2_W_FIFO_EMPTY);) - { - /* Unpack frame to get the accelerometer data */ - rslt = unpack_accel_frame(accel_data, &data_index, &accel_index, data_enable, fifo, dev); - - if (rslt != BMI2_W_FIFO_EMPTY) - { - /* Check for the availability of next two bytes of FIFO data */ - rslt = check_empty_fifo(&data_index, fifo); - } - } - - /* Update number of accelerometer frames to be read */ - (*accel_length) = accel_index; - - /* Update the accelerometer byte index */ - fifo->acc_byte_start_idx = data_index; + /* Parsing the FIFO data in headerless mode */ + rslt = extract_accel_headerless_mode(accel_data, accel_length, fifo, dev); } else { @@ -2865,46 +3053,24 @@ int8_t bmi2_extract_gyro(struct bmi2_sens_axes_data *gyro_data, /* Variable to define error */ int8_t rslt; - /* Variable to index the bytes */ - uint16_t data_index = 0; - - /* Variable to index gyroscope frames */ - uint16_t gyro_index = 0; - - /* Variable to store the number of bytes to be read */ - uint16_t data_read_length = 0; - - /* Variable to define the data enable byte */ - uint8_t data_enable = 0; - /* Null-pointer check */ rslt = null_ptr_check(dev); if ((rslt == BMI2_OK) && (gyro_data != NULL) && (gyro_length != NULL) && (fifo != NULL)) { + /* Check if this is the first iteration of data unpacking + * if yes, then consider dummy byte on SPI + */ + if (fifo->gyr_byte_start_idx == 0) + { + /* Dummy byte included */ + fifo->gyr_byte_start_idx = dev->dummy_byte; + } + /* Parsing the FIFO data in header-less mode */ if (fifo->header_enable == 0) { - /* Get the number of gyro bytes to be read */ - rslt = parse_fifo_gyro_len(&data_index, &data_read_length, gyro_length, fifo); - - /* Convert word to byte since all sensor enables are in a byte */ - data_enable = (uint8_t)(fifo->data_enable >> 8); - for (; (data_index < data_read_length) && (rslt != BMI2_W_FIFO_EMPTY);) - { - /* Unpack frame to get gyroscope data */ - rslt = unpack_gyro_frame(gyro_data, &data_index, &gyro_index, data_enable, fifo, dev); - if (rslt != BMI2_W_FIFO_EMPTY) - { - /* Check for the availability of next two bytes of FIFO data */ - rslt = check_empty_fifo(&data_index, fifo); - } - } - - /* Update number of gyroscope frames to be read */ - (*gyro_length) = gyro_index; - - /* Update the gyroscope byte index */ - fifo->acc_byte_start_idx = data_index; + /* Parsing the FIFO data in headerless mode */ + rslt = extract_gyro_headerless_mode(gyro_data, gyro_length, fifo, dev); } else { @@ -2932,49 +3098,24 @@ int8_t bmi2_extract_aux(struct bmi2_aux_fifo_data *aux, /* Variable to define error */ int8_t rslt; - /* Variable to index the bytes */ - uint16_t data_index = 0; - - /* Variable to index auxiliary frames */ - uint16_t aux_index = 0; - - /* Variable to store the number of bytes to be read */ - uint16_t data_read_length = 0; - - /* Variable to define the data enable byte */ - uint8_t data_enable = 0; - /* Null-pointer check */ rslt = null_ptr_check(dev); if ((rslt == BMI2_OK) && (aux != NULL) && (aux_length != NULL) && (fifo != NULL)) { + /* Check if this is the first iteration of data unpacking + * if yes, then consider dummy byte on SPI + */ + if (fifo->aux_byte_start_idx == 0) + { + /* Dummy byte included */ + fifo->aux_byte_start_idx = dev->dummy_byte; + } + /* Parsing the FIFO data in header-less mode */ if (fifo->header_enable == 0) { - rslt = parse_fifo_aux_len(&data_index, &data_read_length, aux_length, fifo); - - /* Convert word to byte since all sensor enables are in - * a byte - */ - data_enable = (uint8_t)(fifo->data_enable >> 8); - for (; (data_index < data_read_length) && (rslt != BMI2_W_FIFO_EMPTY);) - { - /* Unpack frame to get auxiliary data */ - rslt = unpack_aux_frame(aux, &data_index, &aux_index, data_enable, fifo, dev); - if (rslt != BMI2_W_FIFO_EMPTY) - { - /* Check for the availability of next - * two bytes of FIFO data - */ - rslt = check_empty_fifo(&data_index, fifo); - } - } - - /* Update number of auxiliary frames to be read */ - *aux_length = aux_index; - - /* Update the auxiliary byte index */ - fifo->aux_byte_start_idx = data_index; + /* Parsing the FIFO data in headerless mode */ + rslt = extract_aux_headerless_mode(aux, aux_length, fifo, dev); } else { @@ -3510,78 +3651,6 @@ int8_t bmi2_write_aux_man_mode(uint8_t reg_addr, const uint8_t *aux_data, uint16 return rslt; } -/*! - * @brief This API writes the user-defined bytes of data and the address of - * auxiliary sensor where data is to be written, from an interleaved input, - * in manual mode. - * - * @note Change of BMI2_AUX_WR_ADDR is only allowed if AUX is not busy. - */ -int8_t bmi2_write_aux_interleaved(uint8_t reg_addr, const uint8_t *aux_data, uint16_t len, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt; - - /* Variable to define loop */ - uint8_t loop = 1; - - /* Variable to define APS status */ - uint8_t aps_stat = 0; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (aux_data != NULL)) - { - /* Validate if manual mode */ - if (dev->aux_man_en) - { - /* Get status of advance power save mode */ - aps_stat = dev->aps_status; - if (aps_stat == BMI2_ENABLE) - { - /* Disable APS if enabled */ - rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); - } - - if (rslt == BMI2_OK) - { - /* Write the start register address extracted - * from the interleaved data - */ - rslt = write_aux_data(reg_addr, aux_data[0], dev); - - /* Extract the remaining address and data from - * the interleaved data and write it in the - * corresponding addresses byte by byte - */ - for (; ((loop < len) && (rslt == BMI2_OK)); loop += 2) - { - rslt = write_aux_data(aux_data[loop], aux_data[loop + 1], dev); - dev->delay_us(1000, dev->intf_ptr); - } - - /* Enable Advance power save if disabled for - * writing data and not when already disabled - */ - if ((rslt == BMI2_OK) && (aps_stat == BMI2_ENABLE)) - { - rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); - } - } - } - else - { - rslt = BMI2_E_AUX_INVALID_CFG; - } - } - else - { - rslt = BMI2_E_NULL_PTR; - } - - return rslt; -} - /*! * @brief This API gets the data ready status of accelerometer, gyroscope, * auxiliary, command decoder and busy status of auxiliary. @@ -4352,8 +4421,9 @@ int8_t bmi2_write_gyro_offset_comp_axes(const struct bmi2_sens_axes_data *gyr_of rslt = null_ptr_check(dev); if ((rslt == BMI2_OK) && (gyr_off_comp_axes != NULL)) { - /* Get the MSB values of gyroscope compensated offset values */ - rslt = bmi2_get_regs(BMI2_GYR_OFF_COMP_6_ADDR, ®_data[3], 1, dev); + /* Get the gyroscope offset compensation values of axes */ + rslt = bmi2_get_regs(BMI2_GYR_OFF_COMP_3_ADDR, reg_data, 4, dev); + if (rslt == BMI2_OK) { /* Get MSB value of x-axis from user-input */ @@ -4403,7 +4473,7 @@ int8_t bmi2_get_gyro_cross_sense(struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt = BMI2_OK; - struct bmi2_sensor_data data; + struct bmi2_feat_sensor_data data; /* Check if the feature is supported by this variant */ if (dev->variant_feature & BMI2_GYRO_CROSS_SENS_ENABLE) @@ -4415,7 +4485,7 @@ int8_t bmi2_get_gyro_cross_sense(struct bmi2_dev *dev) data.type = BMI2_GYRO_CROSS_SENSE; /* Get the respective data */ - rslt = bmi2_get_sensor_data(&data, 1, dev); + rslt = bmi2_get_feature_data(&data, 1, dev); if (rslt == BMI2_OK) { /* Update the gyroscope cross sense value of z axis @@ -4429,6 +4499,10 @@ int8_t bmi2_get_gyro_cross_sense(struct bmi2_dev *dev) rslt = BMI2_E_NULL_PTR; } } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } return rslt; } @@ -4445,8 +4519,8 @@ int8_t bmi2_get_internal_status(uint8_t *int_stat, struct bmi2_dev *dev) rslt = null_ptr_check(dev); if ((rslt == BMI2_OK) && (int_stat != NULL)) { - /* Delay to read the internal status */ - dev->delay_us(20000, dev->intf_ptr); + /* Wait till ASIC is initialized */ + dev->delay_us(BMI2_INTERNAL_STATUS_READ_DELAY_MS, dev->intf_ptr); /* Get the error bits and message */ rslt = bmi2_get_regs(BMI2_INTERNAL_STATUS_ADDR, int_stat, 1, dev); @@ -4459,69 +4533,6 @@ int8_t bmi2_get_internal_status(uint8_t *int_stat, struct bmi2_dev *dev) return rslt; } -/*! @cond DOXYGEN_SUPRESS */ - -/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant - * directories */ - -/*! - * @brief This API verifies and allows only the correct position to do Fast Offset Compensation for - * accelerometer & gyro. - */ -static int8_t verify_foc_position(uint8_t sens_list, - const struct bmi2_accel_foc_g_value *accel_g_axis, - struct bmi2_dev *dev) -{ - int8_t rslt; - - struct bmi2_sens_axes_data avg_foc_data = { 0 }; - struct bmi2_foc_temp_value temp_foc_data = { 0 }; - - rslt = null_ptr_check(dev); - if (rslt == BMI2_OK) - { - /* Enable sensor */ - rslt = bmi2_sensor_enable(&sens_list, 1, dev); - } - - if (rslt == BMI2_OK) - { - - rslt = get_average_of_sensor_data(sens_list, &temp_foc_data, dev); - if (rslt == BMI2_OK) - { - if (sens_list == BMI2_ACCEL) - { - - /* Taking modulus to make negative values as positive */ - if ((accel_g_axis->x == 1) && (accel_g_axis->sign == 1)) - { - temp_foc_data.x = temp_foc_data.x * -1; - } - else if ((accel_g_axis->y == 1) && (accel_g_axis->sign == 1)) - { - temp_foc_data.y = temp_foc_data.y * -1; - } - else if ((accel_g_axis->z == 1) && (accel_g_axis->sign == 1)) - { - temp_foc_data.z = temp_foc_data.z * -1; - } - } - - /* Typecasting into 16bit */ - avg_foc_data.x = (int16_t)(temp_foc_data.x); - avg_foc_data.y = (int16_t)(temp_foc_data.y); - avg_foc_data.z = (int16_t)(temp_foc_data.z); - - rslt = validate_foc_position(sens_list, accel_g_axis, avg_foc_data, dev); - } - } - - return rslt; -} - -/*! @endcond */ - /*! * @brief This API performs Fast Offset Compensation for accelerometer. */ @@ -4547,17 +4558,12 @@ int8_t bmi2_perform_accel_foc(const struct bmi2_accel_foc_g_value *accel_g_value if ((((BMI2_ABS(accel_g_value->x)) + (BMI2_ABS(accel_g_value->y)) + (BMI2_ABS(accel_g_value->z))) == 1) && ((accel_g_value->sign == 1) || (accel_g_value->sign == 0))) { - rslt = verify_foc_position(BMI2_ACCEL, accel_g_value, dev); - if (rslt == BMI2_OK) - { - - /* Save accelerometer configurations, accelerometer - * enable status and advance power save status - */ - rslt = save_accel_foc_config(&acc_cfg, &aps, &acc_en, dev); - } - - /* Set configurations for FOC */ + /* Save accelerometer configurations, accelerometer + * enable status and advance power save status + */ + rslt = save_accel_foc_config(&acc_cfg, &aps, &acc_en, dev); + + /* Set configurations for FOC */ if (rslt == BMI2_OK) { rslt = set_accel_foc_config(dev); @@ -4624,92 +4630,87 @@ int8_t bmi2_perform_gyro_foc(struct bmi2_dev *dev) rslt = null_ptr_check(dev); if (rslt == BMI2_OK) { - /* Argument2 is not applicable for gyro */ - rslt = verify_foc_position(BMI2_GYRO, 0, dev); + /* Save gyroscope configurations, gyroscope enable + * status and advance power save status + */ + rslt = save_gyro_config(&gyr_cfg, &aps, &gyr_en, dev); + + /* Set configurations for gyroscope FOC */ if (rslt == BMI2_OK) { - /* Save gyroscope configurations, gyroscope enable - * status and advance power save status - */ - rslt = save_gyro_config(&gyr_cfg, &aps, &gyr_en, dev); - - /* Set configurations for gyroscope FOC */ - if (rslt == BMI2_OK) - { - rslt = set_gyro_foc_config(dev); - } + rslt = set_gyro_foc_config(dev); + } - /* Perform FOC */ - if (rslt == BMI2_OK) + /* Perform FOC */ + if (rslt == BMI2_OK) + { + for (loop = 0; loop < 128; loop++) { - for (loop = 0; loop < 128; loop++) - { - /* Giving a delay of more than 40ms since ODR is configured as 25Hz */ - dev->delay_us(50000, dev->intf_ptr); - - /* Get gyroscope data ready interrupt status */ - rslt = bmi2_get_status(®_status, dev); + /* Giving a delay of more than 40ms since ODR is configured as 25Hz */ + dev->delay_us(50000, dev->intf_ptr); - /* Read 128 samples of gyroscope data on data ready interrupt */ - if ((rslt == BMI2_OK) && (reg_status & BMI2_DRDY_GYR)) - { - rslt = read_gyro_xyz(&gyr_value[loop], dev); - if (rslt == BMI2_OK) - { - /* Store the data in a temporary structure */ - temp.x = temp.x + (int32_t)gyr_value[loop].x; - temp.y = temp.y + (int32_t)gyr_value[loop].y; - temp.z = temp.z + (int32_t)gyr_value[loop].z; - } - } + /* Get gyroscope data ready interrupt status */ + rslt = bmi2_get_status(®_status, dev); - if (rslt != BMI2_OK) - { - break; - } - else if ((reg_status & BMI2_DRDY_GYR) != BMI2_DRDY_GYR) + /* Read 128 samples of gyroscope data on data ready interrupt */ + if ((rslt == BMI2_OK) && (reg_status & BMI2_DRDY_GYR)) + { + rslt = read_gyro_xyz(&gyr_value[loop], dev); + if (rslt == BMI2_OK) { - rslt = BMI2_E_INVALID_STATUS; - break; + /* Store the data in a temporary structure */ + temp.x = temp.x + (int32_t)gyr_value[loop].x; + temp.y = temp.y + (int32_t)gyr_value[loop].y; + temp.z = temp.z + (int32_t)gyr_value[loop].z; } } - if (rslt == BMI2_OK) + if (rslt != BMI2_OK) { - /* Take average of x, y and z data for lesser - * noise. It is same as offset data since lsb/dps - * is same for both data and offset register - */ - gyro_offset.x = (int16_t)(temp.x / 128); - gyro_offset.y = (int16_t)(temp.y / 128); - gyro_offset.z = (int16_t)(temp.z / 128); + break; + } + else if ((reg_status & BMI2_DRDY_GYR) != BMI2_DRDY_GYR) + { + rslt = BMI2_E_INVALID_STATUS; + break; + } + } - /* Saturate gyroscope data since the offset - * registers are of 10 bit value where as the - * gyroscope data is of 16 bit value - */ - saturate_gyro_data(&gyro_offset); + if (rslt == BMI2_OK) + { + /* Take average of x, y and z data for lesser + * noise. It is same as offset data since lsb/dps + * is same for both data and offset register + */ + gyro_offset.x = (int16_t)(temp.x / 128); + gyro_offset.y = (int16_t)(temp.y / 128); + gyro_offset.z = (int16_t)(temp.z / 128); - /* Invert the gyroscope offset data */ - invert_gyro_offset(&gyro_offset); + /* Saturate gyroscope data since the offset + * registers are of 10 bit value where as the + * gyroscope data is of 16 bit value + */ + saturate_gyro_data(&gyro_offset); - /* Write offset data in the gyroscope offset - * compensation register - */ - rslt = bmi2_write_gyro_offset_comp_axes(&gyro_offset, dev); - } + /* Invert the gyroscope offset data */ + invert_gyro_offset(&gyro_offset); - /* Enable gyroscope offset compensation */ - if (rslt == BMI2_OK) - { - rslt = bmi2_set_gyro_offset_comp(BMI2_ENABLE, dev); - } + /* Write offset data in the gyroscope offset + * compensation register + */ + rslt = bmi2_write_gyro_offset_comp_axes(&gyro_offset, dev); + } - /* Restore the saved gyroscope configurations */ - if (rslt == BMI2_OK) - { - rslt = restore_gyro_config(&gyr_cfg, aps, gyr_en, dev); - } + /* Enable gyroscope offset compensation */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_gyro_offset_comp(BMI2_ENABLE, dev); + } + + /* Restore the saved gyroscope configurations */ + if (rslt == BMI2_OK) + { + rslt = restore_gyro_config(&gyr_cfg, aps, gyr_en, dev); } } } @@ -4924,8 +4925,6 @@ static int8_t write_config_file(struct bmi2_dev *dev) /* Enable loading of the configuration */ rslt = set_config_load(BMI2_ENABLE, dev); - /* Wait till ASIC is initialized */ - dev->delay_us(150000, dev->intf_ptr); if (rslt == BMI2_OK) { /* Enable advanced power save mode */ @@ -5787,60 +5786,6 @@ static int8_t map_feat_int(uint8_t *reg_data_array, enum bmi2_hw_int_pin int_pin return rslt; } -/*! - * @brief This internal API gets the accelerometer data from the register. - */ -static int8_t get_accel_sensor_data(struct bmi2_sens_axes_data *data, uint8_t reg_addr, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt; - - /* Array to define data stored in register */ - uint8_t reg_data[BMI2_ACC_GYR_NUM_BYTES] = { 0 }; - - /* Read the sensor data */ - rslt = bmi2_get_regs(reg_addr, reg_data, BMI2_ACC_GYR_NUM_BYTES, dev); - if (rslt == BMI2_OK) - { - /* Get accelerometer data from the register */ - get_acc_gyr_data(data, reg_data); - - /* Get the re-mapped accelerometer data */ - get_remapped_data(data, dev); - } - - return rslt; -} - -/*! - * @brief This internal API gets the gyroscope data from the register. - */ -static int8_t get_gyro_sensor_data(struct bmi2_sens_axes_data *data, uint8_t reg_addr, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt; - - /* Array to define data stored in register */ - uint8_t reg_data[BMI2_ACC_GYR_NUM_BYTES] = { 0 }; - - /* Read the sensor data */ - rslt = bmi2_get_regs(reg_addr, reg_data, BMI2_ACC_GYR_NUM_BYTES, dev); - if (rslt == BMI2_OK) - { - /* Get gyroscope data from the register */ - get_acc_gyr_data(data, reg_data); - - /* Get the compensated gyroscope data */ - comp_gyro_cross_axis_sensitivity(data, dev); - - /* Get the re-mapped gyroscope data */ - get_remapped_data(data, dev); - - } - - return rslt; -} - /*! * @brief This internal API gets the accelerometer/gyroscope data. */ @@ -6012,46 +5957,6 @@ static int8_t write_aux_data(uint8_t reg_addr, uint8_t reg_data, struct bmi2_dev return rslt; } -/*! - * @brief This internal API reads the user-defined bytes of data from the given - * register address of auxiliary sensor in data mode. - */ -static int8_t read_aux_data_mode(uint8_t *aux_data, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt; - - /* Variables to define loop */ - uint8_t count = 0; - - /* Variables to define index */ - uint8_t index = 0; - - /* Array to define data stored in register */ - uint8_t reg_data[BMI2_AUX_NUM_BYTES] = { 0 }; - - /* Check if data mode */ - if (!dev->aux_man_en) - { - /* Read the auxiliary sensor data */ - rslt = bmi2_get_regs(BMI2_AUX_X_LSB_ADDR, reg_data, BMI2_AUX_NUM_BYTES, dev); - if (rslt == BMI2_OK) - { - /* Get the 8 bytes of auxiliary data */ - do - { - *(aux_data + count++) = *(reg_data + index++); - } while (count < BMI2_AUX_NUM_BYTES); - } - } - else - { - rslt = BMI2_E_AUX_INVALID_CFG; - } - - return rslt; -} - /*! * @brief This internal API maps the actual burst read length with that of the * register value set by user. @@ -6090,6 +5995,7 @@ static int8_t map_read_len(uint8_t *len, const struct bmi2_dev *dev) */ static int8_t parse_fifo_accel_len(uint16_t *start_idx, uint16_t *len, + uint8_t *skip_length, const uint16_t *acc_count, const struct bmi2_fifo_frame *fifo) { @@ -6104,24 +6010,45 @@ static int8_t parse_fifo_accel_len(uint16_t *start_idx, { /* Number of bytes to be read */ (*len) = (uint16_t)((*acc_count) * BMI2_FIFO_ACC_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ACC_LENGTH; } /* If only accelerometer and auxiliary are enabled */ else if (fifo->data_enable == (BMI2_FIFO_ACC_EN | BMI2_FIFO_AUX_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*acc_count) * BMI2_FIFO_ACC_AUX_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ACC_AUX_LENGTH; + + /* Data start index */ + (*start_idx) = fifo->acc_byte_start_idx + BMI2_FIFO_AUX_LENGTH; } /* If only accelerometer and gyroscope are enabled */ else if (fifo->data_enable == (BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*acc_count) * BMI2_FIFO_ACC_GYR_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ACC_GYR_LENGTH; + + /* Data start index */ + (*start_idx) = fifo->acc_byte_start_idx + BMI2_FIFO_GYR_LENGTH; } /* If only accelerometer, gyroscope and auxiliary are enabled */ else if (fifo->data_enable == (BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN | BMI2_FIFO_AUX_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*acc_count) * BMI2_FIFO_ALL_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ALL_LENGTH; + + /* Data start index */ + (*start_idx) = fifo->acc_byte_start_idx + BMI2_FIFO_GYR_AUX_LENGTH; } else { @@ -6143,6 +6070,109 @@ static int8_t parse_fifo_accel_len(uint16_t *start_idx, return rslt; } +/*! + * @brief This internal API is used to skip dummy frames in FIFO headerless mode + */ +static int8_t check_dummy_frame(uint8_t dummy_frame_header, + uint16_t *data_index, + uint8_t skip_length, + const struct bmi2_fifo_frame *fifo) +{ + int8_t rslt; + + /* Validate data index */ + if (((*data_index) + 6) < fifo->length) + { + /* Check if FIFO contains dummy frame */ + if (((fifo->data[(*data_index)] == dummy_frame_header) && + (fifo->data[(*data_index) + 1] == BMI2_FIFO_HEADERLESS_DUMMY_BYTE_1) && + (fifo->data[(*data_index) + 2] == BMI2_FIFO_HEADERLESS_DUMMY_BYTE_2)) && + ((fifo->data[(*data_index) + 3] == BMI2_FIFO_HEADERLESS_DUMMY_BYTE_3))) + { + /* Move the data index to next frame */ + (*data_index) = (*data_index) + skip_length; + + /* Dummy byte parsed */ + rslt = BMI2_W_DUMMY_BYTE; + } + else + { + /* Valid frame */ + rslt = BMI2_OK; + } + } + else + { + /* Move the data index to the last byte to mark completion */ + (*data_index) = fifo->length; + + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + } + + return rslt; + +} + +/*! + * @brief This internal API is used to parse the accelerometer data from the + * FIFO in headerless mode. + */ +static int8_t extract_accel_headerless_mode(struct bmi2_sens_axes_data *acc, + uint16_t *accel_length, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + int8_t rslt; + + /* Variable to index the bytes */ + uint16_t data_index = 0; + + /* Variable to define the data enable byte */ + uint8_t data_enable; + + /* Variable to index accelerometer frames */ + uint16_t accel_index = 0; + + /* Variable to store the number of bytes to be read */ + uint16_t data_read_length = 0; + + /* Number of bytes to skip in case dummy frame is obtained */ + uint8_t skip_length = 0; + + /* Get the number of accelerometer bytes to be read */ + rslt = parse_fifo_accel_len(&data_index, &data_read_length, &skip_length, accel_length, fifo); + + /* Convert word to byte since all sensor enables are in a byte */ + data_enable = (uint8_t)(fifo->data_enable >> 8); + + for (; (data_index < data_read_length) && (rslt != BMI2_W_FIFO_EMPTY);) + { + rslt = check_dummy_frame(BMI2_FIFO_HEADERLESS_DUMMY_ACC, &data_index, skip_length, fifo); + + /* Unpack only if Valid frame is present */ + if (rslt == BMI2_OK) + { + /* Unpack frame to get the accelerometer data */ + rslt = unpack_accel_headerless_frame(acc, &data_index, &accel_index, data_enable, fifo, dev); + + if (rslt != BMI2_W_FIFO_EMPTY) + { + /* Check for the availability of next two bytes of FIFO data */ + rslt = check_empty_fifo(&data_index, fifo); + } + } + } + + /* Update number of accelerometer frames to be read */ + (*accel_length) = accel_index; + + /* Update the accelerometer byte index */ + fifo->acc_byte_start_idx = data_index; + + return rslt; +} + /*! * @brief This internal API is used to parse the accelerometer data from the * FIFO in header mode. @@ -6186,7 +6216,7 @@ static int8_t extract_accel_header_mode(struct bmi2_sens_axes_data *acc, case BMI2_FIFO_HEADER_ALL_FRM: /* Unpack from normal frames */ - rslt = unpack_accel_frame(acc, &data_index, &accel_index, frame_header, fifo, dev); + rslt = unpack_accel_header_frame(acc, &data_index, &accel_index, frame_header, fifo, dev); break; /* If header defines only gyroscope frame */ @@ -6259,15 +6289,15 @@ static int8_t extract_accel_header_mode(struct bmi2_sens_axes_data *acc, /*! * @brief This internal API is used to parse the accelerometer data from the - * FIFO data in both header and header-less mode. It updates the current data + * FIFO data in header-less mode. It updates the current data * byte to be parsed. */ -static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, - uint16_t *idx, - uint16_t *acc_idx, - uint8_t frame, - const struct bmi2_fifo_frame *fifo, - const struct bmi2_dev *dev) +static int8_t unpack_accel_headerless_frame(struct bmi2_sens_axes_data *acc, + uint16_t *idx, + uint16_t *acc_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt = BMI2_OK; @@ -6275,7 +6305,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, switch (frame) { /* If frame contains only accelerometer data */ - case BMI2_FIFO_HEADER_ACC_FRM: case BMI2_FIFO_HEAD_LESS_ACC_FRM: /* Partially read, then skip the data */ @@ -6284,8 +6313,7 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, /* Update the data index as complete*/ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -6309,7 +6337,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, break; /* If frame contains accelerometer and gyroscope data */ - case BMI2_FIFO_HEADER_GYR_ACC_FRM: case BMI2_FIFO_HEAD_LESS_GYR_ACC_FRM: /* Partially read, then skip the data */ @@ -6318,13 +6345,12 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } /* Get the accelerometer data */ - unpack_accel_data(&acc[(*acc_idx)], ((*idx) + BMI2_FIFO_GYR_LENGTH), fifo, dev); + unpack_accel_data(&acc[(*acc_idx)], *idx, fifo, dev); /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_ACC_GYR_LENGTH; @@ -6343,7 +6369,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, break; /* If frame contains accelerometer and auxiliary data */ - case BMI2_FIFO_HEADER_AUX_ACC_FRM: case BMI2_FIFO_HEAD_LESS_AUX_ACC_FRM: /* Partially read, then skip the data */ @@ -6352,13 +6377,12 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } /* Get the accelerometer data */ - unpack_accel_data(&acc[(*acc_idx)], ((*idx) + BMI2_FIFO_AUX_LENGTH), fifo, dev); + unpack_accel_data(&acc[(*acc_idx)], *idx, fifo, dev); /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_ACC_AUX_LENGTH; @@ -6377,7 +6401,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, break; /* If frame contains accelerometer, gyroscope and auxiliary data */ - case BMI2_FIFO_HEADER_ALL_FRM: case BMI2_FIFO_HEAD_LESS_ALL_FRM: /* Partially read, then skip the data*/ @@ -6386,13 +6409,12 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } /* Get the accelerometer data */ - unpack_accel_data(&acc[(*acc_idx)], ((*idx) + BMI2_FIFO_GYR_AUX_LENGTH), fifo, dev); + unpack_accel_data(&acc[(*acc_idx)], *idx, fifo, dev); /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_ALL_LENGTH; @@ -6411,7 +6433,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, break; /* If frame contains gyroscope and auxiliary data */ - case BMI2_FIFO_HEADER_AUX_GYR_FRM: case BMI2_FIFO_HEAD_LESS_GYR_AUX_FRM: /* Update data index */ @@ -6422,7 +6443,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, break; /* If frame contains only auxiliary data */ - case BMI2_FIFO_HEADER_AUX_FRM: case BMI2_FIFO_HEAD_LESS_AUX_FRM: /* Update data index */ @@ -6433,7 +6453,6 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, break; /* If frame contains only gyroscope data */ - case BMI2_FIFO_HEADER_GYR_FRM: case BMI2_FIFO_HEAD_LESS_GYR_FRM: /* Update data index */ @@ -6456,24 +6475,211 @@ static int8_t unpack_accel_frame(struct bmi2_sens_axes_data *acc, } /*! - * @brief This internal API is used to parse accelerometer data from the - * FIFO data. + * @brief This internal API is used to parse the accelerometer data from the + * FIFO data in header mode. It updates the current data + * byte to be parsed. */ -static void unpack_accel_data(struct bmi2_sens_axes_data *acc, - uint16_t data_start_index, - const struct bmi2_fifo_frame *fifo, - const struct bmi2_dev *dev) +static int8_t unpack_accel_header_frame(struct bmi2_sens_axes_data *acc, + uint16_t *idx, + uint16_t *acc_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) { - /* Variables to store LSB value */ - uint16_t data_lsb; + /* Variable to define error */ + int8_t rslt = BMI2_OK; - /* Variables to store MSB value */ - uint16_t data_msb; + switch (frame) + { + /* If frame contains only accelerometer data */ + case BMI2_FIFO_HEADER_ACC_FRM: - /* Accelerometer raw x data */ - data_lsb = fifo->data[data_start_index++]; - data_msb = fifo->data[data_start_index++]; - acc->x = (int16_t)((data_msb << 8) | data_lsb); + /* Partially read, then skip the data */ + if (((*idx) + fifo->acc_frm_len) > fifo->length) + { + /* Update the data index as complete*/ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the accelerometer data */ + unpack_accel_data(&acc[(*acc_idx)], *idx, fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_ACC_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&acc[(*acc_idx)], idx, fifo); + } + + /* Update accelerometer frame index */ + (*acc_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains accelerometer and gyroscope data */ + case BMI2_FIFO_HEADER_GYR_ACC_FRM: + + /* Partially read, then skip the data */ + if (((*idx) + fifo->acc_gyr_frm_len) > fifo->length) + { + /* Move the data index to the last byte */ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the accelerometer data */ + unpack_accel_data(&acc[(*acc_idx)], ((*idx) + BMI2_FIFO_GYR_LENGTH), fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_ACC_GYR_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&acc[(*acc_idx)], idx, fifo); + } + + /* Update accelerometer frame index */ + (*acc_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains accelerometer and auxiliary data */ + case BMI2_FIFO_HEADER_AUX_ACC_FRM: + + /* Partially read, then skip the data */ + if (((*idx) + fifo->acc_aux_frm_len) > fifo->length) + { + /* Move the data index to the last byte */ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the accelerometer data */ + unpack_accel_data(&acc[(*acc_idx)], ((*idx) + BMI2_FIFO_AUX_LENGTH), fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_ACC_AUX_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&acc[(*acc_idx)], idx, fifo); + } + + /* Update accelerometer frame index */ + (*acc_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains accelerometer, gyroscope and auxiliary data */ + case BMI2_FIFO_HEADER_ALL_FRM: + + /* Partially read, then skip the data*/ + if ((*idx + fifo->all_frm_len) > fifo->length) + { + /* Move the data index to the last byte */ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the accelerometer data */ + unpack_accel_data(&acc[(*acc_idx)], ((*idx) + BMI2_FIFO_GYR_AUX_LENGTH), fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_ALL_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&acc[(*acc_idx)], idx, fifo); + } + + /* Update accelerometer frame index */ + (*acc_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains gyroscope and auxiliary data */ + case BMI2_FIFO_HEADER_AUX_GYR_FRM: + + /* Update data index */ + (*idx) = (*idx) + fifo->aux_gyr_frm_len; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains only auxiliary data */ + case BMI2_FIFO_HEADER_AUX_FRM: + + /* Update data index */ + (*idx) = (*idx) + fifo->aux_frm_len; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains only gyroscope data */ + case BMI2_FIFO_HEADER_GYR_FRM: + + /* Update data index */ + (*idx) = (*idx) + fifo->gyr_frm_len; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + default: + + /* Move the data index to the last byte in case of invalid values */ + (*idx) = fifo->length; + + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + break; + } + + return rslt; +} + +/*! + * @brief This internal API is used to parse accelerometer data from the + * FIFO data. + */ +static void unpack_accel_data(struct bmi2_sens_axes_data *acc, + uint16_t data_start_index, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + /* Variables to store LSB value */ + uint16_t data_lsb; + + /* Variables to store MSB value */ + uint16_t data_msb; + + /* Accelerometer raw x data */ + data_lsb = fifo->data[data_start_index++]; + data_msb = fifo->data[data_start_index++]; + acc->x = (int16_t)((data_msb << 8) | data_lsb); /* Accelerometer raw y data */ data_lsb = fifo->data[data_start_index++]; @@ -6494,7 +6700,8 @@ static void unpack_accel_data(struct bmi2_sens_axes_data *acc, * which is to be parsed in header-less mode. */ static int8_t parse_fifo_gyro_len(uint16_t *start_idx, - uint16_t(*len), + uint16_t *len, + uint8_t *skip_length, const uint16_t *gyr_count, const struct bmi2_fifo_frame *fifo) { @@ -6509,24 +6716,42 @@ static int8_t parse_fifo_gyro_len(uint16_t *start_idx, { /* Number of bytes to be read */ (*len) = (uint16_t)((*gyr_count) * BMI2_FIFO_GYR_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_GYR_LENGTH; } /* If only gyroscope and auxiliary are enabled */ else if (fifo->data_enable == (BMI2_FIFO_GYR_EN | BMI2_FIFO_AUX_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*gyr_count) * BMI2_FIFO_GYR_AUX_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_GYR_AUX_LENGTH; + + /* Data start index */ + (*start_idx) = fifo->gyr_byte_start_idx + BMI2_FIFO_AUX_LENGTH; } /* If only accelerometer and gyroscope are enabled */ else if (fifo->data_enable == (BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*gyr_count) * BMI2_FIFO_ACC_GYR_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ACC_GYR_LENGTH; } /* If only accelerometer, gyroscope and auxiliary are enabled */ else if (fifo->data_enable == (BMI2_FIFO_GYR_EN | BMI2_FIFO_AUX_EN | BMI2_FIFO_ACC_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*gyr_count) * BMI2_FIFO_ALL_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ALL_LENGTH; + + /* Data start index */ + (*start_idx) = fifo->gyr_byte_start_idx + BMI2_FIFO_AUX_LENGTH; } else { @@ -6548,6 +6773,65 @@ static int8_t parse_fifo_gyro_len(uint16_t *start_idx, return rslt; } +/*! + * @brief This internal API is used to parse the gyroscope data from the + * FIFO in headerless mode. + */ +static int8_t extract_gyro_headerless_mode(struct bmi2_sens_axes_data *gyr, + uint16_t *gyro_length, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + int8_t rslt; + + /* Variable to index the bytes */ + uint16_t data_index = 0; + + /* Variable to index gyroscope frames */ + uint16_t gyro_index = 0; + + /* Variable to store the number of bytes to be read */ + uint16_t data_read_length = 0; + + /* Variable to define the data enable byte */ + uint8_t data_enable; + + /* Variable to hold number of bytes to skip in case dummy frame is obtained */ + uint8_t skip_length = 0; + + /* Get the number of gyro bytes to be read */ + rslt = parse_fifo_gyro_len(&data_index, &data_read_length, &skip_length, gyro_length, fifo); + + /* Convert word to byte since all sensor enables are in a byte */ + data_enable = (uint8_t)(fifo->data_enable >> 8); + + for (; (data_index < data_read_length) && (rslt != BMI2_W_FIFO_EMPTY);) + { + rslt = check_dummy_frame(BMI2_FIFO_HEADERLESS_DUMMY_GYR, &data_index, skip_length, fifo); + + /* Unpack only if Valid frame is present */ + if (rslt == BMI2_OK) + { + /* Unpack frame to get gyroscope data */ + rslt = unpack_gyro_headerless_frame(gyr, &data_index, &gyro_index, data_enable, fifo, dev); + + if (rslt != BMI2_W_FIFO_EMPTY) + { + /* Check for the availability of next two bytes of FIFO data */ + rslt = check_empty_fifo(&data_index, fifo); + } + } + } + + /* Update number of gyroscope frames to be read */ + (*gyro_length) = gyro_index; + + /* Update the gyroscope byte index */ + fifo->gyr_byte_start_idx = data_index; + + return rslt; +} + /*! * @brief This internal API is used to parse the gyroscope data from the * FIFO data in header mode. @@ -6591,7 +6875,7 @@ static int8_t extract_gyro_header_mode(struct bmi2_sens_axes_data *gyr, case BMI2_FIFO_HEADER_ALL_FRM: /* Unpack from normal frames */ - rslt = unpack_gyro_frame(gyr, &data_index, &gyro_index, frame_header, fifo, dev); + rslt = unpack_gyro_header_frame(gyr, &data_index, &gyro_index, frame_header, fifo, dev); break; /* If header defines only accelerometer frame */ @@ -6604,75 +6888,263 @@ static int8_t extract_gyro_header_mode(struct bmi2_sens_axes_data *gyr, rslt = move_next_frame(&data_index, fifo->aux_frm_len, fifo); break; - /* If header defines only auxiliary and accelerometer frame */ - case BMI2_FIFO_HEADER_AUX_ACC_FRM: - rslt = move_next_frame(&data_index, fifo->acc_aux_frm_len, fifo); - break; + /* If header defines only auxiliary and accelerometer frame */ + case BMI2_FIFO_HEADER_AUX_ACC_FRM: + rslt = move_next_frame(&data_index, fifo->acc_aux_frm_len, fifo); + break; + + /* If header defines sensor time frame */ + case BMI2_FIFO_HEADER_SENS_TIME_FRM: + rslt = unpack_sensortime_frame(&data_index, fifo); + break; + + /* If header defines skip frame */ + case BMI2_FIFO_HEADER_SKIP_FRM: + rslt = unpack_skipped_frame(&data_index, fifo); + break; + + /* If header defines Input configuration frame */ + case BMI2_FIFO_HEADER_INPUT_CFG_FRM: + rslt = move_next_frame(&data_index, BMI2_FIFO_INPUT_CFG_LENGTH, fifo); + break; + + /* If header defines invalid frame or end of valid data */ + case BMI2_FIFO_HEAD_OVER_READ_MSB: + + /* Move the data index to the last byte */ + data_index = fifo->length; + + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + break; + case BMI2_FIFO_VIRT_ACT_RECOG_FRM: + rslt = move_next_frame(&data_index, BMI2_FIFO_VIRT_ACT_DATA_LENGTH, fifo); + break; + default: + + /* Move the data index to the last byte in case of invalid values */ + data_index = fifo->length; + + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + break; + } + + /* Break if number of frames to be read is complete or FIFO is empty */ + if ((frame_to_read == gyro_index) || (rslt == BMI2_W_FIFO_EMPTY)) + { + break; + } + } + + /* Update the gyroscope frame index */ + (*gyro_length) = gyro_index; + + /* Update the gyroscope byte index */ + fifo->gyr_byte_start_idx = data_index; + + return rslt; +} + +/*! + * @brief This internal API is used to parse the gyroscope data from the FIFO + * data in header mode. It updates the current data byte to + * be parsed. + */ +static int8_t unpack_gyro_header_frame(struct bmi2_sens_axes_data *gyr, + uint16_t *idx, + uint16_t *gyr_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + switch (frame) + { + /* If frame contains only gyroscope data */ + case BMI2_FIFO_HEADER_GYR_FRM: + + /* Partially read, then skip the data */ + if (((*idx) + fifo->gyr_frm_len) > fifo->length) + { + /* Update the data index as complete*/ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the gyroscope data */ + unpack_gyro_data(&gyr[(*gyr_idx)], *idx, fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_GYR_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&gyr[(*gyr_idx)], idx, fifo); + } + + /* Update gyroscope frame index */ + (*gyr_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains accelerometer and gyroscope data */ + case BMI2_FIFO_HEADER_GYR_ACC_FRM: + + /* Partially read, then skip the data */ + if (((*idx) + fifo->acc_gyr_frm_len) > fifo->length) + { + /* Move the data index to the last byte */ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the gyroscope data */ + unpack_gyro_data(&gyr[(*gyr_idx)], (*idx), fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_ACC_GYR_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&gyr[(*gyr_idx)], idx, fifo); + } + + /* Update gyroscope frame index */ + (*gyr_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains gyroscope and auxiliary data */ + case BMI2_FIFO_HEADER_AUX_GYR_FRM: + + /* Partially read, then skip the data */ + if (((*idx) + fifo->aux_gyr_frm_len) > fifo->length) + { + /* Move the data index to the last byte */ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the gyroscope data */ + unpack_gyro_data(&gyr[(*gyr_idx)], ((*idx) + BMI2_FIFO_AUX_LENGTH), fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_GYR_AUX_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&gyr[(*gyr_idx)], idx, fifo); + } + + /* Update gyroscope frame index */ + (*gyr_idx)++; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; + + /* If frame contains accelerometer, gyroscope and auxiliary data */ + case BMI2_FIFO_HEADER_ALL_FRM: + + /* Partially read, then skip the data*/ + if ((*idx + fifo->all_frm_len) > fifo->length) + { + /* Move the data index to the last byte */ + (*idx) = fifo->length; + + rslt = BMI2_OK; + break; + } + + /* Get the gyroscope data */ + unpack_gyro_data(&gyr[(*gyr_idx)], ((*idx) + BMI2_FIFO_AUX_LENGTH), fifo, dev); + + /* Update data index */ + (*idx) = (*idx) + BMI2_FIFO_ALL_LENGTH; + + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_sensor_time(&gyr[(*gyr_idx)], idx, fifo); + } + + /* Update gyroscope frame index */ + (*gyr_idx)++; - /* If header defines sensor time frame */ - case BMI2_FIFO_HEADER_SENS_TIME_FRM: - rslt = unpack_sensortime_frame(&data_index, fifo); - break; + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; - /* If header defines skip frame */ - case BMI2_FIFO_HEADER_SKIP_FRM: - rslt = unpack_skipped_frame(&data_index, fifo); - break; + /* If frame contains accelerometer and auxiliary data */ + case BMI2_FIFO_HEADER_AUX_ACC_FRM: - /* If header defines Input configuration frame */ - case BMI2_FIFO_HEADER_INPUT_CFG_FRM: - rslt = move_next_frame(&data_index, BMI2_FIFO_INPUT_CFG_LENGTH, fifo); - break; + /* Update data index */ + (*idx) = (*idx) + fifo->acc_aux_frm_len; - /* If header defines invalid frame or end of valid data */ - case BMI2_FIFO_HEAD_OVER_READ_MSB: + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; - /* Move the data index to the last byte */ - data_index = fifo->length; + /* If frame contains only auxiliary data */ + case BMI2_FIFO_HEADER_AUX_FRM: + case BMI2_FIFO_HEAD_LESS_AUX_FRM: - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; - break; - case BMI2_FIFO_VIRT_ACT_RECOG_FRM: - rslt = move_next_frame(&data_index, BMI2_FIFO_VIRT_ACT_DATA_LENGTH, fifo); - break; - default: + /* Update data index */ + (*idx) = (*idx) + fifo->aux_frm_len; - /* Move the data index to the last byte in case of invalid values */ - data_index = fifo->length; + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; + break; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; - break; - } + /* If frame contains only accelerometer data */ + case BMI2_FIFO_HEADER_ACC_FRM: - /* Break if number of frames to be read is complete or FIFO is empty */ - if ((frame_to_read == gyro_index) || (rslt == BMI2_W_FIFO_EMPTY)) - { + /* Update data index */ + (*idx) = (*idx) + fifo->acc_frm_len; + + /* More frames could be read */ + rslt = BMI2_W_PARTIAL_READ; break; - } - } + default: - /* Update the gyroscope frame index */ - (*gyro_length) = gyro_index; + /* Move the data index to the last byte in case of invalid values */ + (*idx) = fifo->length; - /* Update the gyroscope byte index */ - fifo->gyr_byte_start_idx = data_index; + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + break; + } return rslt; } /*! * @brief This internal API is used to parse the gyroscope data from the FIFO - * data in both header and header-less mode. It updates the current data byte to + * data in header-less mode. It updates the current data byte to * be parsed. */ -static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, - uint16_t *idx, - uint16_t *gyr_idx, - uint8_t frame, - const struct bmi2_fifo_frame *fifo, - const struct bmi2_dev *dev) +static int8_t unpack_gyro_headerless_frame(struct bmi2_sens_axes_data *gyr, + uint16_t *idx, + uint16_t *gyr_idx, + uint8_t frame, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt = BMI2_OK; @@ -6680,7 +7152,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, switch (frame) { /* If frame contains only gyroscope data */ - case BMI2_FIFO_HEADER_GYR_FRM: case BMI2_FIFO_HEAD_LESS_GYR_FRM: /* Partially read, then skip the data */ @@ -6689,8 +7160,7 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, /* Update the data index as complete*/ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -6714,7 +7184,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, break; /* If frame contains accelerometer and gyroscope data */ - case BMI2_FIFO_HEADER_GYR_ACC_FRM: case BMI2_FIFO_HEAD_LESS_GYR_ACC_FRM: /* Partially read, then skip the data */ @@ -6723,8 +7192,7 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -6748,7 +7216,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, break; /* If frame contains gyroscope and auxiliary data */ - case BMI2_FIFO_HEADER_AUX_GYR_FRM: case BMI2_FIFO_HEAD_LESS_GYR_AUX_FRM: /* Partially read, then skip the data */ @@ -6757,13 +7224,12 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } /* Get the gyroscope data */ - unpack_gyro_data(&gyr[(*gyr_idx)], ((*idx) + BMI2_FIFO_AUX_LENGTH), fifo, dev); + unpack_gyro_data(&gyr[(*gyr_idx)], (*idx), fifo, dev); /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_GYR_AUX_LENGTH; @@ -6782,7 +7248,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, break; /* If frame contains accelerometer, gyroscope and auxiliary data */ - case BMI2_FIFO_HEADER_ALL_FRM: case BMI2_FIFO_HEAD_LESS_ALL_FRM: /* Partially read, then skip the data*/ @@ -6791,13 +7256,12 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } /* Get the gyroscope data */ - unpack_gyro_data(&gyr[(*gyr_idx)], ((*idx) + BMI2_FIFO_AUX_LENGTH), fifo, dev); + unpack_gyro_data(&gyr[(*gyr_idx)], (*idx), fifo, dev); /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_ALL_LENGTH; @@ -6816,7 +7280,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, break; /* If frame contains accelerometer and auxiliary data */ - case BMI2_FIFO_HEADER_AUX_ACC_FRM: case BMI2_FIFO_HEAD_LESS_AUX_ACC_FRM: /* Update data index */ @@ -6827,7 +7290,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, break; /* If frame contains only auxiliary data */ - case BMI2_FIFO_HEADER_AUX_FRM: case BMI2_FIFO_HEAD_LESS_AUX_FRM: /* Update data index */ @@ -6838,7 +7300,6 @@ static int8_t unpack_gyro_frame(struct bmi2_sens_axes_data *gyr, break; /* If frame contains only accelerometer data */ - case BMI2_FIFO_HEADER_ACC_FRM: case BMI2_FIFO_HEAD_LESS_ACC_FRM: /* Update data index */ @@ -6901,7 +7362,8 @@ static void unpack_gyro_data(struct bmi2_sens_axes_data *gyr, * to be parsed in header-less mode. */ static int8_t parse_fifo_aux_len(uint16_t *start_idx, - uint16_t(*len), + uint16_t *len, + uint8_t *skip_length, const uint16_t *aux_count, const struct bmi2_fifo_frame *fifo) { @@ -6916,30 +7378,40 @@ static int8_t parse_fifo_aux_len(uint16_t *start_idx, { /* Number of bytes to be read */ (*len) = (uint16_t)((*aux_count) * BMI2_FIFO_AUX_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_AUX_LENGTH; } /* If only accelerometer and auxiliary are enabled */ else if (fifo->data_enable == (BMI2_FIFO_AUX_EN | BMI2_FIFO_ACC_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*aux_count) * BMI2_FIFO_ACC_AUX_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ACC_AUX_LENGTH; } /* If only accelerometer and gyroscope are enabled */ else if (fifo->data_enable == (BMI2_FIFO_AUX_EN | BMI2_FIFO_GYR_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*aux_count) * BMI2_FIFO_GYR_AUX_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_GYR_AUX_LENGTH; } /* If only accelerometer, gyroscope and auxiliary are enabled */ else if (fifo->data_enable == (BMI2_FIFO_AUX_EN | BMI2_FIFO_GYR_EN | BMI2_FIFO_ACC_EN)) { /* Number of bytes to be read */ (*len) = (uint16_t)((*aux_count) * BMI2_FIFO_ALL_LENGTH); + + /* Number of bytes to skip in case dummy frame is obtained */ + (*skip_length) = BMI2_FIFO_ALL_LENGTH; } else { - /* Move the data index to the last byte to mark completion when - * no sensors or sensors apart from gyroscope are enabled - */ + /* Move the data index to the last byte to mark completion */ (*start_idx) = fifo->length; /* FIFO is empty */ @@ -6955,6 +7427,64 @@ static int8_t parse_fifo_aux_len(uint16_t *start_idx, return rslt; } +/*! + * @brief This internal API is used to parse the auxiliary data from the + * FIFO in headerless mode. + */ +static int8_t extract_aux_headerless_mode(struct bmi2_aux_fifo_data *aux, + uint16_t *aux_length, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + int8_t rslt; + + /* Variable to index the bytes */ + uint16_t data_index = 0; + + /* Variable to index auxiliary frames */ + uint16_t aux_index = 0; + + /* Variable to store the number of bytes to be read */ + uint16_t data_read_length = 0; + + /* Variable to define the data enable byte */ + uint8_t data_enable; + + /* Number of bytes to skip in case dummy frame is obtained */ + uint8_t skip_length = 0; + + rslt = parse_fifo_aux_len(&data_index, &data_read_length, &skip_length, aux_length, fifo); + + /* Convert word to byte since all sensor enables are in a byte */ + data_enable = (uint8_t)(fifo->data_enable >> 8); + + for (; (data_index < data_read_length) && (rslt != BMI2_W_FIFO_EMPTY);) + { + rslt = check_dummy_frame(BMI2_FIFO_HEADERLESS_DUMMY_AUX, &data_index, skip_length, fifo); + + /* Unpack only if Valid frame is present */ + if (rslt == BMI2_OK) + { + /* Unpack frame to get auxiliary data */ + rslt = unpack_aux_frame(aux, &data_index, &aux_index, data_enable, fifo, dev); + + if (rslt != BMI2_W_FIFO_EMPTY) + { + /* Check for the availability of next two bytes of FIFO data */ + rslt = check_empty_fifo(&data_index, fifo); + } + } + } + + /* Update number of auxiliary frames to be read */ + *aux_length = aux_index; + + /* Update the auxiliary byte index */ + fifo->aux_byte_start_idx = data_index; + + return rslt; +} + /*! * @brief This API is used to parse the auxiliary data from the FIFO data in * header mode. @@ -7100,8 +7630,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Update the data index as complete*/ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -7111,11 +7640,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_AUX_LENGTH; - /* Get virtual sensor time if S4S is enabled */ - if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) - { - unpack_virt_aux_sensor_time(&aux[(*aux_idx)], idx, fifo); - } + unpack_virtual_aux_data(&aux[(*aux_idx)], idx, aux_idx, fifo, dev); /* Update auxiliary frame index */ (*aux_idx)++; @@ -7134,8 +7659,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -7145,11 +7669,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_ACC_AUX_LENGTH; - /* Get virtual sensor time if S4S is enabled */ - if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) - { - unpack_virt_aux_sensor_time(&aux[(*aux_idx)], idx, fifo); - } + unpack_virtual_aux_data(&aux[(*aux_idx)], idx, aux_idx, fifo, dev); /* Update auxiliary frame index */ (*aux_idx)++; @@ -7168,8 +7688,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -7179,11 +7698,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_GYR_AUX_LENGTH; - /* Get virtual sensor time if S4S is enabled */ - if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) - { - unpack_virt_aux_sensor_time(&aux[(*aux_idx)], idx, fifo); - } + unpack_virtual_aux_data(&aux[(*aux_idx)], idx, aux_idx, fifo, dev); /* Update auxiliary frame index */ (*aux_idx)++; @@ -7202,8 +7717,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Move the data index to the last byte */ (*idx) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; break; } @@ -7213,11 +7727,7 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, /* Update data index */ (*idx) = (*idx) + BMI2_FIFO_ALL_LENGTH; - /* Get virtual sensor time if S4S is enabled */ - if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) - { - unpack_virt_aux_sensor_time(&aux[(*aux_idx)], idx, fifo); - } + unpack_virtual_aux_data(&aux[(*aux_idx)], idx, aux_idx, fifo, dev); /* Update auxiliary frame index */ (*aux_idx)++; @@ -7273,6 +7783,22 @@ static int8_t unpack_aux_frame(struct bmi2_aux_fifo_data *aux, return rslt; } +/*! + * @brief This internal API is used to unpack virtual auxillary sensortime data. + */ +static void unpack_virtual_aux_data(struct bmi2_aux_fifo_data *aux, + uint16_t *idx, + const uint16_t *aux_idx, + const struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + /* Get virtual sensor time if S4S is enabled */ + if (dev->sens_en_stat & BMI2_EXT_SENS_SEL) + { + unpack_virt_aux_sensor_time(&aux[(*aux_idx)], idx, fifo); + } +} + /*! * @brief This internal API is used to parse auxiliary data from the FIFO data. */ @@ -7416,12 +7942,12 @@ static int8_t check_empty_fifo(uint16_t *data_index, const struct bmi2_fifo_fram if (((*data_index) + 6) < fifo->length) { /* Check if FIFO is empty */ - if (((fifo->data[(*data_index)] == BMI2_FIFO_MSB_CONFIG_CHECK) && - (fifo->data[(*data_index) + 1] == BMI2_FIFO_LSB_CONFIG_CHECK)) && - ((fifo->data[(*data_index) + 2] == BMI2_FIFO_MSB_CONFIG_CHECK) && - (fifo->data[(*data_index) + 3] == BMI2_FIFO_LSB_CONFIG_CHECK)) && - ((fifo->data[(*data_index) + 4] == BMI2_FIFO_MSB_CONFIG_CHECK) && - (fifo->data[(*data_index) + 5] == BMI2_FIFO_LSB_CONFIG_CHECK))) + if (((fifo->data[(*data_index)] == BMI2_FIFO_LSB_CONFIG_CHECK) && + (fifo->data[(*data_index) + 1] == BMI2_FIFO_MSB_CONFIG_CHECK) && + (fifo->data[(*data_index) + 2] == BMI2_FIFO_LSB_CONFIG_CHECK)) && + ((fifo->data[(*data_index) + 3] == BMI2_FIFO_MSB_CONFIG_CHECK) && + (fifo->data[(*data_index) + 4] == BMI2_FIFO_LSB_CONFIG_CHECK)) && + ((fifo->data[(*data_index) + 5] == BMI2_FIFO_MSB_CONFIG_CHECK))) { /* Move the data index to the last byte to mark completion */ (*data_index) = fifo->length; @@ -7455,8 +7981,7 @@ static int8_t move_next_frame(uint16_t *data_index, uint8_t current_frame_length /* Move the data index to the last byte */ (*data_index) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; } else { @@ -7490,8 +8015,7 @@ static int8_t unpack_sensortime_frame(uint16_t *data_index, struct bmi2_fifo_fra /* Move the data index to the last byte */ (*data_index) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; } else { @@ -7528,8 +8052,7 @@ static int8_t unpack_skipped_frame(uint16_t *data_index, struct bmi2_fifo_frame /* Update the data index to the last byte */ (*data_index) = fifo->length; - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; + rslt = BMI2_OK; } else { @@ -7699,9 +8222,9 @@ static int8_t read_accel_xyz(struct bmi2_sens_axes_data *accel, struct bmi2_dev uint16_t msb = 0; /* Array to define data buffer */ - uint8_t data[BMI2_ACC_GYR_NUM_BYTES] = { 0 }; + uint8_t data[BMI2_ACC_NUM_BYTES] = { 0 }; - rslt = bmi2_get_regs(BMI2_ACC_X_LSB_ADDR, data, BMI2_ACC_GYR_NUM_BYTES, dev); + rslt = bmi2_get_regs(BMI2_ACC_X_LSB_ADDR, data, BMI2_ACC_NUM_BYTES, dev); if (rslt == BMI2_OK) { /* Accelerometer data x axis */ @@ -7739,9 +8262,9 @@ static int8_t read_gyro_xyz(struct bmi2_sens_axes_data *gyro, struct bmi2_dev *d uint16_t msb = 0; /* Array to define data buffer */ - uint8_t data[BMI2_ACC_GYR_NUM_BYTES] = { 0 }; + uint8_t data[BMI2_GYR_NUM_BYTES] = { 0 }; - rslt = bmi2_get_regs(BMI2_GYR_X_LSB_ADDR, data, BMI2_ACC_GYR_NUM_BYTES, dev); + rslt = bmi2_get_regs(BMI2_GYR_X_LSB_ADDR, data, BMI2_GYR_NUM_BYTES, dev); if (rslt == BMI2_OK) { /* Gyroscope data x axis */ @@ -8036,14 +8559,37 @@ static int8_t set_remap_axes(const struct bmi2_axes_remap *remap, struct bmi2_de return rslt; } +/*! + * @brief This internal API clips the gyroscope cross-axis sensitivity within signed 16-bit limit + */ +static int16_t saturate(int32_t value, uint16_t saturation_val) +{ + int16_t retval = (int16_t)value; + + if (value > (int32_t)saturation_val) + { + retval = (int16_t)saturation_val; + } + else if (value < (-(int32_t)saturation_val - 1)) + { + retval = -(int16_t)saturation_val - 1; + } + + return retval; +} + /*! * @brief This internal API corrects the gyroscope cross-axis sensitivity * between the z and the x axis. */ static void comp_gyro_cross_axis_sensitivity(struct bmi2_sens_axes_data *gyr_data, const struct bmi2_dev *dev) { + uint16_t int16_max = UINT16_C(32767); + /* Get the compensated gyroscope x-axis */ - gyr_data->x = gyr_data->x - (int16_t)(((int32_t) dev->gyr_cross_sens_zx * (int32_t) gyr_data->z) / 512); + gyr_data->x = + saturate((int32_t)(gyr_data->x - (int16_t)(((int32_t) dev->gyr_cross_sens_zx * (int32_t) gyr_data->z) / 512)), + int16_max); } /*! @@ -9026,11 +9572,8 @@ int8_t bmi2_do_crt(struct bmi2_dev *dev) static int8_t do_gtrigger_test(uint8_t gyro_st_crt, struct bmi2_dev *dev) { int8_t rslt; - int8_t rslt_crt = BMI2_OK; uint8_t st_status = 0; uint8_t max_burst_length = 0; - uint8_t download_ready = 0; - uint8_t cmd = BMI2_G_TRIGGER_CMD; struct bmi2_gyro_self_test_status gyro_st_result = { 0 }; /* Variable to get the status of advance power save */ @@ -9057,98 +9600,15 @@ static int8_t do_gtrigger_test(uint8_t gyro_st_crt, struct bmi2_dev *dev) } /* Checking for CRT running status */ - if (rslt == BMI2_OK) - { - rslt = get_st_running(&st_status, dev); - } - - /* CRT is not running and Max burst length is zero */ - if (st_status == 0) - { - if (rslt == BMI2_OK) - { - rslt = set_st_running(BMI2_ENABLE, dev); - } - - /* Preparing the setup */ - if (rslt == BMI2_OK) - { - rslt = crt_prepare_setup(dev); - } - - /* Enable the gyro self-test, CRT */ - if (rslt == BMI2_OK) - { - rslt = select_self_test(gyro_st_crt, dev); - } - - /* Check if FIFO is unchanged by checking the max burst length */ - if ((rslt == BMI2_OK) && (max_burst_length == 0)) - { - /* Trigger CRT */ - rslt = bmi2_set_regs(BMI2_CMD_REG_ADDR, &cmd, 1, dev); - if (rslt == BMI2_OK) - { - /* Wait until st_status = 0 or time out is 2 seconds */ - rslt = wait_st_running(BMI2_CRT_WAIT_RUNNING_RETRY_EXECUTION, dev); - - /* CRT Running wait & check is successful */ - if (rslt == BMI2_OK) - { - rslt = crt_gyro_st_update_result(dev); - } - } - } - else - { - /* FIFO may be used */ - if (rslt == BMI2_OK) - { - if (dev->read_write_len < 2) - { - dev->read_write_len = 2; - } - - if (dev->read_write_len > (BMI2_CRT_MAX_BURST_WORD_LENGTH * 2)) - { - dev->read_write_len = BMI2_CRT_MAX_BURST_WORD_LENGTH * 2; - } - - /* Reset the max burst length to default value */ - rslt = set_maxburst_len(dev->read_write_len, dev); - } - - if (rslt == BMI2_OK) - { - rslt = get_rdy_for_dl(&download_ready, dev); - } - - /* Trigger CRT */ - if (rslt == BMI2_OK) - { - rslt = bmi2_set_regs(BMI2_CMD_REG_ADDR, &cmd, 1, dev); - } - - /* Wait till either ready for download toggle or crt running = 0 */ - if (rslt == BMI2_OK) - { - rslt = wait_rdy_for_dl_toggle(BMI2_CRT_READY_FOR_DOWNLOAD_RETRY, download_ready, dev); - if (rslt == BMI2_OK) - { - rslt = write_crt_config_file(dev->read_write_len, BMI2_CRT_CONFIG_FILE_SIZE, 0x1800, dev); - } + if (rslt == BMI2_OK) + { + rslt = get_st_running(&st_status, dev); + } - if (rslt == BMI2_OK) - { - rslt = wait_st_running(BMI2_CRT_WAIT_RUNNING_RETRY_EXECUTION, dev); - rslt_crt = crt_gyro_st_update_result(dev); - if (rslt == BMI2_OK) - { - rslt = rslt_crt; - } - } - } - } + /* CRT is not running and Max burst length is zero */ + if (st_status == 0) + { + rslt = gyro_crt_test(max_burst_length, gyro_st_crt, dev); } else { @@ -9171,6 +9631,10 @@ static int8_t do_gtrigger_test(uint8_t gyro_st_crt, struct bmi2_dev *dev) rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); } } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } } return rslt; @@ -9504,7 +9968,7 @@ static int8_t select_self_test(uint8_t gyro_st_crt, struct bmi2_dev *dev) /* Define the offset in bytes */ idx = gyro_self_test_crt_config.start_addr; - /* update the gyro self-test crt enable bit */ + /* Update the gyro self-test crt enable bit */ feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_GYRO_SELF_TEST_CRT_EN, gyro_st_crt); /* Update the register address */ @@ -9674,96 +10138,6 @@ static int8_t gyro_self_test_completed(struct bmi2_gyro_self_test_status *gyro_s return rslt; } -/*! - * @brief This api validates accel foc position as per the range - */ -static int8_t validate_foc_position(uint8_t sens_list, - const struct bmi2_accel_foc_g_value *accel_g_axis, - struct bmi2_sens_axes_data avg_foc_data, - struct bmi2_dev *dev) -{ - int8_t rslt = BMI2_E_INVALID_INPUT; - - if (sens_list == BMI2_ACCEL) - { - if (accel_g_axis->x == 1) - { - rslt = validate_foc_accel_axis(avg_foc_data.x, dev); - } - else if (accel_g_axis->y == 1) - { - rslt = validate_foc_accel_axis(avg_foc_data.y, dev); - } - else - { - rslt = validate_foc_accel_axis(avg_foc_data.z, dev); - } - } - else if (sens_list == BMI2_GYRO) - { - if (((avg_foc_data.x >= BMI2_GYRO_FOC_NOISE_LIMIT_NEGATIVE) && - (avg_foc_data.x <= BMI2_GYRO_FOC_NOISE_LIMIT_POSITIVE)) && - ((avg_foc_data.y >= BMI2_GYRO_FOC_NOISE_LIMIT_NEGATIVE) && - (avg_foc_data.y <= BMI2_GYRO_FOC_NOISE_LIMIT_POSITIVE)) && - ((avg_foc_data.z >= BMI2_GYRO_FOC_NOISE_LIMIT_NEGATIVE) && - (avg_foc_data.z <= BMI2_GYRO_FOC_NOISE_LIMIT_POSITIVE))) - { - rslt = BMI2_OK; - } - else - { - rslt = BMI2_E_INVALID_FOC_POSITION; - } - } - - return rslt; -} - -/*! - * @brief This api validates depends on accel foc access input - */ -static int8_t validate_foc_accel_axis(int16_t avg_foc_data, struct bmi2_dev *dev) -{ - struct bmi2_sens_config sens_cfg = { 0 }; - uint8_t range; - int8_t rslt; - - sens_cfg.type = BMI2_ACCEL; - rslt = bmi2_get_sensor_config(&sens_cfg, 1, dev); - range = sens_cfg.cfg.acc.range; - - /* reference LSB value of 16G */ - if ((range == BMI2_ACC_RANGE_2G) && (avg_foc_data > BMI2_ACC_2G_MIN_NOISE_LIMIT) && - (avg_foc_data < BMI2_ACC_2G_MAX_NOISE_LIMIT)) - { - rslt = BMI2_OK; - } - /* reference LSB value of 16G */ - else if ((range == BMI2_ACC_RANGE_4G) && (avg_foc_data > BMI2_ACC_4G_MIN_NOISE_LIMIT) && - (avg_foc_data < BMI2_ACC_4G_MAX_NOISE_LIMIT)) - { - rslt = BMI2_OK; - } - /* reference LSB value of 16G */ - else if ((range == BMI2_ACC_RANGE_8G) && (avg_foc_data > BMI2_ACC_8G_MIN_NOISE_LIMIT) && - (avg_foc_data < BMI2_ACC_8G_MAX_NOISE_LIMIT)) - { - rslt = BMI2_OK; - } - /* reference LSB value of 16G */ - else if ((range == BMI2_ACC_RANGE_16G) && (avg_foc_data > BMI2_ACC_16G_MIN_NOISE_LIMIT) && - (avg_foc_data < BMI2_ACC_16G_MAX_NOISE_LIMIT)) - { - rslt = BMI2_OK; - } - else - { - rslt = BMI2_E_INVALID_FOC_POSITION; - } - - return rslt; -} - /*! @brief This api is used for programming the non volatile memory(nvm) */ int8_t bmi2_nvm_prog(struct bmi2_dev *dev) { @@ -9858,83 +10232,6 @@ int8_t bmi2_nvm_prog(struct bmi2_dev *dev) return rslt; } -/*! - * @brief This API reads and provides average for 128 samples of sensor data for foc operation - * gyro. - */ -static int8_t get_average_of_sensor_data(uint8_t sens_list, - struct bmi2_foc_temp_value *temp_foc_data, - struct bmi2_dev *dev) -{ - int8_t rslt = 0; - struct bmi2_sensor_data sensor_data = { 0 }; - uint8_t sample_count = 0; - uint8_t datardy_try_cnt; - uint8_t drdy_status = 0; - uint8_t sensor_drdy = 0; - - sensor_data.type = sens_list; - if (sens_list == BMI2_ACCEL) - { - sensor_drdy = BMI2_DRDY_ACC; - } - else - { - sensor_drdy = BMI2_DRDY_GYR; - } - - /* Read sensor values before FOC */ - while (sample_count < BMI2_FOC_SAMPLE_LIMIT) - { - datardy_try_cnt = 5; - do - { - dev->delay_us(20000, dev->intf_ptr); - rslt = bmi2_get_status(&drdy_status, dev); - datardy_try_cnt--; - } while ((rslt == BMI2_OK) && (!(drdy_status & sensor_drdy)) && (datardy_try_cnt)); - - if ((rslt != BMI2_OK) || (datardy_try_cnt == 0)) - { - rslt = BMI2_E_DATA_RDY_INT_FAILED; - break; - } - - rslt = bmi2_get_sensor_data(&sensor_data, 1, dev); - - if (rslt == BMI2_OK) - { - if (sensor_data.type == BMI2_ACCEL) - { - temp_foc_data->x += sensor_data.sens_data.acc.x; - temp_foc_data->y += sensor_data.sens_data.acc.y; - temp_foc_data->z += sensor_data.sens_data.acc.z; - } - else if (sensor_data.type == BMI2_GYRO) - { - temp_foc_data->x += sensor_data.sens_data.gyr.x; - temp_foc_data->y += sensor_data.sens_data.gyr.y; - temp_foc_data->z += sensor_data.sens_data.gyr.z; - } - } - else - { - break; - } - - sample_count++; - } - - if (rslt == BMI2_OK) - { - temp_foc_data->x = (temp_foc_data->x / BMI2_FOC_SAMPLE_LIMIT); - temp_foc_data->y = (temp_foc_data->y / BMI2_FOC_SAMPLE_LIMIT); - temp_foc_data->z = (temp_foc_data->z / BMI2_FOC_SAMPLE_LIMIT); - } - - return rslt; -} - /*! * @brief This internal API extract the identification feature from the DMR page * and retrieve the config file major and minor version. @@ -10335,4 +10632,261 @@ static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev) return rslt; } +/*! + * @brief This internal API reads accelerometer, gyroscope and auxiliary sensor data. + */ +static int8_t read_sensor_data(uint8_t aux_len, + uint8_t acc_len, + uint8_t gyr_len, + uint8_t *sensor_data, + struct bmi2_dev *dev) +{ + int8_t rslt; + uint8_t start_addr = 0; + uint8_t len = 0; + + /* Read data with auxiliary sensor data */ + if (aux_len != 0) + { + /* Read auxiliary, accelerometer and gyroscope sensor data */ + if ((acc_len != 0) && (gyr_len != 0)) + { + start_addr = BMI2_AUX_X_LSB_ADDR; + len = BMI2_ACC_GYR_AUX_NUM_BYTES; + } + /* Read auxiliary and accelerometer sensor data */ + else if ((acc_len != 0) && (gyr_len == 0)) + { + start_addr = BMI2_AUX_X_LSB_ADDR; + len = BMI2_AUX_ACC_NUM_BYTES; + } + /* Read auxiliary and gyroscope sensor data */ + else if ((gyr_len != 0) && (acc_len == 0)) + { + start_addr = BMI2_AUX_X_LSB_ADDR; + len = BMI2_ACC_GYR_AUX_NUM_BYTES; + } + /* Read only auxiliary sensor data */ + else if ((acc_len == 0) && (gyr_len == 0)) + { + start_addr = BMI2_AUX_X_LSB_ADDR; + len = BMI2_AUX_NUM_BYTES; + } + } + /* Read data without auxiliary sensor data */ + else + { + /* Read accelerometer and gyroscope sensor data */ + if ((acc_len != 0) && (gyr_len != 0)) + { + start_addr = BMI2_ACC_X_LSB_ADDR; + len = BMI2_ACC_GYR_NUM_BYTES; + } + /* Read only accelerometer sensor data */ + else if ((acc_len != 0) && (gyr_len == 0)) + { + start_addr = BMI2_ACC_X_LSB_ADDR; + len = BMI2_ACC_NUM_BYTES; + } + /* Read only gyroscope sensor data */ + else if ((gyr_len != 0) && (acc_len == 0)) + { + start_addr = BMI2_GYR_X_LSB_ADDR; + len = BMI2_GYR_NUM_BYTES; + } + } + + /* Read data with start_addr and len determined */ + rslt = bmi2_get_regs(start_addr, sensor_data, len, dev); + + return rslt; +} + +/*! + * @brief This internal API parses accelerometer, gyroscope and auxiliary sensor data with sensortime + */ +static int8_t parse_data(uint8_t aux_len, + uint8_t acc_len, + uint8_t gyr_len, + struct bmi2_sens_data *data, + const uint8_t *sensor_data, + struct bmi2_dev *dev) +{ + int8_t rslt; + + uint8_t sens_time[3] = { 0 }; + + /* Variables to define loop */ + uint8_t count = 0; + + /* Variables to define index */ + uint8_t index = 0; + + uint32_t sensor_time_byte3 = 0; + uint16_t sensor_time_byte2 = 0; + uint8_t sensor_time_byte1 = 0; + + /* Parse auxiliary sensor data */ + if (aux_len != 0) + { + /* Get the 8 bytes of auxiliary data */ + do + { + *(data->aux_data + count++) = *(sensor_data + index++); + } while (count < BMI2_AUX_NUM_BYTES); + } + + /* Parse auxiliary(if enabled) and accelerometer sensor data */ + if (acc_len != 0) + { + /* Get accelerometer data from the register */ + get_acc_gyr_data(&data->acc, sensor_data + (acc_len - BMI2_ACC_NUM_BYTES)); + + /* Get the re-mapped accelerometer data */ + get_remapped_data(&data->acc, dev); + } + + /* Parse auxiliary(if enabled), acceleromter(if enabled) and gyroscope sensor data */ + if (gyr_len != 0) + { + if ((aux_len != 0) && (acc_len != 0)) + { + /* Get gyroscope data from the register */ + get_acc_gyr_data(&data->gyr, sensor_data + BMI2_AUX_ACC_NUM_BYTES); + } + + if ((aux_len != 0) && (acc_len == 0)) + { + /* Get gyroscope data from the register */ + get_acc_gyr_data(&data->gyr, sensor_data + BMI2_AUX_ACC_NUM_BYTES); + } + + if ((acc_len != 0) && (aux_len == 0)) + { + /* Get gyroscope data from the register */ + get_acc_gyr_data(&data->gyr, sensor_data + BMI2_ACC_NUM_BYTES); + } + + if ((acc_len == 0) && (aux_len == 0)) + { + /* Get gyroscope data from the register */ + get_acc_gyr_data(&data->gyr, sensor_data); + } + + /* Get the compensated gyroscope data */ + comp_gyro_cross_axis_sensitivity(&data->gyr, dev); + + /* Get the re-mapped gyroscope data */ + get_remapped_data(&data->gyr, dev); + } + + /* Read sensortime */ + rslt = bmi2_get_regs(BMI2_SENSORTIME_ADDR, sens_time, 3, dev); + if (rslt == BMI2_OK) + { + sensor_time_byte3 = sens_time[BMI2_SENSOR_TIME_MSB_BYTE] << 16; + sensor_time_byte2 = sens_time[BMI2_SENSOR_TIME_XLSB_BYTE] << 8; + sensor_time_byte1 = sens_time[0]; + + data->sens_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1); + } + + return rslt; +} + +/*! + * @brief This internal API is used to test gyro CRT. + */ +static int8_t gyro_crt_test(uint8_t max_burst_length, uint8_t gyro_st_crt, struct bmi2_dev *dev) +{ + int8_t rslt; + int8_t rslt_crt = BMI2_OK; + uint8_t cmd = BMI2_G_TRIGGER_CMD; + uint8_t download_ready = 0; + + rslt = set_st_running(BMI2_ENABLE, dev); + + /* Preparing the setup */ + if (rslt == BMI2_OK) + { + rslt = crt_prepare_setup(dev); + } + + /* Enable the gyro self-test, CRT */ + if (rslt == BMI2_OK) + { + rslt = select_self_test(gyro_st_crt, dev); + } + + /* Check if FIFO is unchanged by checking the max burst length */ + if ((rslt == BMI2_OK) && (max_burst_length == 0)) + { + /* Trigger CRT */ + rslt = bmi2_set_regs(BMI2_CMD_REG_ADDR, &cmd, 1, dev); + if (rslt == BMI2_OK) + { + /* Wait until st_status = 0 or time out is 2 seconds */ + rslt = wait_st_running(BMI2_CRT_WAIT_RUNNING_RETRY_EXECUTION, dev); + + /* CRT Running wait & check is successful */ + if (rslt == BMI2_OK) + { + rslt = crt_gyro_st_update_result(dev); + } + } + } + else + { + /* FIFO may be used */ + if (rslt == BMI2_OK) + { + if (dev->read_write_len < 2) + { + dev->read_write_len = 2; + } + + if (dev->read_write_len > (BMI2_CRT_MAX_BURST_WORD_LENGTH * 2)) + { + dev->read_write_len = BMI2_CRT_MAX_BURST_WORD_LENGTH * 2; + } + + /* Reset the max burst length to default value */ + rslt = set_maxburst_len(dev->read_write_len, dev); + } + + if (rslt == BMI2_OK) + { + rslt = get_rdy_for_dl(&download_ready, dev); + } + + /* Trigger CRT */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_regs(BMI2_CMD_REG_ADDR, &cmd, 1, dev); + } + + /* Wait till either ready for download toggle or crt running = 0 */ + if (rslt == BMI2_OK) + { + rslt = wait_rdy_for_dl_toggle(BMI2_CRT_READY_FOR_DOWNLOAD_RETRY, download_ready, dev); + if (rslt == BMI2_OK) + { + rslt = write_crt_config_file(dev->read_write_len, BMI2_CRT_CONFIG_FILE_SIZE, 0x1800, dev); + } + + if (rslt == BMI2_OK) + { + rslt = wait_st_running(BMI2_CRT_WAIT_RUNNING_RETRY_EXECUTION, dev); + rslt_crt = crt_gyro_st_update_result(dev); + if (rslt == BMI2_OK) + { + rslt = rslt_crt; + } + } + } + } + + return rslt; +} + /*! @endcond */ diff --git a/bmi2.h b/bmi2.h index 1f51339..39f8da5 100644 --- a/bmi2.h +++ b/bmi2.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi2.h -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -483,26 +483,21 @@ int8_t bmi2_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2 /*! * \ingroup bmi2ApiSensorD - * \page bmi2_api_bmi2_get_sensor_data bmi2_get_sensor_data + * \page bmi2_api_bmi2_get_feature_data bmi2_get_feature_data * \code - * int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev); + * int8_t bmi2_get_feature_data(struct bmi2_feat_sensor_data *feat_sensor_data, uint8_t n_sens, struct bmi2_dev *dev); * \endcode - * @details This API gets the sensor/feature data for accelerometer, gyroscope, - * auxiliary sensor, step counter, high-g, gyroscope user-gain update, - * orientation, gyroscope cross sensitivity and error status for NVM and VFRM. + * @details This API gets the feature data for gyroscope user-gain update and gyroscope cross sensitivity * - * @param[out] sensor_data : Structure instance of bmi2_sensor_data. - * @param[in] n_sens : Number of sensors selected. - * @param[in] dev : Structure instance of bmi2_dev. + * @param[out] feat_sensor_data : Structure instance of bmi2_feat_sensor_data. + * @param[in] n_sens : Number of sensors selected. + * @param[in] dev : Structure instance of bmi2_dev. * * @note Sensors/features whose data can be read * *@verbatim * sens_list | Values * ---------------------|----------- - * BMI2_ACCEL | 0 - * BMI2_GYRO | 1 - * BMI2_AUX | 2 * BMI2_GYRO_GAIN_UPDATE| 12 * BMI2_GYRO_CROSS_SENSE| 28 *@endverbatim @@ -511,7 +506,24 @@ int8_t bmi2_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2 * @retval 0 -> Success * @retval < 0 -> Fail */ -int8_t bmi2_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev); +int8_t bmi2_get_feature_data(struct bmi2_feat_sensor_data *feat_sensor_data, uint8_t n_sens, struct bmi2_dev *dev); + +/*! + * \ingroup bmi2ApiSensorD + * \page bmi2_api_bmi2_get_sensor_data bmi2_get_sensor_data + * \code + * int8_t bmi2_get_sensor_data(struct bmi2_sens_data *data, struct bmi2_dev *dev); + * \endcode + * @details This API gets the sensor data for accelerometer, gyroscope and auxiliary sensor + * + * @param[out] data : Structure instance of bmi2_sensor_data. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi2_get_sensor_data(struct bmi2_sens_data *data, struct bmi2_dev *dev); /** * \ingroup bmi2 @@ -573,6 +585,8 @@ int8_t bmi2_get_fifo_config(uint16_t *fifo_config, struct bmi2_dev *dev); * @param[in] dev : Structure instance of bmi2_dev. * * @note APS has to be disabled before calling this function. + * @note Dummy byte (for SPI Interface) required for FIFO data read + * must be given as part of data pointer in struct bmi2_fifo_frame * * @return Result of API execution status * @retval 0 -> Success @@ -1001,29 +1015,6 @@ int8_t bmi2_read_aux_man_mode(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, */ int8_t bmi2_write_aux_man_mode(uint8_t reg_addr, const uint8_t *aux_data, uint16_t len, struct bmi2_dev *dev); -/*! - * \ingroup bmi2ApiAux - * \page bmi2_api_bmi2_write_aux_interleaved bmi2_write_aux_interleaved - * \code - * int8_t bmi2_write_aux_interleaved(uint8_t reg_addr, const uint8_t *aux_data, uint16_t len, struct bmi2_dev *dev); - * \endcode - * @details This API writes the user-defined bytes of data and the address of - * auxiliary sensor where data is to be written, from an interleaved input, - * in manual mode. - * - * @param[in] reg_addr : AUX address where data is to be written. - * @param[in] aux_data : Pointer to data to be written. - * @param[in] len : Total length of data to be written. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @note Change of BMI2_AUX_WR_ADDR is only allowed if AUX is not busy. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -int8_t bmi2_write_aux_interleaved(uint8_t reg_addr, const uint8_t *aux_data, uint16_t len, struct bmi2_dev *dev); - /** * \ingroup bmi2 * \defgroup bmi2ApiStatus Sensor Status @@ -1403,25 +1394,6 @@ int8_t bmi2_do_crt(struct bmi2_dev *dev); * @brief Enable / Abort CRT and self test operations of gyroscope */ -/*! - * \ingroup bmi2ApiCRTSt - * \page bmi2_api_bmi2_set_gyro_self_test_crt bmi2_set_gyro_self_test_crt - * \code - * int8_t bmi2_set_gyro_self_test_crt - * \endcode - * @details This api is used to enable the gyro self-test and crt. - * *gyro_self_test_crt -> 0 then gyro self test enable - * *gyro_self_test_crt -> 1 then CRT enable - * - * @param[in] gyro_self_test_crt : enable the gyro self test or crt. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -int8_t bmi2_set_gyro_self_test_crt(uint8_t *gyro_self_test_crt, struct bmi2_dev *dev); - /*! * \ingroup bmi2ApiCRTSt * \page bmi2_api_bmi2_abort_crt_gyro_st bmi2_abort_crt_gyro_st diff --git a/bmi270.c b/bmi270.c index 9ad7cda..1059eaf 100644 --- a/bmi270.c +++ b/bmi270.c @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi270.c -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -887,14 +887,30 @@ static int8_t set_step_config(const struct bmi2_step_config *config, struct bmi2 * @param[in, out] dev : Structure instance of bmi2_dev. * * @verbatim - *----------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- * bmi2_wrist_gest_config | * Structure parameters | Description - *--------------------------|-------------------------------------------------- + * -------------------------------------------------------------------------------------------- * | Device in left (0) or right (1) arm. By default, - * wear_arm | the wearable device is assumed to be in left arm + * wearable_arm | the wearable device is assumed to be in left arm * | i.e. default value is 0. - * -------------------------|--------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * | Sine of the minimum tilt angle in portrait down + * | direction of the device when wrist is rolled away + * | (roll-out) from user. + * min_flick_peak | The configuration parameter is scaled by 2048 + * | i.e. 2048 * sin(angle). + * | Range is 1448 to 1774. Default value is 1774. + * -------------------------------------------------------------------------------------------- + * | Value of minimum time difference between wrist + * | roll-out and roll-in movement during flick gesture. + * min_flick_samples | Range is 3 to 5 samples at 50Hz (i.e. 0.06 to 0.1 seconds). + * | Default value is 4 (i.e. 0.08 seconds). + * -------------------------------------------------------------------------------------------- + * | Maximum time within which gesture movement has to be completed. + * max_duration | Range is 150 to 250 samples at 50Hz (i.e. 3 to 5 seconds). + * | Default value is 200 (i.e. 4 seconds). + * -------------------------------------------------------------------------------------------- * @endverbatim * * @return Result of API execution status @@ -918,8 +934,8 @@ static int8_t set_wrist_gest_config(const struct bmi2_wrist_gest_config *config, *----------------------------------|------------------------------------------- * | To set the wrist wear wake-up parameters like * | min_angle_focus, min_angle_nonfocus, - * wrist_wear_wakeup_params | angle_landscape_left, angle_landscape_right, - * | angle_potrait_up and down. + * wrist_wear_wakeup_params | max_tilt_lr, max_tilt_ll, + * | max_tilt_pd and max_tilt_pu. * ---------------------------------|------------------------------------------- * @endverbatim * @@ -952,7 +968,8 @@ static int8_t set_wrist_wear_wake_up_config(const struct bmi2_wrist_wear_wake_up * threshold | Range is 0 to 1g. * | Default value is 0xAA = 83mg. * -------------------------|--------------------------------------------------- - * x_sel, y_sel, z_sel | Selects the feature on a per-axis basis + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis * -------------------------|--------------------------------------------------- * @endverbatim * @@ -985,7 +1002,8 @@ static int8_t get_any_motion_config(struct bmi2_any_motion_config *config, struc * threshold | Range is 0 to 1g. * | Default value is 0xAA = 83mg. * -------------------------|--------------------------------------------------- - * x_sel, y_sel, z_sel | Selects the feature on a per-axis basis + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis * -------------------------|--------------------------------------------------- * @endverbatim * @@ -1042,7 +1060,7 @@ static int8_t get_step_count_params_config(uint16_t *step_count_params, struct b *--------------------------|-------------------------------------------------- * | The Step-counter will trigger output every time * | the number of steps are counted. Holds implicitly - * water-mark level | a 20x factor, so the range is 0 to 10230, + * water-mark level | a 20x factor, so the range is 0 to 20460, * | with resolution of 20 steps. * -------------------------|--------------------------------------------------- * reset counter | Flag to reset the counted steps. @@ -1063,14 +1081,30 @@ static int8_t get_step_config(struct bmi2_step_config *config, struct bmi2_dev * * @param[in, out] dev : Structure instance of bmi2_dev. * * @verbatim - *----------------------------------------------------------------------------- + * -------------------------------------------------------------------------------------------- * bmi2_wrist_gest_config | * Structure parameters | Description - *--------------------------|-------------------------------------------------- + * -------------------------------------------------------------------------------------------- * | Device in left (0) or right (1) arm. By default, - * wear_arm | the wearable device is assumed to be in left arm + * wearable_arm | the wearable device is assumed to be in left arm * | i.e. default value is 0. - * -------------------------|--------------------------------------------------- + * -------------------------------------------------------------------------------------------- + * | Sine of the minimum tilt angle in portrait down + * | direction of the device when wrist is rolled away + * | (roll-out) from user. + * min_flick_peak | The configuration parameter is scaled by 2048 + * | i.e. 2048 * sin(angle). + * | Range is 1448 to 1774. Default value is 1774. + * -------------------------------------------------------------------------------------------- + * | Value of minimum time difference between wrist + * | roll-out and roll-in movement during flick gesture. + * min_flick_samples | Range is 3 to 5 samples at 50Hz (i.e. 0.06 to 0.1 seconds). + * | Default value is 4 (i.e. 0.08 seconds). + * -------------------------------------------------------------------------------------------- + * | Maximum time within which gesture movement has to be completed. + * max_duration | Range is 150 to 250 samples at 50Hz (i.e. 3 to 5 seconds). + * | Default value is 200 (i.e. 4 seconds). + * -------------------------------------------------------------------------------------------- * @endverbatim * * @return Result of API execution status @@ -1088,15 +1122,15 @@ static int8_t get_wrist_gest_config(struct bmi2_wrist_gest_config *config, struc * @param[in, out] dev : Structure instance of bmi2_dev. * * @verbatim - *------------------------------------|--------------------------------------- - * bmi2_wrist_wear_wake_up_wh_config | - * Structure parameters | Description - *------------------------------------|------------------------------------------- - * | To get the wrist wear wake-up parameters like - * | min_angle_focus, min_angle_nonfocus, - * wrist_wear_wake_params | angle_landscape_left, angle_landscape_right, - * | angle_potrait_up and down. - * -----------------------------------|------------------------------------------- + *----------------------------------------------------------------------------- + * bmi2_wrist_wear_wake_up_config | + * Structure parameters | Description + *----------------------------------|------------------------------------------- + * | To set the wrist wear wake-up parameters like + * | min_angle_focus, min_angle_nonfocus, + * wrist_wear_wakeup_params | max_tilt_lr, max_tilt_ll, + * | max_tilt_pd and max_tilt_pu. + * ---------------------------------|------------------------------------------- * @endverbatim * * @return Result of API execution status @@ -1230,6 +1264,80 @@ static uint8_t extract_output_feat_config(struct bmi2_feature_config *feat_outpu uint8_t type, const struct bmi2_dev *dev); +/*! + * @brief This internal API sets feature configuration to the sensor. + * + * @param[in] sens_cfg : Structure instance of bmi2_sens_config. + * @param[in] loop : Variable to loop the sensor feature. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_feat_config(const struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets feature configuration from the sensor. + * + * @param[in] sens_cfg : Structure instance of bmi2_sens_config. + * @param[in] loop : Variable to loop the sensor feature. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_feat_config(struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable main sensors like accel, gyro, aux and temperature. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable sensor features. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to disable main sensors like accel, gyro, aux and temperature. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t disable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to disable sensor features. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t disable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev); + /***************************************************************************/ /*! User Interface Definitions @@ -1432,53 +1540,10 @@ int8_t bmi270_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sen if (rslt == BMI2_OK) { - switch (sens_cfg[loop].type) - { - /* Set any motion configuration */ - case BMI2_ANY_MOTION: - rslt = set_any_motion_config(&sens_cfg[loop].cfg.any_motion, dev); - break; - - /* Set no motion configuration */ - case BMI2_NO_MOTION: - rslt = set_no_motion_config(&sens_cfg[loop].cfg.no_motion, dev); - break; - - /* Set sig-motion configuration */ - case BMI2_SIG_MOTION: - rslt = set_sig_motion_config(&sens_cfg[loop].cfg.sig_motion, dev); - break; - - /* Set the step counter parameters */ - case BMI2_STEP_COUNTER_PARAMS: - rslt = set_step_count_params_config(sens_cfg[loop].cfg.step_counter_params, dev); - break; - - /* Set step counter/detector/activity configuration */ - case BMI2_STEP_DETECTOR: - case BMI2_STEP_COUNTER: - case BMI2_STEP_ACTIVITY: - rslt = set_step_config(&sens_cfg[loop].cfg.step_counter, dev); - break; - - /* Set the wrist gesture configuration */ - case BMI2_WRIST_GESTURE: - rslt = set_wrist_gest_config(&sens_cfg[loop].cfg.wrist_gest, dev); - break; - - /* Set the wrist wear wake-up configuration */ - case BMI2_WRIST_WEAR_WAKE_UP: - rslt = set_wrist_wear_wake_up_config(&sens_cfg[loop].cfg.wrist_wear_wake_up, dev); - break; - - default: - rslt = BMI2_E_INVALID_SENSOR; - break; - } + rslt = set_feat_config(sens_cfg, loop, dev); } - /* Return error if any of the set configurations fail */ - if (rslt != BMI2_OK) + else { break; } @@ -1547,53 +1612,10 @@ int8_t bmi270_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sen if (rslt == BMI2_OK) { - switch (sens_cfg[loop].type) - { - /* Get sig-motion configuration */ - case BMI2_SIG_MOTION: - rslt = get_sig_motion_config(&sens_cfg[loop].cfg.sig_motion, dev); - break; - - /* Get any motion configuration */ - case BMI2_ANY_MOTION: - rslt = get_any_motion_config(&sens_cfg[loop].cfg.any_motion, dev); - break; - - /* Get no motion configuration */ - case BMI2_NO_MOTION: - rslt = get_no_motion_config(&sens_cfg[loop].cfg.no_motion, dev); - break; - - /* Set the step counter parameters */ - case BMI2_STEP_COUNTER_PARAMS: - rslt = get_step_count_params_config(sens_cfg[loop].cfg.step_counter_params, dev); - break; - - /* Get step counter/detector/activity configuration */ - case BMI2_STEP_DETECTOR: - case BMI2_STEP_COUNTER: - case BMI2_STEP_ACTIVITY: - rslt = get_step_config(&sens_cfg[loop].cfg.step_counter, dev); - break; - - /* Get the wrist gesture configuration */ - case BMI2_WRIST_GESTURE: - rslt = get_wrist_gest_config(&sens_cfg[loop].cfg.wrist_gest, dev); - break; - - /* Get the wrist wear wake-up configuration */ - case BMI2_WRIST_WEAR_WAKE_UP: - rslt = get_wrist_wear_wake_up_config(&sens_cfg[loop].cfg.wrist_wear_wake_up, dev); - break; - - default: - rslt = BMI2_E_INVALID_SENSOR; - break; - } + rslt = get_feat_config(sens_cfg, loop, dev); } - /* Return error if any of the get configurations fail */ - if (rslt != BMI2_OK) + else { break; } @@ -1617,11 +1639,9 @@ int8_t bmi270_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sen } /*! - * @brief This API gets the sensor/feature data for accelerometer, gyroscope, - * auxiliary sensor, step counter, high-g, gyroscope user-gain update, - * orientation, gyroscope cross sensitivity and error status for NVM and VFRM. + * @brief This API gets the feature data. */ -int8_t bmi270_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev) +int8_t bmi270_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt; @@ -1634,24 +1654,23 @@ int8_t bmi270_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_se /* Null-pointer check */ rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (sensor_data != NULL)) + if ((rslt == BMI2_OK) && (feature_data != NULL)) { /* Get status of advance power save mode */ aps_stat = dev->aps_status; for (loop = 0; loop < n_sens; loop++) { - if ((sensor_data[loop].type == BMI2_ACCEL) || (sensor_data[loop].type == BMI2_GYRO) || - (sensor_data[loop].type == BMI2_AUX) || (sensor_data[loop].type == BMI2_GYRO_GAIN_UPDATE) || - (sensor_data[loop].type == BMI2_GYRO_CROSS_SENSE)) + if ((feature_data[loop].type == BMI2_GYRO_GAIN_UPDATE) || + (feature_data[loop].type == BMI2_GYRO_CROSS_SENSE)) { - rslt = bmi2_get_sensor_data(&sensor_data[loop], 1, dev); + rslt = bmi2_get_feature_data(&feature_data[loop], 1, dev); } else { /* Disable Advance power save if enabled for feature * configurations */ - if (sensor_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) + if (feature_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) { if (aps_stat == BMI2_ENABLE) { @@ -1664,32 +1683,32 @@ int8_t bmi270_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_se if (rslt == BMI2_OK) { - switch (sensor_data[loop].type) + switch (feature_data[loop].type) { case BMI2_STEP_COUNTER: /* Get step counter output */ - rslt = get_step_counter_output(&sensor_data[loop].sens_data.step_counter_output, dev); + rslt = get_step_counter_output(&feature_data[loop].sens_data.step_counter_output, dev); break; case BMI2_STEP_ACTIVITY: /* Get step activity output */ - rslt = get_step_activity_output(&sensor_data[loop].sens_data.activity_output, dev); + rslt = get_step_activity_output(&feature_data[loop].sens_data.activity_output, dev); break; case BMI2_NVM_STATUS: /* Get NVM error status */ - rslt = get_nvm_error_status(&sensor_data[loop].sens_data.nvm_status, dev); + rslt = get_nvm_error_status(&feature_data[loop].sens_data.nvm_status, dev); break; case BMI2_VFRM_STATUS: /* Get VFRM error status */ - rslt = get_vfrm_error_status(&sensor_data[loop].sens_data.vfrm_status, dev); + rslt = get_vfrm_error_status(&feature_data[loop].sens_data.vfrm_status, dev); break; case BMI2_WRIST_GESTURE: /* Get wrist gesture status */ - rslt = get_wrist_gest_status(&sensor_data[loop].sens_data.wrist_gesture_output, dev); + rslt = get_wrist_gest_status(&feature_data[loop].sens_data.wrist_gesture_output, dev); break; default: rslt = BMI2_E_INVALID_SENSOR; @@ -2002,48 +2021,10 @@ static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev) /* Variable to define error */ int8_t rslt; - /* Variable to store register values */ - uint8_t reg_data = 0; - - /* Variable to define loop */ - uint8_t loop = 1; - /* Variable to get the status of advance power save */ uint8_t aps_stat = 0; - rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - if (rslt == BMI2_OK) - { - /* Enable accelerometer */ - if (sensor_sel & BMI2_ACCEL_SENS_SEL) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_ACC_EN, BMI2_ENABLE); - } - - /* Enable gyroscope */ - if (sensor_sel & BMI2_GYRO_SENS_SEL) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_EN, BMI2_ENABLE); - } - - /* Enable auxiliary sensor */ - if (sensor_sel & BMI2_AUX_SENS_SEL) - { - reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_AUX_EN, BMI2_ENABLE); - } - - /* Enable temperature sensor */ - if (sensor_sel & BMI2_TEMP_SENS_SEL) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_TEMP_EN, BMI2_ENABLE); - } - - /* Enable the sensors that are set in the power control register */ - if (sensor_sel & BMI2_MAIN_SENSORS) - { - rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - } - } + rslt = enable_main_sensors(sensor_sel, dev); if ((rslt == BMI2_OK) && (sensor_sel & ~(BMI2_MAIN_SENSORS))) { @@ -2057,148 +2038,7 @@ static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev) if (rslt == BMI2_OK) { - while (loop--) - { - /* Enable sig-motion feature */ - if (sensor_sel & BMI2_SIG_MOTION_SEL) - { - rslt = set_sig_motion(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_SIG_MOTION_SEL; - } - else - { - break; - } - } - - /* Enable any motion feature */ - if (sensor_sel & BMI2_ANY_MOT_SEL) - { - rslt = set_any_motion(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_ANY_MOT_SEL; - } - else - { - break; - } - } - - /* Enable no motion feature */ - if (sensor_sel & BMI2_NO_MOT_SEL) - { - rslt = set_no_motion(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_NO_MOT_SEL; - } - else - { - break; - } - } - - /* Enable step detector feature */ - if (sensor_sel & BMI2_STEP_DETECT_SEL) - { - rslt = set_step_detector(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_STEP_DETECT_SEL; - } - else - { - break; - } - } - - /* Enable step counter feature */ - if (sensor_sel & BMI2_STEP_COUNT_SEL) - { - rslt = set_step_counter(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_STEP_COUNT_SEL; - } - else - { - break; - } - } - - /* Enable step activity feature */ - if (sensor_sel & BMI2_STEP_ACT_SEL) - { - rslt = set_step_activity(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_STEP_ACT_SEL; - } - else - { - break; - } - } - - /* Enable gyroscope user gain */ - if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) - { - rslt = set_gyro_user_gain(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_GYRO_GAIN_UPDATE_SEL; - } - else - { - break; - } - } - - /* Enable gyroscope self-offset correction feature */ - if (sensor_sel & BMI2_GYRO_SELF_OFF_SEL) - { - rslt = set_gyro_self_offset_corr(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_GYRO_SELF_OFF_SEL; - } - else - { - break; - } - } - - /* Enable wrist gesture feature for wearable variant */ - if (sensor_sel & BMI2_WRIST_GEST_SEL) - { - rslt = set_wrist_gesture(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_WRIST_GEST_SEL; - } - else - { - break; - } - } - - /* Enable wrist wear wake-up feature */ - if (sensor_sel & BMI2_WRIST_WEAR_WAKE_UP_SEL) - { - rslt = set_wrist_wear_wake_up(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_WRIST_WEAR_WAKE_UP_SEL; - } - else - { - break; - } - } - } + rslt = enable_sensor_features(sensor_sel, dev); /* Enable Advance power save if disabled while * configuring and not when already disabled @@ -2221,48 +2061,10 @@ static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev) /* Variable to define error */ int8_t rslt; - /* Variable to store register values */ - uint8_t reg_data = 0; - - /* Variable to define loop */ - uint8_t loop = 1; - /* Variable to get the status of advance power save */ uint8_t aps_stat = 0; - rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - if (rslt == BMI2_OK) - { - /* Disable accelerometer */ - if (sensor_sel & BMI2_ACCEL_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_ACC_EN); - } - - /* Disable gyroscope */ - if (sensor_sel & BMI2_GYRO_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_GYR_EN); - } - - /* Disable auxiliary sensor */ - if (sensor_sel & BMI2_AUX_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_AUX_EN); - } - - /* Disable temperature sensor */ - if (sensor_sel & BMI2_TEMP_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_TEMP_EN); - } - - /* Disable the sensors that are set in the power control register */ - if (sensor_sel & BMI2_MAIN_SENSORS) - { - rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - } - } + rslt = disable_main_sensors(sensor_sel, dev); if ((rslt == BMI2_OK) && (sensor_sel & ~(BMI2_MAIN_SENSORS))) { @@ -2276,155 +2078,14 @@ static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev) if (rslt == BMI2_OK) { - while (loop--) - { - /* Disable sig-motion feature */ - if (sensor_sel & BMI2_SIG_MOTION_SEL) - { - rslt = set_sig_motion(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_SIG_MOTION_SEL; - } - else - { - break; - } - } - - /* Disable any-motion feature */ - if (sensor_sel & BMI2_ANY_MOT_SEL) - { - rslt = set_any_motion(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_ANY_MOT_SEL; - } - else - { - break; - } - } - - /* Disable no-motion feature */ - if (sensor_sel & BMI2_NO_MOT_SEL) - { - rslt = set_no_motion(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_NO_MOT_SEL; - } - else - { - break; - } - } + rslt = disable_sensor_features(sensor_sel, dev); - /* Disable step detector feature */ - if (sensor_sel & BMI2_STEP_DETECT_SEL) - { - rslt = set_step_detector(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_STEP_DETECT_SEL; - } - else - { - break; - } - } - - /* Disable step counter feature */ - if (sensor_sel & BMI2_STEP_COUNT_SEL) - { - rslt = set_step_counter(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_STEP_COUNT_SEL; - } - else - { - break; - } - } - - /* Disable step activity feature */ - if (sensor_sel & BMI2_STEP_ACT_SEL) - { - rslt = set_step_activity(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_STEP_ACT_SEL; - } - else - { - break; - } - } - - /* Disable gyroscope user gain */ - if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) - { - rslt = set_gyro_user_gain(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_GYRO_GAIN_UPDATE_SEL; - } - else - { - break; - } - } - - /* Disable gyroscope self-offset correction feature */ - if (sensor_sel & BMI2_GYRO_SELF_OFF_SEL) - { - rslt = set_gyro_self_offset_corr(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_GYRO_SELF_OFF_SEL; - } - else - { - break; - } - } - - /* Disable wrist gesture feature for wearable variant*/ - if (sensor_sel & BMI2_WRIST_GEST_SEL) - { - rslt = set_wrist_gesture(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_WRIST_GEST_SEL; - } - else - { - break; - } - } - - /* Enable wrist wear wake-up feature */ - if (sensor_sel & BMI2_WRIST_WEAR_WAKE_UP_SEL) - { - rslt = set_wrist_wear_wake_up(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_WRIST_WEAR_WAKE_UP_SEL; - } - else - { - break; - } - } - - /* Enable Advance power save if disabled while - * configuring and not when already disabled - */ - if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) - { - rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); - } + /* Enable Advance power save if disabled while + * configuring and not when already disabled + */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); } } } @@ -2468,6 +2129,15 @@ static int8_t set_any_motion(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_ANY_MOT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_ANY_MOT_SEL; + } } } else @@ -2514,6 +2184,15 @@ static int8_t set_no_motion(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_NO_MOT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_NO_MOT_SEL; + } } } else @@ -2560,6 +2239,15 @@ static int8_t set_step_detector(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_DETECT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_DETECT_SEL; + } } } else @@ -2606,6 +2294,15 @@ static int8_t set_step_counter(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_COUNT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_COUNT_SEL; + } } } else @@ -2652,6 +2349,15 @@ static int8_t set_sig_motion(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_SIG_MOTION_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_SIG_MOTION_SEL; + } } } else @@ -2700,6 +2406,15 @@ static int8_t set_step_activity(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_ACT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_ACT_SEL; + } } } else @@ -2749,6 +2464,15 @@ static int8_t set_gyro_self_offset_corr(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_GYRO_SELF_OFF_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_GYRO_SELF_OFF_SEL; + } } } else @@ -2795,6 +2519,15 @@ static int8_t set_wrist_gesture(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_WRIST_GEST_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_WRIST_GEST_SEL; + } } } else @@ -2843,6 +2576,15 @@ static int8_t set_wrist_wear_wake_up(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_WRIST_WEAR_WAKE_UP_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_WRIST_WEAR_WAKE_UP_SEL; + } } } else @@ -2890,6 +2632,15 @@ static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_GYRO_GAIN_UPDATE_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_GYRO_GAIN_UPDATE_SEL; + } } } else @@ -3136,7 +2887,7 @@ static int8_t set_sig_motion_config(const struct bmi2_sig_motion_config *config, /* Set parameter 5 */ *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_SIG_MOT_PARAM_5, config->param_5); - /* Increment offset by 1 word to set output- configuration */ + /* Increment offset by 1 more word to get the total length in words */ idx++; /* Get total length in bytes to copy from local pointer to the array */ @@ -3337,12 +3088,6 @@ static int8_t set_step_config(const struct bmi2_step_config *config, struct bmi2 */ idx++; - /* Set step buffer size */ - *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_STEP_BUFFER_SIZE, config->step_buffer_size); - - /* Increment offset by 1 more word to get the total length in words */ - idx++; - /* Get total length in bytes to copy from local pointer to the array */ idx = (uint8_t)(idx * 2) - step_count_config.start_addr; @@ -3487,6 +3232,9 @@ static int8_t set_wrist_wear_wake_up_config(const struct bmi2_wrist_wear_wake_up /* Get offset in words since all the features are set in words length */ idx = idx / 2; + /* Increment offset by 1 more word to set min_angle_focus */ + idx++; + *(data_p + idx) = config->min_angle_focus; /* Increment offset by 1 more word to set min_angle_nonfocus */ @@ -3943,13 +3691,6 @@ static int8_t get_step_config(struct bmi2_step_config *config, struct bmi2_dev * /* Get reset counter */ config->reset_counter = (lsb_msb & BMI2_STEP_COUNT_RST_CNT_MASK) >> BMI2_STEP_COUNT_RST_CNT_POS; - - /* Get word to calculate output configuration of step detector and activity */ - lsb = (uint16_t) feat_config[idx++]; - msb = ((uint16_t) feat_config[idx++] << 8); - lsb_msb = lsb | msb; - - config->step_buffer_size = (lsb_msb & BMI2_STEP_BUFFER_SIZE_MASK) >> BMI2_STEP_BUFFER_SIZE_POS; } } else @@ -4060,6 +3801,9 @@ static int8_t get_wrist_wear_wake_up_config(struct bmi2_wrist_wear_wake_up_confi /* Get offset in words since all the features are set in words length */ idx = idx / 2; + /* Increment the offset value by 1 word to get min_angle_focus */ + idx++; + config->min_angle_focus = *(data_p + idx); /* Increment the offset value by 1 word to get min_angle_nonfocus */ @@ -4081,7 +3825,6 @@ static int8_t get_wrist_wear_wake_up_config(struct bmi2_wrist_wear_wake_up_confi /* Increment the offset value by 1 word to get max_tilt_pu */ idx++; config->max_tilt_pu = *(data_p + idx); - } } else @@ -4449,3 +4192,353 @@ static uint8_t extract_output_feat_config(struct bmi2_feature_config *feat_outpu /* Return flag */ return feat_found; } + +/*! + * @brief This internal API sets feature configuration to the sensor. + */ +static int8_t set_feat_config(const struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + switch (sens_cfg[loop].type) + { + /* Set any motion configuration */ + case BMI2_ANY_MOTION: + rslt = set_any_motion_config(&sens_cfg[loop].cfg.any_motion, dev); + break; + + /* Set no motion configuration */ + case BMI2_NO_MOTION: + rslt = set_no_motion_config(&sens_cfg[loop].cfg.no_motion, dev); + break; + + /* Set sig-motion configuration */ + case BMI2_SIG_MOTION: + rslt = set_sig_motion_config(&sens_cfg[loop].cfg.sig_motion, dev); + break; + + /* Set the step counter parameters */ + case BMI2_STEP_COUNTER_PARAMS: + rslt = set_step_count_params_config(sens_cfg[loop].cfg.step_counter_params, dev); + break; + + /* Set step counter/detector/activity configuration */ + case BMI2_STEP_DETECTOR: + case BMI2_STEP_COUNTER: + case BMI2_STEP_ACTIVITY: + rslt = set_step_config(&sens_cfg[loop].cfg.step_counter, dev); + break; + + /* Set the wrist gesture configuration */ + case BMI2_WRIST_GESTURE: + rslt = set_wrist_gest_config(&sens_cfg[loop].cfg.wrist_gest, dev); + break; + + /* Set the wrist wear wake-up configuration */ + case BMI2_WRIST_WEAR_WAKE_UP: + rslt = set_wrist_wear_wake_up_config(&sens_cfg[loop].cfg.wrist_wear_wake_up, dev); + break; + + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief This internal API gets feature configuration from the sensor. + */ +static int8_t get_feat_config(struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + switch (sens_cfg[loop].type) + { + /* Get sig-motion configuration */ + case BMI2_SIG_MOTION: + rslt = get_sig_motion_config(&sens_cfg[loop].cfg.sig_motion, dev); + break; + + /* Get any motion configuration */ + case BMI2_ANY_MOTION: + rslt = get_any_motion_config(&sens_cfg[loop].cfg.any_motion, dev); + break; + + /* Get no motion configuration */ + case BMI2_NO_MOTION: + rslt = get_no_motion_config(&sens_cfg[loop].cfg.no_motion, dev); + break; + + /* Set the step counter parameters */ + case BMI2_STEP_COUNTER_PARAMS: + rslt = get_step_count_params_config(sens_cfg[loop].cfg.step_counter_params, dev); + break; + + /* Get step counter/detector/activity configuration */ + case BMI2_STEP_DETECTOR: + case BMI2_STEP_COUNTER: + case BMI2_STEP_ACTIVITY: + rslt = get_step_config(&sens_cfg[loop].cfg.step_counter, dev); + break; + + /* Get the wrist gesture configuration */ + case BMI2_WRIST_GESTURE: + rslt = get_wrist_gest_config(&sens_cfg[loop].cfg.wrist_gest, dev); + break; + + /* Get the wrist wear wake-up configuration */ + case BMI2_WRIST_WEAR_WAKE_UP: + rslt = get_wrist_wear_wake_up_config(&sens_cfg[loop].cfg.wrist_wear_wake_up, dev); + break; + + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable main sensors like accel, gyro, aux and temperature. + */ +static int8_t enable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to store register values */ + uint8_t reg_data; + + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + + if (rslt == BMI2_OK) + { + /* Enable accelerometer */ + if (sensor_sel & BMI2_ACCEL_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_ACC_EN, BMI2_ENABLE); + } + + /* Enable gyroscope */ + if (sensor_sel & BMI2_GYRO_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_EN, BMI2_ENABLE); + } + + /* Enable auxiliary sensor */ + if (sensor_sel & BMI2_AUX_SENS_SEL) + { + reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_AUX_EN, BMI2_ENABLE); + } + + /* Enable temperature sensor */ + if (sensor_sel & BMI2_TEMP_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_TEMP_EN, BMI2_ENABLE); + } + + /* Enable the sensors that are set in the power control register */ + if (sensor_sel & BMI2_MAIN_SENSORS) + { + rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable sensor features. + */ +static int8_t enable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Enable sig-motion feature */ + if (sensor_sel & BMI2_SIG_MOTION_SEL) + { + rslt = set_sig_motion(BMI2_ENABLE, dev); + } + + /* Enable any motion feature */ + if (sensor_sel & BMI2_ANY_MOT_SEL) + { + rslt = set_any_motion(BMI2_ENABLE, dev); + } + + /* Enable no motion feature */ + if (sensor_sel & BMI2_NO_MOT_SEL) + { + rslt = set_no_motion(BMI2_ENABLE, dev); + } + + /* Enable step detector feature */ + if (sensor_sel & BMI2_STEP_DETECT_SEL) + { + rslt = set_step_detector(BMI2_ENABLE, dev); + } + + /* Enable step counter feature */ + if (sensor_sel & BMI2_STEP_COUNT_SEL) + { + rslt = set_step_counter(BMI2_ENABLE, dev); + } + + /* Enable step activity feature */ + if (sensor_sel & BMI2_STEP_ACT_SEL) + { + rslt = set_step_activity(BMI2_ENABLE, dev); + } + + /* Enable gyroscope user gain */ + if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) + { + rslt = set_gyro_user_gain(BMI2_ENABLE, dev); + } + + /* Enable gyroscope self-offset correction feature */ + if (sensor_sel & BMI2_GYRO_SELF_OFF_SEL) + { + rslt = set_gyro_self_offset_corr(BMI2_ENABLE, dev); + } + + /* Enable wrist gesture feature for wearable variant */ + if (sensor_sel & BMI2_WRIST_GEST_SEL) + { + rslt = set_wrist_gesture(BMI2_ENABLE, dev); + } + + /* Enable wrist wear wake-up feature */ + if (sensor_sel & BMI2_WRIST_WEAR_WAKE_UP_SEL) + { + rslt = set_wrist_wear_wake_up(BMI2_ENABLE, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to disable main sensors like accel, gyro, aux and temperature. + */ +static int8_t disable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to store register values */ + uint8_t reg_data; + + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + + if (rslt == BMI2_OK) + { + /* Disable accelerometer */ + if (sensor_sel & BMI2_ACCEL_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_ACC_EN); + } + + /* Disable gyroscope */ + if (sensor_sel & BMI2_GYRO_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_GYR_EN); + } + + /* Disable auxiliary sensor */ + if (sensor_sel & BMI2_AUX_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_AUX_EN); + } + + /* Disable temperature sensor */ + if (sensor_sel & BMI2_TEMP_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_TEMP_EN); + } + + /* Disable the sensors that are set in the power control register */ + if (sensor_sel & BMI2_MAIN_SENSORS) + { + rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to disable sensor features. + */ +static int8_t disable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Disable sig-motion feature */ + if (sensor_sel & BMI2_SIG_MOTION_SEL) + { + rslt = set_sig_motion(BMI2_DISABLE, dev); + } + + /* Disable any-motion feature */ + if (sensor_sel & BMI2_ANY_MOT_SEL) + { + rslt = set_any_motion(BMI2_DISABLE, dev); + } + + /* Disable no-motion feature */ + if (sensor_sel & BMI2_NO_MOT_SEL) + { + rslt = set_no_motion(BMI2_DISABLE, dev); + } + + /* Disable step detector feature */ + if (sensor_sel & BMI2_STEP_DETECT_SEL) + { + rslt = set_step_detector(BMI2_DISABLE, dev); + } + + /* Disable step counter feature */ + if (sensor_sel & BMI2_STEP_COUNT_SEL) + { + rslt = set_step_counter(BMI2_DISABLE, dev); + } + + /* Disable step activity feature */ + if (sensor_sel & BMI2_STEP_ACT_SEL) + { + rslt = set_step_activity(BMI2_DISABLE, dev); + } + + /* Disable gyroscope user gain */ + if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) + { + rslt = set_gyro_user_gain(BMI2_DISABLE, dev); + } + + /* Disable gyroscope self-offset correction feature */ + if (sensor_sel & BMI2_GYRO_SELF_OFF_SEL) + { + rslt = set_gyro_self_offset_corr(BMI2_DISABLE, dev); + } + + /* Disable wrist gesture feature for wearable variant*/ + if (sensor_sel & BMI2_WRIST_GEST_SEL) + { + rslt = set_wrist_gesture(BMI2_DISABLE, dev); + } + + /* Enable wrist wear wake-up feature */ + if (sensor_sel & BMI2_WRIST_WEAR_WAKE_UP_SEL) + { + rslt = set_wrist_wear_wake_up(BMI2_DISABLE, dev); + } + + return rslt; +} diff --git a/bmi270.h b/bmi270.h index 968366a..38355f1 100644 --- a/bmi270.h +++ b/bmi270.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi270.h -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -318,23 +318,21 @@ int8_t bmi270_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sen /** * \ingroup bmi270 - * \defgroup bmi270ApiSensorD Sensor Data - * @brief Get sensor data + * \defgroup bmi270ApiSensorD Feature Sensor Data + * @brief Get feature sensor data */ /*! * \ingroup bmi270ApiSensorD - * \page bmi270_api_bmi270_get_sensor_data bmi270_get_sensor_data + * \page bmi270_api_bmi270_get_feature_data bmi270_get_feature_data * \code - * int8_t bmi270_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev); + * int8_t bmi270_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev); * \endcode - * @details This API gets the sensor/feature data for accelerometer, gyroscope, - * auxiliary sensor, step counter, high-g, gyroscope user-gain update, - * orientation, gyroscope cross sensitivity and error status for NVM and VFRM. + * @details This API gets the feature data. * - * @param[out] sensor_data : Structure instance of bmi2_sensor_data. - * @param[in] n_sens : Number of sensors selected. - * @param[in] dev : Structure instance of bmi2_dev. + * @param[out] feature_data : Structure instance of bmi2_feat_sensor_data. + * @param[in] n_sens : Number of sensors selected. + * @param[in] dev : Structure instance of bmi2_dev. * * @note Sensors/features whose data can be read * @@ -352,7 +350,7 @@ int8_t bmi270_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sen * @retval 0 -> Success * @retval < 0 -> Fail */ -int8_t bmi270_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev); +int8_t bmi270_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev); /** * \ingroup bmi270 diff --git a/bmi270_context.c b/bmi270_context.c index a6ea2d8..b3bfd3a 100644 --- a/bmi270_context.c +++ b/bmi270_context.c @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi270_context.c -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -604,24 +604,6 @@ static int8_t set_step_detector(uint8_t enable, struct bmi2_dev *dev); */ static int8_t set_step_counter(uint8_t enable, struct bmi2_dev *dev); -/*! - * @brief This internal API is used to enable/disable gyroscope user gain - * feature. - * - * @param[in] dev : Structure instance of bmi2_dev. - * @param[in] enable : Enables/Disables gyroscope user gain. - * - * Enable | Description - * -------------|--------------- - * BMI2_DISABLE | Disables gyroscope user gain - * BMI2_ENABLE | Enables gyroscope user gain - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev); - /*! * @brief This internal API enables/disables the activity recognition feature. * @@ -663,7 +645,7 @@ static int8_t set_step_count_params_config(const uint16_t *step_count_params, st *--------------------------|-------------------------------------------------- * | The Step-counter will trigger output every time * | the number of steps are counted. Holds implicitly - * water-mark level | a 20x factor, so the range is 0 to 10230, + * water-mark level | a 20x factor, so the range is 0 to 20460, * | with resolution of 20 steps. * -------------------------|--------------------------------------------------- * reset counter | Flag to reset the counted steps. @@ -701,7 +683,7 @@ static int8_t get_step_count_params_config(uint16_t *step_count_params, struct b *--------------------------|-------------------------------------------------- * | The Step-counter will trigger output every time * | the number of steps are counted. Holds implicitly - * water-mark level | a 20x factor, so the range is 0 to 10230, + * water-mark level | a 20x factor, so the range is 0 to 20460, * | with resolution of 20 steps. * -------------------------|--------------------------------------------------- * reset counter | Flag to reset the counted steps. @@ -768,19 +750,6 @@ static int8_t get_nvm_error_status(struct bmi2_nvm_err_status *nvm_err_stat, str */ static int8_t get_vfrm_error_status(struct bmi2_vfrm_err_status *vfrm_err_stat, struct bmi2_dev *dev); -/*! - * @brief This internal API is used to get enable status of gyroscope user gain - * update. - * - * @param[out] status : Stores status of gyroscope user gain update. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -static int8_t get_user_gain_upd_status(uint8_t *status, struct bmi2_dev *dev); - /*! * @brief This internal API skips S4S frame in the FIFO data while getting * activity recognition output. @@ -797,24 +766,6 @@ static int8_t get_user_gain_upd_status(uint8_t *status, struct bmi2_dev *dev); */ static int8_t move_if_s4s_frame(const uint8_t *frame_header, uint16_t *data_index, const struct bmi2_fifo_frame *fifo); -/*! - * @brief This internal API enables/disables compensation of the gain defined - * in the GAIN register. - * - * @param[in] enable : Enables/Disables gain compensation - * @param[in] dev : Structure instance of bmi2_dev. - * - * enable | Description - * -------------|--------------- - * BMI2_ENABLE | Enable gain compensation. - * BMI2_DISABLE | Disable gain compensation. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -static int8_t enable_gyro_gain(uint8_t enable, struct bmi2_dev *dev); - /*! * @brief This internal API is used to extract the output feature configuration * details like page and start address from the look-up table. @@ -849,6 +800,73 @@ static uint8_t extract_output_feat_config(struct bmi2_feature_config *feat_outpu */ static int8_t move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi2_fifo_frame *fifo); +/*! + * @brief This internal API is used to select the header byte frame + * + * @param[in, out] frame_to_read : Variable to indicate activity frames read. + * @param[in, out] act_frm_len : Number of activity frames parsed. + * @param[in] act_recog : Structure instance of bmi2_act_recog_output. + * @param[in] fifo : Structure instance of bmi2_fifo_frame. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t fifo_header_frame(uint16_t frame_to_read, + uint16_t *act_frm_len, + struct bmi2_act_recog_output *act_recog, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable main sensors like accel, gyro, aux and temperature. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable sensor features. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to disable main sensors like accel, gyro, aux and temperature. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t disable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to disable sensor features. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t disable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev); + /***************************************************************************/ /*! User Interface Definitions @@ -1181,11 +1199,9 @@ int8_t bmi270_context_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8 } /*! - * @brief This API gets the sensor/feature data for accelerometer, gyroscope, - * auxiliary sensor, step counter, high-g, gyroscope user-gain update, - * orientation, gyroscope cross sensitivity and error status for NVM and VFRM. + * @brief This API gets the feature data. */ -int8_t bmi270_context_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev) +int8_t bmi270_context_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt; @@ -1198,24 +1214,23 @@ int8_t bmi270_context_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint /* Null-pointer check */ rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (sensor_data != NULL)) + if ((rslt == BMI2_OK) && (feature_data != NULL)) { /* Get status of advance power save mode */ aps_stat = dev->aps_status; for (loop = 0; loop < n_sens; loop++) { - if ((sensor_data[loop].type == BMI2_ACCEL) || (sensor_data[loop].type == BMI2_GYRO) || - (sensor_data[loop].type == BMI2_AUX) || (sensor_data[loop].type == BMI2_GYRO_GAIN_UPDATE) || - (sensor_data[loop].type == BMI2_GYRO_CROSS_SENSE)) + if ((feature_data[loop].type == BMI2_GYRO_GAIN_UPDATE) || + (feature_data[loop].type == BMI2_GYRO_CROSS_SENSE)) { - rslt = bmi2_get_sensor_data(&sensor_data[loop], 1, dev); + rslt = bmi2_get_feature_data(&feature_data[loop], 1, dev); } else { /* Disable Advance power save if enabled for feature * configurations */ - if (sensor_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) + if (feature_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) { if (aps_stat == BMI2_ENABLE) { @@ -1228,22 +1243,22 @@ int8_t bmi270_context_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint if (rslt == BMI2_OK) { - switch (sensor_data[loop].type) + switch (feature_data[loop].type) { case BMI2_STEP_COUNTER: /* Get step counter output */ - rslt = get_step_counter_output(&sensor_data[loop].sens_data.step_counter_output, dev); + rslt = get_step_counter_output(&feature_data[loop].sens_data.step_counter_output, dev); break; case BMI2_NVM_STATUS: /* Get NVM error status */ - rslt = get_nvm_error_status(&sensor_data[loop].sens_data.nvm_status, dev); + rslt = get_nvm_error_status(&feature_data[loop].sens_data.nvm_status, dev); break; case BMI2_VFRM_STATUS: /* Get VFRM error status */ - rslt = get_vfrm_error_status(&sensor_data[loop].sens_data.vfrm_status, dev); + rslt = get_vfrm_error_status(&feature_data[loop].sens_data.vfrm_status, dev); break; default: rslt = BMI2_E_INVALID_SENSOR; @@ -1329,7 +1344,7 @@ int8_t bmi270_context_get_act_recg_sett(struct bmi2_act_recg_sett *sett, struct idx = bmi2_act_recg_sett.start_addr; /* get the status of enable/disable post processing */ - sett->act_rec_1 = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_POST_PROS_EN_DIS); + sett->pp_en = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_POST_PROS_EN_DIS); /* increment idx by 2 to point min gdi thres addres */ idx = idx + 2; @@ -1337,7 +1352,7 @@ int8_t bmi270_context_get_act_recg_sett(struct bmi2_act_recg_sett *sett, struct idx++; msb = feat_config[idx]; msb_lsb = (uint16_t)(lsb | msb << 8); - sett->act_rec_2 = msb_lsb; + sett->min_gdi_thres = msb_lsb; /* increment idx by 1 to point max gdi thres addres */ idx++; @@ -1345,15 +1360,15 @@ int8_t bmi270_context_get_act_recg_sett(struct bmi2_act_recg_sett *sett, struct idx++; msb = feat_config[idx]; msb_lsb = (uint16_t)(lsb | msb << 8); - sett->act_rec_3 = msb_lsb; + sett->max_gdi_thres = msb_lsb; /* increment idx by 1 to point buffer size */ idx++; - sett->act_rec_4 = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_BUFF_SIZE); + sett->buf_size = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_BUFF_SIZE); /* increment idx by 2 to to point to min segment confidence */ idx = idx + 2; - sett->act_rec_5 = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_MIN_SEG_CONF); + sett->min_seg_conf = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_MIN_SEG_CONF); } /* Enable Advance power save if disabled while @@ -1422,36 +1437,36 @@ int8_t bmi270_context_set_act_recg_sett(const struct bmi2_act_recg_sett *sett, s { /* Define the offset in bytes */ idx = bmi2_act_recg_sett.start_addr; - if ((sett->act_rec_4 > 10) || (sett->act_rec_5 > 10)) + if ((sett->buf_size > 10) || (sett->min_seg_conf > 10)) { rslt = BMI2_E_INVALID_INPUT; } if (rslt == BMI2_OK) { - feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], - BMI2_ACT_RECG_POST_PROS_EN_DIS, - sett->act_rec_1); + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_POST_PROS_EN_DIS, sett->pp_en); /* Increment idx by 2 to point min gdi thres addres */ idx = idx + 2; - feat_config[idx] = BMI2_GET_LSB(sett->act_rec_2); + feat_config[idx] = BMI2_GET_LSB(sett->min_gdi_thres); idx++; - feat_config[idx] = BMI2_GET_MSB(sett->act_rec_2); + feat_config[idx] = BMI2_GET_MSB(sett->min_gdi_thres); /* Increment idx by 1 to point max gdi thres addres */ idx++; - feat_config[idx] = BMI2_GET_LSB(sett->act_rec_3); + feat_config[idx] = BMI2_GET_LSB(sett->max_gdi_thres); idx++; - feat_config[idx] = BMI2_GET_MSB(sett->act_rec_3); + feat_config[idx] = BMI2_GET_MSB(sett->max_gdi_thres); /* Increment idx by 1 to point buffer size */ idx++; - feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_BUFF_SIZE, sett->act_rec_4); + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_BUFF_SIZE, sett->buf_size); /* Increment idx by 2 to to point to min segment confidence */ idx = idx + 2; - feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ACT_RECG_MIN_SEG_CONF, sett->act_rec_5); + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], + BMI2_ACT_RECG_MIN_SEG_CONF, + sett->min_seg_conf); rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); } @@ -1486,134 +1501,18 @@ int8_t bmi270_context_get_act_recog_output(struct bmi2_act_recog_output *act_rec /* Variable to define error */ int8_t rslt; - /* Variable to define header frame */ - uint8_t frame_header = 0; - - /* Variable to index the data bytes */ - uint16_t data_index; - - /* Variable to index activity frames */ - uint16_t act_idx = 0; - /* Variable to indicate activity frames read */ uint16_t frame_to_read = 0; /* Null-pointer check */ rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (act_recog != NULL) && (act_frm_len != NULL) && (fifo != NULL)) { - /* Store the number of frames to be read */ frame_to_read = *act_frm_len; - for (data_index = fifo->act_recog_byte_start_idx; data_index < fifo->length;) - { - /* Get frame header byte */ - frame_header = fifo->data[data_index] & BMI2_FIFO_TAG_INTR_MASK; - - /* Skip S4S frames if S4S is enabled */ - rslt = move_if_s4s_frame(&frame_header, &data_index, fifo); - - /* Break if FIFO is empty */ - if (rslt == BMI2_W_FIFO_EMPTY) - { - break; - } - - /* Index shifted to next byte where data starts */ - data_index++; - switch (frame_header) - { - /* If header defines accelerometer frame */ - case BMI2_FIFO_HEADER_ACC_FRM: - rslt = move_next_frame(&data_index, fifo->acc_frm_len, fifo); - break; - - /* If header defines accelerometer and auxiliary frames */ - case BMI2_FIFO_HEADER_AUX_ACC_FRM: - rslt = move_next_frame(&data_index, fifo->acc_aux_frm_len, fifo); - break; - - /* If header defines accelerometer and gyroscope frames */ - case BMI2_FIFO_HEADER_GYR_ACC_FRM: - rslt = move_next_frame(&data_index, fifo->acc_gyr_frm_len, fifo); - break; - - /* If header defines accelerometer, auxiliary and gyroscope frames */ - case BMI2_FIFO_HEADER_ALL_FRM: - rslt = move_next_frame(&data_index, fifo->all_frm_len, fifo); - break; - - /* If header defines only gyroscope frame */ - case BMI2_FIFO_HEADER_GYR_FRM: - rslt = move_next_frame(&data_index, fifo->gyr_frm_len, fifo); - break; - - /* If header defines only auxiliary frame */ - case BMI2_FIFO_HEADER_AUX_FRM: - rslt = move_next_frame(&data_index, fifo->aux_frm_len, fifo); - break; - - /* If header defines auxiliary and gyroscope frame */ - case BMI2_FIFO_HEADER_AUX_GYR_FRM: - rslt = move_next_frame(&data_index, fifo->aux_gyr_frm_len, fifo); - break; - - /* If header defines sensor time frame */ - case BMI2_FIFO_HEADER_SENS_TIME_FRM: - rslt = move_next_frame(&data_index, BMI2_SENSOR_TIME_LENGTH, fifo); - break; - - /* If header defines skip frame */ - case BMI2_FIFO_HEADER_SKIP_FRM: - rslt = move_next_frame(&data_index, BMI2_FIFO_SKIP_FRM_LENGTH, fifo); - break; - - /* If header defines Input configuration frame */ - case BMI2_FIFO_HEADER_INPUT_CFG_FRM: - rslt = move_next_frame(&data_index, BMI2_FIFO_INPUT_CFG_LENGTH, fifo); - break; - - /* If header defines invalid frame or end of valid data */ - case BMI2_FIFO_HEAD_OVER_READ_MSB: - - /* Move the data index to the last byte to mark completion */ - data_index = fifo->length; - - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; - break; - - /* If header defines activity recognition frame */ - case BMI2_FIFO_VIRT_ACT_RECOG_FRM: - - /* Get the activity output */ - rslt = unpack_act_recog_output(&act_recog[(act_idx)], &data_index, fifo); - /* Update activity frame index */ - (act_idx)++; - break; - default: - - /* Move the data index to the last byte in case of invalid values */ - data_index = fifo->length; - - /* FIFO is empty */ - rslt = BMI2_W_FIFO_EMPTY; - break; - } - - /* Number of frames to be read is complete or FIFO is empty */ - if ((frame_to_read == act_idx) || (rslt == BMI2_W_FIFO_EMPTY)) - { - break; - } - } - - /* Update the activity frame index */ - (*act_frm_len) = act_idx; - - /* Update the activity byte index */ - fifo->act_recog_byte_start_idx = data_index; + rslt = fifo_header_frame(frame_to_read, act_frm_len, act_recog, fifo, dev); } else { @@ -1624,90 +1523,38 @@ int8_t bmi270_context_get_act_recog_output(struct bmi2_act_recog_output *act_rec } /*! - * @brief This API updates the gyroscope user-gain. + * @brief This API maps/unmaps feature interrupts to that of interrupt pins. */ -int8_t bmi270_context_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev) +int8_t bmi270_context_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt; - /* Variable to select sensor */ - uint8_t sens_sel[2] = { BMI2_GYRO, BMI2_GYRO_GAIN_UPDATE }; - - /* Structure to define sensor configurations */ - struct bmi2_sens_config sens_cfg; - - /* Variable to store status of user-gain update module */ - uint8_t status = 0; - - /* Variable to define count */ - uint8_t count = 100; + /* Variable to define loop */ + uint8_t loop; /* Null-pointer check */ rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (user_gain != NULL)) + if ((rslt == BMI2_OK) && (sens_int != NULL)) { - /* Select type of feature */ - sens_cfg.type = BMI2_GYRO_GAIN_UPDATE; - - /* Get the user gain configurations */ - rslt = bmi270_context_get_sensor_config(&sens_cfg, 1, dev); - if (rslt == BMI2_OK) - { - /* Get the user-defined ratio */ - sens_cfg.cfg.gyro_gain_update = *user_gain; - - /* Set rate ratio for all axes */ - rslt = bmi270_context_set_sensor_config(&sens_cfg, 1, dev); - } - - /* Disable gyroscope */ - if (rslt == BMI2_OK) - { - rslt = bmi270_context_sensor_disable(&sens_sel[0], 1, dev); - } - - /* Enable gyroscope user-gain update module */ - if (rslt == BMI2_OK) - { - rslt = bmi270_context_sensor_enable(&sens_sel[1], 1, dev); - } - - /* Set the command to trigger the computation */ - if (rslt == BMI2_OK) - { - rslt = bmi2_set_command_register(BMI2_USR_GAIN_CMD, dev); - } - - if (rslt == BMI2_OK) + for (loop = 0; loop < n_sens; loop++) { - /* Poll until enable bit of user-gain update is 0 */ - while (count--) + switch (sens_int[loop].type) { - rslt = get_user_gain_upd_status(&status, dev); - if ((rslt == BMI2_OK) && (status == 0)) - { - /* Enable compensation of gain defined - * in the GAIN register - */ - rslt = enable_gyro_gain(BMI2_ENABLE, dev); - - /* Enable gyroscope */ - if (rslt == BMI2_OK) - { - rslt = bmi270_context_sensor_enable(&sens_sel[0], 1, dev); - } + case BMI2_STEP_COUNTER: + case BMI2_STEP_DETECTOR: + rslt = bmi2_map_feat_int(sens_int[loop].type, sens_int[loop].hw_int_pin, dev); + break; + default: + rslt = BMI2_E_INVALID_SENSOR; break; - } - - dev->delay_us(10000, dev->intf_ptr); } - /* Return error if user-gain update is failed */ - if ((rslt == BMI2_OK) && (status != 0)) + /* Return error if interrupt mapping fails */ + if (rslt != BMI2_OK) { - rslt = BMI2_E_GYR_USER_GAIN_UPD_FAIL; + break; } } } @@ -1719,37 +1566,23 @@ int8_t bmi270_context_update_gyro_user_gain(const struct bmi2_gyro_user_gain_con return rslt; } +/***************************************************************************/ + +/*! Local Function Definitions + ****************************************************************************/ + /*! - * @brief This API reads the compensated gyroscope user-gain values. + * @brief This internal API is used to validate the device structure pointer for + * null conditions. */ -int8_t bmi270_context_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev) +static int8_t null_ptr_check(const struct bmi2_dev *dev) { /* Variable to define error */ - int8_t rslt; - - /* Variable to define register data */ - uint8_t reg_data[3] = { 0 }; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (gyr_usr_gain != NULL)) - { - /* Get the gyroscope compensated gain values */ - rslt = bmi2_get_regs(BMI2_GYR_USR_GAIN_0_ADDR, reg_data, 3, dev); - if (rslt == BMI2_OK) - { - /* Gyroscope user gain correction X-axis */ - gyr_usr_gain->x = (int8_t)BMI2_GET_BIT_POS0(reg_data[0], BMI2_GYR_USR_GAIN_X); - - /* Gyroscope user gain correction Y-axis */ - gyr_usr_gain->y = (int8_t)BMI2_GET_BIT_POS0(reg_data[1], BMI2_GYR_USR_GAIN_Y); + int8_t rslt = BMI2_OK; - /* Gyroscope user gain correction z-axis */ - gyr_usr_gain->z = (int8_t)BMI2_GET_BIT_POS0(reg_data[2], BMI2_GYR_USR_GAIN_Z); - } - } - else + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL)) { + /* Device structure pointer is not valid */ rslt = BMI2_E_NULL_PTR; } @@ -1757,77 +1590,10 @@ int8_t bmi270_context_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_u } /*! - * @brief This API maps/unmaps feature interrupts to that of interrupt pins. + * @brief This internal API selects the sensor/features to be enabled or + * disabled. */ -int8_t bmi270_context_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt; - - /* Variable to define loop */ - uint8_t loop; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if ((rslt == BMI2_OK) && (sens_int != NULL)) - { - for (loop = 0; loop < n_sens; loop++) - { - switch (sens_int[loop].type) - { - case BMI2_STEP_COUNTER: - case BMI2_STEP_DETECTOR: - - rslt = bmi2_map_feat_int(sens_int[loop].type, sens_int[loop].hw_int_pin, dev); - break; - default: - rslt = BMI2_E_INVALID_SENSOR; - break; - } - - /* Return error if interrupt mapping fails */ - if (rslt != BMI2_OK) - { - break; - } - } - } - else - { - rslt = BMI2_E_NULL_PTR; - } - - return rslt; -} - -/***************************************************************************/ - -/*! Local Function Definitions - ****************************************************************************/ - -/*! - * @brief This internal API is used to validate the device structure pointer for - * null conditions. - */ -static int8_t null_ptr_check(const struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt = BMI2_OK; - - if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL)) - { - /* Device structure pointer is not valid */ - rslt = BMI2_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This internal API selects the sensor/features to be enabled or - * disabled. - */ -static int8_t select_sensor(const uint8_t *sens_list, uint8_t n_sens, uint64_t *sensor_sel) +static int8_t select_sensor(const uint8_t *sens_list, uint8_t n_sens, uint64_t *sensor_sel) { /* Variable to define error */ int8_t rslt = BMI2_OK; @@ -1880,48 +1646,10 @@ static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev) /* Variable to define error */ int8_t rslt; - /* Variable to store register values */ - uint8_t reg_data = 0; - - /* Variable to define loop */ - uint8_t loop = 1; - /* Variable to get the status of advance power save */ uint8_t aps_stat = 0; - rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - if (rslt == BMI2_OK) - { - /* Enable accelerometer */ - if (sensor_sel & BMI2_ACCEL_SENS_SEL) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_ACC_EN, BMI2_ENABLE); - } - - /* Enable gyroscope */ - if (sensor_sel & BMI2_GYRO_SENS_SEL) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_EN, BMI2_ENABLE); - } - - /* Enable auxiliary sensor */ - if (sensor_sel & BMI2_AUX_SENS_SEL) - { - reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_AUX_EN, BMI2_ENABLE); - } - - /* Enable temperature sensor */ - if (sensor_sel & BMI2_TEMP_SENS_SEL) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_TEMP_EN, BMI2_ENABLE); - } - - /* Enable the sensors that are set in the power control register */ - if (sensor_sel & BMI2_MAIN_SENSORS) - { - rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - } - } + rslt = enable_main_sensors(sensor_sel, dev); if ((rslt == BMI2_OK) && (sensor_sel & ~(BMI2_MAIN_SENSORS))) { @@ -1935,64 +1663,7 @@ static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev) if (rslt == BMI2_OK) { - while (loop--) - { - /* Enable step detector feature */ - if (sensor_sel & BMI2_STEP_DETECT_SEL) - { - rslt = set_step_detector(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_STEP_DETECT_SEL; - } - else - { - break; - } - } - - /* Enable step counter feature */ - if (sensor_sel & BMI2_STEP_COUNT_SEL) - { - rslt = set_step_counter(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_STEP_COUNT_SEL; - } - else - { - break; - } - } - - /* Enable gyroscope user gain */ - if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) - { - rslt = set_gyro_user_gain(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_GYRO_GAIN_UPDATE_SEL; - } - else - { - break; - } - } - - /* Enable activity recognition feature */ - if (sensor_sel & BMI2_ACTIVITY_RECOGNITION_SEL) - { - rslt = set_act_recog(BMI2_ENABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_ACTIVITY_RECOGNITION_SEL; - } - else - { - break; - } - } - } + rslt = enable_sensor_features(sensor_sel, dev); /* Enable Advance power save if disabled while * configuring and not when already disabled @@ -2015,48 +1686,10 @@ static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev) /* Variable to define error */ int8_t rslt; - /* Variable to store register values */ - uint8_t reg_data = 0; - - /* Variable to define loop */ - uint8_t loop = 1; - /* Variable to get the status of advance power save */ uint8_t aps_stat = 0; - rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - if (rslt == BMI2_OK) - { - /* Disable accelerometer */ - if (sensor_sel & BMI2_ACCEL_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_ACC_EN); - } - - /* Disable gyroscope */ - if (sensor_sel & BMI2_GYRO_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_GYR_EN); - } - - /* Disable auxiliary sensor */ - if (sensor_sel & BMI2_AUX_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_AUX_EN); - } - - /* Disable temperature sensor */ - if (sensor_sel & BMI2_TEMP_SENS_SEL) - { - reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_TEMP_EN); - } - - /* Disable the sensors that are set in the power control register */ - if (sensor_sel & BMI2_MAIN_SENSORS) - { - rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); - } - } + rslt = disable_main_sensors(sensor_sel, dev); if ((rslt == BMI2_OK) && (sensor_sel & ~(BMI2_MAIN_SENSORS))) { @@ -2070,70 +1703,14 @@ static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev) if (rslt == BMI2_OK) { - while (loop--) - { - /* Disable step detector feature */ - if (sensor_sel & BMI2_STEP_DETECT_SEL) - { - rslt = set_step_detector(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_STEP_DETECT_SEL; - } - else - { - break; - } - } - - /* Disable step counter feature */ - if (sensor_sel & BMI2_STEP_COUNT_SEL) - { - rslt = set_step_counter(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_STEP_COUNT_SEL; - } - else - { - break; - } - } - - /* Disable gyroscope user gain */ - if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) - { - rslt = set_gyro_user_gain(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat &= ~BMI2_GYRO_GAIN_UPDATE_SEL; - } - else - { - break; - } - } - - if (sensor_sel & BMI2_ACTIVITY_RECOGNITION_SEL) - { - rslt = set_act_recog(BMI2_DISABLE, dev); - if (rslt == BMI2_OK) - { - dev->sens_en_stat |= BMI2_ACTIVITY_RECOGNITION_SEL; - } - else - { - break; - } - } + rslt = disable_sensor_features(sensor_sel, dev); - /* Enable Advance power save if disabled while - * configuring and not when already disabled - */ - if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) - { - rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); - } + /* Enable Advance power save if disabled while + * configuring and not when already disabled + */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); } } } @@ -2177,6 +1754,15 @@ static int8_t set_step_detector(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_DETECT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_DETECT_SEL; + } } } else @@ -2223,6 +1809,15 @@ static int8_t set_step_counter(uint8_t enable, struct bmi2_dev *dev) /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_COUNT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_COUNT_SEL; + } } } else @@ -2234,10 +1829,9 @@ static int8_t set_step_counter(uint8_t enable, struct bmi2_dev *dev) } /*! - * @brief This internal API is used to enable/disable gyroscope user gain - * feature. + * @brief This internal API enables/disables the activity recognition feature. */ -static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev) +static int8_t set_act_recog(uint8_t enable, struct bmi2_dev *dev) { /* Variable to define error */ int8_t rslt; @@ -2251,25 +1845,36 @@ static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev) /* Variable to set flag */ uint8_t feat_found; - /* Initialize feature configuration for gyroscope user gain */ - struct bmi2_feature_config gyr_user_gain_cfg = { 0, 0, 0 }; + /* Initialize feature configuration for activity recognition */ + struct bmi2_feature_config act_recog_cfg = { 0, 0, 0 }; - /* Search for user gain feature and extract its configuration details */ - feat_found = bmi2_extract_input_feat_config(&gyr_user_gain_cfg, BMI2_GYRO_GAIN_UPDATE, dev); + /* Search for activity recognition and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&act_recog_cfg, BMI2_ACTIVITY_RECOGNITION, dev); if (feat_found) { - /* Get the configuration from the page where user gain feature resides */ - rslt = bmi2_get_feat_config(gyr_user_gain_cfg.page, feat_config, dev); + /* Get the configuration from the page where activity + * recognition feature resides + */ + rslt = bmi2_get_feat_config(act_recog_cfg.page, feat_config, dev); if (rslt == BMI2_OK) { - /* Define the offset for enable/disable of user gain */ - idx = gyr_user_gain_cfg.start_addr + BMI2_GYR_USER_GAIN_FEAT_EN_OFFSET; + /* Define the offset for enable/disable of activity recognition */ + idx = act_recog_cfg.start_addr; /* Set the feature enable bit */ - feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_GYR_USER_GAIN_FEAT_EN, enable); + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ACTIVITY_RECOG_EN, enable); /* Set the configuration back to the page */ rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_ACT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_ACT_SEL; + } } } else @@ -2281,66 +1886,18 @@ static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev) } /*! - * @brief This internal API enables/disables the activity recognition feature. + * @brief This internal API sets step counter parameter configurations. */ -static int8_t set_act_recog(uint8_t enable, struct bmi2_dev *dev) +static int8_t set_step_count_params_config(const uint16_t *step_count_params, struct bmi2_dev *dev) { /* Variable to define error */ - int8_t rslt; + int8_t rslt = BMI2_OK; /* Array to define the feature configuration */ uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; - /* Variable to define the array offset */ - uint8_t idx = 0; - - /* Variable to set flag */ - uint8_t feat_found; - - /* Initialize feature configuration for activity recognition */ - struct bmi2_feature_config act_recog_cfg = { 0, 0, 0 }; - - /* Search for activity recognition and extract its configuration details */ - feat_found = bmi2_extract_input_feat_config(&act_recog_cfg, BMI2_ACTIVITY_RECOGNITION, dev); - if (feat_found) - { - /* Get the configuration from the page where activity - * recognition feature resides - */ - rslt = bmi2_get_feat_config(act_recog_cfg.page, feat_config, dev); - if (rslt == BMI2_OK) - { - /* Define the offset for enable/disable of activity recognition */ - idx = act_recog_cfg.start_addr; - - /* Set the feature enable bit */ - feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ACTIVITY_RECOG_EN, enable); - - /* Set the configuration back to the page */ - rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); - } - } - else - { - rslt = BMI2_E_INVALID_SENSOR; - } - - return rslt; -} - -/*! - * @brief This internal API sets step counter parameter configurations. - */ -static int8_t set_step_count_params_config(const uint16_t *step_count_params, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt = BMI2_OK; - - /* Array to define the feature configuration */ - uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; - - /* Variable to define index */ - uint8_t index = 0; + /* Variable to define index */ + uint8_t index = 0; /* Variable to set flag */ uint8_t feat_found; @@ -2499,14 +2056,6 @@ static int8_t set_step_config(const struct bmi2_step_config *config, struct bmi2 /* Set reset-counter */ *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_STEP_COUNT_RST_CNT, config->reset_counter); - /* Increment offset by 1 word to set output - * configuration of step detector and step activity - */ - idx++; - - /* Set step buffer size */ - *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_STEP_BUFFER_SIZE, config->step_buffer_size); - /* Increment offset by 1 more word to get the total length in words */ idx++; @@ -2701,13 +2250,6 @@ static int8_t get_step_config(struct bmi2_step_config *config, struct bmi2_dev * /* Get reset counter */ config->reset_counter = (lsb_msb & BMI2_STEP_COUNT_RST_CNT_MASK) >> BMI2_STEP_COUNT_RST_CNT_POS; - - /* Get word to calculate output configuration of step detector and activity */ - lsb = (uint16_t) feat_config[idx++]; - msb = ((uint16_t) feat_config[idx++] << 8); - lsb_msb = lsb | msb; - - config->step_buffer_size = (lsb_msb & BMI2_STEP_BUFFER_SIZE_MASK) >> BMI2_STEP_BUFFER_SIZE_POS; } } else @@ -2822,69 +2364,6 @@ static int8_t get_nvm_error_status(struct bmi2_nvm_err_status *nvm_err_stat, str return rslt; } -/*! - * @brief This internal API is used to get enable status of gyroscope user gain - * update. - */ -static int8_t get_user_gain_upd_status(uint8_t *status, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt = BMI2_OK; - - /* Array to define the feature configuration */ - uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; - - /* Variable to define the array offset */ - uint8_t idx = 0; - - /* Variable to set flag */ - uint8_t feat_found; - - /* Variable to check APS status */ - uint8_t aps_stat = 0; - - /* Initialize feature configuration for gyroscope user gain */ - struct bmi2_feature_config gyr_user_gain_cfg = { 0, 0, 0 }; - - /* Search for user gain feature and extract its configuration details */ - feat_found = bmi2_extract_input_feat_config(&gyr_user_gain_cfg, BMI2_GYRO_GAIN_UPDATE, dev); - if (feat_found) - { - /* Disable advance power save */ - aps_stat = dev->aps_status; - if (aps_stat == BMI2_ENABLE) - { - rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); - } - - if (rslt == BMI2_OK) - { - /* Get the configuration from the page where user gain feature resides */ - rslt = bmi2_get_feat_config(gyr_user_gain_cfg.page, feat_config, dev); - if (rslt == BMI2_OK) - { - /* Define the offset for enable/disable of user gain */ - idx = gyr_user_gain_cfg.start_addr + BMI2_GYR_USER_GAIN_FEAT_EN_OFFSET; - - /* Set the feature enable status */ - *status = BMI2_GET_BITS(feat_config[idx], BMI2_GYR_USER_GAIN_FEAT_EN); - } - } - } - else - { - rslt = BMI2_E_INVALID_SENSOR; - } - - /* Enable Advance power save if disabled while configuring and not when already disabled */ - if ((rslt == BMI2_OK) && (aps_stat == BMI2_ENABLE)) - { - rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); - } - - return rslt; -} - /*! * @brief This internal API is used to parse and store the activity recognition * output from the FIFO data. @@ -3037,28 +2516,6 @@ static int8_t move_if_s4s_frame(const uint8_t *frame_header, uint16_t *data_inde return rslt; } -/*! - * @brief This internal API enables/disables compensation of the gain defined - * in the GAIN register. - */ -static int8_t enable_gyro_gain(uint8_t enable, struct bmi2_dev *dev) -{ - /* Variable to define error */ - int8_t rslt; - - /* Variable to define register data */ - uint8_t reg_data = 0; - - rslt = bmi2_get_regs(BMI2_GYR_OFF_COMP_6_ADDR, ®_data, 1, dev); - if (rslt == BMI2_OK) - { - reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_GAIN_EN, enable); - rslt = bmi2_set_regs(BMI2_GYR_OFF_COMP_6_ADDR, ®_data, 1, dev); - } - - return rslt; -} - /*! * @brief This internal API is used to extract the output feature configuration * details from the look-up table. @@ -3120,3 +2577,300 @@ static int8_t move_next_frame(uint16_t *data_index, uint8_t current_frame_length return rslt; } + +/*! + * @brief This internal API is used to select the header byte frame + */ +static int8_t fifo_header_frame(uint16_t frame_to_read, + uint16_t *act_frm_len, + struct bmi2_act_recog_output *act_recog, + struct bmi2_fifo_frame *fifo, + const struct bmi2_dev *dev) +{ + /* Variables to define error */ + int8_t rslt = BMI2_OK; + + /* Variable to index the data bytes */ + uint16_t data_index; + + /* Variable to define header frame */ + uint8_t frame_header = 0; + + /* Variable to index activity frames */ + uint16_t act_idx = 0; + + /* Check if this is the first iteration of data unpacking + * if yes, then consider dummy byte on SPI + */ + if (fifo->act_recog_byte_start_idx == 0) + { + /* Dummy byte included */ + fifo->act_recog_byte_start_idx = dev->dummy_byte; + } + + for (data_index = fifo->act_recog_byte_start_idx; data_index < fifo->length;) + { + /* Get frame header byte */ + frame_header = fifo->data[data_index] & BMI2_FIFO_TAG_INTR_MASK; + + /* Skip S4S frames if S4S is enabled */ + rslt = move_if_s4s_frame(&frame_header, &data_index, fifo); + + /* Break if FIFO is empty */ + if (rslt == BMI2_W_FIFO_EMPTY) + { + break; + } + + /* Index shifted to next byte where data starts */ + data_index++; + + if (rslt == BMI2_OK) + { + switch (frame_header) + { + /* If header defines accelerometer frame */ + case BMI2_FIFO_HEADER_ACC_FRM: + rslt = move_next_frame(&data_index, fifo->acc_frm_len, fifo); + break; + + /* If header defines accelerometer and auxiliary frames */ + case BMI2_FIFO_HEADER_AUX_ACC_FRM: + rslt = move_next_frame(&data_index, fifo->acc_aux_frm_len, fifo); + break; + + /* If header defines accelerometer and gyroscope frames */ + case BMI2_FIFO_HEADER_GYR_ACC_FRM: + rslt = move_next_frame(&data_index, fifo->acc_gyr_frm_len, fifo); + break; + + /* If header defines accelerometer, auxiliary and gyroscope frames */ + case BMI2_FIFO_HEADER_ALL_FRM: + rslt = move_next_frame(&data_index, fifo->all_frm_len, fifo); + break; + + /* If header defines only gyroscope frame */ + case BMI2_FIFO_HEADER_GYR_FRM: + rslt = move_next_frame(&data_index, fifo->gyr_frm_len, fifo); + break; + + /* If header defines only auxiliary frame */ + case BMI2_FIFO_HEADER_AUX_FRM: + rslt = move_next_frame(&data_index, fifo->aux_frm_len, fifo); + break; + + /* If header defines auxiliary and gyroscope frame */ + case BMI2_FIFO_HEADER_AUX_GYR_FRM: + rslt = move_next_frame(&data_index, fifo->aux_gyr_frm_len, fifo); + break; + + /* If header defines sensor time frame */ + case BMI2_FIFO_HEADER_SENS_TIME_FRM: + rslt = move_next_frame(&data_index, BMI2_SENSOR_TIME_LENGTH, fifo); + break; + + /* If header defines skip frame */ + case BMI2_FIFO_HEADER_SKIP_FRM: + rslt = move_next_frame(&data_index, BMI2_FIFO_SKIP_FRM_LENGTH, fifo); + break; + + /* If header defines Input configuration frame */ + case BMI2_FIFO_HEADER_INPUT_CFG_FRM: + rslt = move_next_frame(&data_index, BMI2_FIFO_INPUT_CFG_LENGTH, fifo); + break; + + /* If header defines invalid frame or end of valid data */ + case BMI2_FIFO_HEAD_OVER_READ_MSB: + + /* Move the data index to the last byte to mark completion */ + data_index = fifo->length; + + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + break; + + /* If header defines activity recognition frame */ + case BMI2_FIFO_VIRT_ACT_RECOG_FRM: + + /* Get the activity output */ + rslt = unpack_act_recog_output(&act_recog[(act_idx)], &data_index, fifo); + + /* Update activity frame index */ + (act_idx)++; + break; + default: + + /* Move the data index to the last byte in case of invalid values */ + data_index = fifo->length; + + /* FIFO is empty */ + rslt = BMI2_W_FIFO_EMPTY; + break; + } + + /* Number of frames to be read is complete or FIFO is empty */ + if ((frame_to_read == act_idx) || (rslt == BMI2_W_FIFO_EMPTY)) + { + break; + } + } + } + + /* Update the activity frame index */ + (*act_frm_len) = act_idx; + + /* Update the activity byte index */ + fifo->act_recog_byte_start_idx = data_index; + + return rslt; +} + +/*! + * @brief This internal API is used to enable main sensors like accel, gyro, aux and temperature. + */ +static int8_t enable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to store register values */ + uint8_t reg_data; + + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + + if (rslt == BMI2_OK) + { + /* Enable accelerometer */ + if (sensor_sel & BMI2_ACCEL_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_ACC_EN, BMI2_ENABLE); + } + + /* Enable gyroscope */ + if (sensor_sel & BMI2_GYRO_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_EN, BMI2_ENABLE); + } + + /* Enable auxiliary sensor */ + if (sensor_sel & BMI2_AUX_SENS_SEL) + { + reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_AUX_EN, BMI2_ENABLE); + } + + /* Enable temperature sensor */ + if (sensor_sel & BMI2_TEMP_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_TEMP_EN, BMI2_ENABLE); + } + + /* Enable the sensors that are set in the power control register */ + if (sensor_sel & BMI2_MAIN_SENSORS) + { + rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable sensor features. + */ +static int8_t enable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Enable step detector feature */ + if (sensor_sel & BMI2_STEP_DETECT_SEL) + { + rslt = set_step_detector(BMI2_ENABLE, dev); + } + + /* Enable step counter feature */ + if (sensor_sel & BMI2_STEP_COUNT_SEL) + { + rslt = set_step_counter(BMI2_ENABLE, dev); + } + + /* Enable activity recognition feature */ + if (sensor_sel & BMI2_ACTIVITY_RECOGNITION_SEL) + { + rslt = set_act_recog(BMI2_ENABLE, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to disable main sensors like accel, gyro, aux and temperature. + */ +static int8_t disable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to store register values */ + uint8_t reg_data; + + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + + if (rslt == BMI2_OK) + { + /* Disable accelerometer */ + if (sensor_sel & BMI2_ACCEL_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_ACC_EN); + } + + /* Disable gyroscope */ + if (sensor_sel & BMI2_GYRO_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_GYR_EN); + } + + /* Disable auxiliary sensor */ + if (sensor_sel & BMI2_AUX_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_AUX_EN); + } + + /* Disable the sensors that are set in the power control register */ + if (sensor_sel & BMI2_MAIN_SENSORS) + { + rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to disable sensor features. + */ +static int8_t disable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Enable step detector feature */ + if (sensor_sel & BMI2_STEP_DETECT_SEL) + { + rslt = set_step_detector(BMI2_DISABLE, dev); + } + + /* Enable step counter feature */ + if (sensor_sel & BMI2_STEP_COUNT_SEL) + { + rslt = set_step_counter(BMI2_DISABLE, dev); + } + + /* Enable activity recognition feature */ + if (sensor_sel & BMI2_ACTIVITY_RECOGNITION_SEL) + { + rslt = set_act_recog(BMI2_DISABLE, dev); + } + + return rslt; +} diff --git a/bmi270_context.h b/bmi270_context.h index 7078f23..6649ef5 100644 --- a/bmi270_context.h +++ b/bmi270_context.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi270_context.h -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -274,23 +274,21 @@ int8_t bmi270_context_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8 /** * \ingroup bmi270_context - * \defgroup bmi270_contextApiSensorD Sensor Data - * @brief Get sensor data + * \defgroup bmi270_contextApiSensorD Feature Sensor Data + * @brief Get feature sensor data */ /*! * \ingroup bmi270_contextApiSensorD - * \page bmi270_context_api_bmi270_context_get_sensor_data bmi270_context_get_sensor_data + * \page bmi270_context_api_bmi270_context_get_feature_data bmi270_context_get_feature_data * \code - * int8_t bmi270_context_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev); + * int8_t bmi270_context_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev); * \endcode - * @details This API gets the sensor/feature data for accelerometer, gyroscope, - * auxiliary sensor, step counter, high-g, gyroscope user-gain update, - * orientation, gyroscope cross sensitivity and error status for NVM and VFRM. + * @details This API gets the feature data. * - * @param[out] sensor_data : Structure instance of bmi2_sensor_data. - * @param[in] n_sens : Number of sensors selected. - * @param[in] dev : Structure instance of bmi2_dev. + * @param[out] feature_data : Structure instance of bmi2_feat_sensor_data. + * @param[in] n_sens : Number of sensors selected. + * @param[in] dev : Structure instance of bmi2_dev. * * @note Sensors/features whose data can be read * @@ -306,7 +304,8 @@ int8_t bmi270_context_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8 * @retval 0 -> Success * @retval < 0 -> Fail */ -int8_t bmi270_context_get_sensor_data(struct bmi2_sensor_data *sensor_data, uint8_t n_sens, struct bmi2_dev *dev); +int8_t bmi270_context_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, + struct bmi2_dev *dev); /** * \ingroup bmi270_context @@ -425,46 +424,6 @@ int8_t bmi270_context_get_act_recog_output(struct bmi2_act_recog_output *act_rec struct bmi2_fifo_frame *fifo, const struct bmi2_dev *dev); -/** - * \ingroup bmi270_contex - * \defgroup bmi270_contextApiGyroUG Gyro User Gain - * @brief Set / Get Gyro User Gain of the sensor - */ - -/*! - * \ingroup bmi270_contextApiGyroUG - * \page bmi270_context_api_bmi270_context_update_gyro_user_gain bmi270_context_update_gyro_user_gain - * \code - * int8_t bmi270_context_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev); - * \endcode - * @details This API updates the gyroscope user-gain. - * - * @param[in] user_gain : Structure that stores user-gain configurations. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -int8_t bmi270_context_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev); - -/*! - * \ingroup bmi270_contextApiGyroUG - * \page bmi270_context_api_bmi270_context_read_gyro_user_gain bmi270_context_read_gyro_user_gain - * \code - * int8_t bmi270_context_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, const struct bmi2_dev *dev); - * \endcode - * @details This API reads the compensated gyroscope user-gain values. - * - * @param[out] gyr_usr_gain : Structure that stores gain values. - * @param[in] dev : Structure instance of bmi2_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval < 0 -> Fail - */ -int8_t bmi270_context_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev); - /*! * \ingroup bmi270_contextApiInt * \page bmi270_context_api_bmi270_context_map_feat_int bmi270_context_map_feat_int diff --git a/examples/bmi270_context/accel/Makefile b/bmi270_context_examples/accel/Makefile similarity index 100% rename from examples/bmi270_context/accel/Makefile rename to bmi270_context_examples/accel/Makefile diff --git a/examples/bmi270_context/accel/accel.c b/bmi270_context_examples/accel/accel.c similarity index 87% rename from examples/bmi270_context/accel/accel.c rename to bmi270_context_examples/accel/accel.c index 5b36fff..a652871 100644 --- a/examples/bmi270_context/accel/accel.c +++ b/bmi270_context_examples/accel/accel.c @@ -59,7 +59,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Initialize the interrupt status of accel. */ uint16_t int_status = 0; @@ -80,18 +80,20 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the accel sensor. */ - rslt = bmi270_context_sensor_enable(&sensor_list, 1, &bmi2_dev); + /* Accel configuration settings. */ + rslt = set_accel_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Accel configuration settings. */ - rslt = set_accel_config(&bmi2_dev); + /* NOTE: + * Accel enable must be done after setting configurations + */ + + /* Enable the accel sensor. */ + rslt = bmi270_context_sensor_enable(&sensor_list, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Assign accel sensor. */ - sensor_data.type = BMI2_ACCEL; printf("Accel and m/s2 data \n"); printf("Accel data collected at 2G Range with 16-bit resolution\n"); @@ -106,16 +108,16 @@ int main(void) if (int_status & BMI2_ACC_DRDY_INT_MASK) { /* Get accelerometer data for x, y and z axis. */ - rslt = bmi270_context_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("\nAcc_X = %d\t", sensor_data.sens_data.acc.x); - printf("Acc_Y = %d\t", sensor_data.sens_data.acc.y); - printf("Acc_Z = %d\r\n", sensor_data.sens_data.acc.z); + printf("\nAcc_X = %d\t", sensor_data.acc.x); + printf("Acc_Y = %d\t", sensor_data.acc.y); + printf("Acc_Z = %d\r\n", sensor_data.acc.z); /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data.sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data.sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data.sens_data.acc.z, 2, bmi2_dev.resolution); + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); /* Print the data in m/s2. */ printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); diff --git a/bmi270_context_examples/accel_foc/Makefile b/bmi270_context_examples/accel_foc/Makefile new file mode 100644 index 0000000..7a80879 --- /dev/null +++ b/bmi270_context_examples/accel_foc/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accel_foc.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/accel_foc/accel_foc.c b/bmi270_context_examples/accel_foc/accel_foc.c new file mode 100644 index 0000000..9468ade --- /dev/null +++ b/bmi270_context_examples/accel_foc/accel_foc.c @@ -0,0 +1,729 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include +#include +#include +#include + +#include "bmi270_context.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macro Definitions */ + +#define ACCEL_SAMPLE_COUNT UINT8_C(100) + +/******************************************************************************/ +/*! Global Variable Declaration */ + +/* Structure to store temporary axes data values */ +struct temp_axes_val +{ + /* X data */ + int32_t x; + + /* Y data */ + int32_t y; + + /* Z data */ + int32_t z; +}; + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used perform accel foc and determine limits based on range + * + * @param[in] range : Range of Accel + * @param[in] input_axis : Axis selected for Accel FOC + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t perform_foc_range_test(uint8_t range, uint8_t input_axis, struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to determine if average accel FOC data is within limits + * + * @param[in] range : Value of Accel range + * @param[in] avg_accel_foc_data : Average Accel FOC value + * @param[in] reference : Reference LSB based on Accel Range + * @param[in] foc_sign : Input sign of performed Accel FOC + * @param[in] min_val : Minimum acceptable LSB limit + * @param[in] max_val : Maximum acceptable LSB limit + * + * @return Status of execution. + */ +static int8_t accel_foc_report(uint8_t range, + int16_t avg_accel_foc_data, + int16_t reference, + uint8_t foc_sign, + int16_t min_val, + int16_t max_val); + +/*! + * @brief This internal API is to collect and verify accel sensor data + * + * @param[in] range : Value of Accel range + * @param[in] reference : Reference LSB based on Accel Range + * @param[in] matched_axis : Input Axis to perform Accel FOC + * @param[in] foc_sign : Input sign to perform Accel FOC + * @param[in,out] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t verify_accel_foc_data(uint8_t range, + int16_t reference, + int8_t matched_axis, + uint8_t foc_sign, + struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to calculate noise level for Accel FOC data + * + * @param[in] matched_axis : Input Axis to perform accel FOC + * @param[in] accel_foc_data : Array of Accel FOC data + * @param[in] avg_accel_foc_data : Average Accel FOC data + * + * @return Status of execution. + */ +static void calculate_noise(int8_t matched_axis, + struct bmi2_sens_axes_data *accel_foc_data, + struct bmi2_sens_axes_data avg_accel_foc_data); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + uint8_t try = 0, j = 0; + int8_t rslt; + uint8_t sens_list = BMI2_ACCEL; + struct bmi2_sens_config sens_cfg = { 0 }; + uint8_t data = 0, range, input_axis = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + printf("Functional test for accel foc start..\n\n"); + + printf("Choose the axis for accel FOC to be done\n"); + printf("Press '1' to choose X axis\n"); + printf("Press '2' to choose Y axis\n"); + printf("Press '3' to choose Z axis\n"); + + printf("Press '4' to choose -X axis\n"); + printf("Press '5' to choose -Y axis\n"); + printf("Press '6' to choose -Z axis\n"); + + while (1) + { + scanf("%hu", (short unsigned int *)&input_axis); + if (input_axis > 0 && input_axis < 7) + { + break; + } + } + + if (input_axis == 1) + { + printf("The choosen input axis for FOC is : X\n"); + } + else if (input_axis == 2) + { + printf("The choosen input axis for FOC is : Y\n"); + } + else if (input_axis == 3) + { + printf("The choosen input axis for FOC is : Z\n"); + } + else if (input_axis == 4) + { + printf("The choosen input axis for FOC is : -X\n"); + } + else if (input_axis == 5) + { + printf("The choosen input axis for FOC is : -Y\n"); + } + else if (input_axis == 6) + { + printf("The choosen input axis for FOC is : -Z\n"); + } + + printf("Confirm your chosen axis and the sensor keeping position are same before doing FOC\n"); + + for (j = 0; j < 2; j++) + { + try = 0; + + if (j == 1) + { + printf("Keep sensor in wrong position and press 5\n"); + } + else if (j == 0) + { + printf("Keep sensor in right position and press 5\n"); + } + + while (1) + { + scanf("%hu", (short unsigned int *)&try); + if (try == 5) + { + break; + } + } + + for (range = BMI2_ACC_RANGE_2G; range <= BMI2_ACC_RANGE_16G; range++) + { + /****************************************************************/ + /* Initialize by enabling configuration load */ + printf("#########################################################\n\n"); + + rslt = bmi270_context_init(&dev); + bmi2_error_codes_print_result(rslt); + + sens_cfg.type = BMI2_ACCEL; + + /* Testing with different settings other than the default configurations + * Default is : 50Hz ODR and 2g RANGE + * Note - Change accel_conf.range for testing in different range values + */ + sens_cfg.cfg.acc.odr = BMI2_ACC_ODR_50HZ; + sens_cfg.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /****************************************************************/ + sens_cfg.cfg.acc.range = range; + + /* Set the configuration details */ + rslt = bmi270_context_set_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Get the configuration details to verify whether the configured values are set */ + rslt = bmi270_context_get_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("ODR = %d, RANGE = %d, BANDWIDTH = %d\n", + sens_cfg.cfg.acc.odr, + sens_cfg.cfg.acc.range, + sens_cfg.cfg.acc.bwp); + + /* Perform FOC for different ranges */ + rslt = perform_foc_range_test(range, input_axis, &dev); + + if ((j == 1) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - Wrong position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_OK)) + { + printf("\n######### Valid input - Right position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 1) && (rslt == BMI2_OK)) + { + printf("\n######### Invalid input - Right position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Wrong position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - Right position #########\n\n"); + printf("\n######### Before FOC is better than after FOC #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 1) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Right position #########\n\n"); + printf("\n######### Before FOC is better than after FOC #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + } + + /* Disable offset compensation */ + rslt = bmi2_get_regs(BMI2_NV_CONF_ADDR, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + data = BMI2_SET_BIT_VAL0(data, BMI2_NV_ACC_OFFSET); + + rslt = bmi2_set_regs(BMI2_NV_CONF_ADDR, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Get the accelerometer configuration details to verify whether it is reverted back to the configured ones */ + rslt = bmi270_context_get_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + } + + bmi2_coines_deinit(); + + return rslt; +} + +static int8_t accel_foc_report(uint8_t range, + int16_t avg_accel_foc_data, + int16_t reference, + uint8_t foc_sign, + int16_t min_val, + int16_t max_val) +{ + int8_t rslt = BMI2_OK; + int16_t diff_after = 0; + + if (foc_sign == 0) + { + if ((avg_accel_foc_data >= (min_val)) && (avg_accel_foc_data <= (max_val))) + { + if (avg_accel_foc_data >= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** PASS | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d in range\n", avg_accel_foc_data); + rslt = BMI2_OK; + } + else + { + if (avg_accel_foc_data >= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** FAIL | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d not in range\n", avg_accel_foc_data); + rslt = BMI2_E_OUT_OF_RANGE; + } + } + + if (foc_sign == 1) + { + if ((avg_accel_foc_data <= (min_val)) && (avg_accel_foc_data >= (max_val))) + { + if (avg_accel_foc_data <= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** PASS | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d in range\n", avg_accel_foc_data); + rslt = BMI2_OK; + } + else + { + if (avg_accel_foc_data <= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** FAIL | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d not in range\n", avg_accel_foc_data); + rslt = BMI2_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +static void calculate_noise(int8_t matched_axis, + struct bmi2_sens_axes_data *accel_foc_data, + struct bmi2_sens_axes_data avg_accel_foc_data) +{ + uint16_t variance = 0; + uint16_t noise_level = 0; + uint16_t index = 0; + + if (matched_axis == 'X') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].x - avg_accel_foc_data.x) * (accel_foc_data[index].x - avg_accel_foc_data.x)); + } + } + else if (matched_axis == 'Y') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].y - avg_accel_foc_data.y) * (accel_foc_data[index].y - avg_accel_foc_data.y)); + } + } + else if (matched_axis == 'Z') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].z - avg_accel_foc_data.z) * (accel_foc_data[index].z - avg_accel_foc_data.z)); + } + } + + noise_level = sqrt(variance); + + printf("\n# ********** NOISE LEVEL = %d **********\n", noise_level); +} + +static int8_t verify_accel_foc_data(uint8_t range, + int16_t reference, + int8_t matched_axis, + uint8_t foc_sign, + struct bmi2_dev *bmi2_dev) +{ + int8_t rslt = BMI2_E_INVALID_STATUS; + uint8_t i; + uint16_t reg_status = 0; + int16_t xl, yl, zl; + int16_t xh, yh, zh; + int16_t min_val = 0; + int16_t max_val = 0; + struct bmi2_sens_axes_data accel_foc_data[ACCEL_SAMPLE_COUNT] = { { 0 } }; + struct temp_axes_val temp_foc_data = { 0 }; + struct bmi2_sens_axes_data avg_accel_foc_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Setting initial values */ + xl = yl = zl = 32767; + xh = yh = zh = -32768; + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read accelerometer values before/after FOC */ + for (i = 0; i < ACCEL_SAMPLE_COUNT; i++) + { + while (1) + { + /* To get the data ready interrupt status */ + rslt = bmi2_get_int_status(®_status, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read accelerometer data based on data ready interrupt */ + if ((rslt == BMI2_OK) && (reg_status & BMI2_ACC_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + memcpy(&accel_foc_data[i], &sensor_data.acc, sizeof(struct bmi2_sens_axes_data)); + + printf("X[%d] = %5d, Y[%d] = %5d, Z[%d] = %5d\n", + i, + accel_foc_data[i].x, + i, + accel_foc_data[i].y, + i, + accel_foc_data[i].z); + + if (xl > accel_foc_data[i].x) + { + xl = accel_foc_data[i].x; + } + + if (xh < accel_foc_data[i].x) + { + xh = accel_foc_data[i].x; + } + + if (yl > accel_foc_data[i].y) + { + yl = accel_foc_data[i].y; + } + + if (yh < accel_foc_data[i].y) + { + yh = accel_foc_data[i].y; + } + + if (zl > accel_foc_data[i].z) + { + zl = accel_foc_data[i].z; + } + + if (zh < accel_foc_data[i].z) + { + zh = accel_foc_data[i].z; + } + + temp_foc_data.x += accel_foc_data[i].x; + temp_foc_data.y += accel_foc_data[i].y; + temp_foc_data.z += accel_foc_data[i].z; + break; + + } + } + } + + /* Taking average values to calculate percentage deviation */ + avg_accel_foc_data.x = (int16_t)(temp_foc_data.x / ACCEL_SAMPLE_COUNT); + avg_accel_foc_data.y = (int16_t)(temp_foc_data.y / ACCEL_SAMPLE_COUNT); + avg_accel_foc_data.z = (int16_t)(temp_foc_data.z / ACCEL_SAMPLE_COUNT); + + printf("********* MIN & MAX VALUES ********\n"); + + printf("XL = %5d YL = %5d ZL = %5d\n", xl, yl, zl); + printf("XH = %5d YH = %5d ZH = %5d\n", xh, yh, zh); + + printf("***** AVERAGE AFTER FOC *****\n"); + printf("Avg-X = %d Avg-Y = %d Avg-Z = %d\n", + avg_accel_foc_data.x, + avg_accel_foc_data.y, + avg_accel_foc_data.z); + + /* Calculate noise level */ + calculate_noise(matched_axis, accel_foc_data, avg_accel_foc_data); + + /* "zero-g offset" of accel is +/- 20 mg for all ranges as per datasheet */ + if (range == 0) + { + /* Min and Max limits for Range 2G */ + min_val = BMI2_ACC_2G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_2G_MAX_NOISE_LIMIT; + } + else if (range == 1) + { + /* Min and Max limits for Range 4G */ + min_val = BMI2_ACC_4G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_4G_MAX_NOISE_LIMIT; + } + else if (range == 2) + { + /* Min and Max limits for Range 8G */ + min_val = BMI2_ACC_8G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_8G_MAX_NOISE_LIMIT; + } + else if (range == 3) + { + /* Min and Max limits for Range 16G */ + min_val = BMI2_ACC_16G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_16G_MAX_NOISE_LIMIT; + } + + if ((matched_axis == 'X') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.x, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.x, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'Y') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.y, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.y, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'Z') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.z, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.z, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'X') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.x, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.x, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + else if ((matched_axis == 'Y') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.y, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.y, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + else if ((matched_axis == 'Z') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.z, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.z, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + + return rslt; +} + +/* Perform FOC for different range and resolutions */ +static int8_t perform_foc_range_test(uint8_t range, uint8_t input_axis, struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + int8_t matched_axis = 0; + int16_t reference = 0; + + /* Set accel foc axis and it's sign (x, y, z, sign)*/ + struct bmi2_accel_foc_g_value g_value_foc = { 0, 0, 0, 0 }; + + if (input_axis == 1) + { + g_value_foc.x = 1; + g_value_foc.y = 0; + g_value_foc.z = 0; + g_value_foc.sign = 0; + } + else if (input_axis == 2) + { + g_value_foc.x = 0; + g_value_foc.y = 1; + g_value_foc.z = 0; + g_value_foc.sign = 0; + } + else if (input_axis == 3) + { + g_value_foc.x = 0; + g_value_foc.y = 0; + g_value_foc.z = 1; + g_value_foc.sign = 0; + } + else if (input_axis == 4) + { + g_value_foc.x = 1; + g_value_foc.y = 0; + g_value_foc.z = 0; + g_value_foc.sign = 1; + } + else if (input_axis == 5) + { + g_value_foc.x = 0; + g_value_foc.y = 1; + g_value_foc.z = 0; + g_value_foc.sign = 1; + } + else if (input_axis == 6) + { + g_value_foc.x = 0; + g_value_foc.y = 0; + g_value_foc.z = 1; + g_value_foc.sign = 1; + } + + switch (range) + { + /* Reference LSB value of 2G */ + case 0: + reference = BMI2_ACC_FOC_2G_REF; + break; + + /* Reference LSB value of 4G */ + case 1: + reference = BMI2_ACC_FOC_4G_REF; + break; + + /* Reference LSB value of 8G */ + case 2: + reference = BMI2_ACC_FOC_8G_REF; + break; + + /* Reference LSB value of 16G */ + case 3: + reference = BMI2_ACC_FOC_16G_REF; + break; + } + + if (g_value_foc.x == 1) + { + matched_axis = 'X'; + } + else if (g_value_foc.y == 1) + { + matched_axis = 'Y'; + } + else if (g_value_foc.z == 1) + { + matched_axis = 'Z'; + } + + if (g_value_foc.sign == 1) + { + printf("MATCHED AXIS is = -%c\n", matched_axis); + } + else + { + printf("MATCHED AXIS is = %c\n", matched_axis); + } + + printf("\n\n# Before FOC\n"); + rslt = verify_accel_foc_data(range, reference, matched_axis, g_value_foc.sign, bmi2_dev); + + printf("\n\n######### Perform Accel FOC #########\n\n"); + + /* Perform accelerometer FOC */ + rslt = bmi2_perform_accel_foc(&g_value_foc, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Provide delay after performing FOC */ + bmi2_dev->delay_us(40000, bmi2_dev->intf_ptr); + + printf("\n\n# After FOC\n"); + rslt = verify_accel_foc_data(range, reference, matched_axis, g_value_foc.sign, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + return rslt; +} diff --git a/examples/bmi270_context/accel_gyro/Makefile b/bmi270_context_examples/accel_gyro/Makefile similarity index 100% rename from examples/bmi270_context/accel_gyro/Makefile rename to bmi270_context_examples/accel_gyro/Makefile diff --git a/examples/bmi270_context/accel_gyro/accel_gyro.c b/bmi270_context_examples/accel_gyro/accel_gyro.c similarity index 83% rename from examples/bmi270_context/accel_gyro/accel_gyro.c rename to bmi270_context_examples/accel_gyro/accel_gyro.c index 7458969..4d0fa85 100644 --- a/examples/bmi270_context/accel_gyro/accel_gyro.c +++ b/bmi270_context_examples/accel_gyro/accel_gyro.c @@ -75,7 +75,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data[2] = { { 0 } }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Initialize the interrupt status of accel and gyro. */ uint16_t int_status = 0; @@ -97,20 +97,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the accel and gyro sensor. */ - rslt = bmi270_context_sensor_enable(sensor_list, 2, &bmi2_dev); + /* Accel and gyro configuration settings. */ + rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Accel and gyro configuration settings. */ - rslt = set_accel_gyro_config(&bmi2_dev); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 2, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Assign accel and gyro sensor. */ - sensor_data[ACCEL].type = BMI2_ACCEL; - sensor_data[GYRO].type = BMI2_GYRO; - /* Loop to print accel and gyro data when interrupt occurs. */ while (indx <= limit) { @@ -122,31 +120,31 @@ int main(void) if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) { /* Get accel and gyro data for x, y and z axis. */ - rslt = bmi270_context_get_sensor_data(sensor_data, 2, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); printf("\n******* Accel(Raw and m/s2) Gyro(Raw and dps) data : %d *******\n", indx); - printf("\nAcc_x = %d\t", sensor_data[ACCEL].sens_data.acc.x); - printf("Acc_y = %d\t", sensor_data[ACCEL].sens_data.acc.y); - printf("Acc_z = %d", sensor_data[ACCEL].sens_data.acc.z); + printf("\nAcc_x = %d\t", sensor_data.acc.x); + printf("Acc_y = %d\t", sensor_data.acc.y); + printf("Acc_z = %d", sensor_data.acc.z); /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.z, 2, bmi2_dev.resolution); + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); /* Print the data in m/s2. */ printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); - printf("\nGyr_X = %d\t", sensor_data[GYRO].sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data[GYRO].sens_data.gyr.y); - printf("Gyr_Z = %d\n", sensor_data[GYRO].sens_data.gyr.z); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z = %d\n", sensor_data.gyr.z); /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.z, 2000, bmi2_dev.resolution); + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); /* Print the data in dps. */ printf("Gyro_DPS_X = %4.2f, Gyro_DPS_Y = %4.2f, Gyro_DPS_Z = %4.2f\n", x, y, z); @@ -264,5 +262,5 @@ static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { float half_scale = ((float)(1 << bit_width) / 2.0f); - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); + return (dps / ((half_scale))) * (val); } diff --git a/examples/bmi270_context/activity_recognition/Makefile b/bmi270_context_examples/activity_recognition/Makefile similarity index 100% rename from examples/bmi270_context/activity_recognition/Makefile rename to bmi270_context_examples/activity_recognition/Makefile diff --git a/examples/bmi270_context/activity_recognition/activity_recognition.c b/bmi270_context_examples/activity_recognition/activity_recognition.c similarity index 58% rename from examples/bmi270_context/activity_recognition/activity_recognition.c rename to bmi270_context_examples/activity_recognition/activity_recognition.c index 9f0714d..0482863 100644 --- a/examples/bmi270_context/activity_recognition/activity_recognition.c +++ b/bmi270_context_examples/activity_recognition/activity_recognition.c @@ -16,11 +16,12 @@ /*! * @brief This internal API is used to set configurations for step counter. * + * @param[in] loop : Iteration count. * @param[in] bmi2_dev : Structure instance of bmi2_dev. * * @return Status of execution. */ -static int8_t set_config(struct bmi2_dev *bmi2_dev); +static int8_t set_config(uint8_t loop, struct bmi2_dev *bmi2_dev); /******************************************************************************/ /*! Functions */ @@ -48,6 +49,9 @@ int main(void) /* Variable to store number of activity frames */ uint16_t act_frames; + /* Variable to store iteration count */ + uint8_t loop = 1; + /* Structure to define a FIFO */ struct bmi2_fifo_frame fifoframe = { 0 }; @@ -60,7 +64,7 @@ int main(void) * For I2C : BMI2_I2C_INTF * For SPI : BMI2_SPI_INTF */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + rslt = bmi2_interface_init(&bmi2_dev, BMI2_SPI_INTF); bmi2_error_codes_print_result(rslt); /* Initialize bmi270_context. */ @@ -69,50 +73,60 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the selected sensor. */ - rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - if (rslt == BMI2_OK) + while (loop <= 5) { - rslt = set_config(&bmi2_dev); + /* Enable the selected sensor. */ + rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Update FIFO structure */ - fifoframe.data = fifo_data; - fifoframe.length = 516; - - rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); - printf("Fifo length = %d \n", fifo_length); - - /* Read FIFO data */ - rslt = bmi2_read_fifo_data(&fifoframe, &bmi2_dev); + rslt = set_config(loop, &bmi2_dev); bmi2_error_codes_print_result(rslt); - while (rslt != BMI2_W_FIFO_EMPTY) + if (rslt == BMI2_OK) { - /* Provide the number of frames to be read */ - act_frames = 5; + /* Update FIFO structure */ + fifoframe.data = fifo_data; + fifoframe.length = 516; - printf("Requested FIFO data frames : %d\n", act_frames); + rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); + printf("Fifo length = %d \n", fifo_length); - /* Get the activity output */ - rslt = bmi270_context_get_act_recog_output(act_recog_data, &act_frames, &fifoframe, &bmi2_dev); + /* Read FIFO data */ + rslt = bmi2_read_fifo_data(&fifoframe, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("Parsed FIFO data frames : %d\r\n", act_frames); - - for (count = 0; count < act_frames; count++) + while (rslt != BMI2_W_FIFO_EMPTY) { - printf( - "Activity Recognition output[%d]:Sensor time: %lu\t Previous activity: %s\t current: %s\n", - count, - act_recog_data[count].time_stamp, - activity_reg_output[act_recog_data[count].prev_act], - activity_reg_output[act_recog_data[count].curr_act]); + /* Provide the number of frames to be read */ + act_frames = 5; + + printf("Requested FIFO data frames : %d\n", act_frames); + + /* Get the activity output */ + rslt = bmi270_context_get_act_recog_output(act_recog_data, &act_frames, &fifoframe, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("Parsed FIFO data frames : %d\r\n", act_frames); + + for (count = 0; count < act_frames; count++) + { + printf( + "Activity Recognition output[%d]:Sensor time: %lu\t Previous activity: %s\t current: %s\n", + count, + (long unsigned int)act_recog_data[count].time_stamp, + activity_reg_output[act_recog_data[count].prev_act], + activity_reg_output[act_recog_data[count].curr_act]); + } + + loop++; } + + /* Enable the selected sensor. */ + rslt = bmi270_context_sensor_disable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + } } } @@ -123,7 +137,7 @@ int main(void) return rslt; } -static int8_t set_config(struct bmi2_dev *bmi2_dev) +static int8_t set_config(uint8_t loop, struct bmi2_dev *bmi2_dev) { /* Status of api are returned to this variable. */ int8_t rslt; @@ -140,6 +154,8 @@ static int8_t set_config(struct bmi2_dev *bmi2_dev) rslt = bmi2_set_command_register(BMI2_FIFO_FLUSH_CMD, bmi2_dev); bmi2_error_codes_print_result(rslt); + printf("\nIteration : %d\n", loop); + printf("Move the board for activity recognition for 30 sec :\n"); bmi2_dev->delay_us(30000000, bmi2_dev->intf_ptr); diff --git a/bmi270_context_examples/aux_fifo_full_header_mode/Makefile b/bmi270_context_examples/aux_fifo_full_header_mode/Makefile new file mode 100644 index 0000000..b63f029 --- /dev/null +++ b/bmi270_context_examples/aux_fifo_full_header_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_full_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c b/bmi270_context_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c new file mode 100644 index 0000000..c81add9 --- /dev/null +++ b/bmi270_context_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c @@ -0,0 +1,462 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_context.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro, 8 Aux and 1 header, + * totaling to 21) which equals to 97. + * + * Extra frames to parse sensortime data + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(120) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(120) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(120) + +/*! Macro to read sensortime byte in FIFO. */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(220) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_context will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_context. */ + rslt = bmi270_context_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", + (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_context_examples/aux_fifo_full_headerless_mode/Makefile b/bmi270_context_examples/aux_fifo_full_headerless_mode/Makefile new file mode 100644 index 0000000..464ed2d --- /dev/null +++ b/bmi270_context_examples/aux_fifo_full_headerless_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_full_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c b/bmi270_context_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c new file mode 100644 index 0000000..34d5a83 --- /dev/null +++ b/bmi270_context_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c @@ -0,0 +1,455 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_context.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro, 8 Aux and 1 header, + * totaling to 21) which equals to 97. + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(97) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(97) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(97) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_context will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_context. */ + rslt = bmi270_context_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in headerless mode\n"); + + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &aux_bmi2_dev); + } + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_context_examples/aux_fifo_watermark_header_mode/Makefile b/bmi270_context_examples/aux_fifo_watermark_header_mode/Makefile new file mode 100644 index 0000000..cd02d6d --- /dev/null +++ b/bmi270_context_examples/aux_fifo_watermark_header_mode/Makefile @@ -0,0 +1,24 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_watermark_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP20 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c b/bmi270_context_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c new file mode 100644 index 0000000..a6d8dcf --- /dev/null +++ b/bmi270_context_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c @@ -0,0 +1,476 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_context.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6, + * aux_frame_len = 8, header_byte = 1. + * fifo_accel_frame_count = (650 / (6 + 6 + 8 + 1 )) = 30 frames + * NOTE: Extra frames are read in order to get sensor time + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(50) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(50) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(50) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*! Macro to read sensortime byte in FIFO */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(250) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_context will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_context. */ + rslt = bmi270_context_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", + (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_context_examples/aux_fifo_watermark_headerless_mode/Makefile b/bmi270_context_examples/aux_fifo_watermark_headerless_mode/Makefile new file mode 100644 index 0000000..271c30b --- /dev/null +++ b/bmi270_context_examples/aux_fifo_watermark_headerless_mode/Makefile @@ -0,0 +1,24 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_watermark_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP20 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c b/bmi270_context_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c new file mode 100644 index 0000000..a7048a4 --- /dev/null +++ b/bmi270_context_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c @@ -0,0 +1,468 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_context.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6, aux_frame_len = 8. + * fifo_accel_frame_count = (650 / (6 + 6 + 8 )) = 32 frames + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(32) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(32) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(32) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_context will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_context. */ + rslt = bmi270_context_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in headerless mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &aux_bmi2_dev); + } + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/examples/bmi270_maximum_fifo/common/common.c b/bmi270_context_examples/common/common.c similarity index 94% rename from examples/bmi270_maximum_fifo/common/common.c rename to bmi270_context_examples/common/common.c index afff37b..0298c30 100644 --- a/examples/bmi270_maximum_fifo/common/common.c +++ b/bmi270_context_examples/common/common.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,7 +8,7 @@ #include #include -#include "coines.h" +#include "common.h" #include "bmi2_defs.h" /******************************************************************************/ @@ -123,7 +123,15 @@ int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) bmi->intf = BMI2_I2C_INTF; bmi->read = bmi2_i2c_read; bmi->write = bmi2_i2c_write; - coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + + /* SDO to Ground */ + coines_set_pin_config(COINES_SHUTTLE_PIN_22, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* Make CSB pin HIGH */ + coines_set_pin_config(COINES_SHUTTLE_PIN_21, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + coines_delay_msec(100); + + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE); } /* Bus configuration : SPI */ else if (intf == BMI2_SPI_INTF) @@ -151,11 +159,11 @@ int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) /* Assign to NULL to load the default config file. */ bmi->config_file_ptr = NULL; - coines_delay_usec(10000); + coines_delay_msec(100); coines_set_shuttleboard_vdd_vddio_config(3300, 3300); - coines_delay_usec(10000); + coines_delay_msec(200); } else { @@ -368,5 +376,14 @@ void bmi2_error_codes_print_result(int8_t rslt) */ void bmi2_coines_deinit(void) { + fflush(stdout); + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Coines interface reset */ + coines_soft_reset(); + coines_delay_msec(100); + coines_close_comm_intf(COINES_COMM_INTF_USB); } diff --git a/examples/bmi270_maximum_fifo/common/common.h b/bmi270_context_examples/common/common.h similarity index 95% rename from examples/bmi270_maximum_fifo/common/common.h rename to bmi270_context_examples/common/common.h index 763983d..c165102 100644 --- a/examples/bmi270_maximum_fifo/common/common.h +++ b/bmi270_context_examples/common/common.h @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -14,6 +14,7 @@ extern "C" { #include #include "bmi2.h" +#include "coines.h" /*! * @brief Function for reading the sensor's registers through I2C bus. @@ -79,7 +80,7 @@ BMI2_INTF_RETURN_TYPE bmi2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the * APIs. * - * @param[in] period_us : The required wait time in microsecond. + * @param[in] period : The required wait time in microsecond. * @param[in] intf_ptr : Interface pointer * * @return void. diff --git a/examples/bmi270_context/component_retrim/Makefile b/bmi270_context_examples/component_retrim/Makefile similarity index 100% rename from examples/bmi270_context/component_retrim/Makefile rename to bmi270_context_examples/component_retrim/Makefile diff --git a/examples/bmi270_context/component_retrim/component_retrim.c b/bmi270_context_examples/component_retrim/component_retrim.c similarity index 100% rename from examples/bmi270_context/component_retrim/component_retrim.c rename to bmi270_context_examples/component_retrim/component_retrim.c diff --git a/examples/bmi270_context/fifo_full_header_mode/Makefile b/bmi270_context_examples/fifo_full_header_mode/Makefile similarity index 94% rename from examples/bmi270_context/fifo_full_header_mode/Makefile rename to bmi270_context_examples/fifo_full_header_mode/Makefile index 2d328d5..6661ce7 100644 --- a/examples/bmi270_context/fifo_full_header_mode/Makefile +++ b/bmi270_context_examples/fifo_full_header_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270_context/fifo_full_header_mode/fifo_full_header_mode.c b/bmi270_context_examples/fifo_full_header_mode/fifo_full_header_mode.c similarity index 90% rename from examples/bmi270_context/fifo_full_header_mode/fifo_full_header_mode.c rename to bmi270_context_examples/fifo_full_header_mode/fifo_full_header_mode.c index 3a5a810..47230e6 100644 --- a/examples/bmi270_context/fifo_full_header_mode/fifo_full_header_mode.c +++ b/bmi270_context_examples/fifo_full_header_mode/fifo_full_header_mode.c @@ -23,14 +23,16 @@ /*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro and 1 header, * totaling to 13) which equals to 157. + * + * Extra frames to parse sensortime data */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(157) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(185) /*! Number of gyro frames to be extracted from FIFO. */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(157) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(185) /*! Macro to read sensortime byte in FIFO. */ -#define SENSORTIME_OVERHEAD_BYTE UINT8_C(3) +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(220) /******************************************************************************/ /*! Static Function Declaration */ @@ -64,12 +66,11 @@ int main(void) uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - int8_t try = 1; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[fifo_buffer_size]; /* Sensor initialization configuration. */ @@ -100,14 +101,16 @@ int main(void) rslt = bmi270_context_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -158,6 +161,9 @@ int main(void) rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -183,18 +189,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len + header_byte)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH + 1)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExtracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -204,11 +200,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { @@ -222,7 +213,7 @@ int main(void) /* Print control frames like sensor time and skipped frame count. */ printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); - printf("Sensor time = %lu\r\n", fifoframe.sensor_time); + printf("Sensor time(in seconds) = %.4lf s\r\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); try++; } @@ -258,7 +249,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) /* NOTE: The user can change the following configuration parameters according to their requirement. */ /* Accel configuration settings. */ /* Set Output Data Rate */ - config[0].cfg.acc.odr = BMI2_ACC_ODR_25HZ; + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; @@ -283,7 +274,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) /* Gyro configuration settings. */ /* Set Output Data Rate */ - config[1].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; diff --git a/examples/bmi270_context/fifo_full_headerless_mode/Makefile b/bmi270_context_examples/fifo_full_headerless_mode/Makefile similarity index 100% rename from examples/bmi270_context/fifo_full_headerless_mode/Makefile rename to bmi270_context_examples/fifo_full_headerless_mode/Makefile diff --git a/examples/bmi270_context/fifo_full_headerless_mode/fifo_full_headerless_mode.c b/bmi270_context_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c similarity index 91% rename from examples/bmi270_context/fifo_full_headerless_mode/fifo_full_headerless_mode.c rename to bmi270_context_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c index bfc1145..49ad919 100644 --- a/examples/bmi270_context/fifo_full_headerless_mode/fifo_full_headerless_mode.c +++ b/bmi270_context_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c @@ -24,10 +24,10 @@ /*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro totaling to * 12) which equals to 170. */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(169) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(170) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(169) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(170) /******************************************************************************/ /*! Static Function Declaration */ @@ -60,10 +60,9 @@ int main(void) uint16_t gyro_frame_length; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; /* Sensor initialization configuration. */ @@ -94,14 +93,16 @@ int main(void) rslt = bmi270_context_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -152,6 +153,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -177,18 +181,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExtracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -198,11 +192,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { diff --git a/examples/bmi270_context/fifo_watermark_header_mode/Makefile b/bmi270_context_examples/fifo_watermark_header_mode/Makefile similarity index 94% rename from examples/bmi270_context/fifo_watermark_header_mode/Makefile rename to bmi270_context_examples/fifo_watermark_header_mode/Makefile index 38c5ce6..dd6df7b 100644 --- a/examples/bmi270_context/fifo_watermark_header_mode/Makefile +++ b/bmi270_context_examples/fifo_watermark_header_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270_context/fifo_watermark_header_mode/fifo_watermark_header_mode.c b/bmi270_context_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c similarity index 87% rename from examples/bmi270_context/fifo_watermark_header_mode/fifo_watermark_header_mode.c rename to bmi270_context_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c index 59ff8f7..d81b3e3 100644 --- a/examples/bmi270_context/fifo_watermark_header_mode/fifo_watermark_header_mode.c +++ b/bmi270_context_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c @@ -14,10 +14,10 @@ /*! Macros */ /*! Buffer size allocated to store raw FIFO data */ -#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) /*! Length of data to be read from FIFO */ -#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) /*! Number of accel frames to be extracted from FIFO */ @@ -27,16 +27,16 @@ * fifo_accel_frame_count = (650 / (6 + 6 + 1 )) = 50 frames * NOTE: Extra frames are read in order to get sensor time */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(70) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(70) /*! Setting a watermark level in FIFO */ -#define BMI270_FIFO_WATERMARK_LEVEL UINT16_C(650) +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) /*! Macro to read sensortime byte in FIFO */ -#define SENSORTIME_OVERHEAD_BYTE UINT8_C(3) +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(250) /******************************************************************************/ /*! Static Function Declaration */ @@ -57,9 +57,6 @@ int main(void) /* Status of api are returned to this variable. */ int8_t rslt; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - /* Variable to index bytes. */ uint16_t index = 0; @@ -74,7 +71,9 @@ int main(void) /* To read sensortime, extra 3 bytes are added to fifo buffer */ uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[fifo_buffer_size]; /* Sensor initialization configuration. */ @@ -110,14 +109,16 @@ int main(void) rslt = bmi270_context_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -150,16 +151,12 @@ int main(void) bmi2_error_codes_print_result(rslt); /* Set water-mark level. */ - fifoframe.wm_lvl = BMI270_FIFO_WATERMARK_LEVEL; + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; /* Set the water-mark level if water-mark interrupt is mapped. */ rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &bmi2_dev); bmi2_error_codes_print_result(rslt); - rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - printf("\nFIFO watermark level is %d\n", watermark); - while (try <= 10) { /* Read FIFO data on interrupt. */ @@ -171,7 +168,9 @@ int main(void) { printf("\nIteration : %d\n", try); - printf("\nWatermark interrupt occurred\n"); + rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level is %d\n", watermark); rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -179,6 +178,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -204,18 +206,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len + header_byte)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH + 1)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -225,11 +217,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { @@ -242,7 +229,7 @@ int main(void) /* Print control frames like sensor time and skipped frame count. */ printf("Skipped frame count = %d\n", fifoframe.skipped_frame_count); - printf("Sensor time = %lu\r\n", fifoframe.sensor_time); + printf("Sensor time(in seconds) = %.4lf s\r\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); try++; } @@ -278,7 +265,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *dev) /* NOTE: The user can change the following configuration parameters according to their requirement. */ /* Accel configuration settings. */ /* Set Output Data Rate */ - config[0].cfg.acc.odr = BMI2_ACC_ODR_25HZ; + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; @@ -303,7 +290,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *dev) /* Gyro configuration settings. */ /* Set Output Data Rate */ - config[1].cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; diff --git a/examples/bmi270_context/fifo_watermark_headerless_mode/Makefile b/bmi270_context_examples/fifo_watermark_headerless_mode/Makefile similarity index 94% rename from examples/bmi270_context/fifo_watermark_headerless_mode/Makefile rename to bmi270_context_examples/fifo_watermark_headerless_mode/Makefile index 9d5e86e..9a865ba 100644 --- a/examples/bmi270_context/fifo_watermark_headerless_mode/Makefile +++ b/bmi270_context_examples/fifo_watermark_headerless_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270_context/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c b/bmi270_context_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c similarity index 89% rename from examples/bmi270_context/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c rename to bmi270_context_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c index 878fe43..bd8f88e 100644 --- a/examples/bmi270_context/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c +++ b/bmi270_context_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c @@ -14,10 +14,10 @@ /*! Macros */ /*! Buffer size allocated to store raw FIFO data */ -#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(800) /*! Length of data to be read from FIFO */ -#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(800) /*! Number of accel frames to be extracted from FIFO */ @@ -26,13 +26,13 @@ * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6. * fifo_accel_frame_count = (650 / (6 + 6 )) = 54 frames */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(54) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(54) /*! Setting a watermark level in FIFO */ -#define BMI270_FIFO_WATERMARK_LEVEL UINT16_C(650) +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) /******************************************************************************/ /*! Static Function Declaration */ @@ -56,9 +56,6 @@ int main(void) /* Variable to index bytes. */ uint16_t index = 0; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - uint16_t fifo_length = 0; uint16_t accel_frame_length; @@ -67,7 +64,9 @@ int main(void) uint8_t try = 1; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; /* Sensor initialization configuration. */ @@ -103,14 +102,16 @@ int main(void) rslt = bmi270_context_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -148,7 +149,7 @@ int main(void) bmi2_error_codes_print_result(rslt); /* Set water-mark level. */ - fifoframe.wm_lvl = BMI270_FIFO_WATERMARK_LEVEL; + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; @@ -156,10 +157,6 @@ int main(void) rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &bmi2_dev); bmi2_error_codes_print_result(rslt); - rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - printf("\nFIFO watermark level is %d\n", watermark); - while (try <= 10) { /* Read FIFO data on interrupt. */ @@ -171,7 +168,9 @@ int main(void) { printf("\nIteration : %d\n", try); - printf("\nWatermark interrupt occurred\n"); + rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level is %d\n", watermark); rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -179,6 +178,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -204,18 +206,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -225,11 +217,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { diff --git a/examples/bmi270_context/gyro/Makefile b/bmi270_context_examples/gyro/Makefile similarity index 100% rename from examples/bmi270_context/gyro/Makefile rename to bmi270_context_examples/gyro/Makefile diff --git a/examples/bmi270_context/gyro/gyro.c b/bmi270_context_examples/gyro/gyro.c similarity index 85% rename from examples/bmi270_context/gyro/gyro.c rename to bmi270_context_examples/gyro/gyro.c index 0a057e4..117970c 100644 --- a/examples/bmi270_context/gyro/gyro.c +++ b/bmi270_context_examples/gyro/gyro.c @@ -54,7 +54,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Assign gyro sensor to variable. */ uint8_t sens_list = BMI2_GYRO; @@ -75,18 +75,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the selected sensors. */ - rslt = bmi270_context_sensor_enable(&sens_list, 1, &bmi2_dev); + /* Gyro configuration settings. */ + rslt = set_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Gyro configuration settings. */ - rslt = set_gyro_config(&bmi2_dev); + /* NOTE: + * Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(&sens_list, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Select gyro sensor. */ - sensor_data.type = BMI2_GYRO; printf("Gyro and DPS data\n"); printf("Gyro data collected at Range 2000 dps with 16-bit resolution\n"); @@ -101,17 +101,17 @@ int main(void) if (int_status & BMI2_GYR_DRDY_INT_MASK) { /* Get gyro data for x, y and z axis. */ - rslt = bmi270_context_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("\nGyr_X = %d\t", sensor_data.sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data.sens_data.gyr.y); - printf("Gyr_Z = %d\r\n", sensor_data.sens_data.gyr.z); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z = %d\r\n", sensor_data.gyr.z); /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data.sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data.sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data.sens_data.gyr.z, 2000, bmi2_dev.resolution); + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); /* Print the data in dps. */ printf("Gyr_DPS_X = %4.2f, Gyr_DPS_Y = %4.2f, Gyr_DPS_Z = %4.2f\n", x, y, z); @@ -191,5 +191,5 @@ static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { float half_scale = ((float)(1 << bit_width) / 2.0f); - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); + return (dps / ((half_scale))) * (val); } diff --git a/bmi270_context_examples/gyro_foc/Makefile b/bmi270_context_examples/gyro_foc/Makefile new file mode 100644 index 0000000..3794cf3 --- /dev/null +++ b/bmi270_context_examples/gyro_foc/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= gyro_foc.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/gyro_foc/gyro_foc.c b/bmi270_context_examples/gyro_foc/gyro_foc.c new file mode 100644 index 0000000..9e6d5aa --- /dev/null +++ b/bmi270_context_examples/gyro_foc/gyro_foc.c @@ -0,0 +1,307 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include +#include +#include + +#include "bmi270_context.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macro Definitions */ + +#define GYRO_SAMPLE_COUNT UINT8_C(100) + +/******************************************************************************/ +/*! Global Variable Declaration */ + +/* Structure to store temporary axes data values */ +struct temp_axes_val +{ + /* X data */ + int32_t x; + + /* Y data */ + int32_t y; + + /* Z data */ + int32_t z; +}; + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is to perform gyro FOC + * + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t perform_gyro_foc_test(struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to determind if gyro FOC data is within defined limits + * + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t verify_gyro_foc_data(struct bmi2_dev *bmi2_dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + uint8_t try = 0, j = 0; + int8_t rslt; + uint8_t sens_list = BMI2_GYRO; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + printf("Functional test for gyro foc start..\n"); + + /* Perform FOC for different ranges */ + for (j = 0; j < 2; j++) + { + rslt = 0; + try = 0; + + if (j == 0) + { + printf("Shake the sensor and press 5\n"); + } + else if (j > 0) + { + printf("Keep sensor stable in right position and press 5\n"); + } + + while (1) + { + scanf("%hu", (short unsigned int *)&try); + if (try == 5) + { + break; + } + } + + /* Initialize the sensor */ + rslt = bmi270_context_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Enable gyroscope */ + rslt = bmi270_context_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + rslt = perform_gyro_foc_test(&dev); + + if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - sensor is shaking #########\n\n"); + if (rslt != BMI2_E_OUT_OF_RANGE) + { + printf("rslt != BMI2_E_OUT_OF_RANGE\n"); + break; + } + } + else if ((j > 0) && (rslt == BMI2_OK)) + { + printf("\n######### Valid input - Sensor is not shaking #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_OK)) + { + printf("\n######### Invalid input - sensor is not shaking #########\n\n"); + if (rslt == BMI2_OK) + { + printf("rslt == BMI2_OK\n"); + break; + } + } + else if ((j > 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Sensor is shaking #########\n\n"); + if (rslt == BMI2_E_OUT_OF_RANGE) + { + printf("rslt == BMI2_E_OUT_OF_RANGE\n"); + break; + } + } + else if (rslt == BMI2_E_OUT_OF_RANGE) + { + bmi2_error_codes_print_result(rslt); + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +static int8_t verify_gyro_foc_data(struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + struct bmi2_sens_axes_data gyr_foc_data[GYRO_SAMPLE_COUNT] = { { 0 } }; + struct temp_axes_val temp_foc_data = { 0 }; + struct bmi2_sens_axes_data avg_foc_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; + uint16_t drdy_status = 0; + uint8_t i; + + /* Read gyroscope values before/after FOC */ + for (i = 0; i < GYRO_SAMPLE_COUNT; i++) + { + while (1) + { + /* To get the data ready interrupt status of gyro. */ + rslt = bmi2_get_int_status(&drdy_status, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read gyroscope data based on data ready interrupt */ + if ((rslt == BMI2_OK) && (drdy_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + memcpy(&gyr_foc_data[i], &sensor_data.gyr, sizeof(struct bmi2_sens_axes_data)); + + printf("X[%d] = %5d, Y[%d] = %5d, Z[%d] = %5d\n", + i, + gyr_foc_data[i].x, + i, + gyr_foc_data[i].y, + i, + gyr_foc_data[i].z); + + temp_foc_data.x += gyr_foc_data[i].x; + temp_foc_data.y += gyr_foc_data[i].y; + temp_foc_data.z += gyr_foc_data[i].z; + break; + } + } + } + + /* Taking average values to calculate percentage deviation */ + avg_foc_data.x = (int16_t)(temp_foc_data.x / GYRO_SAMPLE_COUNT); + avg_foc_data.y = (int16_t)(temp_foc_data.y / GYRO_SAMPLE_COUNT); + avg_foc_data.z = (int16_t)(temp_foc_data.z / GYRO_SAMPLE_COUNT); + + printf("# Average GYRO Axes FOC\n"); + + printf("\n# Avg_X = %5d \t Avg_Y = %5d \t Avg_Z = %5d\n", avg_foc_data.x, avg_foc_data.y, avg_foc_data.z); + + /* The measurement result should be 0 +/- 1dps */ + if (((avg_foc_data.x >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.x <= BMI2_GYRO_FOC_2000_DPS_REF)) && + ((avg_foc_data.y >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.y <= (BMI2_GYRO_FOC_2000_DPS_REF))) && + ((avg_foc_data.z >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.z <= BMI2_GYRO_FOC_2000_DPS_REF))) + { + printf("\n### Gyro Axes data within range ###\n"); + rslt = BMI2_OK; + } + else + { + printf("\n### Gyro Axes data out of range ###\n"); + rslt = BMI2_E_OUT_OF_RANGE; + } + + return rslt; +} + +/* Perform FOC for different ranges*/ +static int8_t perform_gyro_foc_test(struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + struct bmi2_sens_config config = { 0 }; + + uint8_t sens_list = BMI2_GYRO; + + /* Initialize the sensor */ + rslt = bmi270_context_init(bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_GYRO; + + rslt = bmi270_context_get_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set Output Data Rate to 25Hz */ + config.cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config.cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Set Gyroscope bandwidth to CIC mode */ + config.cfg.gyr.bwp = BMI2_GYR_CIC_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config.cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config.cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the gyro configurations. */ + rslt = bmi270_context_set_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(&sens_list, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("# BWP : %d ODR : %d Range : %d\n", config.cfg.gyr.bwp, config.cfg.gyr.odr, config.cfg.gyr.range); + + printf("\n# Before GYRO FOC\n"); + + rslt = verify_gyro_foc_data(bmi2_dev); + + printf("\n\n########## Perform GYRO FOC ##########\n\n"); + + /* Perform gyroscope FOC */ + rslt = bmi2_perform_gyro_foc(bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Provide delay after performing FOC */ + bmi2_dev->delay_us(40000, bmi2_dev->intf_ptr); + + if (rslt == BMI2_OK) + { + printf("\n# After GYRO FOC\n"); + + rslt = verify_gyro_foc_data(bmi2_dev); + } + + return rslt; +} diff --git a/bmi270_context_examples/read_aux_data_mode/Makefile b/bmi270_context_examples/read_aux_data_mode/Makefile new file mode 100644 index 0000000..27b8040 --- /dev/null +++ b/bmi270_context_examples/read_aux_data_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_aux_data_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/read_aux_data_mode/read_aux_data_mode.c b/bmi270_context_examples/read_aux_data_mode/read_aux_data_mode.c new file mode 100644 index 0000000..6a3572a --- /dev/null +++ b/bmi270_context_examples/read_aux_data_mode/read_aux_data_mode.c @@ -0,0 +1,409 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_context.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_context. */ + rslt = bmi270_context_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL, AND GYRO DATA IN DATA MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK) && + (int_status & BMI2_AUX_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(sensor_data.aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in data mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in data mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_context_examples/read_aux_manual_mode/Makefile b/bmi270_context_examples/read_aux_manual_mode/Makefile new file mode 100644 index 0000000..e9b4145 --- /dev/null +++ b/bmi270_context_examples/read_aux_manual_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_aux_manual_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_context.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_context_examples/read_aux_manual_mode/read_aux_manual_mode.c b/bmi270_context_examples/read_aux_manual_mode/read_aux_manual_mode.c new file mode 100644 index 0000000..470e6b6 --- /dev/null +++ b/bmi270_context_examples/read_aux_manual_mode/read_aux_manual_mode.c @@ -0,0 +1,408 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_context.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* Array of eight bytes to store x, y, z and r axis aux data. */ + uint8_t aux_data[8] = { 0 }; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_context. */ + rslt = bmi270_context_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim register */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_context_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.manual_en = BMI2_ENABLE; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_context_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_context_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL AND GYRO DATA IN MANUAL MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + } + + /* Read aux data from the bmm150 data registers. */ + rslt = bmi2_read_aux_man_mode(BMM150_REG_DATA_X_LSB, aux_data, 8, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/examples/bmi270_context/step_counter/Makefile b/bmi270_context_examples/step_counter/Makefile similarity index 100% rename from examples/bmi270_context/step_counter/Makefile rename to bmi270_context_examples/step_counter/Makefile diff --git a/examples/bmi270_context/step_counter/step_counter.c b/bmi270_context_examples/step_counter/step_counter.c similarity index 94% rename from examples/bmi270_context/step_counter/step_counter.c rename to bmi270_context_examples/step_counter/step_counter.c index 2513b02..f265503 100644 --- a/examples/bmi270_context/step_counter/step_counter.c +++ b/bmi270_context_examples/step_counter/step_counter.c @@ -32,7 +32,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Structure to define type of sensor and their respective data. */ - struct bmi2_sensor_data sensor_data; + struct bmi2_feat_sensor_data sensor_data; /* Status of api are returned to this variable. */ int8_t rslt; @@ -96,11 +96,13 @@ int main(void) printf("Step counter interrupt occurred when watermark level (20 steps) is reached\n"); /* Get step counter output. */ - rslt = bmi270_context_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi270_context_get_feature_data(&sensor_data, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); /* Print the step counter output. */ - printf("No of steps counted = %ld", sensor_data.sens_data.step_counter_output); + printf("No of steps counted = %lu", + (long unsigned int)sensor_data.sens_data.step_counter_output); + break; } } while (rslt == BMI2_OK); diff --git a/examples/bmi270/accel/Makefile b/bmi270_examples/accel/Makefile similarity index 100% rename from examples/bmi270/accel/Makefile rename to bmi270_examples/accel/Makefile diff --git a/examples/bmi270/accel/accel.c b/bmi270_examples/accel/accel.c similarity index 86% rename from examples/bmi270/accel/accel.c rename to bmi270_examples/accel/accel.c index ea385d7..055000c 100644 --- a/examples/bmi270/accel/accel.c +++ b/bmi270_examples/accel/accel.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -59,7 +59,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Initialize the interrupt status of accel. */ uint16_t int_status = 0; @@ -80,18 +80,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the accel sensor. */ - rslt = bmi270_sensor_enable(&sensor_list, 1, &bmi2_dev); + /* Accel configuration settings. */ + rslt = set_accel_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Accel configuration settings. */ - rslt = set_accel_config(&bmi2_dev); + /* NOTE: + * Accel enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(&sensor_list, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Assign accel sensor. */ - sensor_data.type = BMI2_ACCEL; printf("Accel and m/s2 data \n"); printf("Accel data collected at 2G Range with 16-bit resolution\n"); @@ -106,16 +106,16 @@ int main(void) if (int_status & BMI2_ACC_DRDY_INT_MASK) { /* Get accelerometer data for x, y and z axis. */ - rslt = bmi270_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("\nAcc_X = %d\t", sensor_data.sens_data.acc.x); - printf("Acc_Y = %d\t", sensor_data.sens_data.acc.y); - printf("Acc_Z = %d\r\n", sensor_data.sens_data.acc.z); + printf("\nAcc_X = %d\t", sensor_data.acc.x); + printf("Acc_Y = %d\t", sensor_data.acc.y); + printf("Acc_Z = %d\r\n", sensor_data.acc.z); /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data.sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data.sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data.sens_data.acc.z, 2, bmi2_dev.resolution); + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); /* Print the data in m/s2. */ printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); diff --git a/bmi270_examples/accel_foc/Makefile b/bmi270_examples/accel_foc/Makefile new file mode 100644 index 0000000..72a50b9 --- /dev/null +++ b/bmi270_examples/accel_foc/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accel_foc.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/accel_foc/accel_foc.c b/bmi270_examples/accel_foc/accel_foc.c new file mode 100644 index 0000000..101be34 --- /dev/null +++ b/bmi270_examples/accel_foc/accel_foc.c @@ -0,0 +1,729 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include +#include +#include +#include + +#include "bmi270.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macro Definitions */ + +#define ACCEL_SAMPLE_COUNT UINT8_C(100) + +/******************************************************************************/ +/*! Global Variable Declaration */ + +/* Structure to store temporary axes data values */ +struct temp_axes_val +{ + /* X data */ + int32_t x; + + /* Y data */ + int32_t y; + + /* Z data */ + int32_t z; +}; + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used perform accel foc and determine limits based on range + * + * @param[in] range : Range of Accel + * @param[in] input_axis : Axis selected for Accel FOC + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t perform_foc_range_test(uint8_t range, uint8_t input_axis, struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to determine if average accel FOC data is within limits + * + * @param[in] range : Value of Accel range + * @param[in] avg_accel_foc_data : Average Accel FOC value + * @param[in] reference : Reference LSB based on Accel Range + * @param[in] foc_sign : Input sign of performed Accel FOC + * @param[in] min_val : Minimum acceptable LSB limit + * @param[in] max_val : Maximum acceptable LSB limit + * + * @return Status of execution. + */ +static int8_t accel_foc_report(uint8_t range, + int16_t avg_accel_foc_data, + int16_t reference, + uint8_t foc_sign, + int16_t min_val, + int16_t max_val); + +/*! + * @brief This internal API is to collect and verify accel sensor data + * + * @param[in] range : Value of Accel range + * @param[in] reference : Reference LSB based on Accel Range + * @param[in] matched_axis : Input Axis to perform Accel FOC + * @param[in] foc_sign : Input sign to perform Accel FOC + * @param[in,out] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t verify_accel_foc_data(uint8_t range, + int16_t reference, + int8_t matched_axis, + uint8_t foc_sign, + struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to calculate noise level for Accel FOC data + * + * @param[in] matched_axis : Input Axis to perform accel FOC + * @param[in] accel_foc_data : Array of Accel FOC data + * @param[in] avg_accel_foc_data : Average Accel FOC data + * + * @return Status of execution. + */ +static void calculate_noise(int8_t matched_axis, + struct bmi2_sens_axes_data *accel_foc_data, + struct bmi2_sens_axes_data avg_accel_foc_data); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + uint8_t try = 0, j = 0; + int8_t rslt; + uint8_t sens_list = BMI2_ACCEL; + struct bmi2_sens_config sens_cfg = { 0 }; + uint8_t data = 0, range, input_axis = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + printf("Functional test for accel foc start..\n\n"); + + printf("Choose the axis for accel FOC to be done\n"); + printf("Press '1' to choose X axis\n"); + printf("Press '2' to choose Y axis\n"); + printf("Press '3' to choose Z axis\n"); + + printf("Press '4' to choose -X axis\n"); + printf("Press '5' to choose -Y axis\n"); + printf("Press '6' to choose -Z axis\n"); + + while (1) + { + scanf("%hu", (short unsigned int *)&input_axis); + if (input_axis > 0 && input_axis < 7) + { + break; + } + } + + if (input_axis == 1) + { + printf("The choosen input axis for FOC is : X\n"); + } + else if (input_axis == 2) + { + printf("The choosen input axis for FOC is : Y\n"); + } + else if (input_axis == 3) + { + printf("The choosen input axis for FOC is : Z\n"); + } + else if (input_axis == 4) + { + printf("The choosen input axis for FOC is : -X\n"); + } + else if (input_axis == 5) + { + printf("The choosen input axis for FOC is : -Y\n"); + } + else if (input_axis == 6) + { + printf("The choosen input axis for FOC is : -Z\n"); + } + + printf("Confirm your chosen axis and the sensor keeping position are same before doing FOC\n"); + + for (j = 0; j < 2; j++) + { + try = 0; + + if (j == 1) + { + printf("Keep sensor in wrong position and press 5\n"); + } + else if (j == 0) + { + printf("Keep sensor in right position and press 5\n"); + } + + while (1) + { + scanf("%hu", (short unsigned int *)&try); + if (try == 5) + { + break; + } + } + + for (range = BMI2_ACC_RANGE_2G; range <= BMI2_ACC_RANGE_16G; range++) + { + /****************************************************************/ + /* Initialize by enabling configuration load */ + printf("#########################################################\n\n"); + + rslt = bmi270_init(&dev); + bmi2_error_codes_print_result(rslt); + + sens_cfg.type = BMI2_ACCEL; + + /* Testing with different settings other than the default configurations + * Default is : 50Hz ODR and 2g RANGE + * Note - Change accel_conf.range for testing in different range values + */ + sens_cfg.cfg.acc.odr = BMI2_ACC_ODR_50HZ; + sens_cfg.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /****************************************************************/ + sens_cfg.cfg.acc.range = range; + + /* Set the configuration details */ + rslt = bmi270_set_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Get the configuration details to verify whether the configured values are set */ + rslt = bmi270_get_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("ODR = %d, RANGE = %d, BANDWIDTH = %d\n", + sens_cfg.cfg.acc.odr, + sens_cfg.cfg.acc.range, + sens_cfg.cfg.acc.bwp); + + /* Perform FOC for different ranges */ + rslt = perform_foc_range_test(range, input_axis, &dev); + + if ((j == 1) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - Wrong position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_OK)) + { + printf("\n######### Valid input - Right position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 1) && (rslt == BMI2_OK)) + { + printf("\n######### Invalid input - Right position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Wrong position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - Right position #########\n\n"); + printf("\n######### Before FOC is better than after FOC #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 1) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Right position #########\n\n"); + printf("\n######### Before FOC is better than after FOC #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + } + + /* Disable offset compensation */ + rslt = bmi2_get_regs(BMI2_NV_CONF_ADDR, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + data = BMI2_SET_BIT_VAL0(data, BMI2_NV_ACC_OFFSET); + + rslt = bmi2_set_regs(BMI2_NV_CONF_ADDR, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Get the accelerometer configuration details to verify whether it is reverted back to the configured ones */ + rslt = bmi270_get_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + } + + bmi2_coines_deinit(); + + return rslt; +} + +static int8_t accel_foc_report(uint8_t range, + int16_t avg_accel_foc_data, + int16_t reference, + uint8_t foc_sign, + int16_t min_val, + int16_t max_val) +{ + int8_t rslt = BMI2_OK; + int16_t diff_after = 0; + + if (foc_sign == 0) + { + if ((avg_accel_foc_data >= (min_val)) && (avg_accel_foc_data <= (max_val))) + { + if (avg_accel_foc_data >= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** PASS | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d in range\n", avg_accel_foc_data); + rslt = BMI2_OK; + } + else + { + if (avg_accel_foc_data >= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** FAIL | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d not in range\n", avg_accel_foc_data); + rslt = BMI2_E_OUT_OF_RANGE; + } + } + + if (foc_sign == 1) + { + if ((avg_accel_foc_data <= (min_val)) && (avg_accel_foc_data >= (max_val))) + { + if (avg_accel_foc_data <= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** PASS | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d in range\n", avg_accel_foc_data); + rslt = BMI2_OK; + } + else + { + if (avg_accel_foc_data <= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** FAIL | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d not in range\n", avg_accel_foc_data); + rslt = BMI2_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +static void calculate_noise(int8_t matched_axis, + struct bmi2_sens_axes_data *accel_foc_data, + struct bmi2_sens_axes_data avg_accel_foc_data) +{ + uint16_t variance = 0; + uint16_t noise_level = 0; + uint16_t index = 0; + + if (matched_axis == 'X') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].x - avg_accel_foc_data.x) * (accel_foc_data[index].x - avg_accel_foc_data.x)); + } + } + else if (matched_axis == 'Y') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].y - avg_accel_foc_data.y) * (accel_foc_data[index].y - avg_accel_foc_data.y)); + } + } + else if (matched_axis == 'Z') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].z - avg_accel_foc_data.z) * (accel_foc_data[index].z - avg_accel_foc_data.z)); + } + } + + noise_level = sqrt(variance); + + printf("\n# ********** NOISE LEVEL = %d **********\n", noise_level); +} + +static int8_t verify_accel_foc_data(uint8_t range, + int16_t reference, + int8_t matched_axis, + uint8_t foc_sign, + struct bmi2_dev *bmi2_dev) +{ + int8_t rslt = BMI2_E_INVALID_STATUS; + uint8_t i; + uint16_t reg_status = 0; + int16_t xl, yl, zl; + int16_t xh, yh, zh; + int16_t min_val = 0; + int16_t max_val = 0; + struct bmi2_sens_axes_data accel_foc_data[ACCEL_SAMPLE_COUNT] = { { 0 } }; + struct temp_axes_val temp_foc_data = { 0 }; + struct bmi2_sens_axes_data avg_accel_foc_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Setting initial values */ + xl = yl = zl = 32767; + xh = yh = zh = -32768; + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read accelerometer values before/after FOC */ + for (i = 0; i < ACCEL_SAMPLE_COUNT; i++) + { + while (1) + { + /* To get the data ready interrupt status */ + rslt = bmi2_get_int_status(®_status, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read accelerometer data based on data ready interrupt */ + if ((rslt == BMI2_OK) && (reg_status & BMI2_ACC_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + memcpy(&accel_foc_data[i], &sensor_data.acc, sizeof(struct bmi2_sens_axes_data)); + + printf("X[%d] = %5d, Y[%d] = %5d, Z[%d] = %5d\n", + i, + accel_foc_data[i].x, + i, + accel_foc_data[i].y, + i, + accel_foc_data[i].z); + + if (xl > accel_foc_data[i].x) + { + xl = accel_foc_data[i].x; + } + + if (xh < accel_foc_data[i].x) + { + xh = accel_foc_data[i].x; + } + + if (yl > accel_foc_data[i].y) + { + yl = accel_foc_data[i].y; + } + + if (yh < accel_foc_data[i].y) + { + yh = accel_foc_data[i].y; + } + + if (zl > accel_foc_data[i].z) + { + zl = accel_foc_data[i].z; + } + + if (zh < accel_foc_data[i].z) + { + zh = accel_foc_data[i].z; + } + + temp_foc_data.x += accel_foc_data[i].x; + temp_foc_data.y += accel_foc_data[i].y; + temp_foc_data.z += accel_foc_data[i].z; + break; + + } + } + } + + /* Taking average values to calculate percentage deviation */ + avg_accel_foc_data.x = (int16_t)(temp_foc_data.x / ACCEL_SAMPLE_COUNT); + avg_accel_foc_data.y = (int16_t)(temp_foc_data.y / ACCEL_SAMPLE_COUNT); + avg_accel_foc_data.z = (int16_t)(temp_foc_data.z / ACCEL_SAMPLE_COUNT); + + printf("********* MIN & MAX VALUES ********\n"); + + printf("XL = %5d YL = %5d ZL = %5d\n", xl, yl, zl); + printf("XH = %5d YH = %5d ZH = %5d\n", xh, yh, zh); + + printf("***** AVERAGE AFTER FOC *****\n"); + printf("Avg-X = %d Avg-Y = %d Avg-Z = %d\n", + avg_accel_foc_data.x, + avg_accel_foc_data.y, + avg_accel_foc_data.z); + + /* Calculate noise level */ + calculate_noise(matched_axis, accel_foc_data, avg_accel_foc_data); + + /* "zero-g offset" of accel is +/- 20 mg for all ranges as per datasheet */ + if (range == 0) + { + /* Min and Max limits for Range 2G */ + min_val = BMI2_ACC_2G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_2G_MAX_NOISE_LIMIT; + } + else if (range == 1) + { + /* Min and Max limits for Range 4G */ + min_val = BMI2_ACC_4G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_4G_MAX_NOISE_LIMIT; + } + else if (range == 2) + { + /* Min and Max limits for Range 8G */ + min_val = BMI2_ACC_8G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_8G_MAX_NOISE_LIMIT; + } + else if (range == 3) + { + /* Min and Max limits for Range 16G */ + min_val = BMI2_ACC_16G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_16G_MAX_NOISE_LIMIT; + } + + if ((matched_axis == 'X') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.x, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.x, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'Y') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.y, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.y, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'Z') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.z, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.z, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'X') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.x, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.x, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + else if ((matched_axis == 'Y') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.y, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.y, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + else if ((matched_axis == 'Z') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.z, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.z, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + + return rslt; +} + +/* Perform FOC for different range and resolutions */ +static int8_t perform_foc_range_test(uint8_t range, uint8_t input_axis, struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + int8_t matched_axis = 0; + int16_t reference = 0; + + /* Set accel foc axis and it's sign (x, y, z, sign)*/ + struct bmi2_accel_foc_g_value g_value_foc = { 0, 0, 0, 0 }; + + if (input_axis == 1) + { + g_value_foc.x = 1; + g_value_foc.y = 0; + g_value_foc.z = 0; + g_value_foc.sign = 0; + } + else if (input_axis == 2) + { + g_value_foc.x = 0; + g_value_foc.y = 1; + g_value_foc.z = 0; + g_value_foc.sign = 0; + } + else if (input_axis == 3) + { + g_value_foc.x = 0; + g_value_foc.y = 0; + g_value_foc.z = 1; + g_value_foc.sign = 0; + } + else if (input_axis == 4) + { + g_value_foc.x = 1; + g_value_foc.y = 0; + g_value_foc.z = 0; + g_value_foc.sign = 1; + } + else if (input_axis == 5) + { + g_value_foc.x = 0; + g_value_foc.y = 1; + g_value_foc.z = 0; + g_value_foc.sign = 1; + } + else if (input_axis == 6) + { + g_value_foc.x = 0; + g_value_foc.y = 0; + g_value_foc.z = 1; + g_value_foc.sign = 1; + } + + switch (range) + { + /* Reference LSB value of 2G */ + case 0: + reference = BMI2_ACC_FOC_2G_REF; + break; + + /* Reference LSB value of 4G */ + case 1: + reference = BMI2_ACC_FOC_4G_REF; + break; + + /* Reference LSB value of 8G */ + case 2: + reference = BMI2_ACC_FOC_8G_REF; + break; + + /* Reference LSB value of 16G */ + case 3: + reference = BMI2_ACC_FOC_16G_REF; + break; + } + + if (g_value_foc.x == 1) + { + matched_axis = 'X'; + } + else if (g_value_foc.y == 1) + { + matched_axis = 'Y'; + } + else if (g_value_foc.z == 1) + { + matched_axis = 'Z'; + } + + if (g_value_foc.sign == 1) + { + printf("MATCHED AXIS is = -%c\n", matched_axis); + } + else + { + printf("MATCHED AXIS is = %c\n", matched_axis); + } + + printf("\n\n# Before FOC\n"); + rslt = verify_accel_foc_data(range, reference, matched_axis, g_value_foc.sign, bmi2_dev); + + printf("\n\n######### Perform Accel FOC #########\n\n"); + + /* Perform accelerometer FOC */ + rslt = bmi2_perform_accel_foc(&g_value_foc, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Provide delay after performing FOC */ + bmi2_dev->delay_us(40000, bmi2_dev->intf_ptr); + + printf("\n\n# After FOC\n"); + rslt = verify_accel_foc_data(range, reference, matched_axis, g_value_foc.sign, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + return rslt; +} diff --git a/examples/bmi270/accel_gyro/Makefile b/bmi270_examples/accel_gyro/Makefile similarity index 100% rename from examples/bmi270/accel_gyro/Makefile rename to bmi270_examples/accel_gyro/Makefile diff --git a/examples/bmi270/accel_gyro/accel_gyro.c b/bmi270_examples/accel_gyro/accel_gyro.c similarity index 82% rename from examples/bmi270/accel_gyro/accel_gyro.c rename to bmi270_examples/accel_gyro/accel_gyro.c index 1e7c9df..014886d 100644 --- a/examples/bmi270/accel_gyro/accel_gyro.c +++ b/bmi270_examples/accel_gyro/accel_gyro.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -75,7 +75,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data[2] = { { 0 } }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Initialize the interrupt status of accel and gyro. */ uint16_t int_status = 0; @@ -88,7 +88,7 @@ int main(void) * For I2C : BMI2_I2C_INTF * For SPI : BMI2_SPI_INTF */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_SPI_INTF); + rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); bmi2_error_codes_print_result(rslt); /* Initialize bmi270. */ @@ -97,20 +97,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the accel and gyro sensor. */ - rslt = bmi270_sensor_enable(sensor_list, 2, &bmi2_dev); + /* Accel and gyro configuration settings. */ + rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Accel and gyro configuration settings. */ - rslt = set_accel_gyro_config(&bmi2_dev); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 2, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Assign accel and gyro sensor. */ - sensor_data[ACCEL].type = BMI2_ACCEL; - sensor_data[GYRO].type = BMI2_GYRO; - /* Loop to print accel and gyro data when interrupt occurs. */ while (indx <= limit) { @@ -122,31 +120,31 @@ int main(void) if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) { /* Get accel and gyro data for x, y and z axis. */ - rslt = bmi270_get_sensor_data(sensor_data, 2, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); printf("\n******* Accel(Raw and m/s2) Gyro(Raw and dps) data : %d *******\n", indx); - printf("\nAcc_x = %d\t", sensor_data[ACCEL].sens_data.acc.x); - printf("Acc_y = %d\t", sensor_data[ACCEL].sens_data.acc.y); - printf("Acc_z = %d", sensor_data[ACCEL].sens_data.acc.z); + printf("\nAcc_x = %d\t", sensor_data.acc.x); + printf("Acc_y = %d\t", sensor_data.acc.y); + printf("Acc_z = %d", sensor_data.acc.z); /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.z, 2, bmi2_dev.resolution); + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); /* Print the data in m/s2. */ printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); - printf("\nGyr_X = %d\t", sensor_data[GYRO].sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data[GYRO].sens_data.gyr.y); - printf("Gyr_Z= %d\n", sensor_data[GYRO].sens_data.gyr.z); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z= %d\n", sensor_data.gyr.z); /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.z, 2000, bmi2_dev.resolution); + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); /* Print the data in dps. */ printf("Gyro_DPS_X = %4.2f, Gyro_DPS_Y = %4.2f, Gyro_DPS_Z = %4.2f\n", x, y, z); @@ -264,5 +262,5 @@ static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { float half_scale = ((float)(1 << bit_width) / 2.0f); - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); + return (dps / ((half_scale))) * (val); } diff --git a/examples/bmi270/any_motion_interrupt/Makefile b/bmi270_examples/any_motion_interrupt/Makefile similarity index 100% rename from examples/bmi270/any_motion_interrupt/Makefile rename to bmi270_examples/any_motion_interrupt/Makefile diff --git a/examples/bmi270/any_motion_interrupt/any_motion_interrupt.c b/bmi270_examples/any_motion_interrupt/any_motion_interrupt.c similarity index 98% rename from examples/bmi270/any_motion_interrupt/any_motion_interrupt.c rename to bmi270_examples/any_motion_interrupt/any_motion_interrupt.c index 062b29e..3f9fe59 100644 --- a/examples/bmi270/any_motion_interrupt/any_motion_interrupt.c +++ b/bmi270_examples/any_motion_interrupt/any_motion_interrupt.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ diff --git a/bmi270_examples/aux_fifo_full_header_mode/Makefile b/bmi270_examples/aux_fifo_full_header_mode/Makefile new file mode 100644 index 0000000..45fbd4e --- /dev/null +++ b/bmi270_examples/aux_fifo_full_header_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_full_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c b/bmi270_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c new file mode 100644 index 0000000..9650bf5 --- /dev/null +++ b/bmi270_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c @@ -0,0 +1,462 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro, 8 Aux and 1 header, + * totaling to 21) which equals to 97. + * + * Extra frames to parse sensortime data + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(120) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(120) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(120) + +/*! Macro to read sensortime byte in FIFO. */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(220) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", + (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_examples/aux_fifo_full_headerless_mode/Makefile b/bmi270_examples/aux_fifo_full_headerless_mode/Makefile new file mode 100644 index 0000000..e873f27 --- /dev/null +++ b/bmi270_examples/aux_fifo_full_headerless_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_full_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c b/bmi270_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c new file mode 100644 index 0000000..01a2296 --- /dev/null +++ b/bmi270_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c @@ -0,0 +1,455 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro, 8 Aux and 1 header, + * totaling to 21) which equals to 97. + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(97) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(97) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(97) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in headerless mode\n"); + + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &aux_bmi2_dev); + } + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_examples/aux_fifo_watermark_header_mode/Makefile b/bmi270_examples/aux_fifo_watermark_header_mode/Makefile new file mode 100644 index 0000000..c7dd72b --- /dev/null +++ b/bmi270_examples/aux_fifo_watermark_header_mode/Makefile @@ -0,0 +1,24 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_watermark_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP20 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c b/bmi270_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c new file mode 100644 index 0000000..0e5e83c --- /dev/null +++ b/bmi270_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c @@ -0,0 +1,476 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6, + * aux_frame_len = 8, header_byte = 1. + * fifo_accel_frame_count = (650 / (6 + 6 + 8 + 1 )) = 30 frames + * NOTE: Extra frames are read in order to get sensor time + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(50) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(50) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(50) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*! Macro to read sensortime byte in FIFO */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(250) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", + (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_examples/aux_fifo_watermark_headerless_mode/Makefile b/bmi270_examples/aux_fifo_watermark_headerless_mode/Makefile new file mode 100644 index 0000000..787e77d --- /dev/null +++ b/bmi270_examples/aux_fifo_watermark_headerless_mode/Makefile @@ -0,0 +1,24 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_watermark_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP20 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c b/bmi270_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c new file mode 100644 index 0000000..caaacd3 --- /dev/null +++ b/bmi270_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c @@ -0,0 +1,468 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6, aux_frame_len = 8. + * fifo_accel_frame_count = (650 / (6 + 6 + 8 )) = 32 frames + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(32) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(32) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(32) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in headerless mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &aux_bmi2_dev); + } + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_examples/axis_remap/Makefile b/bmi270_examples/axis_remap/Makefile new file mode 100644 index 0000000..d2c8377 --- /dev/null +++ b/bmi270_examples/axis_remap/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= axis_remap.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/axis_remap/axis_remap.c b/bmi270_examples/axis_remap/axis_remap.c new file mode 100644 index 0000000..92c2670 --- /dev/null +++ b/bmi270_examples/axis_remap/axis_remap.c @@ -0,0 +1,507 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include + +#include "bmi270.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel. + * + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_accel_config(struct bmi2_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Status of api are returned to this variable. */ + int8_t rslt; + + struct bmi2_remap remapped_axis = { 0 }; + + /* Initialize the interrupt status of accel. */ + uint16_t int_status = 0; + + /* Select sensors for enable and setting */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_GYRO }; + + char data_array[13][12] = + { { 0 }, { "BMI2_X" }, { "BMI2_Y" }, { 0 }, { "BMI2_Z" }, { 0 }, { 0 }, { 0 }, { 0 }, { "BMI2_NEG_X" }, + { "BMI2_NEG_Y" }, { 0 }, { "BMI2_NEG_Z" } }; + + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize the sensor by enabling write configuration */ + rslt = bmi270_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Accel configuration settings. */ + rslt = set_accel_config(&dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + printf("\nAXIS_REMAP_FUNC_TEST 1\n"); + printf("Get default values of re-mapped axes sensor data\n"); + + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + + printf("Expected Re-mapped x value = BMI2_X\n"); + printf("Expected Re-mapped y value = BMI2_Y\n"); + printf("Expected Re-mapped z value = BMI2_Z\n"); + + if ((remapped_axis.x == BMI2_X) && (remapped_axis.y == BMI2_Y) && (remapped_axis.z == BMI2_Z)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 1 Failed\n"); + exit(COINES_E_FAILURE); + } + + printf("Print un-mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 2\n"); + printf("Get sensor data of re-mapped axes\n"); + + remapped_axis.x = BMI2_NEG_Y; + remapped_axis.y = BMI2_Z; + remapped_axis.z = BMI2_NEG_X; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_NEG_Y\n"); + printf("Expected Re-mapped y value = BMI2_Z\n"); + printf("Expected Re-mapped z value = BMI2_NEG_X\n"); + + if ((remapped_axis.x == BMI2_NEG_Y) && (remapped_axis.y == BMI2_Z) && (remapped_axis.z == BMI2_NEG_X)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 2 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 3\n"); + printf("Get sensor data of re-mapped axes - 2nd combination\n"); + + remapped_axis.x = BMI2_NEG_Z; + remapped_axis.y = BMI2_NEG_X; + remapped_axis.z = BMI2_Y; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_NEG_Z\n"); + printf("Expected Re-mapped y value = BMI2_NEG_X\n"); + printf("Expected Re-mapped z value = BMI2_Y\n"); + + if ((remapped_axis.x == BMI2_NEG_Z) && (remapped_axis.y == BMI2_NEG_X) && (remapped_axis.z == BMI2_Y)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 3 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 4\n"); + printf("Get sensor data of re-mapped axes - 3rd combination\n"); + + remapped_axis.x = BMI2_Y; + remapped_axis.y = BMI2_Z; + remapped_axis.z = BMI2_X; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_Y\n"); + printf("Expected Re-mapped y value = BMI2_Z\n"); + printf("Expected Re-mapped z value = BMI2_X\n"); + + if ((remapped_axis.x == BMI2_Y) && (remapped_axis.y == BMI2_Z) && (remapped_axis.z == BMI2_X)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 4 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 5\n"); + printf("Get sensor data of re-mapped axes - 4th combination\n"); + + remapped_axis.x = BMI2_NEG_X; + remapped_axis.y = BMI2_NEG_Y; + remapped_axis.z = BMI2_NEG_Z; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_NEG_X\n"); + printf("Expected Re-mapped y value = BMI2_NEG_Y\n"); + printf("Expected Re-mapped z value = BMI2_NEG_Z\n"); + + if ((remapped_axis.x == BMI2_NEG_X) && (remapped_axis.y == BMI2_NEG_Y) && (remapped_axis.z == BMI2_NEG_Z)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 5 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel. + */ +static int8_t set_accel_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accelerometer configuration. */ + struct bmi2_sens_config config; + + /* Configure the type of feature. */ + config.type = BMI2_ACCEL; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(&config, 1, dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Output Data Rate. By default ODR is set as 100Hz for accel. */ + config.cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config.cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples. + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config.cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the accel configurations. */ + rslt = bmi270_set_sensor_config(&config, 1, dev); + } + + return rslt; +} diff --git a/examples/bmi270/common/common.c b/bmi270_examples/common/common.c similarity index 94% rename from examples/bmi270/common/common.c rename to bmi270_examples/common/common.c index afff37b..0298c30 100644 --- a/examples/bmi270/common/common.c +++ b/bmi270_examples/common/common.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,7 +8,7 @@ #include #include -#include "coines.h" +#include "common.h" #include "bmi2_defs.h" /******************************************************************************/ @@ -123,7 +123,15 @@ int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) bmi->intf = BMI2_I2C_INTF; bmi->read = bmi2_i2c_read; bmi->write = bmi2_i2c_write; - coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + + /* SDO to Ground */ + coines_set_pin_config(COINES_SHUTTLE_PIN_22, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* Make CSB pin HIGH */ + coines_set_pin_config(COINES_SHUTTLE_PIN_21, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + coines_delay_msec(100); + + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE); } /* Bus configuration : SPI */ else if (intf == BMI2_SPI_INTF) @@ -151,11 +159,11 @@ int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) /* Assign to NULL to load the default config file. */ bmi->config_file_ptr = NULL; - coines_delay_usec(10000); + coines_delay_msec(100); coines_set_shuttleboard_vdd_vddio_config(3300, 3300); - coines_delay_usec(10000); + coines_delay_msec(200); } else { @@ -368,5 +376,14 @@ void bmi2_error_codes_print_result(int8_t rslt) */ void bmi2_coines_deinit(void) { + fflush(stdout); + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Coines interface reset */ + coines_soft_reset(); + coines_delay_msec(100); + coines_close_comm_intf(COINES_COMM_INTF_USB); } diff --git a/examples/bmi270_context/common/common.h b/bmi270_examples/common/common.h similarity index 95% rename from examples/bmi270_context/common/common.h rename to bmi270_examples/common/common.h index 763983d..c165102 100644 --- a/examples/bmi270_context/common/common.h +++ b/bmi270_examples/common/common.h @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -14,6 +14,7 @@ extern "C" { #include #include "bmi2.h" +#include "coines.h" /*! * @brief Function for reading the sensor's registers through I2C bus. @@ -79,7 +80,7 @@ BMI2_INTF_RETURN_TYPE bmi2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the * APIs. * - * @param[in] period_us : The required wait time in microsecond. + * @param[in] period : The required wait time in microsecond. * @param[in] intf_ptr : Interface pointer * * @return void. diff --git a/examples/bmi270/component_retrim/Makefile b/bmi270_examples/component_retrim/Makefile similarity index 100% rename from examples/bmi270/component_retrim/Makefile rename to bmi270_examples/component_retrim/Makefile diff --git a/examples/bmi270/component_retrim/component_retrim.c b/bmi270_examples/component_retrim/component_retrim.c similarity index 95% rename from examples/bmi270/component_retrim/component_retrim.c rename to bmi270_examples/component_retrim/component_retrim.c index d85c148..83744cc 100644 --- a/examples/bmi270/component_retrim/component_retrim.c +++ b/bmi270_examples/component_retrim/component_retrim.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ diff --git a/examples/bmi270/fifo_full_header_mode/Makefile b/bmi270_examples/fifo_full_header_mode/Makefile similarity index 94% rename from examples/bmi270/fifo_full_header_mode/Makefile rename to bmi270_examples/fifo_full_header_mode/Makefile index 83a8f49..c1e7aeb 100644 --- a/examples/bmi270/fifo_full_header_mode/Makefile +++ b/bmi270_examples/fifo_full_header_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270/fifo_full_header_mode/fifo_full_header_mode.c b/bmi270_examples/fifo_full_header_mode/fifo_full_header_mode.c similarity index 89% rename from examples/bmi270/fifo_full_header_mode/fifo_full_header_mode.c rename to bmi270_examples/fifo_full_header_mode/fifo_full_header_mode.c index 2118c24..9e294be 100644 --- a/examples/bmi270/fifo_full_header_mode/fifo_full_header_mode.c +++ b/bmi270_examples/fifo_full_header_mode/fifo_full_header_mode.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -23,14 +23,16 @@ /*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro and 1 header, * totaling to 13) which equals to 157. + * + * Extra frames to parse sensortime data */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(157) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(185) /*! Number of gyro frames to be extracted from FIFO. */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(157) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(185) /*! Macro to read sensortime byte in FIFO. */ -#define SENSORTIME_OVERHEAD_BYTE UINT8_C(3) +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(220) /******************************************************************************/ /*! Static Function Declaration */ @@ -64,12 +66,11 @@ int main(void) uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - int8_t try = 1; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[fifo_buffer_size]; /* Sensor initialization configuration. */ @@ -100,14 +101,16 @@ int main(void) rslt = bmi270_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -158,6 +161,9 @@ int main(void) rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -183,18 +189,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len + header_byte)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH + 1)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExtracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -204,11 +200,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { @@ -222,7 +213,7 @@ int main(void) /* Print control frames like sensor time and skipped frame count. */ printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); - printf("Sensor time = %lu\r\n", fifoframe.sensor_time); + printf("Sensor time(in seconds) = %.4lf s\r\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); try++; } @@ -258,7 +249,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) /* NOTE: The user can change the following configuration parameters according to their requirement. */ /* Accel configuration settings. */ /* Set Output Data Rate */ - config[0].cfg.acc.odr = BMI2_ACC_ODR_25HZ; + config[0].cfg.acc.odr = BMI2_ACC_ODR_50HZ; /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; @@ -283,7 +274,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) /* Gyro configuration settings. */ /* Set Output Data Rate */ - config[1].cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + config[1].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; diff --git a/examples/bmi270/fifo_full_headerless_mode/Makefile b/bmi270_examples/fifo_full_headerless_mode/Makefile similarity index 100% rename from examples/bmi270/fifo_full_headerless_mode/Makefile rename to bmi270_examples/fifo_full_headerless_mode/Makefile diff --git a/examples/bmi270/fifo_full_headerless_mode/fifo_full_headerless_mode.c b/bmi270_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c similarity index 91% rename from examples/bmi270/fifo_full_headerless_mode/fifo_full_headerless_mode.c rename to bmi270_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c index 53dddc4..b8e4e63 100644 --- a/examples/bmi270/fifo_full_headerless_mode/fifo_full_headerless_mode.c +++ b/bmi270_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -24,10 +24,10 @@ /*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro totaling to * 12) which equals to 170. */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(169) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(170) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(169) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(170) /******************************************************************************/ /*! Static Function Declaration */ @@ -60,10 +60,9 @@ int main(void) uint16_t gyro_frame_length; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; /* Sensor initialization configuration. */ @@ -94,14 +93,16 @@ int main(void) rslt = bmi270_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -152,6 +153,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -177,18 +181,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExtracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -198,11 +192,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { diff --git a/examples/bmi270/fifo_watermark_header_mode/Makefile b/bmi270_examples/fifo_watermark_header_mode/Makefile similarity index 94% rename from examples/bmi270/fifo_watermark_header_mode/Makefile rename to bmi270_examples/fifo_watermark_header_mode/Makefile index 0815820..67e73bf 100644 --- a/examples/bmi270/fifo_watermark_header_mode/Makefile +++ b/bmi270_examples/fifo_watermark_header_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270/fifo_watermark_header_mode/fifo_watermark_header_mode.c b/bmi270_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c similarity index 86% rename from examples/bmi270/fifo_watermark_header_mode/fifo_watermark_header_mode.c rename to bmi270_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c index faaeb30..cc1b87a 100644 --- a/examples/bmi270/fifo_watermark_header_mode/fifo_watermark_header_mode.c +++ b/bmi270_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -14,10 +14,10 @@ /*! Macros */ /*! Buffer size allocated to store raw FIFO data */ -#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) /*! Length of data to be read from FIFO */ -#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) /*! Number of accel frames to be extracted from FIFO */ @@ -27,16 +27,16 @@ * fifo_accel_frame_count = (650 / (6 + 6 + 1 )) = 50 frames * NOTE: Extra frames are read in order to get sensor time */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(70) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(70) /*! Setting a watermark level in FIFO */ -#define BMI270_FIFO_WATERMARK_LEVEL UINT16_C(650) +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) /*! Macro to read sensortime byte in FIFO */ -#define SENSORTIME_OVERHEAD_BYTE UINT8_C(3) +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(250) /******************************************************************************/ /*! Static Function Declaration */ @@ -57,9 +57,6 @@ int main(void) /* Status of api are returned to this variable. */ int8_t rslt; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - /* Variable to index bytes. */ uint16_t index = 0; @@ -74,7 +71,9 @@ int main(void) /* To read sensortime, extra 3 bytes are added to fifo buffer */ uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[fifo_buffer_size]; /* Sensor initialization configuration. */ @@ -110,14 +109,16 @@ int main(void) rslt = bmi270_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -150,16 +151,12 @@ int main(void) bmi2_error_codes_print_result(rslt); /* Set water-mark level. */ - fifoframe.wm_lvl = BMI270_FIFO_WATERMARK_LEVEL; + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; /* Set the water-mark level if water-mark interrupt is mapped. */ rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &bmi2_dev); bmi2_error_codes_print_result(rslt); - rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - printf("\nFIFO watermark level is %d\n", watermark); - while (try <= 10) { /* Read FIFO data on interrupt. */ @@ -171,17 +168,19 @@ int main(void) { printf("\nIteration : %d\n", try); - printf("\nWatermark interrupt occurred\n"); + rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level : %d\n", watermark); rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); - accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; - gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; - printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + bmi2_dev.dummy_byte; + /* Read FIFO data. */ rslt = bmi2_read_fifo_data(&fifoframe, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -192,6 +191,9 @@ int main(void) if (rslt == BMI2_OK) { + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ @@ -204,18 +206,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len + header_byte)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH + 1)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -225,11 +217,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { @@ -242,7 +229,7 @@ int main(void) /* Print control frames like sensor time and skipped frame count. */ printf("Skipped frame count = %d\n", fifoframe.skipped_frame_count); - printf("Sensor time = %lu\r\n", fifoframe.sensor_time); + printf("Sensor time(in seconds) = %.4lf s\r\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); try++; } @@ -278,7 +265,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *dev) /* NOTE: The user can change the following configuration parameters according to their requirement. */ /* Accel configuration settings. */ /* Set Output Data Rate */ - config[0].cfg.acc.odr = BMI2_ACC_ODR_25HZ; + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; @@ -303,7 +290,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *dev) /* Gyro configuration settings. */ /* Set Output Data Rate */ - config[1].cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; diff --git a/examples/bmi270/fifo_watermark_headerless_mode/Makefile b/bmi270_examples/fifo_watermark_headerless_mode/Makefile similarity index 94% rename from examples/bmi270/fifo_watermark_headerless_mode/Makefile rename to bmi270_examples/fifo_watermark_headerless_mode/Makefile index 527a18a..af671a1 100644 --- a/examples/bmi270/fifo_watermark_headerless_mode/Makefile +++ b/bmi270_examples/fifo_watermark_headerless_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c b/bmi270_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c similarity index 87% rename from examples/bmi270/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c rename to bmi270_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c index b3adf89..c7cf70a 100644 --- a/examples/bmi270/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c +++ b/bmi270_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -14,10 +14,10 @@ /*! Macros */ /*! Buffer size allocated to store raw FIFO data */ -#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(800) /*! Length of data to be read from FIFO */ -#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(800) /*! Number of accel frames to be extracted from FIFO */ @@ -26,13 +26,13 @@ * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6. * fifo_accel_frame_count = (650 / (6 + 6 )) = 54 frames */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(54) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(54) /*! Setting a watermark level in FIFO */ -#define BMI270_FIFO_WATERMARK_LEVEL UINT16_C(650) +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) /******************************************************************************/ /*! Static Function Declaration */ @@ -56,9 +56,6 @@ int main(void) /* Variable to index bytes. */ uint16_t index = 0; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - uint16_t fifo_length = 0; uint16_t accel_frame_length; @@ -67,7 +64,9 @@ int main(void) uint8_t try = 1; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; /* Sensor initialization configuration. */ @@ -96,21 +95,23 @@ int main(void) * For I2C : BMI2_I2C_INTF * For SPI : BMI2_SPI_INTF */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + rslt = bmi2_interface_init(&bmi2_dev, BMI2_SPI_INTF); bmi2_error_codes_print_result(rslt); /* Initialize bmi270. */ rslt = bmi270_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -148,7 +149,7 @@ int main(void) bmi2_error_codes_print_result(rslt); /* Set water-mark level. */ - fifoframe.wm_lvl = BMI270_FIFO_WATERMARK_LEVEL; + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; @@ -156,10 +157,6 @@ int main(void) rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &bmi2_dev); bmi2_error_codes_print_result(rslt); - rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - printf("\nFIFO watermark level is %d\n", watermark); - while (try <= 10) { /* Read FIFO data on interrupt. */ @@ -171,7 +168,9 @@ int main(void) { printf("\nIteration : %d\n", try); - printf("\nWatermark interrupt occurred\n"); + rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level : %d\n", watermark); rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -179,6 +178,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -204,18 +206,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -225,11 +217,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { diff --git a/examples/bmi270/gyro/Makefile b/bmi270_examples/gyro/Makefile similarity index 100% rename from examples/bmi270/gyro/Makefile rename to bmi270_examples/gyro/Makefile diff --git a/examples/bmi270/gyro/gyro.c b/bmi270_examples/gyro/gyro.c similarity index 83% rename from examples/bmi270/gyro/gyro.c rename to bmi270_examples/gyro/gyro.c index 1bb0ca4..fa938f3 100644 --- a/examples/bmi270/gyro/gyro.c +++ b/bmi270_examples/gyro/gyro.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -54,7 +54,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Assign gyro sensor to variable. */ uint8_t sens_list = BMI2_GYRO; @@ -66,7 +66,7 @@ int main(void) * For I2C : BMI2_I2C_INTF * For SPI : BMI2_SPI_INTF */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + rslt = bmi2_interface_init(&bmi2_dev, BMI2_SPI_INTF); bmi2_error_codes_print_result(rslt); /* Initialize bmi270. */ @@ -75,18 +75,20 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the selected sensors. */ - rslt = bmi270_sensor_enable(&sens_list, 1, &bmi2_dev); + /* Gyro configuration settings. */ + rslt = set_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Gyro configuration settings. */ - rslt = set_gyro_config(&bmi2_dev); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + + /* Enable the selected sensors. */ + rslt = bmi270_sensor_enable(&sens_list, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Select gyro sensor. */ - sensor_data.type = BMI2_GYRO; printf("Gyro and DPS data\n"); printf("Gyro data collected at Range 2000 dps with 16-bit resolution\n"); @@ -101,17 +103,17 @@ int main(void) if (int_status & BMI2_GYR_DRDY_INT_MASK) { /* Get gyro data for x, y and z axis. */ - rslt = bmi270_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("\nGyr_X = %d\t", sensor_data.sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data.sens_data.gyr.y); - printf("Gyr_Z = %d\r\n", sensor_data.sens_data.gyr.z); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z = %d\r\n", sensor_data.gyr.z); /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data.sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data.sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data.sens_data.gyr.z, 2000, bmi2_dev.resolution); + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); /* Print the data in dps. */ printf("Gyr_DPS_X = %4.2f, Gyr_DPS_Y = %4.2f, Gyr_DPS_Z = %4.2f\n", x, y, z); @@ -191,5 +193,5 @@ static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { float half_scale = ((float)(1 << bit_width) / 2.0f); - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); + return (dps / ((half_scale))) * (val); } diff --git a/bmi270_examples/gyro_foc/Makefile b/bmi270_examples/gyro_foc/Makefile new file mode 100644 index 0000000..6da1649 --- /dev/null +++ b/bmi270_examples/gyro_foc/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= gyro_foc.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/gyro_foc/gyro_foc.c b/bmi270_examples/gyro_foc/gyro_foc.c new file mode 100644 index 0000000..279fb88 --- /dev/null +++ b/bmi270_examples/gyro_foc/gyro_foc.c @@ -0,0 +1,307 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include +#include +#include + +#include "bmi270.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macro Definitions */ + +#define GYRO_SAMPLE_COUNT UINT8_C(100) + +/******************************************************************************/ +/*! Global Variable Declaration */ + +/* Structure to store temporary axes data values */ +struct temp_axes_val +{ + /* X data */ + int32_t x; + + /* Y data */ + int32_t y; + + /* Z data */ + int32_t z; +}; + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is to perform gyro FOC + * + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t perform_gyro_foc_test(struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to determind if gyro FOC data is within defined limits + * + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t verify_gyro_foc_data(struct bmi2_dev *bmi2_dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + uint8_t try = 0, j = 0; + int8_t rslt; + uint8_t sens_list = BMI2_GYRO; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + printf("Functional test for gyro foc start..\n"); + + /* Perform FOC for different ranges */ + for (j = 0; j < 2; j++) + { + rslt = 0; + try = 0; + + if (j == 0) + { + printf("Shake the sensor and press 5\n"); + } + else if (j > 0) + { + printf("Keep sensor stable in right position and press 5\n"); + } + + while (1) + { + scanf("%hu", (short unsigned int *)&try); + if (try == 5) + { + break; + } + } + + /* Initialize the sensor */ + rslt = bmi270_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Enable gyroscope */ + rslt = bmi270_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + rslt = perform_gyro_foc_test(&dev); + + if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - sensor is shaking #########\n\n"); + if (rslt != BMI2_E_OUT_OF_RANGE) + { + printf("rslt != BMI2_E_OUT_OF_RANGE\n"); + break; + } + } + else if ((j > 0) && (rslt == BMI2_OK)) + { + printf("\n######### Valid input - Sensor is not shaking #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_OK)) + { + printf("\n######### Invalid input - sensor is not shaking #########\n\n"); + if (rslt == BMI2_OK) + { + printf("rslt == BMI2_OK\n"); + break; + } + } + else if ((j > 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Sensor is shaking #########\n\n"); + if (rslt == BMI2_E_OUT_OF_RANGE) + { + printf("rslt == BMI2_E_OUT_OF_RANGE\n"); + break; + } + } + else if (rslt == BMI2_E_OUT_OF_RANGE) + { + bmi2_error_codes_print_result(rslt); + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +static int8_t verify_gyro_foc_data(struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + struct bmi2_sens_axes_data gyr_foc_data[GYRO_SAMPLE_COUNT] = { { 0 } }; + struct temp_axes_val temp_foc_data = { 0 }; + struct bmi2_sens_axes_data avg_foc_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; + uint16_t drdy_status = 0; + uint8_t i; + + /* Read gyroscope values before/after FOC */ + for (i = 0; i < GYRO_SAMPLE_COUNT; i++) + { + while (1) + { + /* To get the data ready interrupt status of gyro. */ + rslt = bmi2_get_int_status(&drdy_status, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read gyroscope data based on data ready interrupt */ + if ((rslt == BMI2_OK) && (drdy_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + memcpy(&gyr_foc_data[i], &sensor_data.gyr, sizeof(struct bmi2_sens_axes_data)); + + printf("X[%d] = %5d, Y[%d] = %5d, Z[%d] = %5d\n", + i, + gyr_foc_data[i].x, + i, + gyr_foc_data[i].y, + i, + gyr_foc_data[i].z); + + temp_foc_data.x += gyr_foc_data[i].x; + temp_foc_data.y += gyr_foc_data[i].y; + temp_foc_data.z += gyr_foc_data[i].z; + break; + } + } + } + + /* Taking average values to calculate percentage deviation */ + avg_foc_data.x = (int16_t)(temp_foc_data.x / GYRO_SAMPLE_COUNT); + avg_foc_data.y = (int16_t)(temp_foc_data.y / GYRO_SAMPLE_COUNT); + avg_foc_data.z = (int16_t)(temp_foc_data.z / GYRO_SAMPLE_COUNT); + + printf("# Average GYRO Axes FOC\n"); + + printf("\n# Avg_X = %5d \t Avg_Y = %5d \t Avg_Z = %5d\n", avg_foc_data.x, avg_foc_data.y, avg_foc_data.z); + + /* The measurement result should be 0 +/- 1dps */ + if (((avg_foc_data.x >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.x <= BMI2_GYRO_FOC_2000_DPS_REF)) && + ((avg_foc_data.y >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.y <= (BMI2_GYRO_FOC_2000_DPS_REF))) && + ((avg_foc_data.z >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.z <= BMI2_GYRO_FOC_2000_DPS_REF))) + { + printf("\n### Gyro Axes data within range ###\n"); + rslt = BMI2_OK; + } + else + { + printf("\n### Gyro Axes data out of range ###\n"); + rslt = BMI2_E_OUT_OF_RANGE; + } + + return rslt; +} + +/* Perform FOC for different ranges*/ +static int8_t perform_gyro_foc_test(struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + struct bmi2_sens_config config = { 0 }; + + uint8_t sens_list = BMI2_GYRO; + + /* Initialize the sensor */ + rslt = bmi270_init(bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_GYRO; + + rslt = bmi270_get_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set Output Data Rate to 25Hz */ + config.cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config.cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Set Gyroscope bandwidth to CIC mode */ + config.cfg.gyr.bwp = BMI2_GYR_CIC_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config.cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config.cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the gyro configurations. */ + rslt = bmi270_set_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(&sens_list, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("# BWP : %d ODR : %d Range : %d\n", config.cfg.gyr.bwp, config.cfg.gyr.odr, config.cfg.gyr.range); + + printf("\n# Before GYRO FOC\n"); + + rslt = verify_gyro_foc_data(bmi2_dev); + + printf("\n\n########## Perform GYRO FOC ##########\n\n"); + + /* Perform gyroscope FOC */ + rslt = bmi2_perform_gyro_foc(bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Provide delay after performing FOC */ + bmi2_dev->delay_us(40000, bmi2_dev->intf_ptr); + + if (rslt == BMI2_OK) + { + printf("\n# After GYRO FOC\n"); + + rslt = verify_gyro_foc_data(bmi2_dev); + } + + return rslt; +} diff --git a/examples/bmi270/no_motion_interrupt/Makefile b/bmi270_examples/no_motion_interrupt/Makefile similarity index 100% rename from examples/bmi270/no_motion_interrupt/Makefile rename to bmi270_examples/no_motion_interrupt/Makefile diff --git a/examples/bmi270/no_motion_interrupt/no_motion_interrupt.c b/bmi270_examples/no_motion_interrupt/no_motion_interrupt.c similarity index 98% rename from examples/bmi270/no_motion_interrupt/no_motion_interrupt.c rename to bmi270_examples/no_motion_interrupt/no_motion_interrupt.c index 5c46306..cf65c3d 100644 --- a/examples/bmi270/no_motion_interrupt/no_motion_interrupt.c +++ b/bmi270_examples/no_motion_interrupt/no_motion_interrupt.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ diff --git a/examples/bmi270/read_aux_data_mode/Makefile b/bmi270_examples/read_aux_data_mode/Makefile similarity index 100% rename from examples/bmi270/read_aux_data_mode/Makefile rename to bmi270_examples/read_aux_data_mode/Makefile diff --git a/bmi270_examples/read_aux_data_mode/read_aux_data_mode.c b/bmi270_examples/read_aux_data_mode/read_aux_data_mode.c new file mode 100644 index 0000000..8947bd7 --- /dev/null +++ b/bmi270_examples/read_aux_data_mode/read_aux_data_mode.c @@ -0,0 +1,409 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL, AND GYRO DATA IN DATA MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK) && + (int_status & BMI2_AUX_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(sensor_data.aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in data mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in data mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/examples/bmi270/read_aux_manual_mode/Makefile b/bmi270_examples/read_aux_manual_mode/Makefile similarity index 100% rename from examples/bmi270/read_aux_manual_mode/Makefile rename to bmi270_examples/read_aux_manual_mode/Makefile diff --git a/bmi270_examples/read_aux_manual_mode/read_aux_manual_mode.c b/bmi270_examples/read_aux_manual_mode/read_aux_manual_mode.c new file mode 100644 index 0000000..9df9f54 --- /dev/null +++ b/bmi270_examples/read_aux_manual_mode/read_aux_manual_mode.c @@ -0,0 +1,408 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* Array of eight bytes to store x, y, z and r axis aux data. */ + uint8_t aux_data[8] = { 0 }; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim register */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.manual_en = BMI2_ENABLE; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL AND GYRO DATA IN MANUAL MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + } + + /* Read aux data from the bmm150 data registers. */ + rslt = bmi2_read_aux_man_mode(BMM150_REG_DATA_X_LSB, aux_data, 8, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_examples/sensor_data/Makefile b/bmi270_examples/sensor_data/Makefile new file mode 100644 index 0000000..0f00d38 --- /dev/null +++ b/bmi270_examples/sensor_data/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= sensor_data.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_examples/sensor_data/sensor_data.c b/bmi270_examples/sensor_data/sensor_data.c new file mode 100644 index 0000000..491205f --- /dev/null +++ b/bmi270_examples/sensor_data/sensor_data.c @@ -0,0 +1,412 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270. */ + rslt = bmi270_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL, AND GYRO DATA IN DATA MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK) && + (int_status & BMI2_AUX_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(sensor_data.aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + + printf("\nSensor time(in seconds) = %.4lf s\n", + (sensor_data.sens_time * BMI2_SENSORTIME_RESOLUTION)); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in data mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in data mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/examples/bmi270/sig_motion/Makefile b/bmi270_examples/sig_motion/Makefile similarity index 100% rename from examples/bmi270/sig_motion/Makefile rename to bmi270_examples/sig_motion/Makefile diff --git a/examples/bmi270/sig_motion/sig_motion.c b/bmi270_examples/sig_motion/sig_motion.c similarity index 97% rename from examples/bmi270/sig_motion/sig_motion.c rename to bmi270_examples/sig_motion/sig_motion.c index 47e1c28..51b3fe6 100644 --- a/examples/bmi270/sig_motion/sig_motion.c +++ b/bmi270_examples/sig_motion/sig_motion.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ diff --git a/examples/bmi270/step_activity/Makefile b/bmi270_examples/step_activity/Makefile similarity index 100% rename from examples/bmi270/step_activity/Makefile rename to bmi270_examples/step_activity/Makefile diff --git a/examples/bmi270/step_activity/step_activity.c b/bmi270_examples/step_activity/step_activity.c similarity index 94% rename from examples/bmi270/step_activity/step_activity.c rename to bmi270_examples/step_activity/step_activity.c index 87775b7..dcaf7d6 100644 --- a/examples/bmi270/step_activity/step_activity.c +++ b/bmi270_examples/step_activity/step_activity.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -19,7 +19,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Structure to define the type of sensor and their respective data. */ - struct bmi2_sensor_data sensor_data; + struct bmi2_feat_sensor_data sensor_data = { 0 }; /* Structure to define the type of sensor and its configurations. */ struct bmi2_sens_config config; @@ -91,7 +91,7 @@ int main(void) printf("Step detected\n"); /* Get step activity output. */ - rslt = bmi270_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi270_get_feature_data(&sensor_data, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); /* Print the step activity output. */ diff --git a/examples/bmi270/step_counter/Makefile b/bmi270_examples/step_counter/Makefile similarity index 100% rename from examples/bmi270/step_counter/Makefile rename to bmi270_examples/step_counter/Makefile diff --git a/examples/bmi270/step_counter/step_counter.c b/bmi270_examples/step_counter/step_counter.c similarity index 92% rename from examples/bmi270/step_counter/step_counter.c rename to bmi270_examples/step_counter/step_counter.c index b08f958..35ecdb1 100644 --- a/examples/bmi270/step_counter/step_counter.c +++ b/bmi270_examples/step_counter/step_counter.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -32,7 +32,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Structure to define type of sensor and their respective data. */ - struct bmi2_sensor_data sensor_data; + struct bmi2_feat_sensor_data sensor_data = { 0 }; /* Status of api are returned to this variable. */ int8_t rslt; @@ -96,11 +96,13 @@ int main(void) printf("Step counter interrupt occurred when watermark level (20 steps) is reached\n"); /* Get step counter output. */ - rslt = bmi270_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi270_get_feature_data(&sensor_data, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); /* Print the step counter output. */ - printf("No of steps counted = %ld", sensor_data.sens_data.step_counter_output); + printf("No of steps counted = %lu", + (long unsigned int)sensor_data.sens_data.step_counter_output); + break; } } while (rslt == BMI2_OK); diff --git a/examples/bmi270/wrist_gesture/Makefile b/bmi270_examples/wrist_gesture/Makefile similarity index 100% rename from examples/bmi270/wrist_gesture/Makefile rename to bmi270_examples/wrist_gesture/Makefile diff --git a/examples/bmi270/wrist_gesture/wrist_gesture.c b/bmi270_examples/wrist_gesture/wrist_gesture.c similarity index 95% rename from examples/bmi270/wrist_gesture/wrist_gesture.c rename to bmi270_examples/wrist_gesture/wrist_gesture.c index be494b8..acf960f 100644 --- a/examples/bmi270/wrist_gesture/wrist_gesture.c +++ b/bmi270_examples/wrist_gesture/wrist_gesture.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -41,7 +41,7 @@ int main(void) struct bmi2_sens_int_config sens_int = { .type = BMI2_WRIST_GESTURE, .hw_int_pin = BMI2_INT1 }; /* Sensor data structure */ - struct bmi2_sensor_data sens_data = { 0 }; + struct bmi2_feat_sensor_data sens_data = { 0 }; /* The gesture movements are listed in array */ const char *gesture_output[6] = @@ -88,7 +88,7 @@ int main(void) printf("Wrist gesture detected\n"); /* Get wrist gesture output */ - rslt = bmi270_get_sensor_data(&sens_data, 1, &bmi2_dev); + rslt = bmi270_get_feature_data(&sens_data, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); printf("Wrist gesture = %d\r\n", sens_data.sens_data.wrist_gesture_output); diff --git a/examples/bmi270/wrist_wear_wakeup/Makefile b/bmi270_examples/wrist_wear_wakeup/Makefile similarity index 100% rename from examples/bmi270/wrist_wear_wakeup/Makefile rename to bmi270_examples/wrist_wear_wakeup/Makefile diff --git a/examples/bmi270/wrist_wear_wakeup/wrist_wear_wakeup.c b/bmi270_examples/wrist_wear_wakeup/wrist_wear_wakeup.c similarity index 98% rename from examples/bmi270/wrist_wear_wakeup/wrist_wear_wakeup.c rename to bmi270_examples/wrist_wear_wakeup/wrist_wear_wakeup.c index 3547b2d..17c1cab 100644 --- a/examples/bmi270/wrist_wear_wakeup/wrist_wear_wakeup.c +++ b/bmi270_examples/wrist_wear_wakeup/wrist_wear_wakeup.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ diff --git a/bmi270_legacy.c b/bmi270_legacy.c new file mode 100644 index 0000000..62755a6 --- /dev/null +++ b/bmi270_legacy.c @@ -0,0 +1,5935 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmi270_legacy.c +* @date 2021-09-30 +* @version v2.71.8 +* +*/ + +/* BMI270_legacy offers same low-power features as in BMI160 */ + +/***************************************************************************/ + +/*! Header files + ****************************************************************************/ +#include "bmi270_legacy.h" + +/******************************************************************************/ +/*! @name Structure Declaration */ +/******************************************************************************/ + +/*! @name Structure to define tap configuration */ +struct bmi2_tap_config *bmi270_legacy_config; + +/***************************************************************************/ + +/*! Global Variable + ****************************************************************************/ + +/*! @name Global array that stores the configuration file of BMI270_LEGACY */ +const uint8_t bmi270_legacy_config_file[] = { + 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x3c, 0xb2, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x9b, 0x03, 0x80, 0x2e, 0xa4, + 0xb3, 0x80, 0x2e, 0xb8, 0x03, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0xc4, 0xb2, 0x50, 0x30, 0x21, 0x2e, 0x59, 0xf5, + 0x10, 0x30, 0x21, 0x2e, 0x4a, 0xf1, 0x21, 0x2e, 0x6a, 0xf5, 0x80, 0x2e, 0xe5, 0x01, 0x00, 0x5d, 0x01, 0x00, 0x22, + 0x00, 0x77, 0x00, 0x00, 0x10, 0x00, 0x10, 0xd1, 0x00, 0x45, 0xf5, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x45, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x88, 0x00, 0x05, 0xe0, 0xaa, 0x38, 0x05, 0xe0, 0x90, + 0x30, 0x00, 0x00, 0x30, 0x0a, 0x80, 0x40, 0x10, 0x27, 0xe8, 0x73, 0x04, 0x30, 0x00, 0x02, 0x00, 0x01, 0x00, 0x30, + 0x10, 0x0b, 0x09, 0x08, 0xfa, 0x00, 0x96, 0x00, 0x4b, 0x09, 0x11, 0x00, 0x11, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x06, 0x00, 0x09, 0x00, + 0x82, 0x00, 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4c, 0x04, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x32, 0x01, 0xe6, 0x78, 0x84, 0x00, 0x9c, 0x6c, + 0x07, 0x00, 0x64, 0x75, 0xaa, 0x7e, 0x5f, 0x05, 0xbe, 0x0a, 0x5f, 0x05, 0x96, 0xe8, 0xef, 0x41, 0x01, 0x00, 0x0c, + 0x00, 0x0c, 0x00, 0x4a, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9a, 0x00, 0x9a, + 0x01, 0x9f, 0x01, 0x88, 0x01, 0x96, 0x01, 0x84, 0x01, 0x00, 0x0c, 0xff, 0x0f, 0x00, 0x04, 0xc0, 0x00, 0x5b, 0xf5, + 0x98, 0xf1, 0x7b, 0x01, 0x7a, 0x01, 0x1e, 0xf2, 0xfd, 0xf5, 0xfc, 0xf5, 0x76, 0x01, 0x7e, 0x01, 0x80, 0x00, 0xa0, + 0x00, 0x5f, 0xff, 0xc8, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xd2, 0x00, 0x81, 0x01, 0x69, 0xf5, 0xe0, 0x00, 0x3f, 0xff, + 0x19, 0xf4, 0x58, 0xf5, 0x66, 0xf5, 0xff, 0x00, 0x64, 0xf5, 0xc0, 0xf1, 0xba, 0xf1, 0xae, 0xf1, 0xa0, 0x00, 0xdf, + 0x00, 0xa2, 0x01, 0xfa, 0x00, 0xfc, 0x00, 0xff, 0x3f, 0xff, 0xfb, 0x00, 0x38, 0x00, 0x30, 0xb3, 0x01, 0xba, 0x01, + 0xbc, 0x01, 0xc2, 0x01, 0xca, 0x01, 0xff, 0x7f, 0xff, 0x01, 0x8e, 0x01, 0x74, 0xf7, 0x00, 0x40, 0x5f, 0x0f, 0xeb, + 0x00, 0x7f, 0xff, 0xc2, 0xf5, 0x68, 0xf7, 0x59, 0x0f, 0x4d, 0x0f, 0x53, 0x0f, 0x72, 0x0f, 0x58, 0xf7, 0x5b, 0xf7, + 0x75, 0x0f, 0x00, 0x80, 0x86, 0x00, 0x64, 0x0f, 0x77, 0x0f, 0xb3, 0xf1, 0x71, 0x0f, 0x6c, 0xf7, 0xb9, 0xf1, 0xc6, + 0xf1, 0x00, 0xe0, 0x00, 0xff, 0xd1, 0xf5, 0x79, 0x0f, 0x7c, 0x0f, 0xff, 0x03, 0x00, 0xfc, 0xf0, 0x3f, 0x8b, 0x00, + 0x90, 0x00, 0x95, 0x00, 0x92, 0x00, 0x98, 0x00, 0x8d, 0x00, 0xa2, 0x00, 0xb9, 0x00, 0x2d, 0xf5, 0xca, 0xf5, 0x7c, + 0x01, 0x20, 0xf2, 0xdb, 0x01, 0x00, 0x08, 0x00, 0xf8, 0xe8, 0x03, 0x01, 0x80, 0xb8, 0x7e, 0xe1, 0x7a, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xa9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1a, 0x24, 0x22, 0x00, 0x80, 0x2e, 0x00, 0xb0, 0x1d, 0x52, 0x00, 0x2e, 0x60, 0x40, 0x41, 0x40, 0x0d, 0xbc, + 0x98, 0xbc, 0xc0, 0x2e, 0x01, 0x0a, 0x0f, 0xb8, 0x1f, 0x52, 0x53, 0x3c, 0x52, 0x40, 0x40, 0x40, 0x4b, 0x00, 0x82, + 0x16, 0x26, 0xb9, 0x01, 0xb8, 0x41, 0x40, 0x10, 0x08, 0x97, 0xb8, 0x01, 0x08, 0xc0, 0x2e, 0x11, 0x30, 0x01, 0x08, + 0x43, 0x86, 0x25, 0x40, 0x04, 0x40, 0xd8, 0xbe, 0x2c, 0x0b, 0x22, 0x11, 0x54, 0x42, 0x03, 0x80, 0x4b, 0x0e, 0xf6, + 0x2f, 0xb8, 0x2e, 0x21, 0x50, 0x10, 0x50, 0x23, 0x52, 0x05, 0x2e, 0xd5, 0x00, 0xfb, 0x7f, 0x00, 0x2e, 0x13, 0x40, + 0x93, 0x42, 0x41, 0x0e, 0xfb, 0x2f, 0x98, 0x2e, 0x91, 0x03, 0x98, 0x2e, 0x87, 0xcf, 0x01, 0x2e, 0x70, 0x01, 0x00, + 0xb2, 0xfb, 0x6f, 0x0b, 0x2f, 0x01, 0x2e, 0x69, 0xf7, 0xb1, 0x3f, 0x01, 0x08, 0x01, 0x30, 0xf0, 0x5f, 0x23, 0x2e, + 0x70, 0x01, 0x21, 0x2e, 0x69, 0xf7, 0x80, 0x2e, 0x2e, 0x02, 0xf0, 0x5f, 0xb8, 0x2e, 0x03, 0x2e, 0xfc, 0xf5, 0x01, + 0x2e, 0xc0, 0xf8, 0x25, 0x54, 0x27, 0x56, 0x82, 0x08, 0x0b, 0x2e, 0x69, 0xf7, 0xcb, 0x0a, 0x29, 0x58, 0x80, 0x90, + 0xdd, 0xbe, 0x4c, 0x08, 0x5f, 0xb9, 0x59, 0x22, 0x80, 0x90, 0x07, 0x2f, 0x03, 0x34, 0xc3, 0x08, 0xf2, 0x3a, 0x0a, + 0x08, 0x02, 0x35, 0xc0, 0x90, 0x4a, 0x0a, 0x48, 0x22, 0xc0, 0x2e, 0x23, 0x2e, 0xfc, 0xf5, 0x01, 0x2e, 0x7e, 0x01, + 0x01, 0x8a, 0xf0, 0x50, 0x50, 0x41, 0x1a, 0x25, 0x03, 0xbd, 0x71, 0x82, 0x02, 0xbe, 0x2f, 0xb9, 0x42, 0x42, 0x81, + 0xbd, 0x45, 0x41, 0x4f, 0xba, 0xf1, 0x7f, 0xbf, 0xb8, 0x0f, 0xb8, 0x5c, 0xb9, 0x24, 0x7f, 0x00, 0xb2, 0x31, 0x7f, + 0xeb, 0x7f, 0xd2, 0x7f, 0x08, 0x2f, 0x10, 0x6f, 0x00, 0x90, 0x0b, 0x2f, 0x20, 0x6f, 0x00, 0x90, 0x08, 0x2f, 0x30, + 0x6f, 0x00, 0x90, 0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x7d, 0x00, 0xd0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0x05, 0x2e, + 0x7d, 0x00, 0x80, 0x90, 0x00, 0x30, 0x2b, 0x52, 0x2f, 0x56, 0x07, 0x2f, 0x2b, 0x58, 0x00, 0x2e, 0x10, 0x43, 0x63, + 0x0e, 0xfc, 0x2f, 0x81, 0x84, 0x25, 0x2e, 0x7d, 0x00, 0x09, 0x2e, 0x7e, 0x01, 0x02, 0x85, 0x13, 0x41, 0x04, 0x41, + 0xb1, 0xbd, 0xb1, 0xb9, 0x44, 0xbe, 0x82, 0x40, 0x44, 0xba, 0x24, 0xbd, 0xb3, 0x7f, 0x5c, 0x05, 0x24, 0xb9, 0x01, + 0x56, 0x2d, 0x58, 0x92, 0x7f, 0xa5, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x73, 0x7f, 0x64, 0x7f, 0x00, 0x2e, 0xf2, 0x6f, + 0x40, 0x7f, 0x51, 0x7f, 0x00, 0x2e, 0x90, 0x40, 0xf2, 0x7f, 0x00, 0x90, 0x04, 0x2f, 0x51, 0x6f, 0x00, 0x30, 0x40, + 0x42, 0x45, 0x2c, 0x62, 0x6f, 0xc1, 0x40, 0x98, 0x2e, 0x74, 0xc0, 0x51, 0x6f, 0x00, 0x2e, 0x43, 0x40, 0xc0, 0xb2, + 0x2d, 0x2f, 0x62, 0x6f, 0xa5, 0x6f, 0x84, 0x40, 0xc5, 0x0e, 0x07, 0x2f, 0x75, 0x6f, 0x10, 0x30, 0x45, 0x41, 0x40, + 0xa1, 0x05, 0x30, 0x05, 0x22, 0x20, 0x1a, 0x02, 0x2f, 0x00, 0x30, 0x40, 0x42, 0x2c, 0x2d, 0x10, 0x30, 0x18, 0x28, + 0x93, 0x6f, 0x40, 0x42, 0xc3, 0x0e, 0x25, 0x2f, 0xc0, 0x6f, 0x00, 0x90, 0x22, 0x2f, 0x45, 0x6f, 0x10, 0x30, 0xc5, + 0x14, 0x46, 0xbf, 0xb3, 0xbf, 0xb7, 0x0b, 0x2b, 0x58, 0x65, 0x01, 0x2f, 0x5e, 0x0b, 0x30, 0x25, 0x1a, 0x00, 0x2f, + 0x0b, 0x43, 0x01, 0x89, 0x2d, 0x2e, 0x79, 0x01, 0x67, 0x0e, 0xf7, 0x2f, 0x80, 0x7f, 0xc3, 0x7f, 0x0e, 0x2d, 0xb2, + 0x6f, 0xc2, 0x0e, 0x08, 0x2f, 0x10, 0x30, 0x40, 0x42, 0x02, 0x30, 0x74, 0x6f, 0x63, 0x6f, 0x04, 0x41, 0x00, 0xa1, + 0x02, 0x22, 0xc0, 0x42, 0x00, 0x2e, 0x62, 0x6f, 0x40, 0x6f, 0x73, 0x6f, 0x01, 0x80, 0xc1, 0x86, 0x81, 0x84, 0x41, + 0x82, 0x03, 0xa2, 0x62, 0x7f, 0x73, 0x7f, 0xa4, 0x2f, 0xeb, 0x6f, 0xd0, 0x6f, 0x81, 0x6f, 0x10, 0x5f, 0x80, 0x2e, + 0x95, 0xcf, 0x03, 0x2e, 0x7f, 0x01, 0x41, 0x84, 0x50, 0x50, 0x90, 0x40, 0x82, 0x40, 0x83, 0xbd, 0xbf, 0xb9, 0x2c, + 0xba, 0xfb, 0x7f, 0xc0, 0xb2, 0xe4, 0x7f, 0x0b, 0x30, 0x36, 0x2f, 0x07, 0x2e, 0x7e, 0x00, 0xc0, 0x90, 0x04, 0x2f, + 0xc1, 0x86, 0x27, 0x2e, 0x7e, 0x00, 0x37, 0x2e, 0x7f, 0x00, 0xa4, 0xbd, 0x04, 0xbd, 0x34, 0xb8, 0x41, 0x40, 0x91, + 0xbc, 0x91, 0xb9, 0xb3, 0x7f, 0x24, 0xb9, 0x09, 0x52, 0xc0, 0x7f, 0xd2, 0x7f, 0x98, 0x2e, 0xb3, 0xc0, 0xd1, 0x6f, + 0xb2, 0x6f, 0x51, 0x28, 0x41, 0x0f, 0x11, 0x30, 0x0d, 0x2f, 0xc2, 0x0e, 0x07, 0x2e, 0x7f, 0x00, 0x19, 0x28, 0x04, + 0x2f, 0xc0, 0xa6, 0x04, 0x2f, 0x21, 0x2e, 0x7f, 0x00, 0x02, 0x2d, 0x21, 0x2e, 0x7f, 0x00, 0x04, 0x2c, 0x02, 0x30, + 0x02, 0x30, 0x25, 0x2e, 0x7f, 0x00, 0xc0, 0x6f, 0x07, 0x2e, 0x7f, 0x00, 0x58, 0x0f, 0xfb, 0x6f, 0xe0, 0x6f, 0xb0, + 0x5f, 0x4a, 0x22, 0x80, 0x2e, 0x95, 0xcf, 0xe0, 0x6f, 0x01, 0x30, 0x98, 0x2e, 0x95, 0xcf, 0x00, 0x30, 0x21, 0x2e, + 0x7e, 0x00, 0xfb, 0x6f, 0xb0, 0x5f, 0xb8, 0x2e, 0x21, 0x2e, 0x59, 0xf5, 0x10, 0x30, 0xc0, 0x2e, 0x21, 0x2e, 0x4a, + 0xf1, 0x80, 0x2e, 0x00, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x01, + 0x34, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x2e, 0xd5, 0x00, 0x16, 0xb8, 0x02, 0x34, 0x4a, 0x0c, 0x21, 0x2e, 0x2d, 0xf5, 0xc0, 0x2e, 0x23, + 0x2e, 0xd5, 0x00, 0x20, 0x50, 0xf6, 0x7f, 0xe7, 0x7f, 0x00, 0x2e, 0x35, 0x5c, 0x00, 0x2e, 0x87, 0x41, 0xff, 0xbf, + 0xff, 0xbb, 0xc0, 0x91, 0x02, 0x2f, 0x37, 0x30, 0x2f, 0x2e, 0x69, 0xf5, 0xb8, 0x8f, 0x06, 0x32, 0xc7, 0x41, 0xfe, + 0x09, 0xc0, 0xb3, 0x04, 0x2f, 0x17, 0x30, 0x2f, 0x2e, 0x95, 0x01, 0x2d, 0x2e, 0x61, 0xf5, 0xf6, 0x6f, 0xe7, 0x6f, + 0xe0, 0x5f, 0xc8, 0x2e, 0x30, 0x50, 0xe5, 0x7f, 0xf6, 0x7f, 0xd7, 0x7f, 0x00, 0x2e, 0x35, 0x5a, 0x00, 0x2e, 0x46, + 0x41, 0x6f, 0xbf, 0x6f, 0xbb, 0x80, 0x91, 0x02, 0x2f, 0x36, 0x30, 0x2d, 0x2e, 0x69, 0xf5, 0x46, 0x30, 0x0f, 0x2e, + 0xa4, 0xf1, 0xbe, 0x09, 0x77, 0x8b, 0x80, 0xb3, 0x06, 0x2f, 0x0d, 0x2e, 0x6b, 0x01, 0x84, 0xaf, 0x02, 0x2f, 0x16, + 0x30, 0x2d, 0x2e, 0xde, 0x00, 0x86, 0x30, 0x46, 0x43, 0x00, 0x2e, 0xf6, 0x6f, 0xe5, 0x6f, 0xd7, 0x6f, 0xd0, 0x5f, + 0xc8, 0x2e, 0x10, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x56, 0xc7, 0x98, 0x2e, 0x49, 0xc3, 0x02, 0x30, 0x30, 0x30, 0x11, + 0x30, 0xfb, 0x6f, 0xf0, 0x5f, 0x25, 0x2e, 0x7e, 0x00, 0x25, 0x2e, 0xce, 0x00, 0x21, 0x2e, 0xdf, 0x00, 0x23, 0x2e, + 0x7c, 0x00, 0x23, 0x2e, 0xfe, 0x00, 0x21, 0x2e, 0x78, 0x01, 0xb8, 0x2e, 0x11, 0x30, 0x81, 0x08, 0x01, 0x2e, 0x6a, + 0xf7, 0x71, 0x3f, 0x23, 0xbd, 0x01, 0x08, 0x02, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x6a, 0xf7, 0x40, 0x50, 0x98, 0x2e, + 0xbd, 0x0e, 0x50, 0x32, 0x98, 0x2e, 0x48, 0x03, 0x00, 0x30, 0xf0, 0x7f, 0xe0, 0x7f, 0x21, 0x2e, 0x69, 0xf5, 0x00, + 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x00, 0x2e, 0x01, 0x80, 0x08, 0xa2, 0xfb, 0x2f, 0x05, 0x2e, 0xa8, 0x00, 0x2f, 0xbc, + 0xae, 0xbc, 0xad, 0xbd, 0x0f, 0xb8, 0x9f, 0xb8, 0x01, 0x0a, 0x05, 0x2e, 0x93, 0x00, 0xbf, 0xb9, 0xaf, 0xb8, 0x03, + 0x0a, 0x01, 0x0a, 0x21, 0x2e, 0x7a, 0x00, 0x98, 0x2e, 0xeb, 0xb5, 0x03, 0x2e, 0x9d, 0x01, 0x21, 0x2e, 0x7b, 0x00, + 0x40, 0xb2, 0x1a, 0x2f, 0x05, 0x2e, 0x8a, 0x00, 0x01, 0x52, 0x98, 0x2e, 0xc7, 0xc1, 0x03, 0x2e, 0xa8, 0x00, 0x9c, + 0xbc, 0x9f, 0xb8, 0x23, 0x2e, 0xdd, 0x00, 0x40, 0x90, 0xf0, 0x7f, 0x03, 0x2f, 0x01, 0x52, 0x98, 0x2e, 0x4c, 0xb6, + 0x03, 0x2d, 0x03, 0x52, 0x98, 0x2e, 0x4c, 0xb6, 0xe0, 0x7f, 0x98, 0x2e, 0x4b, 0x02, 0x10, 0x30, 0x21, 0x2e, 0x7c, + 0x00, 0x01, 0x2e, 0x99, 0x01, 0x00, 0xb2, 0x07, 0x2f, 0x01, 0x2e, 0x7b, 0x00, 0x00, 0xb2, 0x03, 0x2f, 0x05, 0x50, + 0x07, 0x52, 0x98, 0x2e, 0x07, 0xcc, 0x01, 0x2e, 0x87, 0x01, 0x00, 0xb2, 0x35, 0x2f, 0x05, 0x2e, 0x8a, 0x00, 0x09, + 0x52, 0x98, 0x2e, 0xc7, 0xc1, 0x03, 0x2e, 0x93, 0x01, 0x40, 0xb2, 0xf0, 0x7f, 0x08, 0x2f, 0x01, 0x2e, 0x7b, 0x00, + 0x00, 0xb2, 0x04, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x93, 0x01, 0x98, 0x2e, 0x88, 0xb5, 0x01, 0x2e, 0x79, 0x00, 0x00, + 0xb2, 0x1e, 0x2f, 0x98, 0x2e, 0x78, 0xb4, 0x98, 0x2e, 0x49, 0xb5, 0x09, 0x50, 0x98, 0x2e, 0x4d, 0xc3, 0x09, 0x50, + 0x98, 0x2e, 0x5a, 0xc7, 0x98, 0x2e, 0xf9, 0x02, 0x81, 0x3f, 0x01, 0x2e, 0x79, 0x01, 0x01, 0x08, 0x09, 0x52, 0xd0, + 0x7f, 0x21, 0x2e, 0x79, 0x01, 0x98, 0x2e, 0xff, 0xc5, 0xd1, 0x6f, 0x08, 0x0a, 0x21, 0x2e, 0x79, 0x01, 0x98, 0x2e, + 0xc3, 0xb1, 0x10, 0x30, 0x21, 0x2e, 0x7c, 0x00, 0x01, 0x2e, 0x95, 0x01, 0x00, 0xb2, 0x04, 0x2f, 0x98, 0x2e, 0x2e, + 0x02, 0x00, 0x30, 0x21, 0x2e, 0x95, 0x01, 0x01, 0x2e, 0x6b, 0x01, 0x04, 0xae, 0x0b, 0x2f, 0x01, 0x2e, 0x87, 0x01, + 0x00, 0xb2, 0x07, 0x2f, 0x09, 0x52, 0x98, 0x2e, 0x74, 0x0e, 0x00, 0xb2, 0x02, 0x2f, 0x10, 0x30, 0x21, 0x2e, 0xd7, + 0x00, 0x01, 0x2e, 0xd7, 0x00, 0x00, 0x90, 0x90, 0x2e, 0x72, 0xb1, 0x01, 0x2e, 0x6e, 0x01, 0x00, 0xb2, 0x04, 0x2f, + 0x98, 0x2e, 0x15, 0x0e, 0x00, 0x30, 0x21, 0x2e, 0xde, 0x00, 0x01, 0x2e, 0xde, 0x00, 0x00, 0xb2, 0x12, 0x2f, 0x01, + 0x2e, 0x6b, 0x01, 0x00, 0x90, 0x02, 0x2f, 0x98, 0x2e, 0x05, 0x0e, 0x09, 0x2d, 0x98, 0x2e, 0x5d, 0x0d, 0x01, 0x2e, + 0x6b, 0x01, 0x04, 0x90, 0x02, 0x2f, 0x50, 0x32, 0x98, 0x2e, 0x48, 0x03, 0x00, 0x30, 0x21, 0x2e, 0xde, 0x00, 0x01, + 0x2e, 0xd6, 0x00, 0x00, 0xb2, 0x90, 0x2e, 0x8a, 0xb1, 0x01, 0x2e, 0xd6, 0x00, 0x01, 0x31, 0x01, 0x08, 0x00, 0xb2, + 0x04, 0x2f, 0x98, 0x2e, 0x47, 0xcb, 0x10, 0x30, 0x21, 0x2e, 0x7c, 0x00, 0x81, 0x30, 0x01, 0x2e, 0xd6, 0x00, 0x01, + 0x08, 0x00, 0xb2, 0x61, 0x2f, 0x03, 0x2e, 0x89, 0x00, 0x01, 0x2e, 0x6b, 0x01, 0x98, 0xbc, 0x98, 0xb8, 0x05, 0xb2, + 0x13, 0x58, 0x23, 0x2f, 0x07, 0x90, 0x0d, 0x54, 0x00, 0x30, 0x37, 0x2f, 0x15, 0x41, 0x04, 0x41, 0xdc, 0xbe, 0x44, + 0xbe, 0xdc, 0xba, 0x2c, 0x01, 0x61, 0x00, 0x13, 0x56, 0x4a, 0x0f, 0x0c, 0x2f, 0xd1, 0x42, 0x94, 0xb8, 0xc1, 0x42, + 0x11, 0x30, 0x05, 0x2e, 0x6a, 0xf7, 0x2c, 0xbd, 0x2f, 0xb9, 0x80, 0xb2, 0x08, 0x22, 0x98, 0x2e, 0xf5, 0x03, 0x21, + 0x2d, 0x61, 0x30, 0x23, 0x2e, 0x6b, 0x01, 0x98, 0x2e, 0xf5, 0x03, 0x00, 0x30, 0x21, 0x2e, 0x5a, 0xf5, 0x18, 0x2d, + 0xd1, 0x7f, 0x50, 0x30, 0x98, 0x2e, 0x48, 0x03, 0x13, 0x52, 0x0b, 0x50, 0x50, 0x42, 0x70, 0x30, 0x11, 0x54, 0x42, + 0x42, 0x7e, 0x82, 0xd2, 0x6f, 0x80, 0xb2, 0x42, 0x42, 0x05, 0x2f, 0x21, 0x2e, 0x6b, 0x01, 0x10, 0x30, 0x98, 0x2e, + 0xf5, 0x03, 0x03, 0x2d, 0x60, 0x30, 0x21, 0x2e, 0x6b, 0x01, 0x01, 0x2e, 0x6b, 0x01, 0x06, 0x90, 0x18, 0x2f, 0x01, + 0x2e, 0x78, 0x00, 0x0f, 0x54, 0x0b, 0x52, 0xd0, 0x7f, 0x98, 0x2e, 0x7a, 0xc1, 0xd1, 0x6f, 0x08, 0x1a, 0x40, 0x30, + 0x08, 0x2f, 0x21, 0x2e, 0x6b, 0x01, 0x20, 0x30, 0x98, 0x2e, 0x24, 0xb6, 0x50, 0x32, 0x98, 0x2e, 0x48, 0x03, 0x05, + 0x2d, 0x98, 0x2e, 0x1e, 0x0e, 0x00, 0x30, 0x21, 0x2e, 0x6b, 0x01, 0x41, 0x30, 0x01, 0x2e, 0xd6, 0x00, 0x01, 0x08, + 0x00, 0xb2, 0x26, 0x2f, 0x01, 0x2e, 0x71, 0x01, 0x00, 0xb2, 0x0d, 0x2f, 0x01, 0x90, 0x1d, 0x2f, 0x05, 0x2e, 0xbf, + 0x00, 0x07, 0x2e, 0x72, 0x01, 0xa1, 0x32, 0x17, 0x58, 0x98, 0x2e, 0xae, 0xb7, 0x00, 0x30, 0x21, 0x2e, 0x71, 0x01, + 0x12, 0x2d, 0x15, 0x58, 0xa3, 0x32, 0x10, 0x41, 0x11, 0x41, 0x18, 0xb9, 0x04, 0x41, 0x98, 0xbc, 0x41, 0x0a, 0x94, + 0x0a, 0x98, 0x2e, 0xa0, 0xb7, 0x11, 0x30, 0x21, 0x2e, 0x72, 0x01, 0x21, 0x2e, 0x7b, 0x01, 0x23, 0x2e, 0x71, 0x01, + 0x10, 0x30, 0x21, 0x2e, 0x7c, 0x00, 0x00, 0x30, 0x21, 0x2e, 0xd6, 0x00, 0x18, 0x2d, 0x01, 0x2e, 0x6b, 0x01, 0x03, + 0xaa, 0x01, 0x2f, 0x98, 0x2e, 0x2b, 0x0e, 0x01, 0x2e, 0x6b, 0x01, 0x3f, 0x80, 0x03, 0xa2, 0x01, 0x2f, 0x00, 0x2e, + 0x02, 0x2d, 0x98, 0x2e, 0x41, 0x0e, 0x30, 0x30, 0x98, 0x2e, 0x38, 0xb6, 0x00, 0x30, 0x21, 0x2e, 0xd7, 0x00, 0x50, + 0x32, 0x98, 0x2e, 0x48, 0x03, 0x01, 0x2e, 0x7c, 0x00, 0x00, 0xb2, 0x29, 0x2f, 0x98, 0x2e, 0xf5, 0xcb, 0x03, 0x2e, + 0x6c, 0x01, 0x19, 0x54, 0x41, 0x0a, 0xbc, 0x84, 0x23, 0x2e, 0x7a, 0x01, 0x83, 0x80, 0x74, 0x30, 0x23, 0x40, 0x05, + 0x40, 0x1b, 0x50, 0x81, 0x40, 0xdc, 0x08, 0x18, 0xb9, 0x11, 0x42, 0xd3, 0xbe, 0xe4, 0x6f, 0xc5, 0xbc, 0xdd, 0x0a, + 0x12, 0x42, 0x59, 0x0a, 0x11, 0x42, 0xd0, 0x7f, 0xf1, 0x31, 0x00, 0x40, 0xf2, 0x6f, 0x25, 0xbd, 0x01, 0x08, 0x02, + 0x0a, 0xc0, 0x7f, 0x98, 0x2e, 0xa8, 0xcf, 0x06, 0xbc, 0xc1, 0x6f, 0xd2, 0x6f, 0x08, 0x0a, 0x80, 0x42, 0x98, 0x2e, + 0x0c, 0x02, 0x00, 0x30, 0x21, 0x2e, 0x9d, 0x01, 0x21, 0x2e, 0x99, 0x01, 0x21, 0x2e, 0x7c, 0x00, 0x21, 0x2e, 0x87, + 0x01, 0x80, 0x2e, 0x09, 0xb0, 0x01, 0x2e, 0x80, 0x01, 0x01, 0x40, 0x90, 0x50, 0x9f, 0xbd, 0x13, 0xbd, 0xbf, 0xb9, + 0x2c, 0xb9, 0xfb, 0x7f, 0xe2, 0x7f, 0xc0, 0xb2, 0x0b, 0x30, 0x62, 0x2f, 0x07, 0x2e, 0xce, 0x00, 0x31, 0x54, 0xc0, + 0x90, 0x0b, 0x2f, 0x9b, 0x42, 0xc1, 0x86, 0x9b, 0x42, 0x27, 0x2e, 0xce, 0x00, 0x37, 0x2e, 0xcf, 0x00, 0x37, 0x2e, + 0xd0, 0x00, 0x37, 0x2e, 0xd1, 0x00, 0x8b, 0x42, 0x01, 0x84, 0x17, 0xbc, 0x83, 0x40, 0x32, 0xbd, 0x99, 0xbc, 0x9a, + 0xba, 0xba, 0xbd, 0x0e, 0xb8, 0x28, 0xb9, 0xba, 0xb9, 0x09, 0x58, 0x1a, 0x25, 0x0d, 0x2e, 0xcf, 0x00, 0x77, 0x82, + 0x85, 0x7f, 0xa6, 0x7f, 0x74, 0x7f, 0x93, 0x7f, 0xd2, 0x7f, 0xc0, 0x7f, 0x98, 0x2e, 0xd1, 0xc3, 0x03, 0x2e, 0xcf, + 0x00, 0x08, 0x1a, 0xb0, 0x7f, 0x01, 0x30, 0x01, 0x2f, 0x23, 0x2e, 0xd1, 0x00, 0x01, 0x2e, 0xd1, 0x00, 0xd1, 0x6f, + 0x41, 0x0e, 0x14, 0x2f, 0xc1, 0x6f, 0x40, 0xb2, 0x0b, 0x2f, 0x43, 0xb2, 0x09, 0x2f, 0x09, 0x54, 0x31, 0x56, 0x98, + 0x2e, 0x0b, 0xc4, 0x00, 0x90, 0x06, 0x2f, 0xb1, 0x6f, 0x23, 0x2e, 0xd0, 0x00, 0x03, 0x2d, 0xb1, 0x6f, 0x23, 0x2e, + 0xd0, 0x00, 0xd1, 0x6f, 0x23, 0x2e, 0xd1, 0x00, 0x03, 0x2e, 0xd1, 0x00, 0x41, 0x82, 0x23, 0x2e, 0xd1, 0x00, 0x09, + 0x50, 0x31, 0x52, 0x12, 0x40, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x40, 0x42, + 0x00, 0x2e, 0x03, 0x2e, 0xd0, 0x00, 0xe0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0xb1, 0x6f, 0x23, 0x2e, 0xcf, 0x00, 0x06, + 0x2d, 0x37, 0x2e, 0xce, 0x00, 0xe0, 0x6f, 0x01, 0x30, 0x98, 0x2e, 0x95, 0xcf, 0xfb, 0x6f, 0x70, 0x5f, 0xb8, 0x2e, + 0xd0, 0x50, 0x80, 0x7f, 0x91, 0x7f, 0xd7, 0x7f, 0xc5, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0xe4, 0x7f, 0xf6, 0x7f, 0x7b, + 0x7f, 0x00, 0x2e, 0x35, 0x50, 0x00, 0x2e, 0x01, 0x40, 0x9f, 0xbc, 0x9f, 0xb8, 0x40, 0x90, 0x02, 0x2f, 0x31, 0x30, + 0x23, 0x2e, 0x69, 0xf5, 0x38, 0x82, 0x61, 0x7f, 0x20, 0x30, 0x41, 0x40, 0x23, 0x2e, 0xd6, 0x00, 0x03, 0x2e, 0xd6, + 0x00, 0x08, 0x08, 0x00, 0xb2, 0x11, 0x2f, 0x33, 0x50, 0x1a, 0x25, 0x12, 0x40, 0x32, 0x7f, 0x73, 0x82, 0x12, 0x40, + 0x42, 0x7f, 0x00, 0x2e, 0x00, 0x40, 0x50, 0x7f, 0x98, 0x2e, 0x6a, 0xd6, 0x01, 0x2e, 0x61, 0xf7, 0x01, 0x31, 0x01, + 0x0a, 0x21, 0x2e, 0x61, 0xf7, 0x80, 0x30, 0x03, 0x2e, 0xd6, 0x00, 0x08, 0x08, 0x00, 0xb2, 0x40, 0x2f, 0x03, 0x2e, + 0x89, 0x00, 0x17, 0xbc, 0x96, 0xbc, 0x0f, 0xb8, 0x9f, 0xb8, 0x40, 0x90, 0x21, 0x2e, 0x6f, 0x01, 0x10, 0x30, 0x01, + 0x30, 0x2a, 0x2f, 0x03, 0x2e, 0x6b, 0x01, 0x44, 0xb2, 0x05, 0x2f, 0x47, 0xb2, 0x00, 0x30, 0x2d, 0x2f, 0x21, 0x2e, + 0xd6, 0x00, 0x2b, 0x2d, 0x03, 0x2e, 0xfd, 0xf5, 0x9e, 0xbc, 0x9f, 0xb8, 0x40, 0x90, 0x14, 0x2f, 0x03, 0x2e, 0xfc, + 0xf5, 0x99, 0xbc, 0x9f, 0xb8, 0x40, 0x90, 0x0e, 0x2f, 0x03, 0x2e, 0x49, 0xf1, 0x37, 0x54, 0x4a, 0x08, 0x40, 0x90, + 0x08, 0x2f, 0x98, 0x2e, 0xe9, 0x01, 0x00, 0xb2, 0x10, 0x30, 0x03, 0x2f, 0x50, 0x30, 0x21, 0x2e, 0x6b, 0x01, 0x10, + 0x2d, 0x98, 0x2e, 0x24, 0xb6, 0x00, 0x30, 0x21, 0x2e, 0xd6, 0x00, 0x0a, 0x2d, 0x05, 0x2e, 0x69, 0xf7, 0x2d, 0xbd, + 0x2f, 0xb9, 0x80, 0xb2, 0x01, 0x2f, 0x21, 0x2e, 0xd7, 0x00, 0x23, 0x2e, 0xd6, 0x00, 0x60, 0x6f, 0xe1, 0x31, 0x01, + 0x42, 0x00, 0x2e, 0xf6, 0x6f, 0xe4, 0x6f, 0x80, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc5, 0x6f, 0xd7, 0x6f, + 0x7b, 0x6f, 0x30, 0x5f, 0xc8, 0x2e, 0xa0, 0x50, 0x82, 0x7f, 0x90, 0x7f, 0xd7, 0x7f, 0xc5, 0x7f, 0xb3, 0x7f, 0xa1, + 0x7f, 0xe4, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x35, 0x54, 0x00, 0x2e, 0x80, 0x40, 0x0f, 0xbc, 0x0f, 0xb8, + 0x00, 0x90, 0x02, 0x2f, 0x30, 0x30, 0x21, 0x2e, 0x69, 0xf5, 0xb7, 0x84, 0x62, 0x7f, 0x98, 0x2e, 0xe9, 0x01, 0x00, + 0xb2, 0x90, 0x2e, 0x7f, 0xb3, 0x05, 0x2e, 0xa0, 0x00, 0x03, 0x2e, 0x8c, 0x00, 0x01, 0x2e, 0x8e, 0x00, 0xa3, 0xbd, + 0x9f, 0xb8, 0x0f, 0xb8, 0x08, 0x0a, 0xbf, 0xb9, 0xa4, 0xbc, 0x03, 0x0a, 0x22, 0xbe, 0x9f, 0xb8, 0x07, 0x2e, 0x96, + 0x00, 0x41, 0x0a, 0x4f, 0xba, 0x05, 0x2e, 0x98, 0x00, 0xb3, 0xbd, 0x0c, 0x0b, 0x01, 0x2e, 0x90, 0x00, 0xbf, 0xb9, + 0x2f, 0xbd, 0x03, 0x2e, 0x9f, 0x00, 0x2f, 0xb9, 0x0f, 0xbc, 0xe3, 0x0a, 0x0f, 0xb8, 0x9f, 0xbc, 0x9a, 0x0a, 0x9f, + 0xb8, 0x90, 0x0a, 0x91, 0x0a, 0x25, 0x2e, 0x79, 0x00, 0x05, 0x2e, 0xc1, 0xf5, 0x2e, 0xbd, 0x2e, 0xb9, 0x01, 0x2e, + 0x7b, 0x00, 0x31, 0x30, 0x8a, 0x04, 0x00, 0x90, 0x0b, 0x2f, 0x01, 0x2e, 0x6b, 0x01, 0x04, 0xa2, 0x07, 0x2f, 0x01, + 0x2e, 0x79, 0x00, 0x00, 0x90, 0x03, 0x2f, 0x01, 0x2e, 0xd9, 0x00, 0x00, 0xb2, 0x19, 0x2f, 0x3b, 0x50, 0x09, 0x52, + 0x98, 0x2e, 0x01, 0x02, 0x05, 0x2e, 0xd8, 0x00, 0x25, 0x2e, 0x87, 0x01, 0x05, 0x2e, 0xd8, 0x00, 0x80, 0x90, 0x02, + 0x2f, 0x12, 0x30, 0x25, 0x2e, 0xd8, 0x00, 0x01, 0x2e, 0xd9, 0x00, 0x00, 0xb2, 0x10, 0x30, 0x05, 0x2e, 0x79, 0x00, + 0x01, 0x2f, 0x21, 0x2e, 0x79, 0x00, 0x25, 0x2e, 0xd9, 0x00, 0x98, 0x2e, 0xf2, 0x01, 0x00, 0xb2, 0x22, 0x30, 0x21, + 0x30, 0x03, 0x2f, 0x01, 0x2e, 0x7b, 0x00, 0x00, 0x90, 0x05, 0x2f, 0x01, 0x2e, 0x7a, 0x00, 0x00, 0x90, 0x30, 0x30, + 0x01, 0x30, 0x41, 0x22, 0x01, 0x2e, 0x94, 0x01, 0x08, 0x1a, 0x0e, 0x2f, 0x23, 0x2e, 0x94, 0x01, 0x33, 0x30, 0x3d, + 0x50, 0x0b, 0x09, 0x01, 0x40, 0x39, 0x56, 0x46, 0xbe, 0x4b, 0x08, 0x4c, 0x0a, 0x01, 0x42, 0x0a, 0x80, 0x25, 0x52, + 0x01, 0x42, 0x00, 0x2e, 0x01, 0x2e, 0x79, 0x00, 0x00, 0xb2, 0x1f, 0x2f, 0x03, 0x2e, 0xc0, 0xf5, 0xf0, 0x30, 0x48, + 0x08, 0x47, 0xaa, 0x74, 0x30, 0x07, 0x2e, 0xdc, 0x00, 0x61, 0x22, 0x4b, 0x1a, 0x05, 0x2f, 0x07, 0x2e, 0x66, 0xf5, + 0xbf, 0xbd, 0xbf, 0xb9, 0xc0, 0x90, 0x0b, 0x2f, 0x3f, 0x56, 0x04, 0x30, 0xd4, 0x42, 0xd2, 0x42, 0x81, 0x04, 0x24, + 0xbd, 0xfe, 0x80, 0x81, 0x84, 0xc4, 0x42, 0x23, 0x2e, 0xdc, 0x00, 0x02, 0x42, 0x02, 0x32, 0x25, 0x2e, 0x62, 0xf5, + 0x05, 0x2e, 0x6d, 0x01, 0x81, 0x80, 0x03, 0x2e, 0x8a, 0x00, 0x21, 0x2e, 0x6d, 0x01, 0x0f, 0x56, 0x62, 0x6f, 0x4b, + 0x08, 0x00, 0x31, 0x80, 0x42, 0x40, 0xb2, 0x0b, 0x2f, 0xf2, 0x3e, 0x01, 0x2e, 0xca, 0xf5, 0x82, 0x08, 0x25, 0x2e, + 0xca, 0xf5, 0x05, 0x2e, 0x59, 0xf5, 0xe0, 0x3f, 0x90, 0x08, 0x25, 0x2e, 0x59, 0xf5, 0xf6, 0x6f, 0xe4, 0x6f, 0xa1, + 0x6f, 0xb3, 0x6f, 0xc5, 0x6f, 0xd7, 0x6f, 0x7b, 0x6f, 0x82, 0x6f, 0x90, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0xc0, 0x50, + 0x80, 0x7f, 0x92, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa1, 0x7f, 0xe7, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, + 0x2e, 0x35, 0x50, 0x00, 0x2e, 0x02, 0x40, 0x2f, 0xbd, 0x2f, 0xb9, 0x80, 0x90, 0x02, 0x2f, 0x32, 0x30, 0x25, 0x2e, + 0x69, 0xf5, 0x37, 0x80, 0x00, 0x2e, 0x00, 0x40, 0x60, 0x7f, 0x98, 0x2e, 0xe9, 0x01, 0x0b, 0x30, 0x5b, 0x7f, 0x40, + 0x7f, 0x02, 0x32, 0x64, 0x6f, 0x25, 0x52, 0x43, 0x56, 0x0b, 0x30, 0x80, 0x2e, 0x65, 0xb4, 0x62, 0x09, 0x40, 0xb3, + 0x0b, 0x2f, 0x00, 0xb2, 0x03, 0x2f, 0x0b, 0x2e, 0x79, 0x00, 0x40, 0x91, 0x03, 0x2f, 0xc2, 0x8a, 0x25, 0x2e, 0x64, + 0xf5, 0x4b, 0x43, 0x25, 0x2e, 0x60, 0xf5, 0x21, 0x09, 0x00, 0xb3, 0x79, 0x2f, 0x98, 0x2e, 0xf2, 0x01, 0x00, 0xb2, + 0x06, 0x2f, 0x01, 0x2e, 0x7b, 0x00, 0x00, 0xb2, 0x02, 0x2f, 0x40, 0x6f, 0x00, 0x90, 0x0a, 0x2f, 0x01, 0x2e, 0xdb, + 0x00, 0x00, 0x90, 0x19, 0x2f, 0x10, 0x30, 0x21, 0x2e, 0xdb, 0x00, 0x00, 0x30, 0x98, 0x2e, 0x0d, 0xb6, 0x13, 0x2d, + 0x01, 0x2e, 0xc3, 0xf5, 0x0c, 0xbc, 0x0f, 0xb8, 0x12, 0x30, 0x10, 0x04, 0x03, 0xb0, 0x26, 0x25, 0x45, 0x50, 0x07, + 0x52, 0x98, 0x2e, 0x01, 0x02, 0x10, 0x30, 0x21, 0x2e, 0x99, 0x01, 0x02, 0x30, 0x50, 0x7f, 0x25, 0x2e, 0xdb, 0x00, + 0x40, 0x6f, 0x00, 0xb2, 0x03, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x0e, 0x2f, 0x05, 0x2e, 0xda, 0x00, 0x80, + 0x90, 0x36, 0x2f, 0x11, 0x30, 0x02, 0x30, 0x23, 0x2e, 0xda, 0x00, 0x23, 0x2e, 0x74, 0x01, 0x25, 0x2e, 0x7d, 0x00, + 0x25, 0x2e, 0x9e, 0x01, 0x2c, 0x2d, 0x05, 0x2e, 0x9e, 0x01, 0x81, 0x82, 0x23, 0x2e, 0x9e, 0x01, 0x12, 0x30, 0x4a, + 0x08, 0x40, 0xb2, 0x05, 0x2f, 0x03, 0x2e, 0x58, 0xf5, 0x98, 0xbc, 0x9e, 0xb8, 0x43, 0x90, 0x1a, 0x2f, 0x01, 0x2e, + 0xc1, 0xf5, 0x0e, 0xbd, 0x30, 0x30, 0x2e, 0xb9, 0x82, 0x04, 0x01, 0x52, 0x47, 0x50, 0x62, 0x7f, 0x98, 0x2e, 0x01, + 0x02, 0x01, 0x2e, 0xdd, 0x00, 0x01, 0x90, 0x49, 0x50, 0x03, 0x52, 0x02, 0x2f, 0x62, 0x6f, 0x98, 0x2e, 0x01, 0x02, + 0x12, 0x30, 0x25, 0x2e, 0x9d, 0x01, 0x00, 0x30, 0x21, 0x2e, 0xda, 0x00, 0x40, 0x6f, 0x52, 0x7f, 0x00, 0x2e, 0x52, + 0x6f, 0x80, 0x90, 0x05, 0x2f, 0x02, 0x30, 0x25, 0x2e, 0x94, 0x01, 0x25, 0x54, 0x25, 0x2e, 0x64, 0xf5, 0x25, 0x52, + 0x23, 0x2e, 0x60, 0xf5, 0x02, 0x32, 0x43, 0x56, 0x0b, 0x30, 0x00, 0x90, 0x0b, 0x2f, 0x37, 0x2e, 0xd8, 0x00, 0x41, + 0x50, 0x21, 0x2e, 0x5a, 0xf2, 0x98, 0x2e, 0xdd, 0x03, 0x40, 0x6f, 0x02, 0x32, 0x25, 0x52, 0x43, 0x56, 0x0b, 0x30, + 0x09, 0x2e, 0x60, 0xf5, 0x62, 0x09, 0x40, 0x91, 0x90, 0x2e, 0xc9, 0xb3, 0x61, 0x09, 0x40, 0x91, 0x90, 0x2e, 0xc9, + 0xb3, 0x80, 0x6f, 0x92, 0x6f, 0xa1, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0x7b, 0x6f, 0xf6, 0x6f, 0xe7, 0x6f, + 0x40, 0x5f, 0xc8, 0x2e, 0x4b, 0x52, 0x00, 0x51, 0x52, 0x40, 0x47, 0x40, 0xf8, 0xbc, 0x9c, 0xb9, 0x01, 0x2e, 0x9f, + 0x00, 0xf3, 0x7f, 0x8f, 0xbd, 0x3f, 0xba, 0x1a, 0x25, 0x78, 0xb8, 0x59, 0x56, 0xd3, 0x08, 0x75, 0x8c, 0x73, 0x8a, + 0xeb, 0x7f, 0xfc, 0xbf, 0xd4, 0x7f, 0x0b, 0x30, 0xfc, 0xbb, 0x1c, 0x0b, 0x4b, 0x7f, 0x8b, 0x43, 0x4b, 0x43, 0x21, + 0x2e, 0xe4, 0x00, 0x00, 0xb3, 0xa7, 0x7f, 0xb5, 0x7f, 0xc6, 0x7f, 0x93, 0x7f, 0x90, 0x2e, 0x35, 0xb5, 0x01, 0x2e, + 0xfe, 0x00, 0x00, 0xb2, 0x0b, 0x2f, 0x4f, 0x52, 0x01, 0x2e, 0xf9, 0x00, 0x82, 0x7f, 0x98, 0x2e, 0xbb, 0xcc, 0x0b, + 0x30, 0x37, 0x2e, 0xfe, 0x00, 0x82, 0x6f, 0x93, 0x6f, 0x1a, 0x25, 0xc0, 0xb2, 0x8b, 0x7f, 0x14, 0x2f, 0x26, 0xbc, + 0x25, 0xbd, 0x06, 0xb8, 0x2f, 0xb9, 0x80, 0xb2, 0x14, 0xb0, 0x0c, 0x2f, 0x51, 0x50, 0x53, 0x54, 0x0b, 0x30, 0x0b, + 0x2e, 0xa0, 0x00, 0x57, 0x58, 0x1b, 0x42, 0x9b, 0x42, 0x6c, 0x09, 0x2b, 0x2e, 0xa0, 0x00, 0x0b, 0x42, 0x8b, 0x42, + 0x86, 0x7f, 0x70, 0x84, 0x5b, 0x50, 0xd8, 0x08, 0x55, 0x52, 0x09, 0x50, 0x72, 0x7f, 0x63, 0x7f, 0x98, 0x2e, 0xc2, + 0xc0, 0xd1, 0x6f, 0x62, 0x6f, 0xd1, 0x0a, 0x01, 0x2e, 0xf9, 0x00, 0xc5, 0x6f, 0xb4, 0x6f, 0x72, 0x6f, 0x4f, 0x52, + 0x4d, 0x5c, 0x98, 0x2e, 0x06, 0xcd, 0x53, 0x6f, 0x90, 0x6f, 0x51, 0x52, 0xc0, 0xb2, 0x04, 0xbd, 0x54, 0x40, 0xaf, + 0xb9, 0x45, 0x40, 0xd1, 0x7f, 0x02, 0x30, 0x06, 0x2f, 0xc0, 0xb2, 0x02, 0x30, 0x03, 0x2f, 0x53, 0x5c, 0x12, 0x30, + 0x94, 0x43, 0x85, 0x43, 0x03, 0xbf, 0x6f, 0xbb, 0x80, 0xb3, 0x20, 0x2f, 0x36, 0x6f, 0x26, 0x01, 0x46, 0x6f, 0x6e, + 0x03, 0x45, 0x42, 0xc0, 0x90, 0x29, 0x2e, 0xfa, 0x00, 0x53, 0x52, 0x14, 0x2f, 0x53, 0x5c, 0x00, 0x2e, 0x93, 0x41, + 0x86, 0x41, 0xe3, 0x04, 0xae, 0x07, 0x80, 0xab, 0x04, 0x2f, 0x80, 0x91, 0x0a, 0x2f, 0x86, 0x6f, 0x73, 0x0f, 0x07, + 0x2f, 0x83, 0x6f, 0xc0, 0xb2, 0x04, 0x2f, 0x54, 0x42, 0x45, 0x42, 0x12, 0x30, 0x04, 0x2c, 0x11, 0x30, 0x02, 0x2c, + 0x11, 0x30, 0x11, 0x30, 0x02, 0xbc, 0x0f, 0xb8, 0xc2, 0x7f, 0x00, 0x90, 0x06, 0x2f, 0x31, 0x30, 0x23, 0x2e, 0x78, + 0x01, 0x23, 0x2e, 0xdf, 0x00, 0x0b, 0x2c, 0x01, 0x30, 0x01, 0x2e, 0xdf, 0x00, 0x05, 0x2e, 0x78, 0x01, 0x10, 0x1a, + 0x02, 0x2f, 0x21, 0x2e, 0x78, 0x01, 0x01, 0x2d, 0x01, 0x30, 0xf0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0xc1, 0x6f, 0xa0, + 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0xd2, 0x6f, 0x21, 0x52, 0x01, 0x2e, 0xfa, 0x00, 0x82, 0x40, 0x50, 0x42, 0x11, 0x2c, + 0x42, 0x42, 0x10, 0x30, 0x31, 0x30, 0x21, 0x2e, 0xfe, 0x00, 0x23, 0x2e, 0x78, 0x01, 0x23, 0x2e, 0xdf, 0x00, 0xf0, + 0x6f, 0x01, 0x30, 0x98, 0x2e, 0x95, 0xcf, 0xa0, 0x6f, 0x01, 0x30, 0x98, 0x2e, 0x95, 0xcf, 0x00, 0x2e, 0xeb, 0x6f, + 0x00, 0x5f, 0xb8, 0x2e, 0x07, 0x2e, 0x9f, 0x00, 0x3b, 0xbc, 0x60, 0x50, 0xbf, 0xbd, 0x0c, 0xb8, 0xf0, 0x7f, 0xc0, + 0xb2, 0xeb, 0x7f, 0x2d, 0x2f, 0x07, 0x2e, 0xff, 0x00, 0xc3, 0x40, 0x01, 0x2e, 0x69, 0x01, 0x03, 0x1a, 0x11, 0x2f, + 0x5f, 0x52, 0x27, 0x2e, 0x69, 0x01, 0x50, 0x40, 0xa0, 0x7f, 0x78, 0x80, 0x43, 0x40, 0xd0, 0x7f, 0xb3, 0x7f, 0x98, + 0x2e, 0x64, 0xcf, 0xd0, 0x6f, 0x07, 0x80, 0xa3, 0x6f, 0x13, 0x42, 0x00, 0x2e, 0xb3, 0x6f, 0x03, 0x42, 0x03, 0x30, + 0x01, 0x2e, 0xdf, 0x00, 0x01, 0xb2, 0x01, 0x2f, 0x02, 0x90, 0x00, 0x2f, 0x13, 0x30, 0x1a, 0x25, 0x7c, 0x88, 0x01, + 0x2e, 0xff, 0x00, 0x5d, 0x52, 0x09, 0x54, 0x98, 0x2e, 0xc4, 0xce, 0xc1, 0x6f, 0xf0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, + 0x04, 0x2d, 0x01, 0x30, 0xf0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0xeb, 0x6f, 0xa0, 0x5f, 0xb8, 0x2e, 0x60, 0x51, 0x0a, + 0x25, 0x36, 0x88, 0xf4, 0x7f, 0xeb, 0x7f, 0x00, 0x32, 0x6b, 0x52, 0x32, 0x30, 0x13, 0x30, 0x98, 0x2e, 0x15, 0xcb, + 0x0a, 0x25, 0x33, 0x84, 0xd2, 0x7f, 0x43, 0x30, 0x09, 0x50, 0x67, 0x52, 0x98, 0x2e, 0x95, 0xc1, 0xd2, 0x6f, 0x61, + 0x52, 0x98, 0x2e, 0xd7, 0xc7, 0x2a, 0x25, 0xb0, 0x86, 0xc0, 0x7f, 0xd3, 0x7f, 0xaf, 0x84, 0x63, 0x50, 0xf1, 0x6f, + 0x98, 0x2e, 0x4d, 0xc8, 0x2a, 0x25, 0xae, 0x8a, 0xaa, 0x88, 0xf2, 0x6e, 0x65, 0x50, 0xc1, 0x6f, 0xd3, 0x6f, 0xf4, + 0x7f, 0x98, 0x2e, 0xb6, 0xc8, 0xe0, 0x6e, 0x00, 0xb2, 0x32, 0x2f, 0x6d, 0x54, 0x83, 0x86, 0xf1, 0x6f, 0xc3, 0x7f, + 0x04, 0x30, 0x30, 0x30, 0xf4, 0x7f, 0xd0, 0x7f, 0xb2, 0x7f, 0xe3, 0x30, 0xc5, 0x6f, 0x56, 0x40, 0x45, 0x41, 0x28, + 0x08, 0x03, 0x14, 0x0e, 0xb4, 0x08, 0xbc, 0x82, 0x40, 0x10, 0x0a, 0x69, 0x54, 0x26, 0x05, 0x91, 0x7f, 0x44, 0x28, + 0xa3, 0x7f, 0x98, 0x2e, 0xd9, 0xc0, 0x08, 0xb9, 0x33, 0x30, 0x53, 0x09, 0xc1, 0x6f, 0xd3, 0x6f, 0xf4, 0x6f, 0x83, + 0x17, 0x47, 0x40, 0x6c, 0x15, 0xb2, 0x6f, 0xbe, 0x09, 0x75, 0x0b, 0x90, 0x42, 0x45, 0x42, 0x51, 0x0e, 0x32, 0xbc, + 0x02, 0x89, 0xa1, 0x6f, 0x7e, 0x86, 0xf4, 0x7f, 0xd0, 0x7f, 0xb2, 0x7f, 0x04, 0x30, 0x91, 0x6f, 0xd6, 0x2f, 0xeb, + 0x6f, 0xa0, 0x5e, 0xb8, 0x2e, 0x01, 0x2e, 0x77, 0xf7, 0x09, 0xbc, 0x0f, 0xb8, 0x00, 0xb2, 0x10, 0x50, 0xfb, 0x7f, + 0x10, 0x30, 0x0b, 0x2f, 0x03, 0x2e, 0x8a, 0x00, 0x96, 0xbc, 0x9f, 0xb8, 0x40, 0xb2, 0x05, 0x2f, 0x03, 0x2e, 0x68, + 0xf7, 0x9e, 0xbc, 0x9f, 0xb8, 0x40, 0xb2, 0x07, 0x2f, 0x03, 0x2e, 0x6a, 0x01, 0x41, 0x90, 0x01, 0x2f, 0x98, 0x2e, + 0x0d, 0xb6, 0x03, 0x2c, 0x00, 0x30, 0x21, 0x2e, 0x6a, 0x01, 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x20, 0x50, 0xe0, + 0x7f, 0xfb, 0x7f, 0x00, 0x2e, 0x61, 0x50, 0x98, 0x2e, 0x3b, 0xc8, 0x63, 0x50, 0x98, 0x2e, 0xa7, 0xc8, 0x05, 0x50, + 0x98, 0x2e, 0x55, 0xcc, 0xe1, 0x6f, 0x65, 0x50, 0x98, 0x2e, 0xe0, 0xc9, 0xfb, 0x6f, 0x00, 0x30, 0xe0, 0x5f, 0x21, + 0x2e, 0x6a, 0x01, 0xb8, 0x2e, 0x03, 0xbc, 0x21, 0x2e, 0x6c, 0x01, 0x03, 0x2e, 0x6c, 0x01, 0x40, 0xb2, 0x10, 0x30, + 0x21, 0x2e, 0x7c, 0x00, 0x01, 0x30, 0x05, 0x2f, 0x05, 0x2e, 0x6f, 0x01, 0x80, 0x90, 0x01, 0x2f, 0x23, 0x2e, 0x6f, + 0xf5, 0xc0, 0x2e, 0x21, 0x2e, 0x70, 0x01, 0x30, 0x25, 0x00, 0x30, 0x21, 0x2e, 0x5a, 0xf5, 0x10, 0x50, 0x21, 0x2e, + 0xde, 0x00, 0x21, 0x2e, 0xd6, 0x00, 0xfb, 0x7f, 0x98, 0x2e, 0xf5, 0x03, 0x40, 0x30, 0x21, 0x2e, 0x6b, 0x01, 0xfb, + 0x6f, 0xf0, 0x5f, 0x03, 0x25, 0x80, 0x2e, 0x24, 0xb6, 0x01, 0x2e, 0xa8, 0x00, 0x31, 0x25, 0x08, 0xbd, 0x71, 0x30, + 0x20, 0x50, 0x2c, 0xb9, 0x01, 0x09, 0xf2, 0x7f, 0x00, 0x91, 0xeb, 0x7f, 0x0a, 0x2f, 0x01, 0x30, 0xf0, 0x6f, 0x98, + 0x2e, 0x95, 0xcf, 0x13, 0x30, 0x27, 0x2e, 0x74, 0x01, 0xeb, 0x6f, 0xc0, 0x2e, 0x00, 0x30, 0xe0, 0x5f, 0x01, 0x2e, + 0x74, 0x01, 0x00, 0xb2, 0x05, 0x2f, 0x06, 0x30, 0xc3, 0x50, 0x98, 0x2e, 0x84, 0xb6, 0x2d, 0x2e, 0x74, 0x01, 0x05, + 0x2e, 0x73, 0x01, 0x8b, 0x80, 0xc3, 0x52, 0x04, 0x42, 0x98, 0x2e, 0xbf, 0xb6, 0x10, 0x25, 0xf0, 0x6f, 0xf1, 0x7f, + 0x98, 0x2e, 0x95, 0xcf, 0xf0, 0x6f, 0x00, 0x90, 0x02, 0x2f, 0x01, 0x2e, 0x75, 0x01, 0x02, 0x2d, 0x21, 0x2e, 0x75, + 0x01, 0xeb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x0a, 0x82, 0x02, 0x30, 0x12, 0x42, 0x41, 0x0e, 0xfc, 0x2f, 0x37, 0x80, + 0xc5, 0x52, 0x11, 0x42, 0x00, 0x2e, 0xc7, 0x52, 0x01, 0x42, 0xb8, 0x2e, 0x07, 0x88, 0x46, 0x8e, 0x06, 0x41, 0x3c, + 0x8b, 0x32, 0x1a, 0x42, 0x41, 0xc7, 0x41, 0x16, 0x2f, 0x80, 0x91, 0x23, 0x2f, 0x57, 0x0f, 0x16, 0x30, 0x0c, 0x2f, + 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40, 0x00, 0xb2, 0x04, 0x2f, 0x45, 0x82, 0x00, 0x2e, 0x41, 0x40, 0xd1, 0x0f, 0x02, + 0x2f, 0x06, 0x30, 0x06, 0x43, 0x46, 0x43, 0x80, 0xb3, 0x11, 0x2f, 0x03, 0x43, 0x47, 0x43, 0xb8, 0x2e, 0xd7, 0x0e, + 0x0c, 0x2f, 0x43, 0x82, 0x17, 0x04, 0x41, 0x40, 0x41, 0x0f, 0x07, 0x2f, 0x03, 0x43, 0x42, 0x83, 0x47, 0x43, 0x00, + 0x2e, 0x43, 0x40, 0xc1, 0x86, 0x43, 0x42, 0xb8, 0x2e, 0xb8, 0x2e, 0x88, 0x88, 0xc0, 0x50, 0x39, 0x8d, 0x88, 0x81, + 0xe2, 0x7f, 0x02, 0x30, 0x05, 0x40, 0xf2, 0x7f, 0x41, 0xab, 0x22, 0x30, 0x95, 0x22, 0x86, 0x41, 0x27, 0x5e, 0x9a, + 0x00, 0x04, 0x41, 0x37, 0x18, 0x66, 0x01, 0xc9, 0x56, 0xeb, 0x00, 0xc1, 0x7f, 0xb3, 0x7f, 0xd5, 0x7f, 0x48, 0x82, + 0x39, 0x80, 0x82, 0x40, 0xa0, 0x7f, 0x91, 0x7f, 0x8b, 0x7f, 0x06, 0x30, 0x6f, 0x5a, 0xcb, 0x58, 0x6f, 0x56, 0x98, + 0x2e, 0x67, 0xcc, 0x91, 0x6f, 0x7b, 0x82, 0xc6, 0x6f, 0x42, 0x40, 0x81, 0x84, 0x42, 0x42, 0x43, 0x82, 0x83, 0x8b, + 0x42, 0x40, 0x86, 0x89, 0x7b, 0x82, 0x84, 0x87, 0x71, 0x7f, 0x80, 0xb2, 0x95, 0x7f, 0x64, 0x7f, 0x50, 0x7f, 0x02, + 0x2f, 0xc5, 0x40, 0x41, 0x8b, 0xc5, 0x42, 0x87, 0x89, 0x67, 0x40, 0x07, 0x0f, 0x85, 0x8b, 0x41, 0x7f, 0x82, 0x8d, + 0x47, 0x40, 0x3c, 0x2f, 0x81, 0x41, 0x01, 0x0e, 0xe1, 0x6f, 0x2d, 0x2f, 0x46, 0x8c, 0x90, 0x6f, 0x86, 0x41, 0x07, + 0x40, 0xfe, 0x0e, 0x02, 0x2f, 0x04, 0x41, 0x00, 0xb3, 0x21, 0x2f, 0x44, 0x82, 0x04, 0x30, 0x41, 0x40, 0x71, 0x00, + 0xf9, 0x0e, 0x36, 0x2f, 0x46, 0x41, 0x80, 0xa7, 0x01, 0x30, 0x04, 0x30, 0x0d, 0x2f, 0xe4, 0x6f, 0x00, 0x2e, 0x04, + 0x41, 0x74, 0x0f, 0x04, 0x30, 0x07, 0x2f, 0x80, 0x90, 0x00, 0x2f, 0xc1, 0x42, 0x03, 0x86, 0x81, 0x84, 0xc2, 0x42, + 0x01, 0x42, 0x14, 0x30, 0x42, 0x85, 0x41, 0x43, 0xa1, 0x42, 0x00, 0x2e, 0x82, 0x40, 0x80, 0x90, 0x1c, 0x2f, 0x01, + 0x42, 0x1b, 0x2d, 0x06, 0x42, 0x19, 0x2c, 0x04, 0x30, 0xb2, 0x6f, 0xba, 0x04, 0x02, 0x1e, 0x80, 0x43, 0x12, 0x30, + 0xc0, 0x6f, 0x23, 0x30, 0x98, 0x2e, 0x90, 0xb6, 0x0e, 0x2c, 0x04, 0x30, 0xb2, 0x6f, 0xc0, 0x6f, 0xba, 0x00, 0x51, + 0x6f, 0x01, 0x86, 0x4a, 0x1c, 0xc1, 0x42, 0x22, 0x30, 0xe1, 0x6f, 0x13, 0x30, 0x98, 0x2e, 0x90, 0xb6, 0x04, 0x30, + 0x52, 0x6f, 0xcd, 0x52, 0x40, 0x6f, 0xc4, 0x7f, 0x98, 0x2e, 0xa0, 0xcc, 0x41, 0x6f, 0x70, 0x6f, 0x42, 0x40, 0xcf, + 0x52, 0x98, 0x2e, 0xa0, 0xcc, 0x41, 0x6f, 0x70, 0x6f, 0x42, 0x40, 0x01, 0x40, 0xd3, 0x6f, 0xd3, 0x00, 0xcb, 0x1e, + 0xcf, 0x52, 0x13, 0x42, 0xb0, 0x7f, 0x98, 0x2e, 0xa0, 0xcc, 0xb0, 0x6f, 0x3e, 0x84, 0xd1, 0x6f, 0x82, 0x40, 0x03, + 0x40, 0x51, 0x04, 0x59, 0x1c, 0x01, 0x42, 0x02, 0x82, 0xa0, 0x6f, 0x42, 0x40, 0x03, 0x40, 0xd3, 0x0f, 0x00, 0x30, + 0x14, 0x30, 0x60, 0x22, 0xc5, 0x6f, 0x40, 0x91, 0x01, 0x2f, 0x53, 0x0e, 0x26, 0x2f, 0xe5, 0x6f, 0x47, 0x85, 0x00, + 0x2e, 0x83, 0x40, 0x59, 0x0f, 0x20, 0x2f, 0x62, 0x6f, 0x4a, 0x8f, 0x85, 0x40, 0xc7, 0x41, 0x7f, 0x8d, 0x6f, 0x0f, + 0xa6, 0x15, 0x17, 0x30, 0x04, 0x30, 0x0f, 0x2f, 0xe0, 0x6f, 0x0b, 0x80, 0x00, 0x2e, 0x07, 0x40, 0x3e, 0x08, 0x00, + 0xb2, 0x00, 0x30, 0x06, 0x2f, 0x59, 0x1a, 0x04, 0x2f, 0xfd, 0x12, 0xc0, 0x90, 0x13, 0x30, 0x4b, 0x22, 0x06, 0x25, + 0x71, 0x25, 0xc0, 0xb3, 0x04, 0x2f, 0xa4, 0x42, 0xa4, 0x42, 0x83, 0x82, 0x84, 0x42, 0x44, 0x42, 0x00, 0x2e, 0x8b, + 0x6f, 0x40, 0x5f, 0xb8, 0x2e, 0x40, 0x50, 0x0a, 0x25, 0x3c, 0x80, 0xfb, 0x7f, 0x01, 0x42, 0xd2, 0x7f, 0xe3, 0x7f, + 0x32, 0x30, 0x10, 0x25, 0x98, 0x2e, 0x7a, 0xc1, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0x0a, 0x25, 0x39, + 0x80, 0xf3, 0x7f, 0x03, 0x42, 0xa1, 0x7f, 0xc2, 0x7f, 0xd1, 0x7f, 0x03, 0x30, 0x03, 0x43, 0xe4, 0x7f, 0xbb, 0x7f, + 0x22, 0x30, 0x10, 0x25, 0x98, 0x2e, 0x7a, 0xc1, 0xd2, 0x6f, 0x02, 0x17, 0x04, 0x08, 0xc1, 0x6f, 0x0c, 0x09, 0x04, + 0x1a, 0x10, 0x30, 0x04, 0x30, 0x20, 0x22, 0x01, 0xb2, 0x14, 0x2f, 0xd1, 0x58, 0x14, 0x09, 0xf3, 0x30, 0x93, 0x08, + 0x24, 0xbd, 0x44, 0xba, 0x94, 0x0a, 0x02, 0x17, 0xf3, 0x6f, 0x4c, 0x08, 0x9a, 0x08, 0x8a, 0x0a, 0x9d, 0x52, 0x51, + 0x08, 0x41, 0x58, 0x94, 0x08, 0x28, 0xbd, 0x98, 0xb8, 0xe4, 0x6f, 0x51, 0x0a, 0x01, 0x43, 0x00, 0x2e, 0xbb, 0x6f, + 0x90, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x01, 0x2e, 0x5d, 0xf7, 0x08, 0xbc, 0x80, 0xac, 0x0e, 0xbb, 0x02, 0x2f, + 0x00, 0x30, 0x41, 0x04, 0x82, 0x06, 0xc0, 0xa4, 0x00, 0x30, 0x11, 0x2f, 0x40, 0xa9, 0x03, 0x2f, 0x40, 0x91, 0x0d, + 0x2f, 0x00, 0xa7, 0x0b, 0x2f, 0x80, 0xb3, 0x6f, 0x58, 0x02, 0x2f, 0x90, 0xa1, 0x26, 0x13, 0x20, 0x23, 0x80, 0x90, + 0x10, 0x30, 0x01, 0x2f, 0xcc, 0x0e, 0x00, 0x2f, 0x00, 0x30, 0xb8, 0x2e, 0x77, 0x56, 0x71, 0x54, 0xd0, 0x40, 0xc4, + 0x40, 0x0b, 0x2e, 0xfd, 0xf3, 0x77, 0x52, 0x90, 0x42, 0x94, 0x42, 0x95, 0x42, 0x05, 0x30, 0x79, 0x50, 0x0f, 0x88, + 0x06, 0x40, 0x04, 0x41, 0x96, 0x42, 0xc5, 0x42, 0x48, 0xbe, 0x73, 0x30, 0x0d, 0x2e, 0x6f, 0x01, 0x4f, 0xba, 0x84, + 0x42, 0x03, 0x42, 0x81, 0xb3, 0x02, 0x2f, 0x2b, 0x2e, 0x6f, 0xf5, 0x06, 0x2d, 0x05, 0x2e, 0x77, 0xf7, 0x75, 0x56, + 0x93, 0x08, 0x25, 0x2e, 0x77, 0xf7, 0x73, 0x54, 0x25, 0x2e, 0xc2, 0xf5, 0x07, 0x2e, 0xfd, 0xf3, 0x42, 0x30, 0xb4, + 0x33, 0xda, 0x0a, 0x4c, 0x00, 0x27, 0x2e, 0xfd, 0xf3, 0x43, 0x40, 0xd4, 0x3f, 0xdc, 0x08, 0x43, 0x42, 0x00, 0x2e, + 0x00, 0x2e, 0x43, 0x40, 0x24, 0x30, 0xdc, 0x0a, 0x43, 0x42, 0x04, 0x80, 0x03, 0x2e, 0xfd, 0xf3, 0x4a, 0x0a, 0x23, + 0x2e, 0xfd, 0xf3, 0x61, 0x34, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0xd0, 0x51, 0xfb, 0x7f, 0x98, 0x2e, 0xcf, 0x0d, + 0x5a, 0x25, 0x98, 0x2e, 0xf6, 0x0d, 0x6b, 0x87, 0x81, 0x54, 0xe1, 0x7f, 0xa3, 0x7f, 0xb3, 0x7f, 0xb2, 0x88, 0x7b, + 0x52, 0xc2, 0x7f, 0x65, 0x8b, 0x7d, 0x56, 0x84, 0x7f, 0x61, 0x7f, 0x75, 0x7f, 0xd0, 0x7f, 0x95, 0x7f, 0x53, 0x7f, + 0x14, 0x30, 0x7f, 0x54, 0x81, 0x6f, 0x42, 0x7f, 0x00, 0x2e, 0x53, 0x40, 0x45, 0x8c, 0x42, 0x40, 0x90, 0x41, 0xbb, + 0x83, 0x86, 0x41, 0xd8, 0x04, 0x16, 0x06, 0x00, 0xac, 0x81, 0x7f, 0x02, 0x2f, 0x02, 0x30, 0xd3, 0x04, 0x10, 0x06, + 0xc1, 0x84, 0x01, 0x30, 0xc1, 0x02, 0x0b, 0x16, 0x04, 0x09, 0x14, 0x01, 0x99, 0x02, 0xc1, 0xb9, 0xaf, 0xbc, 0x59, + 0x0a, 0x64, 0x6f, 0x51, 0x43, 0xa1, 0xb4, 0x12, 0x41, 0x13, 0x41, 0x41, 0x43, 0x35, 0x7f, 0x64, 0x7f, 0x26, 0x31, + 0xe5, 0x6f, 0xd4, 0x6f, 0x98, 0x2e, 0x37, 0xca, 0x32, 0x6f, 0x75, 0x6f, 0x83, 0x40, 0x42, 0x41, 0x23, 0x7f, 0x12, + 0x7f, 0xf6, 0x30, 0x40, 0x25, 0x51, 0x25, 0x98, 0x2e, 0x37, 0xca, 0x14, 0x6f, 0x20, 0x05, 0x70, 0x6f, 0x25, 0x6f, + 0x69, 0x07, 0xa2, 0x6f, 0x31, 0x6f, 0x0b, 0x30, 0x04, 0x42, 0x9b, 0x42, 0x8b, 0x42, 0x55, 0x42, 0x32, 0x7f, 0x40, + 0xa9, 0xc3, 0x6f, 0x71, 0x7f, 0x02, 0x30, 0xd0, 0x40, 0xc3, 0x7f, 0x03, 0x2f, 0x40, 0x91, 0x15, 0x2f, 0x00, 0xa7, + 0x13, 0x2f, 0x00, 0xa4, 0x11, 0x2f, 0x84, 0xbd, 0x98, 0x2e, 0x79, 0xca, 0x55, 0x6f, 0x89, 0x54, 0x54, 0x41, 0x82, + 0x00, 0xf3, 0x3f, 0x45, 0x41, 0xcb, 0x02, 0xf6, 0x30, 0x98, 0x2e, 0x37, 0xca, 0x33, 0x6f, 0xa4, 0x6f, 0xc1, 0x42, + 0x03, 0x2c, 0x00, 0x43, 0xa4, 0x6f, 0x33, 0x6f, 0x00, 0x2e, 0x42, 0x6f, 0x55, 0x6f, 0x91, 0x40, 0x42, 0x8b, 0x00, + 0x41, 0x41, 0x00, 0x01, 0x43, 0x55, 0x7f, 0x14, 0x30, 0xc1, 0x40, 0x95, 0x40, 0x4d, 0x02, 0xc5, 0x6f, 0x87, 0x50, + 0x68, 0x0e, 0x75, 0x6f, 0xd1, 0x42, 0xa3, 0x7f, 0x8a, 0x2f, 0x09, 0x2e, 0x6f, 0x01, 0x01, 0xb3, 0x22, 0x2f, 0x81, + 0x58, 0x90, 0x6f, 0x17, 0x30, 0x13, 0x41, 0xb6, 0x6f, 0xe4, 0x7f, 0x00, 0x2e, 0x91, 0x41, 0x14, 0x40, 0x92, 0x41, + 0x15, 0x40, 0x17, 0x2e, 0x6f, 0xf5, 0xb6, 0x7f, 0xd0, 0x7f, 0xcb, 0x7f, 0x98, 0x2e, 0x00, 0x0c, 0x07, 0x15, 0xc2, + 0x6f, 0x14, 0x0b, 0x29, 0x2e, 0x6f, 0xf5, 0xc3, 0xa3, 0xc1, 0x8f, 0xe4, 0x6f, 0xd0, 0x6f, 0xe6, 0x2f, 0x14, 0x30, + 0x05, 0x2e, 0x6f, 0xf5, 0x14, 0x0b, 0x29, 0x2e, 0x6f, 0xf5, 0x44, 0x2d, 0x83, 0x54, 0x01, 0x32, 0x89, 0x58, 0x05, + 0x30, 0x41, 0x50, 0x83, 0x40, 0xd8, 0x08, 0x91, 0x01, 0xb8, 0xbd, 0x38, 0xb5, 0xe6, 0x7f, 0x0a, 0x16, 0xb1, 0x6f, + 0x2a, 0xbb, 0xa6, 0xbd, 0x1c, 0x01, 0x06, 0xbc, 0x52, 0x40, 0x06, 0x0a, 0x53, 0x40, 0x45, 0x03, 0xb1, 0x7f, 0xf6, + 0x30, 0x98, 0x2e, 0x37, 0xca, 0x1a, 0xbd, 0x16, 0xb6, 0x86, 0xba, 0x00, 0xa9, 0xaa, 0x0a, 0x67, 0x52, 0x0f, 0x2f, + 0x00, 0x91, 0x67, 0x52, 0x03, 0x2f, 0x67, 0x5a, 0x55, 0x0f, 0x67, 0x52, 0x08, 0x2f, 0x3f, 0xa1, 0x04, 0x2f, 0x3f, + 0x91, 0x03, 0x2f, 0x89, 0x58, 0xd4, 0x0f, 0x00, 0x2f, 0x89, 0x54, 0x12, 0x25, 0xf2, 0x33, 0x98, 0x2e, 0xd9, 0xc0, + 0xe4, 0x6f, 0xf5, 0x37, 0x45, 0x09, 0x21, 0x85, 0x05, 0x43, 0x05, 0x30, 0x85, 0x52, 0x51, 0x0e, 0x01, 0x32, 0x89, + 0x58, 0xc5, 0x2f, 0x25, 0x54, 0x09, 0x2e, 0x77, 0xf7, 0x22, 0x0b, 0x29, 0x2e, 0x77, 0xf7, 0xfb, 0x6f, 0x30, 0x5e, + 0xb8, 0x2e, 0x10, 0x50, 0x01, 0x2e, 0x6b, 0x01, 0x00, 0xb2, 0xfb, 0x7f, 0x5d, 0x2f, 0x01, 0xb2, 0x54, 0x2f, 0x02, + 0xb2, 0x4e, 0x2f, 0x03, 0x90, 0x63, 0x2f, 0x8f, 0x50, 0x39, 0x82, 0x02, 0x40, 0x81, 0x88, 0x91, 0x54, 0x41, 0x40, + 0x97, 0x56, 0x04, 0x42, 0x00, 0x2e, 0x94, 0x40, 0x95, 0x40, 0xd8, 0xbe, 0x2c, 0x0b, 0x45, 0x40, 0x6c, 0x01, 0x55, + 0x42, 0x0c, 0x17, 0x45, 0x40, 0x2c, 0x03, 0x54, 0x42, 0x53, 0x0e, 0xf2, 0x2f, 0x99, 0x56, 0x3e, 0x82, 0xe2, 0x40, + 0xc3, 0x40, 0x28, 0xbd, 0x93, 0x0a, 0x43, 0x40, 0xda, 0x00, 0x53, 0x42, 0x8a, 0x16, 0x43, 0x40, 0x9a, 0x02, 0x52, + 0x42, 0x00, 0x2e, 0x41, 0x40, 0x25, 0x54, 0x4a, 0x0e, 0x3b, 0x2f, 0x3a, 0x82, 0x00, 0x30, 0x41, 0x40, 0x21, 0x2e, + 0x77, 0x0f, 0x40, 0xb2, 0x0a, 0x2f, 0x98, 0x2e, 0x61, 0x0c, 0x98, 0x2e, 0x2b, 0x0e, 0x98, 0x2e, 0x41, 0x0e, 0xfb, + 0x6f, 0xf0, 0x5f, 0x00, 0x30, 0x80, 0x2e, 0x38, 0xb6, 0x95, 0x54, 0x8b, 0x56, 0x83, 0x42, 0x8f, 0x86, 0x74, 0x30, + 0x93, 0x54, 0xc4, 0x42, 0x11, 0x30, 0x23, 0x2e, 0x6b, 0x01, 0xa1, 0x42, 0x23, 0x30, 0x27, 0x2e, 0x6e, 0x01, 0x21, + 0x2e, 0x6d, 0x01, 0xba, 0x82, 0x18, 0x2c, 0x81, 0x42, 0x30, 0x30, 0x21, 0x2e, 0x6b, 0x01, 0x13, 0x2d, 0x21, 0x30, + 0x00, 0x30, 0x23, 0x2e, 0x6b, 0x01, 0x21, 0x2e, 0x7b, 0xf7, 0x0c, 0x2d, 0x77, 0x30, 0x98, 0x2e, 0x1f, 0x0c, 0x8d, + 0x50, 0x0c, 0x82, 0x12, 0x30, 0x40, 0x42, 0x25, 0x2e, 0x6b, 0x01, 0x2f, 0x2e, 0x7b, 0xf7, 0xfb, 0x6f, 0xf0, 0x5f, + 0xb8, 0x2e, 0x70, 0x50, 0x0a, 0x25, 0x39, 0x86, 0xfb, 0x7f, 0xe1, 0x32, 0x62, 0x30, 0x98, 0x2e, 0xc2, 0xc4, 0x41, + 0x56, 0xa5, 0x6f, 0xab, 0x08, 0x91, 0x6f, 0x4b, 0x08, 0x9b, 0x56, 0xc4, 0x6f, 0x23, 0x09, 0x4d, 0xba, 0x93, 0xbc, + 0x8c, 0x0b, 0xd1, 0x6f, 0x0b, 0x09, 0x81, 0x52, 0x9d, 0x5e, 0x56, 0x42, 0xaf, 0x09, 0x4d, 0xba, 0x23, 0xbd, 0x94, + 0x0a, 0xe5, 0x6f, 0x68, 0xbb, 0xeb, 0x08, 0xbd, 0xb9, 0x63, 0xbe, 0xfb, 0x6f, 0x52, 0x42, 0xe3, 0x0a, 0xc0, 0x2e, + 0x43, 0x42, 0x90, 0x5f, 0x87, 0x50, 0x03, 0x2e, 0x25, 0xf3, 0x12, 0x40, 0x00, 0x40, 0x28, 0xba, 0x9b, 0xbc, 0x88, + 0xbd, 0x93, 0xb4, 0xe3, 0x0a, 0x89, 0x16, 0x08, 0xb6, 0xc0, 0x2e, 0x19, 0x00, 0x62, 0x02, 0x10, 0x50, 0xfb, 0x7f, + 0x98, 0x2e, 0x5d, 0x0d, 0x01, 0x2e, 0x6b, 0x01, 0x31, 0x30, 0x08, 0x04, 0xfb, 0x6f, 0x01, 0x30, 0xf0, 0x5f, 0x23, + 0x2e, 0x6d, 0x01, 0x21, 0x2e, 0x6e, 0x01, 0xb8, 0x2e, 0x01, 0x2e, 0x6e, 0x01, 0x03, 0x2e, 0x6d, 0x01, 0x48, 0x0e, + 0x01, 0x2f, 0x80, 0x2e, 0x05, 0x0e, 0xb8, 0x2e, 0x9f, 0x50, 0x21, 0x34, 0x01, 0x42, 0x82, 0x30, 0xc1, 0x32, 0x25, + 0x2e, 0x62, 0xf5, 0x01, 0x00, 0x22, 0x30, 0x01, 0x40, 0x4a, 0x0a, 0x01, 0x42, 0xb8, 0x2e, 0x9f, 0x54, 0xf0, 0x3b, + 0x83, 0x40, 0xd8, 0x08, 0xa1, 0x52, 0x83, 0x42, 0x00, 0x30, 0x83, 0x30, 0x50, 0x42, 0xc4, 0x32, 0x27, 0x2e, 0x64, + 0xf5, 0x94, 0x00, 0x50, 0x42, 0x40, 0x42, 0xd3, 0x3f, 0x84, 0x40, 0x7d, 0x82, 0xe3, 0x08, 0x40, 0x42, 0x83, 0x42, + 0xb8, 0x2e, 0x95, 0x52, 0x00, 0x30, 0x40, 0x42, 0x7c, 0x86, 0x71, 0x52, 0x09, 0x2e, 0x62, 0x0f, 0x77, 0x54, 0xc4, + 0x42, 0xd3, 0x86, 0x54, 0x40, 0x55, 0x40, 0x94, 0x42, 0x85, 0x42, 0x21, 0x2e, 0x6e, 0x01, 0x42, 0x40, 0x25, 0x2e, + 0xfd, 0xf3, 0xc0, 0x42, 0x7e, 0x82, 0x05, 0x2e, 0xd7, 0x00, 0x80, 0xb2, 0x14, 0x2f, 0x05, 0x2e, 0x89, 0x00, 0x27, + 0xbd, 0x2f, 0xb9, 0x80, 0x90, 0x02, 0x2f, 0x21, 0x2e, 0x6f, 0xf5, 0x0c, 0x2d, 0x07, 0x2e, 0x63, 0x0f, 0x14, 0x30, + 0x1c, 0x09, 0x05, 0x2e, 0x77, 0xf7, 0x75, 0x56, 0x47, 0xbe, 0x93, 0x08, 0x94, 0x0a, 0x25, 0x2e, 0x77, 0xf7, 0xa3, + 0x54, 0x50, 0x42, 0x4a, 0x0e, 0xfc, 0x2f, 0xb8, 0x2e, 0x50, 0x50, 0x02, 0x30, 0x43, 0x86, 0xa1, 0x50, 0xfb, 0x7f, + 0xe3, 0x7f, 0xd2, 0x7f, 0xc0, 0x7f, 0xb1, 0x7f, 0x00, 0x2e, 0x41, 0x40, 0x00, 0x40, 0x48, 0x04, 0x98, 0x2e, 0x74, + 0xc0, 0x1e, 0xaa, 0xd3, 0x6f, 0x14, 0x30, 0xb1, 0x6f, 0xe3, 0x22, 0xc0, 0x6f, 0x52, 0x40, 0xe4, 0x6f, 0x4c, 0x0e, + 0x12, 0x42, 0xd3, 0x7f, 0xeb, 0x2f, 0x03, 0x2e, 0x78, 0x0f, 0x40, 0x90, 0x11, 0x30, 0x03, 0x2f, 0x23, 0x2e, 0x78, + 0x0f, 0x02, 0x2c, 0x00, 0x30, 0xd0, 0x6f, 0xfb, 0x6f, 0xb0, 0x5f, 0xb8, 0x2e, 0x40, 0x50, 0xf1, 0x7f, 0x0a, 0x25, + 0x3c, 0x86, 0xeb, 0x7f, 0x41, 0x33, 0x22, 0x30, 0x98, 0x2e, 0xc2, 0xc4, 0xd3, 0x6f, 0xf4, 0x30, 0xdc, 0x09, 0xa7, + 0x58, 0xc2, 0x6f, 0x94, 0x09, 0xa9, 0x58, 0x6a, 0xbb, 0xdc, 0x08, 0xb4, 0xb9, 0xb1, 0xbd, 0xa5, 0x5a, 0x95, 0x08, + 0x21, 0xbd, 0xf6, 0xbf, 0x77, 0x0b, 0x51, 0xbe, 0xf1, 0x6f, 0xeb, 0x6f, 0x52, 0x42, 0x54, 0x42, 0xc0, 0x2e, 0x43, + 0x42, 0xc0, 0x5f, 0x50, 0x50, 0xbb, 0x50, 0x31, 0x30, 0x11, 0x42, 0xfb, 0x7f, 0x7b, 0x30, 0x0b, 0x42, 0x11, 0x30, + 0x02, 0x80, 0x23, 0x33, 0x01, 0x42, 0x03, 0x00, 0x07, 0x2e, 0x80, 0x03, 0x05, 0x2e, 0xd5, 0x00, 0x33, 0x52, 0xe2, + 0x7f, 0xd3, 0x7f, 0xc0, 0x7f, 0x98, 0x2e, 0x9c, 0x0e, 0xd1, 0x6f, 0x08, 0x0a, 0x1a, 0x25, 0x7b, 0x86, 0xd0, 0x7f, + 0x01, 0x33, 0x12, 0x30, 0x98, 0x2e, 0xc2, 0xc4, 0xd1, 0x6f, 0x08, 0x0a, 0x00, 0xb2, 0x0d, 0x2f, 0xe3, 0x6f, 0x01, + 0x2e, 0x80, 0x03, 0x51, 0x30, 0xc7, 0x86, 0x23, 0x2e, 0x21, 0xf2, 0x08, 0xbc, 0xc0, 0x42, 0x98, 0x2e, 0x91, 0x03, + 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xb0, 0x6f, 0x0b, 0xb8, 0x03, 0x2e, 0x1b, 0x00, 0x08, 0x1a, 0xb0, 0x7f, 0x70, + 0x30, 0x04, 0x2f, 0x21, 0x2e, 0x21, 0xf2, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0x6d, 0xc0, 0x98, 0x2e, + 0x5d, 0xc0, 0xab, 0x50, 0x98, 0x2e, 0x46, 0xc3, 0xad, 0x50, 0x98, 0x2e, 0xfc, 0xc5, 0x5d, 0x50, 0x98, 0x2e, 0x64, + 0xcf, 0xb1, 0x50, 0x21, 0x2e, 0x7e, 0x01, 0xaf, 0x56, 0xb3, 0x52, 0x27, 0x2e, 0x7f, 0x01, 0x23, 0x2e, 0x80, 0x01, + 0xb5, 0x50, 0x98, 0x2e, 0x53, 0xc7, 0xb7, 0x50, 0x98, 0x2e, 0x44, 0xcb, 0x10, 0x30, 0x98, 0x2e, 0x0d, 0xb6, 0x20, + 0x26, 0xc0, 0x6f, 0x02, 0x31, 0x12, 0x42, 0xeb, 0x33, 0x0b, 0x42, 0x37, 0x80, 0x01, 0x30, 0x01, 0x42, 0xf3, 0x37, + 0xbd, 0x52, 0xc1, 0x50, 0x44, 0x40, 0xa2, 0x0a, 0x42, 0x42, 0x8b, 0x31, 0x09, 0x2e, 0x5e, 0xf7, 0xbf, 0x54, 0xe3, + 0x08, 0x83, 0x42, 0x1b, 0x42, 0x23, 0x33, 0x4b, 0x00, 0xbc, 0x84, 0x0b, 0x40, 0x33, 0x30, 0x83, 0x42, 0x0b, 0x42, + 0xe0, 0x7f, 0xd1, 0x7f, 0x98, 0x2e, 0x0c, 0x02, 0xd1, 0x6f, 0x80, 0x30, 0x40, 0x42, 0x03, 0x30, 0xe0, 0x6f, 0xb9, + 0x54, 0x04, 0x30, 0x00, 0x2e, 0x00, 0x2e, 0x01, 0x89, 0x62, 0x0e, 0xfa, 0x2f, 0x43, 0x42, 0x11, 0x30, 0xfb, 0x6f, + 0xc0, 0x2e, 0x01, 0x42, 0xb0, 0x5f, 0xc1, 0x4a, 0x00, 0x00, 0x6d, 0x57, 0x00, 0x00, 0x77, 0x8e, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xd3, 0xff, 0xff, 0xff, 0xe5, 0xff, 0xff, 0xff, 0xee, 0xe1, 0xff, 0xff, 0x7c, 0x13, 0x00, 0x00, + 0x46, 0xe6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, + 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, + 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, + 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, + 0x2e, 0x00, 0xc1 +}; + +/*! @name Global array that stores the feature input configuration of BMI270_LEGACY */ +const struct bmi2_feature_config bmi270_legacy_feat_in[BMI270_LEGACY_MAX_FEAT_IN] = { + { .type = BMI2_CONFIG_ID, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_CONFIG_ID_STRT_ADDR }, + { .type = BMI2_MAX_BURST_LEN, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_MAX_BURST_LEN_STRT_ADDR }, + { .type = BMI2_CRT_GYRO_SELF_TEST, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_CRT_GYRO_SELF_TEST_STRT_ADDR }, + { .type = BMI2_ABORT_CRT_GYRO_SELF_TEST, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_ABORT_STRT_ADDR }, + { .type = BMI2_AXIS_MAP, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_AXIS_MAP_STRT_ADDR }, + { .type = BMI2_GYRO_SELF_OFF, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_GYRO_SELF_OFF_STRT_ADDR }, + { .type = BMI2_NVM_PROG_PREP, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_NVM_PROG_PREP_STRT_ADDR }, + { .type = BMI2_ANY_MOTION, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_ANY_MOT_STRT_ADDR }, + { .type = BMI2_NO_MOTION, .page = BMI2_PAGE_1, .start_addr = BMI270_LEGACY_NO_MOT_STRT_ADDR }, + { .type = BMI2_ORIENTATION, .page = BMI2_PAGE_2, .start_addr = BMI270_LEGACY_ORIENT_STRT_ADDR }, + { .type = BMI2_HIGH_G, .page = BMI2_PAGE_2, .start_addr = BMI270_LEGACY_HIGH_G_STRT_ADDR }, + { .type = BMI2_LOW_G, .page = BMI2_PAGE_2, .start_addr = BMI270_LEGACY_LOW_G_STRT_ADDR }, + { .type = BMI2_FLAT, .page = BMI2_PAGE_3, .start_addr = BMI270_LEGACY_FLAT_STRT_ADDR }, + { .type = BMI2_SIG_MOTION, .page = BMI2_PAGE_3, .start_addr = BMI270_LEGACY_SIG_MOT_STRT_ADDR }, + { .type = BMI2_STEP_DETECTOR, .page = BMI2_PAGE_4, .start_addr = BMI270_LEGACY_STEP_COUNT_STRT_ADDR }, + { .type = BMI2_STEP_COUNTER, .page = BMI2_PAGE_4, .start_addr = BMI270_LEGACY_STEP_COUNT_STRT_ADDR }, + { .type = BMI2_STEP_ACTIVITY, .page = BMI2_PAGE_4, .start_addr = BMI270_LEGACY_STEP_COUNT_STRT_ADDR }, + { .type = BMI2_GYRO_GAIN_UPDATE, .page = BMI2_PAGE_4, .start_addr = BMI270_LEGACY_GYRO_USERGAIN_UPDATE_STRT_ADDR }, + { .type = BMI2_SINGLE_TAP, .page = BMI2_PAGE_5, .start_addr = BMI270_LEGACY_TAP_DETECT_1_STRT_ADDR }, + { .type = BMI2_DOUBLE_TAP, .page = BMI2_PAGE_5, .start_addr = BMI270_LEGACY_TAP_DETECT_1_STRT_ADDR }, + { .type = BMI2_TRIPLE_TAP, .page = BMI2_PAGE_5, .start_addr = BMI270_LEGACY_TAP_DETECT_1_STRT_ADDR }, + { .type = BMI2_TAP_DETECTOR_1, .page = BMI2_PAGE_5, .start_addr = BMI270_LEGACY_TAP_DETECT_1_STRT_ADDR }, + { .type = BMI2_TAP_DETECTOR_2, .page = BMI2_PAGE_6, .start_addr = BMI270_LEGACY_TAP_DETECT_2_STRT_ADDR }, +}; + +/*! @name Global array that stores the feature output configuration */ +const struct bmi2_feature_config bmi270_legacy_feat_out[BMI270_LEGACY_MAX_FEAT_OUT] = { + { .type = BMI2_STEP_COUNTER, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_STEP_CNT_OUT_STRT_ADDR }, + { .type = BMI2_STEP_ACTIVITY, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_STEP_ACT_OUT_STRT_ADDR }, + { .type = BMI2_ORIENTATION, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_ORIENT_HIGH_G_OUT_STRT_ADDR }, + { .type = BMI2_HIGH_G, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_ORIENT_HIGH_G_OUT_STRT_ADDR }, + { .type = BMI2_GYRO_GAIN_UPDATE, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_GYR_USER_GAIN_OUT_STRT_ADDR }, + { .type = BMI2_GYRO_CROSS_SENSE, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_GYRO_CROSS_SENSE_STRT_ADDR }, + { .type = BMI2_NVM_STATUS, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_NVM_VFRM_OUT_STRT_ADDR }, + { .type = BMI2_VFRM_STATUS, .page = BMI2_PAGE_0, .start_addr = BMI270_LEGACY_NVM_VFRM_OUT_STRT_ADDR } +}; + +/*! @name Global array that stores the feature interrupts of BMI270_LEGACY */ +struct bmi2_map_int bmi270_legacy_map_int[BMI270_LEGACY_MAX_INT_MAP] = { + { .type = BMI2_SIG_MOTION, .sens_map_int = BMI270_LEGACY_INT_SIG_MOT_MASK }, + { .type = BMI2_STEP_COUNTER, .sens_map_int = BMI270_LEGACY_INT_STEP_COUNTER_MASK }, + { .type = BMI2_STEP_DETECTOR, .sens_map_int = BMI270_LEGACY_INT_STEP_DETECTOR_MASK }, + { .type = BMI2_STEP_ACTIVITY, .sens_map_int = BMI270_LEGACY_INT_STEP_ACTIVITY_MASK }, + { .type = BMI2_HIGH_G, .sens_map_int = BMI270_LEGACY_INT_HIGH_G_MASK }, + { .type = BMI2_LOW_G, .sens_map_int = BMI270_LEGACY_INT_LOW_G_MASK }, + { .type = BMI2_TAP, .sens_map_int = BMI270_LEGACY_INT_TAP_MASK }, + { .type = BMI2_FLAT, .sens_map_int = BMI270_LEGACY_INT_FLAT_MASK }, + { .type = BMI2_NO_MOTION, .sens_map_int = BMI270_LEGACY_INT_NO_MOT_MASK }, + { .type = BMI2_ANY_MOTION, .sens_map_int = BMI270_LEGACY_INT_ANY_MOT_MASK }, + { .type = BMI2_ORIENTATION, .sens_map_int = BMI270_LEGACY_INT_ORIENT_MASK }, + { .type = BMI2_SINGLE_TAP, .sens_map_int = BMI270_LEGACY_INT_SINGLE_TAP_MASK }, + { .type = BMI2_DOUBLE_TAP, .sens_map_int = BMI270_LEGACY_INT_DOUBLE_TAP_MASK }, + { .type = BMI2_TRIPLE_TAP, .sens_map_int = BMI270_LEGACY_INT_TRIPLE_TAP_MASK } +}; + +/******************************************************************************/ + +/*! Local Function Prototypes + ******************************************************************************/ + +/*! + * @brief This internal API gets tap configurations like data register enable, + * tap sensitivity threshold, max gesture duration, quite time after gesture, + * axis selection and wait for timeout. + * + * @param[out] tap : Void pointer to store bmi2_tap_config structure. + * @param[in, out] bmi2_dev : Void pointer to store bmi2_dev structure. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_tap_config(void *tap, void *bmi2_dev); + +/*! + * @brief This internal API gets tap configurations like data register enable, + * tap sensitivity threshold, max gesture duration and quite time after gesture + * from primary page of tap detector. + * + * @param[out] tap : Void pointer to store bmi2_tap_config structure. + * @param[in, out] bmi2_dev : Void pointer to store bmi2_dev structure. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_tap_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | By enabling this bit, accel data according to the + * data_reg_en | user defined accel configuration is taken for tap + * | detector feature. + * -------------------------|--------------------------------------------------- + * tap_sens_thres | Scaling factor of additional threshold increment + * | for detection of positive and negative peak of tap. + * -------------------------|--------------------------------------------------- + * max_gest_dur | Maximum duration after the first tap within which the + * | second and/or third tap have to be performed for being + * | detected as double-tap. + * -------------------------|--------------------------------------------------- + * quite_time_after_gest | Minimum quite time between the two gesture detection. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_config_page_primary(void *tap, void *bmi2_dev); + +/*! + * @brief This internal API gets tap configurations like time out and + * axis selection from secondary page of tap detector. + * + * @param[out] tap : Void pointer to store bmi2_tap_config structure. + * @param[in, out] bmi2_dev : Void pointer to store bmi2_dev structure. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_tap_config | + * Structure parameters | Description + * -------------------------|--------------------------------------------------- + * wait_for_timeout | Wait for the duration set by max_gest_dur after the + * | first tap and report the tap-gesture based on number + * | of taps detected. + * -------------------------|--------------------------------------------------- + * | Selection of axis from 3D-acceleration signal vector + * axis_sel | for tap detection. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_config_page_secondary(void *tap, void *bmi2_dev); + +/*! + * @brief This internal API sets tap configurations like data register enable, + * tap sensitivity threshold, max gesture duration, quite time after gesture, + * axis selection and wait for timeout. + * + * @param[out] tap : Void pointer to store bmi2_tap_config structure. + * @param[in, out] bmi2_dev : Void pointer to store bmi2_dev structure. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_tap_config(void *tap, void *bmi2_dev); + +/*! + * @brief This internal API sets tap configurations like data register enable, + * tap sensitivity threshold, max gesture duration and quite time after gesture + * from primary page of tap detector. + * + * @param[out] tap : Void pointer to store bmi2_tap_config structure. + * @param[in, out] bmi2_dev : Void pointer to store bmi2_dev structure. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_tap_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | By enabling this bit, accel data according to the + * data_reg_en | user defined accel configuration is taken for tap + * | detector feature. + * -------------------------|--------------------------------------------------- + * tap_sens_thres | Scaling factor of additional threshold increment + * | for detection of positive and negative peak of tap. + * -------------------------|--------------------------------------------------- + * max_gest_dur | Maximum duration after the first tap within which the + * | second and/or third tap have to be performed for being + * | detected as double-tap. + * -------------------------|--------------------------------------------------- + * quite_time_after_gest | Minimum quite time between the two gesture detection. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_config_page_primary(void *tap, void *bmi2_dev); + +/*! + * @brief This internal API sets the tap configurations like time out and + * axis selection to secondary page of tap detector. + * + * @param[out] tap : Void pointer to store bmi2_tap_config structure. + * @param[in, out] bmi2_dev : Void pointer to store bmi2_dev structure. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_tap_config | + * Structure parameters | Description + * -------------------------|--------------------------------------------------- + * wait_for_timeout | Wait for the duration set by max_gest_dur after the + * | first tap and report the tap-gesture based on number + * | of taps detected. + * -------------------------|--------------------------------------------------- + * | Selection of axis from 3D-acceleration signal vector + * axis_sel | for tap detection. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_config_page_secondary(void *tap, void *bmi2_dev); + +/*! + * @brief This internal API is used to validate the device pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t null_ptr_check(const struct bmi2_dev *dev); + +/*! + * @brief This internal API enables the selected sensor/features. + * + * @param[in] sensor_sel : Selects the desired sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API disables the selected sensor/features. + * + * @param[in] sensor_sel : Selects the desired sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API selects the sensors/features to be enabled or + * disabled. + * + * @param[in] sens_list : Pointer to select the sensor. + * @param[in] n_sens : Number of sensors selected. + * @param[out] sensor_sel : Gets the selected sensor. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t select_sensor(const uint8_t *sens_list, uint8_t n_sens, uint64_t *sensor_sel); + +/*! + * @brief This internal API is used to enable/disable any-motion feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables any-motion. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables any-motion. + * BMI2_ENABLE | Enables any-motion. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_any_motion(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable no-motion feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables no-motion. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables no-motion. + * BMI2_ENABLE | Enables no-motion. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_no_motion(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable sig-motion feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables sig-motion. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables sig-motion. + * BMI2_ENABLE | Enables sig-motion. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_sig_motion(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable step detector feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables step-detector. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables step detector + * BMI2_ENABLE | Enables step detector + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_step_detector(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable step counter feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables step counter. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables step counter + * BMI2_ENABLE | Enables step counter + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_step_counter(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable tap feature through + * single tap. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables single tap. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables single tap. + * BMI2_ENABLE | Enables single tap + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_single_tap(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable tap feature through + * double tap. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables double tap. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables double tap. + * BMI2_ENABLE | Enables double tap + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_double_tap(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable tap feature through + * triple tap. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables triple tap. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables triple tap. + * BMI2_ENABLE | Enables triple tap + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_triple_tap(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable orientation feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables orientation. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables orientation + * BMI2_ENABLE | Enables orientation + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_orientation(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable high-g feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables high-g. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables high-g + * BMI2_ENABLE | Enables high-g + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_high_g(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable low-g feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables low-g. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables low-g + * BMI2_ENABLE | Enables low-g + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_low_g(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable flat feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables flat. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables flat + * BMI2_ENABLE | Enables flat + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_flat(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API gives an option to enable offset correction + * feature of gyroscope, either internally or by the host. + * + * @param[in] enable : Enables/Disables self-offset correction. + * @param[in] dev : Structure instance of bmi2_dev. + * + * enable | Description + * -------------|--------------- + * BMI2_ENABLE | gyroscope offset correction values are set internally + * BMI2_DISABLE | gyroscope offset correction values has to be set by host + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_gyro_self_offset_corr(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable gyroscope user gain + * feature. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables gyroscope user gain. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables gyroscope user gain + * BMI2_ENABLE | Enables gyroscope user gain + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets any-motion configurations like axes select, + * duration, threshold and output-configuration. + * + * @param[in] config : Structure instance of bmi2_any_motion_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_any_motion_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | Defines the number of consecutive data points for + * | which the threshold condition must be respected, + * | for interrupt assertion. It is expressed in 50 Hz + * duration | samples (20 msec). + * | Range is 0 to 163sec. + * | Default value is 5 = 100ms. + * -------------------------|--------------------------------------------------- + * | Slope threshold value for in 5.11g format. + * threshold | Range is 0 to 1g. + * | Default value is 0xAA = 83mg. + * -------------------------|--------------------------------------------------- + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_any_motion_config(const struct bmi2_any_motion_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets no-motion configurations like axes select, + * duration, threshold and output-configuration. + * + * @param[in] config : Structure instance of bmi2_no_motion_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_no_motion_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | Defines the number of consecutive data points for + * | which the threshold condition must be respected, + * | for interrupt assertion. It is expressed in 50 Hz + * duration | samples (20 msec). + * | Range is 0 to 163sec. + * | Default value is 5 = 100ms. + * -------------------------|--------------------------------------------------- + * | Slope threshold value for no-motion detection. + * threshold | Range is 0 to 1g. + * | Default value is 0x90 = 70mg. + * -------------------------|--------------------------------------------------- + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_no_motion_config(const struct bmi2_no_motion_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets sig-motion configurations like block-size, + * output-configuration and other parameters. + * + * @param[in] config : Structure instance of bmi2_sig_motion_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + *---------------------------------------------------------------------------- + * bmi2_sig_motion_config | + * Structure parameters | Description + * -------------------------|--------------------------------------------------- + * | Defines the duration after which the significant + * block_size | motion interrupt is triggered. It is expressed in + * | 50 Hz samples (20 ms). Default value is 0xFA=5sec. + *--------------------------|--------------------------------------------------- + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_sig_motion_config(const struct bmi2_sig_motion_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets step counter/detector/activity configurations. + * + * @param[in] config : Structure instance of bmi2_step_config. + * @param[in] dev : Structure instance of bmi2_dev. + * + *--------------------------------------------------------------------------- + * bmi2_step_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | The Step-counter will trigger output every time + * | the number of steps are counted. Holds implicitly + * water-mark level | a 20x factor, so the range is 0 to 10230, + * | with resolution of 20 steps. + * -------------------------|--------------------------------------------------- + * reset counter | Flag to reset the counted steps. + * -------------------------|--------------------------------------------------- + * step_buffer_size | Step counter buffer size + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_step_config(const struct bmi2_step_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets tap configurations like sensitivity, + * single, double and triple tap enable and output-configuration. + * + * @param[in] config : Structure instance of bmi2_tap_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_tap_detector_config(struct bmi2_tap_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets orientation configurations like upside/down + * detection, symmetrical modes, blocking mode, theta, hysteresis and output + * configuration. + * + * @param[in] config : Structure instance of bmi2_orient_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_orient_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * upside/down | Enables upside/down detection, if set to 1. + * detection | + * -------------------------|--------------------------------------------------- + * | Sets the mode: + * mode | Values 0 or 3 - symmetrical. + * | Value 1 - high asymmetrical + * | Value 2 - low asymmetrical + * -------------------------|--------------------------------------------------- + * | Enable - no orientation interrupt will be set. + * blocking | Default value: 3, the most restrictive blocking. + * -------------------------|--------------------------------------------------- + * | Threshold angle used in blocking mode. + * theta | Theta = 64 * (tan(angle)^2) + * | Default value: 40, equivalent to 38 degrees angle. + * -------------------------|--------------------------------------------------- + * | Acceleration hysteresis for Orientation detection + * | is expressed in 5.11g format. + * hysteresis | Default value is 128 = 0.0625g. + * | Range is 0 to 1g. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_orient_config(const struct bmi2_orient_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets high-g configurations like threshold, + * hysteresis, duration, and output configuration. + * + * @param[in] config : Structure instance of bmi2_high_g_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_high_g_config | + * Structure parameter | Description + *--------------------------|-------------------------------------------------- + * threshold | The acceleration threshold above which the + * | high_g motion is signaled. + * | Threshold value for high_g feature. + * | Range is 0 to 16g. + * | Default value is 10000 = 4.9g. + * -------------------------|--------------------------------------------------- + * | Hysteresis value for high_g feature. + * hysteresis | Range is 0 to 2g. + * | Default value is 1000 = 0.49g. + * -------------------------|--------------------------------------------------- + * | Holds the duration in 200 Hz samples (5 ms) for + * | which the threshold has to be exceeded. + * duration | Default value 4 = 20 msec. + * | Range is 0 to 20sec. + * -------------------------|--------------------------------------------------- + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_high_g_config(const struct bmi2_high_g_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets low-g configurations like threshold, + * hysteresis, duration, and output configuration. + * + * @param[in] config : Structure instance of bmi2_low_g_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_low_g_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * threshold | The acceleration threshold above which the + * | low-g motion is signaled. + * | Range is 0 to 1g. + * | Default value is 512 = 0.25g. + * -------------------------|--------------------------------------------------- + * | Hysteresis value for low_g feature. + * | Range is 0 to 0.5g. + * hysteresis | Default value is 256 = 0.125g. + * -------------------------|--------------------------------------------------- + * | Holds the duration in 50 Hz samples (20 ms) for + * | which the threshold has to be exceeded. + * duration | Range is 0 to 82 sec. + * | Default value is 0 = 0 ms. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_low_g_config(const struct bmi2_low_g_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets flat configurations like theta, blocking, + * hold-time, hysteresis, and output configuration. + * + * @param[in] config : Structure instance of bmi2_flat_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_flat_config | + * Structure parameters| Description + *--------------------------|-------------------------------------------------- + * | Sets the theta angle, used for detecting flat + * | position. + * theta | Theta = 64 * (tan(angle)^2); + * | Default value is 8, equivalent to 20 degrees angle + * -------------------------|--------------------------------------------------- + * | Hysteresis for Theta Flat detection. + * hysteresis | Default value is 9 = 2.5 degrees, corresponding + * | to the default Theta angle of 20 degrees. + * -------------------------|--------------------------------------------------- + * | Sets the blocking mode. If blocking is set, no + * | Flat interrupt will be triggered. + * blocking | Default value is 2, the most restrictive blocking + * | mode. + * -------------------------|--------------------------------------------------- + * | Holds the duration in 50Hz samples for which the + * | condition has to be respected. + * hold-time | Default value is 32 = 640 msec. + * | Range is 0 to 5.1 sec. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_flat_config(const struct bmi2_flat_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets any-motion configurations like axes select, + * duration, threshold and output-configuration. + * + * @param[out] config : Structure instance of bmi2_any_motion_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_any_motion_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | Defines the number of consecutive data points for + * | which the threshold condition must be respected, + * | for interrupt assertion. It is expressed in 50 Hz + * duration | samples (20 msec). + * | Range is 0 to 163sec. + * | Default value is 5 = 100ms. + * -------------------------|--------------------------------------------------- + * | Slope threshold value for in 5.11g format. + * threshold | Range is 0 to 1g. + * | Default value is 0xAA = 83mg. + * -------------------------|--------------------------------------------------- + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_any_motion_config(struct bmi2_any_motion_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets no-motion configurations like axes select, + * duration, threshold and output-configuration. + * + * @param[out] config : Structure instance of bmi2_no_motion_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_no_motion_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | Defines the number of consecutive data points for + * | which the threshold condition must be respected, + * | for interrupt assertion. It is expressed in 50 Hz + * duration | samples (20 msec). + * | Range is 0 to 163sec. + * | Default value is 5 = 100ms. + * -------------------------|--------------------------------------------------- + * | Slope threshold value for no-motion detection. + * threshold | Range is 0 to 1g. + * | Default value is 0x90 = 70mg. + * -------------------------|--------------------------------------------------- + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_no_motion_config(struct bmi2_no_motion_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets sig-motion configurations like block-size, + * output-configuration and other parameters. + * + * @param[out] config : Structure instance of bmi2_sig_motion_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + *---------------------------------------------------------------------------- + * bmi2_sig_motion_config | + * Structure parameters | Description + * -------------------------|--------------------------------------------------- + * | Defines the duration after which the significant + * block_size | motion interrupt is triggered. It is expressed in + * | 50 Hz samples (20 ms). Default value is 0xFA=5sec. + *--------------------------|--------------------------------------------------- + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_sig_motion_config(struct bmi2_sig_motion_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets step counter/detector/activity configurations. + * + * @param[out] config : Structure instance of bmi2_step_config. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_step_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * | The Step-counter will trigger output every time + * | the number of steps are counted. Holds implicitly + * water-mark level | a 20x factor, so the range is 0 to 10230, + * | with resolution of 20 steps. + * -------------------------|--------------------------------------------------- + * reset counter | Flag to reset the counted steps. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_step_config(struct bmi2_step_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets tap configurations like sensitivity, + * single, double and triple tap enable and output-configuration. + * + * @param[out] config : Structure instance of bmi2_tap_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_tap_detector_config(struct bmi2_tap_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets orientation configurations like upside/down + * detection, symmetrical modes, blocking mode, theta, hysteresis and output + * configuration. + * + * @param[out] config : Structure instance of bmi2_orient_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_orient_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * upside/down | Enables upside/down detection, if set to 1. + * detection | + * -------------------------|--------------------------------------------------- + * | Sets the mode: + * mode | Values 0 or 3 - symmetrical. + * | Value 1 - high asymmetrical + * | Value 2 - low asymmetrical + * -------------------------|--------------------------------------------------- + * | Enable - no orientation interrupt will be set. + * blocking | Default value: 3, the most restrictive blocking. + * -------------------------|--------------------------------------------------- + * | Threshold angle used in blocking mode. + * theta | Theta = 64 * (tan(angle)^2) + * | Default value: 40, equivalent to 38 degrees angle. + * -------------------------|--------------------------------------------------- + * | Acceleration hysteresis for Orientation detection + * | is expressed in 5.11g format. + * hysteresis | Default value is 128 = 0.0625g. + * | Range is 0 to 1g. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_orient_config(struct bmi2_orient_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets high-g configurations like threshold, + * hysteresis, duration, and output configuration. + * + * @param[out] config : Structure instance of bmi2_high_g_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *----------------------------------------------------------------------------- + * bmi2_high_g_config | + * Structure parameter | Description + *--------------------------|-------------------------------------------------- + * threshold | The acceleration threshold above which the + * | high_g motion is signaled. + * | Holds threshold in 5.11 g format. + * | Default is 3072 = 1.5 g. + * | Range is 0 to 16g. + * -------------------------|--------------------------------------------------- + * | Acceleration hysteresis for high-g detection + * | is expressed in 1.11g format. + * hysteresis | Default value is 256 = 0.125 g. + * | Range is 0 to 2g. + * | Should be smaller than threshold. + * -------------------------|--------------------------------------------------- + * | Holds the duration in 200 Hz samples (5 ms) for + * | which the threshold has to be exceeded. + * duration |Default value 4 = 20 msec. + * | Range is 0 to 20sec. + * -------------------------|--------------------------------------------------- + * select_x, select_y, | + * select_z | Selects the feature on a per-axis basis + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_high_g_config(struct bmi2_high_g_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets low-g configurations like threshold, + * hysteresis, duration, and output configuration. + * + * @param[out] config : Structure instance of bmi2_low_g_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + * bmi2_low_g_config | + * Structure parameters | Description + *--------------------------|-------------------------------------------------- + * threshold | The acceleration threshold above which the + * | low-g motion is signaled. + * | Holds threshold in 5.11 g format. + * | Default is 3072 = 1.5 g. + * -------------------------|--------------------------------------------------- + * | Acceleration hysteresis for low-g detection + * hysteresis | is expressed in 1.11g format. + * | Default value is 512 = 0.250 g. + * | Should be smaller than threshold. + * -------------------------|--------------------------------------------------- + * | Holds the duration in 50 Hz samples (20 ms) for + * | which the threshold has to be exceeded. + * duration | Default value 0 = 1 validation sample = (0+1)*20 + * | = 20 ms. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_low_g_config(struct bmi2_low_g_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets flat configurations like theta, blocking, + * hold-time, hysteresis, and output configuration. + * + * @param[out] config : Structure instance of bmi2_flat_config. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @verbatim + *---------------------------------------------------------------------------- + * bmi2_flat_config | + * Structure parameters| Description + *--------------------------|-------------------------------------------------- + * | Theta angle, used for detecting flat + * | position. + * theta | Theta = 64 * (tan(angle)^2); + * | Default value is 8, equivalent to 20 degrees angle + * -------------------------|--------------------------------------------------- + * | Hysteresis for Theta Flat detection. + * hysteresis | Default value is 9 = 2.5 degrees, corresponding + * | to the default Theta angle of 20 degrees. + * -------------------------|--------------------------------------------------- + * | Sets the blocking mode. If blocking is set, no + * | Flat interrupt will be triggered. + * blocking | Default value is 2, the most restrictive blocking + * | mode. + * -------------------------|--------------------------------------------------- + * | Holds the duration in 50Hz samples for which the + * | condition has to be respected. + * hold-time | Default value is 32 = 640 m-sec. + * | Range is 0 to 5.1 sec. + * -------------------------|--------------------------------------------------- + * @endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_flat_config(struct bmi2_flat_config *config, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets the output values of high-g. + * + * @param[out] high_g_out : Pointer to the stored high-g output. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_high_g_output(uint8_t *high_g_out, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets the output values of step activity. + * + * @param[out] step_act : Pointer to the stored step activity data. + * @param[in] dev : Structure instance of bmi2_dev. + * + * *step_act | Output + * -----------|------------ + * 0x00 | STILL + * 0x01 | WALKING + * 0x02 | RUNNING + * 0x03 | UNKNOWN + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_step_activity_output(uint8_t *step_act, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets the output values of orientation: portrait- + * landscape and face up-down. + * + * @param[out] orient_out : Structure pointer to the orientation data. + * @param[in] dev : Structure instance of bmi2_dev. + * + * + * portrait | + * landscape | Output + * -----------|------------ + * 0x00 | PORTRAIT UPRIGHT + * 0x01 | LANDSCAPE LEFT + * 0x02 | PORTRAIT UPSIDE DOWN + * 0x03 | LANDSCAPE RIGHT + * + * Face | + * up-down | Output + * -----------|------------ + * 0x00 | FACE-UP + * 0x01 | FACE-DOWN + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_orient_output(struct bmi2_orientation_output *orient_out, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets the output values of step counter. + * + * @param[out] step_count : Pointer to the stored step counter data. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_step_counter_output(uint32_t *step_count, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets the error status related to NVM. + * + * @param[out] nvm_err_stat : Stores the NVM error status. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_nvm_error_status(struct bmi2_nvm_err_status *nvm_err_stat, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets the error status related to virtual frames. + * + * @param[out] vfrm_err_stat : Stores the VFRM related error status. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_vfrm_error_status(struct bmi2_vfrm_err_status *vfrm_err_stat, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to get enable status of gyroscope user gain + * update. + * + * @param[out] status : Stores status of gyroscope user gain update. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_user_gain_upd_status(uint8_t *status, struct bmi2_dev *dev); + +/*! + * @brief This internal API enables/disables compensation of the gain defined + * in the GAIN register. + * + * @param[in] enable : Enables/Disables gain compensation + * @param[in] dev : Structure instance of bmi2_dev. + * + * enable | Description + * -------------|--------------- + * BMI2_ENABLE | Enable gain compensation. + * BMI2_DISABLE | Disable gain compensation. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_gyro_gain(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to extract the output feature configuration + * details like page and start address from the look-up table. + * + * @param[out] feat_output : Structure that stores output feature + * configurations. + * @param[in] type : Type of feature or sensor. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Returns the feature found flag. + * + * @retval BMI2_FALSE : Feature not found + * BMI2_TRUE : Feature found + */ +static uint8_t extract_output_feat_config(struct bmi2_feature_config *feat_output, + uint8_t type, + const struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable/disable step activity detection. + * + * @param[in] dev : Structure instance of bmi2_dev. + * @param[in] enable : Enables/Disables step activity. + * + * Enable | Description + * -------------|--------------- + * BMI2_DISABLE | Disables step activity + * BMI2_ENABLE | Enables step activity + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_step_activity(uint8_t enable, struct bmi2_dev *dev); + +/*! + * @brief This internal API sets feature configuration to the sensor. + * + * @param[in] sens_cfg : Structure instance of bmi2_sens_config. + * @param[in] loop : Variable to loop the sensor feature. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t set_feat_config(struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev); + +/*! + * @brief This internal API gets feature configuration from the sensor. + * + * @param[in] sens_cfg : Structure instance of bmi2_sens_config. + * @param[in] loop : Variable to loop the sensor feature. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t get_feat_config(struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev); + +/*! + * @brief This internal API selects the sensors/features to be enabled or + * disabled. + * + * @param[in] sens_list : Pointer to select the sensor. + * @param[in] count : Number of sensors selected. + * @param[in] sensor_sel : Gets the selected sensor. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t sens_select(const uint8_t *sens_list, uint8_t count, uint64_t *sensor_sel); + +/*! + * @brief This internal API is used to enable main sensors like accel, gyro, aux and temperature. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to enable sensor features. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t enable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to disable main sensors like accel, gyro, aux and temperature. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t disable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev); + +/*! + * @brief This internal API is used to disable sensor features. + * + * @param[in] sensor_sel : Gets the selected sensor. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +static int8_t disable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev); + +/***************************************************************************/ + +/*! User Interface Definitions + ****************************************************************************/ + +/*! + * @brief This API: + * 1) Updates the device structure with address of the configuration file. + * 2) Initializes BMI270_LEGACY sensor. + * 3) Writes the configuration file. + * 4) Updates the feature offset parameters in the device structure. + * 5) Updates the maximum number of pages, in the device structure. + */ +int8_t bmi270_legacy_init(struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt == BMI2_OK) + { + /* Assign chip id of BMI270_LEGACY */ + dev->chip_id = BMI270_LEGACY_CHIP_ID; + + /* Get the size of config array */ + dev->config_size = sizeof(bmi270_legacy_config_file); + + /* Enable the variant specific features if any */ + dev->variant_feature = BMI2_CRT_RTOSK_ENABLE | BMI2_GYRO_CROSS_SENS_ENABLE; + + /* An extra dummy byte is read during SPI read */ + if (dev->intf == BMI2_SPI_INTF) + { + dev->dummy_byte = 1; + } + else + { + dev->dummy_byte = 0; + } + + /* If configuration file pointer is not assigned any address */ + if (!dev->config_file_ptr) + { + /* Give the address of the configuration file array to + * the device pointer + */ + dev->config_file_ptr = bmi270_legacy_config_file; + } + + /* Initialize BMI2 sensor */ + rslt = bmi2_sec_init(dev); + if (rslt == BMI2_OK) + { + /* Assign the offsets of the feature input + * configuration to the device structure + */ + dev->feat_config = bmi270_legacy_feat_in; + + /* Assign the offsets of the feature output to + * the device structure + */ + dev->feat_output = bmi270_legacy_feat_out; + + /* Assign the maximum number of pages to the + * device structure + */ + dev->page_max = BMI270_LEGACY_MAX_PAGE_NUM; + + /* Assign maximum number of input sensors + * features to device structure + */ + dev->input_sens = BMI270_LEGACY_MAX_FEAT_IN; + + /* Assign maximum number of output sensors + * features to device structure + */ + dev->out_sens = BMI270_LEGACY_MAX_FEAT_OUT; + + /* Assign the tap get configurations to function pointer */ + dev->get_tap_config = get_tap_config; + + /* Assign the tap set configurations to function pointer */ + dev->set_tap_config = set_tap_config; + + /* Assign the offsets of the feature interrupt + * to the device structure + */ + dev->map_int = bmi270_legacy_map_int; + + /* Assign maximum number of feature interrupts + * to device structure + */ + dev->sens_int_map = BMI270_LEGACY_MAX_INT_MAP; + + /* Get the gyroscope cross axis sensitivity */ + rslt = bmi2_get_gyro_cross_sense(dev); + } + } + + return rslt; +} + +/*! + * @brief This API selects the sensors/features to be enabled. + */ +int8_t bmi270_legacy_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to select sensor */ + uint64_t sensor_sel = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (sens_list != NULL)) + { + /* Get the selected sensors */ + rslt = select_sensor(sens_list, n_sens, &sensor_sel); + if (rslt == BMI2_OK) + { + /* Enable the selected sensors */ + rslt = sensor_enable(sensor_sel, dev); + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API selects the sensors/features to be disabled. + */ +int8_t bmi270_legacy_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to select sensor */ + uint64_t sensor_sel = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (sens_list != NULL)) + { + /* Get the selected sensors */ + rslt = select_sensor(sens_list, n_sens, &sensor_sel); + if (rslt == BMI2_OK) + { + /* Disable the selected sensors */ + rslt = sensor_disable(sensor_sel, dev); + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API sets the sensor/feature configuration. + */ +int8_t bmi270_legacy_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to define loop */ + uint8_t loop; + + /* Variable to get the status of advance power save */ + uint8_t aps_stat = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (sens_cfg != NULL)) + { + /* Get status of advance power save mode */ + aps_stat = dev->aps_status; + + for (loop = 0; loop < n_sens; loop++) + { + if ((sens_cfg[loop].type == BMI2_ACCEL) || (sens_cfg[loop].type == BMI2_GYRO) || + (sens_cfg[loop].type == BMI2_AUX) || (sens_cfg[loop].type == BMI2_GYRO_GAIN_UPDATE)) + { + rslt = bmi2_set_sensor_config(&sens_cfg[loop], 1, dev); + } + else + { + /* Disable Advance power save if enabled for auxiliary + * and feature configurations + */ + if (aps_stat == BMI2_ENABLE) + { + /* Disable advance power save if + * enabled + */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); + } + + if (rslt == BMI2_OK) + { + rslt = set_feat_config(sens_cfg, loop, dev); + } + /* Return error if any of the set configurations fail */ + else + { + break; + } + } + } + + /* Enable Advance power save if disabled while configuring and + * not when already disabled + */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the sensor/feature configuration. + */ +int8_t bmi270_legacy_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to define loop */ + uint8_t loop; + + /* Variable to get the status of advance power save */ + uint8_t aps_stat = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (sens_cfg != NULL)) + { + /* Get status of advance power save mode */ + aps_stat = dev->aps_status; + for (loop = 0; loop < n_sens; loop++) + { + if ((sens_cfg[loop].type == BMI2_ACCEL) || (sens_cfg[loop].type == BMI2_GYRO) || + (sens_cfg[loop].type == BMI2_AUX) || (sens_cfg[loop].type == BMI2_GYRO_GAIN_UPDATE)) + { + rslt = bmi2_get_sensor_config(&sens_cfg[loop], 1, dev); + } + else + { + /* Disable Advance power save if enabled for auxiliary + * and feature configurations + */ + if ((sens_cfg[loop].type >= BMI2_MAIN_SENS_MAX_NUM) || (sens_cfg[loop].type == BMI2_AUX)) + { + + if (aps_stat == BMI2_ENABLE) + { + /* Disable advance power save if + * enabled + */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); + } + } + + if (rslt == BMI2_OK) + { + rslt = get_feat_config(sens_cfg, loop, dev); + } + /* Return error if any of the get configurations fail */ + else + { + break; + } + } + } + + /* Enable Advance power save if disabled while configuring and + * not when already disabled + */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API gets the feature data. + */ +int8_t bmi270_legacy_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to define loop */ + uint8_t loop; + + /* Variable to get the status of advance power save */ + uint8_t aps_stat = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (feature_data != NULL)) + { + /* Get status of advance power save mode */ + aps_stat = dev->aps_status; + for (loop = 0; loop < n_sens; loop++) + { + if ((feature_data[loop].type == BMI2_GYRO_GAIN_UPDATE) || + (feature_data[loop].type == BMI2_GYRO_CROSS_SENSE)) + { + rslt = bmi2_get_feature_data(&feature_data[loop], 1, dev); + } + else + { + /* Disable Advance power save if enabled for feature + * configurations + */ + if (feature_data[loop].type >= BMI2_MAIN_SENS_MAX_NUM) + { + if (aps_stat == BMI2_ENABLE) + { + /* Disable advance power save if + * enabled + */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); + } + } + + if (rslt == BMI2_OK) + { + switch (feature_data[loop].type) + { + case BMI2_STEP_COUNTER: + + /* Get step counter output */ + rslt = get_step_counter_output(&feature_data[loop].sens_data.step_counter_output, dev); + break; + + case BMI2_STEP_ACTIVITY: + + /* Get step activity output */ + rslt = get_step_activity_output(&feature_data[loop].sens_data.activity_output, dev); + break; + + case BMI2_ORIENTATION: + + /* Get orientation output */ + rslt = get_orient_output(&feature_data[loop].sens_data.orient_output, dev); + break; + + case BMI2_HIGH_G: + + /* Get high-g output */ + rslt = get_high_g_output(&feature_data[loop].sens_data.high_g_output, dev); + break; + + case BMI2_NVM_STATUS: + + /* Get NVM error status */ + rslt = get_nvm_error_status(&feature_data[loop].sens_data.nvm_status, dev); + break; + + case BMI2_VFRM_STATUS: + + /* Get VFRM error status */ + rslt = get_vfrm_error_status(&feature_data[loop].sens_data.vfrm_status, dev); + break; + + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + } + + /* Return error if any of the get sensor data fails */ + if (rslt != BMI2_OK) + { + break; + } + } + + /* Enable Advance power save if disabled while + * configuring and not when already disabled + */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); + } + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API updates the gyroscope user-gain. + */ +int8_t bmi270_legacy_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to select sensor */ + uint8_t sens_sel[2] = { BMI2_GYRO, BMI2_GYRO_GAIN_UPDATE }; + + /* Structure to define sensor configurations */ + struct bmi2_sens_config sens_cfg; + + /* Variable to store status of user-gain update module */ + uint8_t status = 0; + + /* Variable to define count */ + uint8_t count = 100; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (user_gain != NULL)) + { + /* Select type of feature */ + sens_cfg.type = BMI2_GYRO_GAIN_UPDATE; + + /* Get the user gain configurations */ + rslt = bmi270_legacy_get_sensor_config(&sens_cfg, 1, dev); + if (rslt == BMI2_OK) + { + /* Get the user-defined ratio */ + sens_cfg.cfg.gyro_gain_update = *user_gain; + + /* Set rate ratio for all axes */ + rslt = bmi270_legacy_set_sensor_config(&sens_cfg, 1, dev); + } + + /* Disable gyroscope */ + if (rslt == BMI2_OK) + { + rslt = bmi270_legacy_sensor_disable(&sens_sel[0], 1, dev); + } + + /* Enable gyroscope user-gain update module */ + if (rslt == BMI2_OK) + { + rslt = bmi270_legacy_sensor_enable(&sens_sel[1], 1, dev); + } + + /* Set the command to trigger the computation */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_command_register(BMI2_USR_GAIN_CMD, dev); + } + + if (rslt == BMI2_OK) + { + /* Poll until enable bit of user-gain update is 0 */ + while (count--) + { + rslt = get_user_gain_upd_status(&status, dev); + if ((rslt == BMI2_OK) && (status == 0)) + { + /* Enable compensation of gain defined + * in the GAIN register + */ + rslt = enable_gyro_gain(BMI2_ENABLE, dev); + + /* Enable gyroscope */ + if (rslt == BMI2_OK) + { + rslt = bmi270_legacy_sensor_enable(&sens_sel[0], 1, dev); + } + + break; + } + + dev->delay_us(10000, dev->intf_ptr); + } + + /* Return error if user-gain update is failed */ + if ((rslt == BMI2_OK) && (status != 0)) + { + rslt = BMI2_E_GYR_USER_GAIN_UPD_FAIL; + } + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API reads the compensated gyroscope user-gain values. + */ +int8_t bmi270_legacy_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to define register data */ + uint8_t reg_data[3] = { 0 }; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (gyr_usr_gain != NULL)) + { + /* Get the gyroscope compensated gain values */ + rslt = bmi2_get_regs(BMI2_GYR_USR_GAIN_0_ADDR, reg_data, 3, dev); + if (rslt == BMI2_OK) + { + /* Gyroscope user gain correction X-axis */ + gyr_usr_gain->x = (int8_t)BMI2_GET_BIT_POS0(reg_data[0], BMI2_GYR_USR_GAIN_X); + + /* Gyroscope user gain correction Y-axis */ + gyr_usr_gain->y = (int8_t)BMI2_GET_BIT_POS0(reg_data[1], BMI2_GYR_USR_GAIN_Y); + + /* Gyroscope user gain correction z-axis */ + gyr_usr_gain->z = (int8_t)BMI2_GET_BIT_POS0(reg_data[2], BMI2_GYR_USR_GAIN_Z); + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API maps/unmaps feature interrupts to that of interrupt pins. + */ +int8_t bmi270_legacy_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to define loop */ + uint8_t loop; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt == BMI2_OK) && (sens_int != NULL)) + { + for (loop = 0; loop < n_sens; loop++) + { + switch (sens_int[loop].type) + { + case BMI2_SIG_MOTION: + case BMI2_TAP: + case BMI2_ORIENTATION: + case BMI2_HIGH_G: + case BMI2_LOW_G: + case BMI2_FLAT: + case BMI2_ANY_MOTION: + case BMI2_NO_MOTION: + case BMI2_STEP_COUNTER: + case BMI2_STEP_DETECTOR: + case BMI2_STEP_ACTIVITY: + + rslt = bmi2_map_feat_int(sens_int[loop].type, sens_int[loop].hw_int_pin, dev); + break; + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + + /* Return error if interrupt mapping fails */ + if (rslt != BMI2_OK) + { + break; + } + } + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/***************************************************************************/ + +/*! Local Function Definitions + ****************************************************************************/ + +/*! + * @brief This internal API is used to get the tap configurations. + */ +static int8_t get_tap_config(void *tap, void *bmi2_dev) +{ + /* Variable to define error */ + int8_t rslt; + + rslt = get_config_page_primary(tap, bmi2_dev); + + if (rslt == BMI2_OK) + { + rslt = get_config_page_secondary(tap, bmi2_dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to get the tap configurations + * from primary page. + */ +static int8_t get_config_page_primary(void *tap, void *bmi2_dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Structure to define BMI2 sensor configurations */ + struct bmi2_dev *dev = (struct bmi2_dev *)bmi2_dev; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint8_t lsb = 0; + + /* Variable to define MSB */ + uint8_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Structure to define tap configurations */ + bmi270_legacy_config = (struct bmi2_tap_config *)tap; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_TAP_DETECTOR_1, dev); + + if (feat_found == BMI2_TRUE) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for tap select */ + idx = tap_config.start_addr; + + /* Get word to calculate single tap, double tap, triple tap, data register + * enable and output configuration + */ + lsb = feat_config[idx++]; + msb = feat_config[idx++]; + lsb_msb = ((uint16_t)msb << 8) | lsb; + + /* Get filtered tap data */ + bmi270_legacy_config->data_reg_en = (lsb_msb & BMI2_TAP_DATA_REG_EN_MASK) >> BMI2_TAP_DATA_REG_EN_POS; + + /* Get word to calculate tap_sens_thres */ + idx = 4; + lsb = feat_config[idx++]; + msb = feat_config[idx++]; + lsb_msb = ((uint16_t)msb << 8) | lsb; + + /* Get scaling factor of threshold */ + bmi270_legacy_config->tap_sens_thres = lsb_msb; + + /* Get word to calculate max_gest_dur */ + idx = 6; + lsb = feat_config[idx++]; + msb = feat_config[idx++]; + lsb_msb = ((uint16_t)msb << 8) | lsb; + + /* Get maximum duration between each taps */ + bmi270_legacy_config->max_gest_dur = lsb_msb; + + /* Get word to calculate quite_time_after_gest */ + idx = 14; + lsb = feat_config[idx++]; + msb = feat_config[idx++]; + lsb_msb = ((uint16_t)msb << 8) | lsb; + + /* Get minimum quite time between the two gesture detection */ + bmi270_legacy_config->quite_time_after_gest = lsb_msb; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to get the tap configurations + * from secondary page. + */ +static int8_t get_config_page_secondary(void *tap, void *bmi2_dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Structure to define BMI2 sensor configurations */ + struct bmi2_dev *dev = (struct bmi2_dev *)bmi2_dev; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint8_t lsb = 0; + + /* Variable to define MSB */ + uint8_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_TAP_DETECTOR_2, dev); + + /* Structure to define tap configurations */ + bmi270_legacy_config = (struct bmi2_tap_config *)tap; + + if (feat_found == BMI2_TRUE) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for tap select */ + idx = tap_config.start_addr; + + /* Get word to calculate wait_for_timeout */ + lsb = feat_config[idx++]; + msb = feat_config[idx++]; + lsb_msb = ((uint16_t)msb << 8) | lsb; + + /* Get number of taps detected based on wait time */ + bmi270_legacy_config->wait_for_timeout = lsb_msb; + + idx = 4; + + /* Get word to calculate axis_sel */ + lsb = feat_config[idx++]; + msb = feat_config[idx++]; + lsb_msb = ((uint16_t)msb << 8) | lsb; + + /* Select axis for tap detection */ + bmi270_legacy_config->axis_sel = (lsb_msb & BMI2_TAP_AXIS_SEL_MASK); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the tap configurations. + */ +static int8_t set_tap_config(void *tap, void *bmi2_dev) +{ + /* Variable to define error */ + int8_t rslt; + + rslt = set_config_page_primary(tap, bmi2_dev); + + if (rslt == BMI2_OK) + { + rslt = set_config_page_secondary(tap, bmi2_dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the tap configurations + * to primary page. + */ +static int8_t set_config_page_primary(void *tap, void *bmi2_dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Structure to define BMI2 sensor configurations */ + struct bmi2_dev *dev = (struct bmi2_dev *)bmi2_dev; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Structure to define tap configurations */ + bmi270_legacy_config = (struct bmi2_tap_config *)tap; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_TAP_DETECTOR_1, dev); + + if (feat_found == BMI2_TRUE) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for tap select */ + idx = tap_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set filtered tap data */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_TAP_DATA_REG_EN, bmi270_legacy_config->data_reg_en); + + /* Starting address of tap_sens_thres represented in word length */ + idx = 2; + + /* Set scaling factor of threshold */ + *(data_p + idx) = bmi270_legacy_config->tap_sens_thres; + + /* Starting address of max_gest_dur represented in word length */ + idx = 3; + + /* Set maximum duration between each taps */ + *(data_p + idx) = bmi270_legacy_config->max_gest_dur; + + /* Starting address of quite_time_after_gest represented in word length */ + idx = 7; + + /* Set minimum quite time between the two gesture detection */ + *(data_p + idx) = bmi270_legacy_config->quite_time_after_gest; + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - tap_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index <= idx; index++) + { + feat_config[tap_config.start_addr + index] = *((uint8_t *) data_p + tap_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the tap configurations + * to secondary page. + */ +static int8_t set_config_page_secondary(void *tap, void *bmi2_dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Structure to define BMI2 sensor configurations */ + struct bmi2_dev *dev = (struct bmi2_dev *)bmi2_dev; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Structure to define tap configurations */ + bmi270_legacy_config = (struct bmi2_tap_config *)tap; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_TAP_DETECTOR_2, dev); + + if (feat_found == BMI2_TRUE) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for tap select */ + idx = tap_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set wait time */ + *(data_p + idx) = bmi270_legacy_config->wait_for_timeout; + + /* Starting address of axis_sel represented in word length */ + idx = 2; + + /* Select axis for tap detection */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_TAP_AXIS_SEL, bmi270_legacy_config->axis_sel); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - tap_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[tap_config.start_addr + index] = *((uint8_t *) data_p + tap_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to validate the device structure pointer for + * null conditions. + */ +static int8_t null_ptr_check(const struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL)) + { + /* Device structure pointer is not valid */ + rslt = BMI2_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This internal API selects the sensor/features to be enabled or + * disabled. + */ +static int8_t select_sensor(const uint8_t *sens_list, uint8_t n_sens, uint64_t *sensor_sel) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Variable to define loop */ + uint8_t count; + + for (count = 0; count < n_sens;) + { + if (sens_list[count] == BMI2_ACCEL) + { + *sensor_sel |= BMI2_ACCEL_SENS_SEL; + count++; + } + + if (sens_list[count] == BMI2_GYRO) + { + *sensor_sel |= BMI2_GYRO_SENS_SEL; + count++; + } + + if (sens_list[count] == BMI2_AUX) + { + *sensor_sel |= BMI2_AUX_SENS_SEL; + count++; + } + + if (sens_list[count] == BMI2_TEMP) + { + *sensor_sel |= BMI2_TEMP_SENS_SEL; + count++; + } + + if (count < n_sens) + { + rslt = sens_select(sens_list, count, sensor_sel); + count++; + } + } + + return rslt; +} + +/*! + * @brief This internal API enables the selected sensor/features. + */ +static int8_t sensor_enable(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to get the status of advance power save */ + uint8_t aps_stat = 0; + + rslt = enable_main_sensors(sensor_sel, dev); + + if ((rslt == BMI2_OK) && (sensor_sel & ~(BMI2_MAIN_SENSORS))) + { + /* Get status of advance power save mode */ + aps_stat = dev->aps_status; + if (aps_stat == BMI2_ENABLE) + { + /* Disable advance power save if enabled */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); + } + + if (rslt == BMI2_OK) + { + rslt = enable_sensor_features(sensor_sel, dev); + + /* Enable Advance power save if disabled while + * configuring and not when already disabled + */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This internal API disables the selected sensors/features. + */ +static int8_t sensor_disable(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to get the status of advance power save */ + uint8_t aps_stat = 0; + + rslt = disable_main_sensors(sensor_sel, dev); + + if ((rslt == BMI2_OK) && (sensor_sel & ~(BMI2_MAIN_SENSORS))) + { + /* Get status of advance power save mode */ + aps_stat = dev->aps_status; + if (aps_stat == BMI2_ENABLE) + { + /* Disable advance power save if enabled */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); + } + + if (rslt == BMI2_OK) + { + rslt = disable_sensor_features(sensor_sel, dev); + + /* Enable Advance power save if disabled while + * configuring and not when already disabled */ + if ((aps_stat == BMI2_ENABLE) && (rslt == BMI2_OK)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable any motion feature. + */ +static int8_t set_any_motion(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for any-motion */ + struct bmi2_feature_config any_mot_config = { 0, 0, 0 }; + + /* Search for any-motion feature and extract its configurations details */ + feat_found = bmi2_extract_input_feat_config(&any_mot_config, BMI2_ANY_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where any-motion feature resides */ + rslt = bmi2_get_feat_config(any_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of any-motion axes */ + idx = any_mot_config.start_addr + BMI2_ANY_MOT_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_ANY_NO_MOT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_ANY_MOT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_ANY_MOT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable no-motion feature. + */ +static int8_t set_no_motion(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for no-motion */ + struct bmi2_feature_config no_mot_config = { 0, 0, 0 }; + + /* Search for no-motion feature and extract its configurations details */ + feat_found = bmi2_extract_input_feat_config(&no_mot_config, BMI2_NO_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where any/no-motion feature resides */ + rslt = bmi2_get_feat_config(no_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of no-motion axes */ + idx = no_mot_config.start_addr + BMI2_NO_MOT_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_ANY_NO_MOT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_NO_MOT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_NO_MOT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable step detector feature. + */ +static int8_t set_step_detector(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for step detector */ + struct bmi2_feature_config step_det_config = { 0, 0, 0 }; + + /* Search for step detector feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&step_det_config, BMI2_STEP_DETECTOR, dev); + if (feat_found) + { + /* Get the configuration from the page where step detector feature resides */ + rslt = bmi2_get_feat_config(step_det_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of step detector */ + idx = step_det_config.start_addr + BMI2_STEP_COUNT_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_STEP_DET_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_DETECT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_DETECT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable step counter feature. + */ +static int8_t set_step_counter(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for step counter */ + struct bmi2_feature_config step_count_config = { 0, 0, 0 }; + + /* Search for step counter feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&step_count_config, BMI2_STEP_COUNTER, dev); + if (feat_found) + { + /* Get the configuration from the page where step-counter feature resides */ + rslt = bmi2_get_feat_config(step_count_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of step counter */ + idx = step_count_config.start_addr + BMI2_STEP_COUNT_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_STEP_COUNT_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_COUNT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_COUNT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable step activity detection. + */ +static int8_t set_step_activity(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for step activity */ + struct bmi2_feature_config step_act_config = { 0, 0, 0 }; + + /* Search for step activity feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&step_act_config, BMI2_STEP_ACTIVITY, dev); + if (feat_found) + { + /* Get the configuration from the page where step-activity + * feature resides + */ + rslt = bmi2_get_feat_config(step_act_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of step activity */ + idx = step_act_config.start_addr + BMI2_STEP_COUNT_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_STEP_ACT_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_STEP_ACT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_STEP_ACT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable sig-motion feature. + */ +static int8_t set_sig_motion(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for sig-motion */ + struct bmi2_feature_config sig_mot_config = { 0, 0, 0 }; + + /* Search for sig-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&sig_mot_config, BMI2_SIG_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where sig-motion feature resides */ + rslt = bmi2_get_feat_config(sig_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of sig-motion */ + idx = sig_mot_config.start_addr + BMI2_SIG_MOT_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_SIG_MOT_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_SIG_MOTION_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_SIG_MOTION_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable tap feature through + * single tap. + */ +static int8_t set_single_tap(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_SINGLE_TAP, dev); + if (feat_found) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of tap */ + idx = tap_config.start_addr; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_TAP_SINGLE_TAP_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_SINGLE_TAP_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_SINGLE_TAP_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable tap feature through + * double tap. + */ +static int8_t set_double_tap(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_DOUBLE_TAP, dev); + if (feat_found) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of tap */ + idx = tap_config.start_addr; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_TAP_DOUBLE_TAP_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_DOUBLE_TAP_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_DOUBLE_TAP_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable tap feature through + * triple tap. + */ +static int8_t set_triple_tap(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for tap */ + struct bmi2_feature_config tap_config = { 0, 0, 0 }; + + /* Search for tap feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&tap_config, BMI2_TRIPLE_TAP, dev); + if (feat_found) + { + /* Get the configuration from the page where tap feature resides */ + rslt = bmi2_get_feat_config(tap_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of tap */ + idx = tap_config.start_addr; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_TAP_TRIPLE_TAP_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_TRIPLE_TAP_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_TRIPLE_TAP_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable orientation feature. + */ +static int8_t set_orientation(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for orientation */ + struct bmi2_feature_config orient_config = { 0, 0, 0 }; + + /* Search for orientation feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&orient_config, BMI2_ORIENTATION, dev); + if (feat_found) + { + /* Get the configuration from the page where orientation feature resides */ + rslt = bmi2_get_feat_config(orient_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of orientation */ + idx = orient_config.start_addr; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_ORIENT_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_ORIENT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_ORIENT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable high-g feature. + */ +static int8_t set_high_g(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for high-g */ + struct bmi2_feature_config high_g_config = { 0, 0, 0 }; + + /* Search for high-g feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&high_g_config, BMI2_HIGH_G, dev); + if (feat_found) + { + /* Get the configuration from the page where high-g feature resides */ + rslt = bmi2_get_feat_config(high_g_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of high-g */ + idx = high_g_config.start_addr + BMI2_HIGH_G_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_HIGH_G_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_HIGH_G_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_HIGH_G_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable low-g feature. + */ +static int8_t set_low_g(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for low-g */ + struct bmi2_feature_config low_g_config = { 0, 0, 0 }; + + /* Search for low-g feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&low_g_config, BMI2_LOW_G, dev); + if (feat_found) + { + /* Get the configuration from the page where low-g feature resides */ + rslt = bmi2_get_feat_config(low_g_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of low-g */ + idx = low_g_config.start_addr + BMI2_LOW_G_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_LOW_G_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_LOW_G_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_LOW_G_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable flat feature. + */ +static int8_t set_flat(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for flat */ + struct bmi2_feature_config flat_config = { 0, 0, 0 }; + + /* Search for flat feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&flat_config, BMI2_FLAT, dev); + if (feat_found) + { + /* Get the configuration from the page where flat feature resides */ + rslt = bmi2_get_feat_config(flat_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of flat */ + idx = flat_config.start_addr; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BIT_POS0(feat_config[idx], BMI2_FLAT_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_FLAT_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_FLAT_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gives an option to enable self-offset correction + * feature of gyroscope, either internally or by the host. + */ +static int8_t set_gyro_self_offset_corr(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for self-offset correction */ + struct bmi2_feature_config self_off_corr_cfg = { 0, 0, 0 }; + + /* Search for self-offset correction and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&self_off_corr_cfg, BMI2_GYRO_SELF_OFF, dev); + if (feat_found) + { + /* Get the configuration from the page where self-offset + * correction feature resides + */ + rslt = bmi2_get_feat_config(self_off_corr_cfg.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of self-offset correction */ + idx = self_off_corr_cfg.start_addr; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_GYR_SELF_OFF_CORR_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_GYRO_SELF_OFF_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_GYRO_SELF_OFF_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable/disable gyroscope user gain + * feature. + */ +static int8_t set_gyro_user_gain(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for gyroscope user gain */ + struct bmi2_feature_config gyr_user_gain_cfg = { 0, 0, 0 }; + + /* Search for user gain feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&gyr_user_gain_cfg, BMI2_GYRO_GAIN_UPDATE, dev); + if (feat_found) + { + /* Get the configuration from the page where user gain feature resides */ + rslt = bmi2_get_feat_config(gyr_user_gain_cfg.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of user gain */ + idx = gyr_user_gain_cfg.start_addr + BMI2_GYR_USER_GAIN_FEAT_EN_OFFSET; + + /* Set the feature enable bit */ + feat_config[idx] = BMI2_SET_BITS(feat_config[idx], BMI2_GYR_USER_GAIN_FEAT_EN, enable); + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + + if ((rslt == BMI2_OK) && (enable == BMI2_ENABLE)) + { + dev->sens_en_stat |= BMI2_GYRO_GAIN_UPDATE_SEL; + } + else + { + dev->sens_en_stat &= ~BMI2_GYRO_GAIN_UPDATE_SEL; + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets any-motion configurations like axes select, + * duration, threshold and output-configuration. + */ +static int8_t set_any_motion_config(const struct bmi2_any_motion_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define count */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for any motion */ + struct bmi2_feature_config any_mot_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for any-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&any_mot_config, BMI2_ANY_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where any-motion feature resides */ + rslt = bmi2_get_feat_config(any_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for any-motion select */ + idx = any_mot_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set duration */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_ANY_NO_MOT_DUR, config->duration); + + /* Set x-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ANY_NO_MOT_X_SEL, config->select_x); + + /* Set y-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ANY_NO_MOT_Y_SEL, config->select_y); + + /* Set z-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ANY_NO_MOT_Z_SEL, config->select_z); + + /* Increment offset by 1 word to set threshold and output configuration */ + idx++; + + /* Set threshold */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_ANY_NO_MOT_THRES, config->threshold); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - any_mot_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[any_mot_config.start_addr + + index] = *((uint8_t *) data_p + any_mot_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets no-motion configurations like axes select, + * duration, threshold and output-configuration. + */ +static int8_t set_no_motion_config(const struct bmi2_no_motion_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define count */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for no-motion */ + struct bmi2_feature_config no_mot_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for no-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&no_mot_config, BMI2_NO_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where no-motion feature resides */ + rslt = bmi2_get_feat_config(no_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for no-motion select */ + idx = no_mot_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set duration */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_ANY_NO_MOT_DUR, config->duration); + + /* Set x-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ANY_NO_MOT_X_SEL, config->select_x); + + /* Set y-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ANY_NO_MOT_Y_SEL, config->select_y); + + /* Set z-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ANY_NO_MOT_Z_SEL, config->select_z); + + /* Increment offset by 1 word to set threshold and output configuration */ + idx++; + + /* Set threshold */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_ANY_NO_MOT_THRES, config->threshold); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - no_mot_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[no_mot_config.start_addr + + index] = *((uint8_t *) data_p + no_mot_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets sig-motion configurations like block-size, + * output-configuration and other parameters. + */ +static int8_t set_sig_motion_config(const struct bmi2_sig_motion_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for sig-motion */ + struct bmi2_feature_config sig_mot_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for sig-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&sig_mot_config, BMI2_SIG_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where sig-motion feature resides */ + rslt = bmi2_get_feat_config(sig_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for sig-motion select */ + idx = sig_mot_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set parameter 1 */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_SIG_MOT_PARAM_1, config->block_size); + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - sig_mot_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[sig_mot_config.start_addr + + index] = *((uint8_t *) data_p + sig_mot_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/* @brief This internal API sets step counter configurations like water-mark + * level, reset-counter and output-configuration step detector and activity. + */ +static int8_t set_step_config(const struct bmi2_step_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for step counter 4 */ + struct bmi2_feature_config step_count_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for step counter feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&step_count_config, BMI2_STEP_COUNTER, dev); + if (feat_found) + { + /* Get the configuration from the page where step counter resides */ + rslt = bmi2_get_feat_config(step_count_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes */ + idx = step_count_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set water-mark level */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_STEP_COUNT_WM_LEVEL, config->watermark_level); + + /* Set reset-counter */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_STEP_COUNT_RST_CNT, config->reset_counter); + + /* Increment offset by 1 word to set output + * configuration of step detector and step activity + */ + idx++; + + /* Set step buffer size */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_STEP_BUFFER_SIZE, config->step_buffer_size); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - step_count_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[step_count_config.start_addr + + index] = *((uint8_t *) data_p + step_count_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/* @brief This internal API sets tap configurations like sensitivity, + * single, double and triple tap enable and output-configuration. + */ +static int8_t set_tap_detector_config(struct bmi2_tap_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + rslt = dev->set_tap_config(config, dev); + + return rslt; +} + +/*! + * @brief This internal API sets orientation configurations like upside/down + * detection, symmetrical modes, blocking mode, theta, hysteresis and output + * configuration. + */ +static int8_t set_orient_config(const struct bmi2_orient_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for orient */ + struct bmi2_feature_config orient_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for orient feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&orient_config, BMI2_ORIENTATION, dev); + if (feat_found) + { + /* Get the configuration from the page where orient feature resides */ + rslt = bmi2_get_feat_config(orient_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for orient select */ + idx = orient_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set upside/down detection */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ORIENT_UP_DOWN, config->ud_en); + + /* Set symmetrical modes */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ORIENT_SYMM_MODE, config->mode); + + /* Set blocking mode */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ORIENT_BLOCK_MODE, config->blocking); + + /* Set theta */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_ORIENT_THETA, config->theta); + + /* Increment offset by 1 more word to set hysteresis and output configuration */ + idx++; + + /* Set hysteresis */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_ORIENT_HYST, config->hysteresis); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - orient_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[orient_config.start_addr + + index] = *((uint8_t *) data_p + orient_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets high-g configurations like threshold, + * hysteresis, duration, and out0put configuration. + */ +static int8_t set_high_g_config(const struct bmi2_high_g_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for high-g */ + struct bmi2_feature_config high_g_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for high-g feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&high_g_config, BMI2_HIGH_G, dev); + if (feat_found) + { + /* Get the configuration from the page where high-g feature resides */ + rslt = bmi2_get_feat_config(high_g_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for high-g select */ + idx = high_g_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set threshold */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_HIGH_G_THRES, config->threshold); + + /* Increment offset by 1 more word to set hysteresis */ + idx++; + + /* Set hysteresis */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_HIGH_G_HYST, config->hysteresis); + + /* Set x-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_HIGH_G_X_SEL, config->select_x); + + /* Set y-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_HIGH_G_Y_SEL, config->select_y); + + /* Set z-select */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_HIGH_G_Z_SEL, config->select_z); + + /* Increment offset by 1 more word to set duration and output configuration */ + idx++; + + /* Set duration */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_HIGH_G_DUR, config->duration); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - high_g_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[high_g_config.start_addr + + index] = *((uint8_t *) data_p + high_g_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets low-g configurations like threshold, + * hysteresis, duration, and output configuration. + */ +static int8_t set_low_g_config(const struct bmi2_low_g_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for low-g */ + struct bmi2_feature_config low_g_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for low-g feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&low_g_config, BMI2_LOW_G, dev); + if (feat_found) + { + /* Get the configuration from the page where low-g feature resides */ + rslt = bmi2_get_feat_config(low_g_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for low-g select */ + idx = low_g_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set threshold */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_LOW_G_THRES, config->threshold); + + /* Increment offset by 1 more word to set hysteresis */ + idx++; + + /* Set hysteresis */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_LOW_G_HYST, config->hysteresis); + + /* Increment offset by 1 more word to set duration and output configuration */ + idx++; + + /* Set duration */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_LOW_G_DUR, config->duration); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - low_g_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[low_g_config.start_addr + index] = *((uint8_t *) data_p + low_g_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets flat configurations like theta, blocking, + * hold-time, hysteresis, and output configuration. + */ +static int8_t set_flat_config(const struct bmi2_flat_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define index */ + uint8_t index = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for flat */ + struct bmi2_feature_config flat_config = { 0, 0, 0 }; + + /* Copy the feature configuration address to a local pointer */ + uint16_t *data_p = (uint16_t *) (void *)feat_config; + + /* Search for flat feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&flat_config, BMI2_FLAT, dev); + if (feat_found) + { + /* Get the configuration from the page where flat feature resides */ + rslt = bmi2_get_feat_config(flat_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for flat select */ + idx = flat_config.start_addr; + + /* Get offset in words since all the features are set in words length */ + idx = idx / 2; + + /* Set theta */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_FLAT_THETA, config->theta); + + /* Set blocking */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_FLAT_BLOCK, config->blocking); + + /* Increment offset by 1 more word to set hysteresis and hold-time */ + idx++; + + /* Set hysteresis */ + *(data_p + idx) = BMI2_SET_BIT_POS0(*(data_p + idx), BMI2_FLAT_HYST, config->hysteresis); + + /* Set hold-time */ + *(data_p + idx) = BMI2_SET_BITS(*(data_p + idx), BMI2_FLAT_HOLD_TIME, config->hold_time); + + /* Increment offset by 1 more word to get the total length in words */ + idx++; + + /* Get total length in bytes to copy from local pointer to the array */ + idx = (uint8_t)(idx * 2) - flat_config.start_addr; + + /* Copy the bytes to be set back to the array */ + for (index = 0; index < idx; index++) + { + feat_config[flat_config.start_addr + index] = *((uint8_t *) data_p + flat_config.start_addr + index); + } + + /* Set the configuration back to the page */ + rslt = bmi2_set_regs(BMI2_FEATURES_REG_ADDR, feat_config, BMI2_FEAT_SIZE_IN_BYTES, dev); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets any-motion configurations like axes select, + * duration, threshold and output-configuration. + */ +static int8_t get_any_motion_config(struct bmi2_any_motion_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb; + + /* Variable to define MSB */ + uint16_t msb; + + /* Variable to define a word */ + uint16_t lsb_msb; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for any-motion */ + struct bmi2_feature_config any_mot_config = { 0, 0, 0 }; + + /* Search for any-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&any_mot_config, BMI2_ANY_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where any-motion feature resides */ + rslt = bmi2_get_feat_config(any_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for feature enable for any-motion */ + idx = any_mot_config.start_addr; + + /* Get word to calculate duration, x, y and z select */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get duration */ + config->duration = lsb_msb & BMI2_ANY_NO_MOT_DUR_MASK; + + /* Get x-select */ + config->select_x = (lsb_msb & BMI2_ANY_NO_MOT_X_SEL_MASK) >> BMI2_ANY_NO_MOT_X_SEL_POS; + + /* Get y-select */ + config->select_y = (lsb_msb & BMI2_ANY_NO_MOT_Y_SEL_MASK) >> BMI2_ANY_NO_MOT_Y_SEL_POS; + + /* Get z-select */ + config->select_z = (lsb_msb & BMI2_ANY_NO_MOT_Z_SEL_MASK) >> BMI2_ANY_NO_MOT_Z_SEL_POS; + + /* Get word to calculate threshold, output configuration from the same word */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get threshold */ + config->threshold = lsb_msb & BMI2_ANY_NO_MOT_THRES_MASK; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets no-motion configurations like axes select, + * duration, threshold and output-configuration. + */ +static int8_t get_no_motion_config(struct bmi2_no_motion_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for no-motion */ + struct bmi2_feature_config no_mot_config = { 0, 0, 0 }; + + /* Search for no-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&no_mot_config, BMI2_NO_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where no-motion feature resides */ + rslt = bmi2_get_feat_config(no_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for feature enable for no-motion */ + idx = no_mot_config.start_addr; + + /* Get word to calculate duration, x, y and z select */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get duration */ + config->duration = lsb_msb & BMI2_ANY_NO_MOT_DUR_MASK; + + /* Get x-select */ + config->select_x = (lsb_msb & BMI2_ANY_NO_MOT_X_SEL_MASK) >> BMI2_ANY_NO_MOT_X_SEL_POS; + + /* Get y-select */ + config->select_y = (lsb_msb & BMI2_ANY_NO_MOT_Y_SEL_MASK) >> BMI2_ANY_NO_MOT_Y_SEL_POS; + + /* Get z-select */ + config->select_z = (lsb_msb & BMI2_ANY_NO_MOT_Z_SEL_MASK) >> BMI2_ANY_NO_MOT_Z_SEL_POS; + + /* Get word to calculate threshold, output configuration from the same word */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get threshold */ + config->threshold = lsb_msb & BMI2_ANY_NO_MOT_THRES_MASK; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets sig-motion configurations like block-size, + * output-configuration and other parameters. + */ +static int8_t get_sig_motion_config(struct bmi2_sig_motion_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration sig-motion */ + struct bmi2_feature_config sig_mot_config = { 0, 0, 0 }; + + /* Search for sig-motion feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&sig_mot_config, BMI2_SIG_MOTION, dev); + if (feat_found) + { + /* Get the configuration from the page where sig-motion feature resides */ + rslt = bmi2_get_feat_config(sig_mot_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for feature enable for sig-motion */ + idx = sig_mot_config.start_addr; + + /* Get word to calculate parameter 1 */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get parameter 1 */ + config->block_size = lsb_msb & BMI2_SIG_MOT_PARAM_1_MASK; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets step counter/detector/activity configurations. + */ +static int8_t get_step_config(struct bmi2_step_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for step counter */ + struct bmi2_feature_config step_count_config = { 0, 0, 0 }; + + /* Search for step counter 4 feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&step_count_config, BMI2_STEP_COUNTER, dev); + if (feat_found) + { + /* Get the configuration from the page where step counter 4 parameter resides */ + rslt = bmi2_get_feat_config(step_count_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for feature enable for step counter/detector/activity */ + idx = step_count_config.start_addr; + + /* Get word to calculate water-mark level and reset counter */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get water-mark level */ + config->watermark_level = lsb_msb & BMI2_STEP_COUNT_WM_LEVEL_MASK; + + /* Get reset counter */ + config->reset_counter = (lsb_msb & BMI2_STEP_COUNT_RST_CNT_MASK) >> BMI2_STEP_COUNT_RST_CNT_POS; + + /* Get word to calculate output configuration of step detector and activity */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + config->step_buffer_size = (lsb_msb & BMI2_STEP_BUFFER_SIZE_MASK) >> BMI2_STEP_BUFFER_SIZE_POS; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets tap configurations like sensitivity, + * single, double and triple tap enable and output-configuration. + */ +static int8_t get_tap_detector_config(struct bmi2_tap_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + rslt = dev->get_tap_config(config, dev); + + return rslt; +} + +/*! + * @brief This internal API gets orientation configurations like upside/down + * detection, symmetrical modes, blocking mode, theta, hysteresis and output + * configuration. + */ +static int8_t get_orient_config(struct bmi2_orient_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for orient */ + struct bmi2_feature_config orient_config = { 0, 0, 0 }; + + /* Search for orient feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&orient_config, BMI2_ORIENTATION, dev); + if (feat_found) + { + /* Get the configuration from the page where orient feature resides */ + rslt = bmi2_get_feat_config(orient_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for orient select */ + idx = orient_config.start_addr; + + /* Get word to calculate upside/down detection, + * symmetrical modes, blocking mode and theta + */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get upside/down detection */ + config->ud_en = (lsb_msb & BMI2_ORIENT_UP_DOWN_MASK) >> BMI2_ORIENT_UP_DOWN_POS; + + /* Get symmetrical modes */ + config->mode = (lsb_msb & BMI2_ORIENT_SYMM_MODE_MASK) >> BMI2_ORIENT_SYMM_MODE_POS; + + /* Get blocking mode */ + config->blocking = (lsb_msb & BMI2_ORIENT_BLOCK_MODE_MASK) >> BMI2_ORIENT_BLOCK_MODE_POS; + + /* Get theta */ + config->theta = (lsb_msb & BMI2_ORIENT_THETA_MASK) >> BMI2_ORIENT_THETA_POS; + + /* Get the next word to calculate hysteresis and output configuration */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get hysteresis */ + config->hysteresis = lsb_msb & BMI2_ORIENT_HYST_MASK; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets high-g configurations like threshold, + * hysteresis, duration, and output configuration. + */ +static int8_t get_high_g_config(struct bmi2_high_g_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for high-g */ + struct bmi2_feature_config high_g_config = { 0, 0, 0 }; + + /* Search for high-g feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&high_g_config, BMI2_HIGH_G, dev); + if (feat_found) + { + /* Get the configuration from the page where high-g feature resides */ + rslt = bmi2_get_feat_config(high_g_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for high-g select */ + idx = high_g_config.start_addr; + + /* Get word to calculate threshold */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get threshold */ + config->threshold = lsb_msb & BMI2_HIGH_G_THRES_MASK; + + /* Get word to calculate hysteresis */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get hysteresis */ + config->hysteresis = lsb_msb & BMI2_HIGH_G_HYST_MASK; + + /* Get x_select */ + config->select_x = (lsb_msb & BMI2_HIGH_G_X_SEL_MASK) >> BMI2_HIGH_G_X_SEL_POS; + + /* Get y_select */ + config->select_y = (lsb_msb & BMI2_HIGH_G_Y_SEL_MASK) >> BMI2_HIGH_G_Y_SEL_POS; + + /* Get z_select */ + config->select_z = (lsb_msb & BMI2_HIGH_G_Z_SEL_MASK) >> BMI2_HIGH_G_Z_SEL_POS; + + /* Get word to calculate duration and output configuration */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get duration */ + config->duration = lsb_msb & BMI2_HIGH_G_DUR_MASK; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets low-g configurations like threshold, + * hysteresis, duration, and output configuration. + */ +static int8_t get_low_g_config(struct bmi2_low_g_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for low-g */ + struct bmi2_feature_config low_g_config = { 0, 0, 0 }; + + /* Search for low-g feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&low_g_config, BMI2_LOW_G, dev); + if (feat_found) + { + /* Get the configuration from the page where low-g feature resides */ + rslt = bmi2_get_feat_config(low_g_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for low-g select */ + idx = low_g_config.start_addr; + + /* Get word to calculate threshold */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get threshold */ + config->threshold = lsb_msb & BMI2_LOW_G_THRES_MASK; + + /* Get word to calculate hysteresis */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get hysteresis */ + config->hysteresis = lsb_msb & BMI2_LOW_G_HYST_MASK; + + /* Get word to calculate duration and output configuration */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get duration */ + config->duration = lsb_msb & BMI2_LOW_G_DUR_MASK; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets flat configurations like theta, blocking, + * hold-time, hysteresis, and output configuration. + */ +static int8_t get_flat_config(struct bmi2_flat_config *config, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to define LSB */ + uint16_t lsb = 0; + + /* Variable to define MSB */ + uint16_t msb = 0; + + /* Variable to define a word */ + uint16_t lsb_msb = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature configuration for flat */ + struct bmi2_feature_config flat_config = { 0, 0, 0 }; + + /* Search for flat feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&flat_config, BMI2_FLAT, dev); + if (feat_found) + { + /* Get the configuration from the page where flat feature resides */ + rslt = bmi2_get_feat_config(flat_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for flat select */ + idx = flat_config.start_addr; + + /* Get word to calculate theta, blocking mode and output configuration */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get theta */ + config->theta = (lsb_msb & BMI2_FLAT_THETA_MASK) >> BMI2_FLAT_THETA_POS; + + /* Get blocking mode */ + config->blocking = (lsb_msb & BMI2_FLAT_BLOCK_MASK) >> BMI2_FLAT_BLOCK_POS; + + /* Get word to calculate hysteresis and hold-time */ + lsb = (uint16_t) feat_config[idx++]; + msb = ((uint16_t) feat_config[idx++] << 8); + lsb_msb = lsb | msb; + + /* Get hysteresis */ + config->hysteresis = lsb_msb & BMI2_FLAT_HYST_MASK; + + /* Get hold-time */ + config->hold_time = (lsb_msb & BMI2_FLAT_HOLD_TIME_MASK) >> BMI2_FLAT_HOLD_TIME_POS; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets the output values of high-g. + */ +static int8_t get_high_g_output(uint8_t *high_g_out, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variables to define index */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature output for high-g */ + struct bmi2_feature_config high_g_out_config = { 0, 0, 0 }; + + /* Search for high-g output feature and extract its configuration details */ + feat_found = extract_output_feat_config(&high_g_out_config, BMI2_HIGH_G, dev); + if (feat_found) + { + /* Get the feature output configuration for high-g */ + rslt = bmi2_get_feat_config(high_g_out_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for high-g output */ + idx = high_g_out_config.start_addr; + + /* Get the high-g output byte */ + *high_g_out = feat_config[idx]; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets the output values of step counter. + */ +static int8_t get_step_counter_output(uint32_t *step_count, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variables to define index */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature output for step counter */ + struct bmi2_feature_config step_cnt_out_config = { 0, 0, 0 }; + + /* Search for step counter output feature and extract its configuration details */ + feat_found = extract_output_feat_config(&step_cnt_out_config, BMI2_STEP_COUNTER, dev); + if (feat_found) + { + /* Get the feature output configuration for step-counter */ + rslt = bmi2_get_feat_config(step_cnt_out_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for step counter output */ + idx = step_cnt_out_config.start_addr; + + /* Get the step counter output in 4 bytes */ + *step_count = (uint32_t) feat_config[idx++]; + *step_count |= ((uint32_t) feat_config[idx++] << 8); + *step_count |= ((uint32_t) feat_config[idx++] << 16); + *step_count |= ((uint32_t) feat_config[idx++] << 24); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets the error status related to NVM. + */ +static int8_t get_nvm_error_status(struct bmi2_nvm_err_status *nvm_err_stat, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variables to define index */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature output for NVM error status */ + struct bmi2_feature_config nvm_err_cfg = { 0, 0, 0 }; + + /* Search for NVM error status feature and extract its configuration details */ + feat_found = extract_output_feat_config(&nvm_err_cfg, BMI2_NVM_STATUS, dev); + if (feat_found) + { + /* Get the feature output configuration for NVM error status */ + rslt = bmi2_get_feat_config(nvm_err_cfg.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for NVM error status */ + idx = nvm_err_cfg.start_addr; + + /* Increment index to get the error status */ + idx++; + + /* Error when NVM load action fails */ + nvm_err_stat->load_error = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_NVM_LOAD_ERR_STATUS); + + /* Error when NVM program action fails */ + nvm_err_stat->prog_error = BMI2_GET_BITS(feat_config[idx], BMI2_NVM_PROG_ERR_STATUS); + + /* Error when NVM erase action fails */ + nvm_err_stat->erase_error = BMI2_GET_BITS(feat_config[idx], BMI2_NVM_ERASE_ERR_STATUS); + + /* Error when NVM program limit is exceeded */ + nvm_err_stat->exceed_error = BMI2_GET_BITS(feat_config[idx], BMI2_NVM_END_EXCEED_STATUS); + + /* Error when NVM privilege mode is not acquired */ + nvm_err_stat->privil_error = BMI2_GET_BITS(feat_config[idx], BMI2_NVM_PRIV_ERR_STATUS); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to get enable status of gyroscope user gain + * update. + */ +static int8_t get_user_gain_upd_status(uint8_t *status, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variable to define the array offset */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Variable to check APS status */ + uint8_t aps_stat = 0; + + /* Initialize feature configuration for gyroscope user gain */ + struct bmi2_feature_config gyr_user_gain_cfg = { 0, 0, 0 }; + + /* Search for user gain feature and extract its configuration details */ + feat_found = bmi2_extract_input_feat_config(&gyr_user_gain_cfg, BMI2_GYRO_GAIN_UPDATE, dev); + if (feat_found) + { + /* Disable advance power save */ + aps_stat = dev->aps_status; + if (aps_stat == BMI2_ENABLE) + { + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, dev); + } + + if (rslt == BMI2_OK) + { + /* Get the configuration from the page where user gain feature resides */ + rslt = bmi2_get_feat_config(gyr_user_gain_cfg.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset for enable/disable of user gain */ + idx = gyr_user_gain_cfg.start_addr + BMI2_GYR_USER_GAIN_FEAT_EN_OFFSET; + + /* Set the feature enable status */ + *status = BMI2_GET_BITS(feat_config[idx], BMI2_GYR_USER_GAIN_FEAT_EN); + } + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + /* Enable Advance power save if disabled while configuring and not when already disabled */ + if ((rslt == BMI2_OK) && (aps_stat == BMI2_ENABLE)) + { + rslt = bmi2_set_adv_power_save(BMI2_ENABLE, dev); + } + + return rslt; +} + +/*! + * @brief This internal API gets the output values of step activity. + */ +static int8_t get_step_activity_output(uint8_t *step_act, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variables to define index */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature output for step activity */ + struct bmi2_feature_config step_act_out_config = { 0, 0, 0 }; + + /* Search for step activity output feature and extract its configuration details */ + feat_found = extract_output_feat_config(&step_act_out_config, BMI2_STEP_ACTIVITY, dev); + if (feat_found) + { + /* Get the feature output configuration for step-activity */ + rslt = bmi2_get_feat_config(step_act_out_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for step activity output */ + idx = step_act_out_config.start_addr; + + /* Get the step activity output */ + *step_act = feat_config[idx]; + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API gets the output values of orientation: portrait- + * landscape and face up-down. + */ +static int8_t get_orient_output(struct bmi2_orientation_output *orient_out, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variables to define index */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature output for orientation */ + struct bmi2_feature_config orient_out_config = { 0, 0, 0 }; + + /* Search for orientation output feature and extract its configuration details */ + feat_found = extract_output_feat_config(&orient_out_config, BMI2_ORIENTATION, dev); + if (feat_found) + { + /* Get the feature output configuration for orientation */ + rslt = bmi2_get_feat_config(orient_out_config.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for orientation output */ + idx = orient_out_config.start_addr; + + /* Get the output value of the orientation detection feature */ + orient_out->portrait_landscape = BMI2_GET_BIT_POS0(feat_config[idx], BMI2_ORIENT_DETECT); + + /* Get the output value of the orientation face up-down feature */ + orient_out->faceup_down = BMI2_GET_BITS(feat_config[idx], BMI2_ORIENT_FACE_UP_DWN); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API enables/disables compensation of the gain defined + * in the GAIN register. + */ +static int8_t enable_gyro_gain(uint8_t enable, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to define register data */ + uint8_t reg_data = 0; + + rslt = bmi2_get_regs(BMI2_GYR_OFF_COMP_6_ADDR, ®_data, 1, dev); + if (rslt == BMI2_OK) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_GAIN_EN, enable); + rslt = bmi2_set_regs(BMI2_GYR_OFF_COMP_6_ADDR, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to extract the output feature configuration + * details from the look-up table. + */ +static uint8_t extract_output_feat_config(struct bmi2_feature_config *feat_output, + uint8_t type, + const struct bmi2_dev *dev) +{ + /* Variable to define loop */ + uint8_t loop = 0; + + /* Variable to set flag */ + uint8_t feat_found = BMI2_FALSE; + + /* Search for the output feature from the output configuration array */ + while (loop < dev->out_sens) + { + if (dev->feat_output[loop].type == type) + { + *feat_output = dev->feat_output[loop]; + feat_found = BMI2_TRUE; + break; + } + + loop++; + } + + /* Return flag */ + return feat_found; +} + +/*! + * @brief This internal API gets the error status related to virtual frames. + */ +static int8_t get_vfrm_error_status(struct bmi2_vfrm_err_status *vfrm_err_stat, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Array to define the feature configuration */ + uint8_t feat_config[BMI2_FEAT_SIZE_IN_BYTES] = { 0 }; + + /* Variables to define index */ + uint8_t idx = 0; + + /* Variable to set flag */ + uint8_t feat_found; + + /* Initialize feature output for VFRM error status */ + struct bmi2_feature_config vfrm_err_cfg = { 0, 0, 0 }; + + /* Search for VFRM error status feature and extract its configuration details */ + feat_found = extract_output_feat_config(&vfrm_err_cfg, BMI2_VFRM_STATUS, dev); + if (feat_found) + { + /* Get the feature output configuration for VFRM error status */ + rslt = bmi2_get_feat_config(vfrm_err_cfg.page, feat_config, dev); + if (rslt == BMI2_OK) + { + /* Define the offset in bytes for VFRM error status */ + idx = vfrm_err_cfg.start_addr; + + /* Increment index to get the error status */ + idx++; + + /* Internal error while acquiring lock for FIFO */ + vfrm_err_stat->lock_error = BMI2_GET_BITS(feat_config[idx], BMI2_VFRM_LOCK_ERR_STATUS); + + /* Internal error while writing byte into FIFO */ + vfrm_err_stat->write_error = BMI2_GET_BITS(feat_config[idx], BMI2_VFRM_WRITE_ERR_STATUS); + + /* Internal error while writing into FIFO */ + vfrm_err_stat->fatal_error = BMI2_GET_BITS(feat_config[idx], BMI2_VFRM_FATAL_ERR_STATUS); + } + } + else + { + rslt = BMI2_E_INVALID_SENSOR; + } + + return rslt; +} + +/*! + * @brief This internal API sets feature configuration to the sensor. + */ +static int8_t set_feat_config(struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + switch (sens_cfg[loop].type) + { + /* Set any-motion configuration */ + case BMI2_ANY_MOTION: + rslt = set_any_motion_config(&sens_cfg[loop].cfg.any_motion, dev); + break; + + /* Set no-motion configuration */ + case BMI2_NO_MOTION: + rslt = set_no_motion_config(&sens_cfg[loop].cfg.no_motion, dev); + break; + + /* Set sig-motion configuration */ + case BMI2_SIG_MOTION: + rslt = set_sig_motion_config(&sens_cfg[loop].cfg.sig_motion, dev); + break; + + /* Set step counter/detector/activity configuration */ + case BMI2_STEP_DETECTOR: + case BMI2_STEP_COUNTER: + case BMI2_STEP_ACTIVITY: + rslt = set_step_config(&sens_cfg[loop].cfg.step_counter, dev); + break; + + /* Set tap configuration */ + case BMI2_TAP: + rslt = set_tap_detector_config(&sens_cfg[loop].cfg.tap_conf, dev); + break; + + /* Set orientation configuration */ + case BMI2_ORIENTATION: + rslt = set_orient_config(&sens_cfg[loop].cfg.orientation, dev); + break; + + /* Set high-g configuration */ + case BMI2_HIGH_G: + rslt = set_high_g_config(&sens_cfg[loop].cfg.high_g, dev); + break; + + /* Set low-g configuration */ + case BMI2_LOW_G: + rslt = set_low_g_config(&sens_cfg[loop].cfg.low_g, dev); + break; + + /* Set flat configuration */ + case BMI2_FLAT: + rslt = set_flat_config(&sens_cfg[loop].cfg.flat, dev); + break; + + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief This internal API gets feature configuration from the sensor. + */ +static int8_t get_feat_config(struct bmi2_sens_config *sens_cfg, uint8_t loop, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + switch (sens_cfg[loop].type) + { + /* Get sig-motion configuration */ + case BMI2_SIG_MOTION: + rslt = get_sig_motion_config(&sens_cfg[loop].cfg.sig_motion, dev); + break; + + /* Get any motion configuration */ + case BMI2_ANY_MOTION: + rslt = get_any_motion_config(&sens_cfg[loop].cfg.any_motion, dev); + break; + + /* Get no motion configuration */ + case BMI2_NO_MOTION: + rslt = get_no_motion_config(&sens_cfg[loop].cfg.no_motion, dev); + break; + + /* Get step counter/detector/activity configuration */ + case BMI2_STEP_DETECTOR: + case BMI2_STEP_COUNTER: + case BMI2_STEP_ACTIVITY: + rslt = get_step_config(&sens_cfg[loop].cfg.step_counter, dev); + break; + + /* Get tap configuration */ + case BMI2_TAP: + rslt = get_tap_detector_config(&sens_cfg[loop].cfg.tap_conf, dev); + break; + + /* Get orientation configuration */ + case BMI2_ORIENTATION: + rslt = get_orient_config(&sens_cfg[loop].cfg.orientation, dev); + break; + + /* Get high-g configuration */ + case BMI2_HIGH_G: + rslt = get_high_g_config(&sens_cfg[loop].cfg.high_g, dev); + break; + + /* Get low-g configuration */ + case BMI2_LOW_G: + rslt = get_low_g_config(&sens_cfg[loop].cfg.low_g, dev); + break; + + /* Get flat configuration */ + case BMI2_FLAT: + rslt = get_flat_config(&sens_cfg[loop].cfg.flat, dev); + break; + + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief This internal API is used to select the sensor feature. + */ +static int8_t sens_select(const uint8_t *sens_list, uint8_t count, uint64_t *sensor_sel) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + switch (sens_list[count]) + { + case BMI2_SIG_MOTION: + *sensor_sel |= BMI2_SIG_MOTION_SEL; + break; + case BMI2_ANY_MOTION: + *sensor_sel |= BMI2_ANY_MOT_SEL; + break; + case BMI2_NO_MOTION: + *sensor_sel |= BMI2_NO_MOT_SEL; + break; + case BMI2_STEP_DETECTOR: + *sensor_sel |= BMI2_STEP_DETECT_SEL; + break; + case BMI2_STEP_COUNTER: + *sensor_sel |= BMI2_STEP_COUNT_SEL; + break; + case BMI2_STEP_ACTIVITY: + *sensor_sel |= BMI2_STEP_ACT_SEL; + break; + case BMI2_GYRO_GAIN_UPDATE: + *sensor_sel |= BMI2_GYRO_GAIN_UPDATE_SEL; + break; + case BMI2_SINGLE_TAP: + *sensor_sel |= BMI2_SINGLE_TAP_SEL; + break; + case BMI2_DOUBLE_TAP: + *sensor_sel |= BMI2_DOUBLE_TAP_SEL; + break; + case BMI2_TRIPLE_TAP: + *sensor_sel |= BMI2_TRIPLE_TAP_SEL; + break; + case BMI2_ORIENTATION: + *sensor_sel |= BMI2_ORIENT_SEL; + break; + case BMI2_HIGH_G: + *sensor_sel |= BMI2_HIGH_G_SEL; + break; + case BMI2_LOW_G: + *sensor_sel |= BMI2_LOW_G_SEL; + break; + case BMI2_FLAT: + *sensor_sel |= BMI2_FLAT_SEL; + break; + case BMI2_GYRO_SELF_OFF: + *sensor_sel |= BMI2_GYRO_SELF_OFF_SEL; + break; + default: + rslt = BMI2_E_INVALID_SENSOR; + break; + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable main sensors like accel, gyro, aux and temperature. + */ +static int8_t enable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to store register values */ + uint8_t reg_data; + + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + + if (rslt == BMI2_OK) + { + /* Enable accelerometer */ + if (sensor_sel & BMI2_ACCEL_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_ACC_EN, BMI2_ENABLE); + } + + /* Enable gyroscope */ + if (sensor_sel & BMI2_GYRO_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_GYR_EN, BMI2_ENABLE); + } + + /* Enable auxiliary sensor */ + if (sensor_sel & BMI2_AUX_SENS_SEL) + { + reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_AUX_EN, BMI2_ENABLE); + } + + /* Enable temperature sensor */ + if (sensor_sel & BMI2_TEMP_SENS_SEL) + { + reg_data = BMI2_SET_BITS(reg_data, BMI2_TEMP_EN, BMI2_ENABLE); + } + + /* Enable the sensors that are set in the power control register */ + if (sensor_sel & BMI2_MAIN_SENSORS) + { + rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable sensor features. + */ +static int8_t enable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Enable sig-motion feature */ + if (sensor_sel & BMI2_SIG_MOTION_SEL) + { + rslt = set_sig_motion(BMI2_ENABLE, dev); + } + + /* Enable any motion feature */ + if (sensor_sel & BMI2_ANY_MOT_SEL) + { + rslt = set_any_motion(BMI2_ENABLE, dev); + } + + /* Enable no motion feature */ + if (sensor_sel & BMI2_NO_MOT_SEL) + { + rslt = set_no_motion(BMI2_ENABLE, dev); + } + + /* Enable step detector feature */ + if (sensor_sel & BMI2_STEP_DETECT_SEL) + { + rslt = set_step_detector(BMI2_ENABLE, dev); + } + + /* Enable step counter feature */ + if (sensor_sel & BMI2_STEP_COUNT_SEL) + { + rslt = set_step_counter(BMI2_ENABLE, dev); + } + + /* Enable step activity feature */ + if (sensor_sel & BMI2_STEP_ACT_SEL) + { + rslt = set_step_activity(BMI2_ENABLE, dev); + } + + /* Enable gyroscope user gain */ + if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) + { + rslt = set_gyro_user_gain(BMI2_ENABLE, dev); + } + + /* Enable single tap feature */ + if (sensor_sel & BMI2_SINGLE_TAP_SEL) + { + rslt = set_single_tap(BMI2_ENABLE, dev); + } + + /* Enable double tap feature */ + if (sensor_sel & BMI2_DOUBLE_TAP_SEL) + { + rslt = set_double_tap(BMI2_ENABLE, dev); + } + + /* Enable triple tap feature */ + if (sensor_sel & BMI2_TRIPLE_TAP_SEL) + { + rslt = set_triple_tap(BMI2_ENABLE, dev); + } + + /* Enable orientation feature */ + if (sensor_sel & BMI2_ORIENT_SEL) + { + rslt = set_orientation(BMI2_ENABLE, dev); + } + + /* Enable high-g feature */ + if (sensor_sel & BMI2_HIGH_G_SEL) + { + rslt = set_high_g(BMI2_ENABLE, dev); + } + + /* Enable low-g feature */ + if (sensor_sel & BMI2_LOW_G_SEL) + { + rslt = set_low_g(BMI2_ENABLE, dev); + } + + /* Enable flat feature */ + if (sensor_sel & BMI2_FLAT_SEL) + { + rslt = set_flat(BMI2_ENABLE, dev); + } + + /* Enable gyroscope self-offset correction feature */ + if (sensor_sel & BMI2_GYRO_SELF_OFF_SEL) + { + rslt = set_gyro_self_offset_corr(BMI2_ENABLE, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to disable main sensors like accel, gyro, aux and temperature. + */ +static int8_t disable_main_sensors(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt; + + /* Variable to store register values */ + uint8_t reg_data; + + rslt = bmi2_get_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + + if (rslt == BMI2_OK) + { + /* Disable accelerometer */ + if (sensor_sel & BMI2_ACCEL_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_ACC_EN); + } + + /* Disable gyroscope */ + if (sensor_sel & BMI2_GYRO_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_GYR_EN); + } + + /* Disable auxiliary sensor */ + if (sensor_sel & BMI2_AUX_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_AUX_EN); + } + + /* Disable temperature sensor */ + if (sensor_sel & BMI2_TEMP_SENS_SEL) + { + reg_data = BMI2_SET_BIT_VAL0(reg_data, BMI2_TEMP_EN); + } + + /* Disable the sensors that are set in the power control register */ + if (sensor_sel & BMI2_MAIN_SENSORS) + { + rslt = bmi2_set_regs(BMI2_PWR_CTRL_ADDR, ®_data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to disable sensor features. + */ +static int8_t disable_sensor_features(uint64_t sensor_sel, struct bmi2_dev *dev) +{ + /* Variable to define error */ + int8_t rslt = BMI2_OK; + + /* Disable sig-motion feature */ + if (sensor_sel & BMI2_SIG_MOTION_SEL) + { + rslt = set_sig_motion(BMI2_DISABLE, dev); + } + + /* Disable any-motion feature */ + if (sensor_sel & BMI2_ANY_MOT_SEL) + { + rslt = set_any_motion(BMI2_DISABLE, dev); + } + + /* Disable no-motion feature */ + if (sensor_sel & BMI2_NO_MOT_SEL) + { + rslt = set_no_motion(BMI2_DISABLE, dev); + } + + /* Disable step detector feature */ + if (sensor_sel & BMI2_STEP_DETECT_SEL) + { + rslt = set_step_detector(BMI2_DISABLE, dev); + } + + /* Disable step counter feature */ + if (sensor_sel & BMI2_STEP_COUNT_SEL) + { + rslt = set_step_counter(BMI2_DISABLE, dev); + } + + /* Disable step activity feature */ + if (sensor_sel & BMI2_STEP_ACT_SEL) + { + rslt = set_step_activity(BMI2_DISABLE, dev); + } + + /* Disable gyroscope user gain */ + if (sensor_sel & BMI2_GYRO_GAIN_UPDATE_SEL) + { + rslt = set_gyro_user_gain(BMI2_DISABLE, dev); + } + + /* Disable single tap feature */ + if (sensor_sel & BMI2_SINGLE_TAP_SEL) + { + rslt = set_single_tap(BMI2_DISABLE, dev); + } + + /* Disable double tap feature */ + if (sensor_sel & BMI2_DOUBLE_TAP_SEL) + { + rslt = set_double_tap(BMI2_DISABLE, dev); + } + + /* Disable triple tap feature */ + if (sensor_sel & BMI2_TRIPLE_TAP_SEL) + { + rslt = set_triple_tap(BMI2_DISABLE, dev); + } + + /* Disable orientation feature */ + if (sensor_sel & BMI2_ORIENT_SEL) + { + rslt = set_orientation(BMI2_DISABLE, dev); + } + + /* Disable high-g feature */ + if (sensor_sel & BMI2_HIGH_G_SEL) + { + rslt = set_high_g(BMI2_DISABLE, dev); + } + + /* Disable low-g feature */ + if (sensor_sel & BMI2_LOW_G_SEL) + { + rslt = set_low_g(BMI2_DISABLE, dev); + } + + /* Disable flat feature */ + if (sensor_sel & BMI2_FLAT_SEL) + { + rslt = set_flat(BMI2_DISABLE, dev); + } + + /* Disable gyroscope self-offset correction feature */ + if (sensor_sel & BMI2_GYRO_SELF_OFF_SEL) + { + rslt = set_gyro_self_offset_corr(BMI2_DISABLE, dev); + } + + return rslt; +} diff --git a/bmi270_legacy.h b/bmi270_legacy.h new file mode 100644 index 0000000..5b9b59b --- /dev/null +++ b/bmi270_legacy.h @@ -0,0 +1,460 @@ +/** +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. +* +* BSD-3-Clause +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +* @file bmi270_legacy.h +* @date 2021-09-30 +* @version v2.71.8 +* +*/ + +/* BMI270_legacy offers same low-power features as in BMI160 */ + +/** + * \ingroup bmi2xy + * \defgroup bmi270_legacy BMI270_LEGACY + * @brief Sensor driver for BMI270_LEGACY sensor + */ + +#ifndef BMI270_LEGACY_H_ +#define BMI270_LEGACY_H_ + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +/*! Header files + ****************************************************************************/ +#include "bmi2.h" + +/***************************************************************************/ + +/*! Macro definitions + ****************************************************************************/ + +/*! @name BMI270_LEGACY chip identifier */ +#define BMI270_LEGACY_CHIP_ID UINT8_C(0x24) + +/*! @name BMI270_LEGACY feature input start addresses */ +#define BMI270_LEGACY_CONFIG_ID_STRT_ADDR UINT8_C(0x00) +#define BMI270_LEGACY_MAX_BURST_LEN_STRT_ADDR UINT8_C(0x02) +#define BMI270_LEGACY_CRT_GYRO_SELF_TEST_STRT_ADDR UINT8_C(0x03) +#define BMI270_LEGACY_ABORT_STRT_ADDR UINT8_C(0x03) +#define BMI270_LEGACY_AXIS_MAP_STRT_ADDR UINT8_C(0x04) +#define BMI270_LEGACY_GYRO_SELF_OFF_STRT_ADDR UINT8_C(0x05) +#define BMI270_LEGACY_NVM_PROG_PREP_STRT_ADDR UINT8_C(0x05) +#define BMI270_LEGACY_ANY_MOT_STRT_ADDR UINT8_C(0x06) +#define BMI270_LEGACY_NO_MOT_STRT_ADDR UINT8_C(0x0A) +#define BMI270_LEGACY_ORIENT_STRT_ADDR UINT8_C(0x00) +#define BMI270_LEGACY_HIGH_G_STRT_ADDR UINT8_C(0x04) +#define BMI270_LEGACY_LOW_G_STRT_ADDR UINT8_C(0x0A) +#define BMI270_LEGACY_FLAT_STRT_ADDR UINT8_C(0x00) +#define BMI270_LEGACY_SIG_MOT_STRT_ADDR UINT8_C(0x04) +#define BMI270_LEGACY_STEP_COUNT_STRT_ADDR UINT8_C(0x00) +#define BMI270_LEGACY_GYRO_USERGAIN_UPDATE_STRT_ADDR UINT8_C(0x04) +#define BMI270_LEGACY_TAP_DETECT_1_STRT_ADDR UINT8_C(0x00) +#define BMI270_LEGACY_TAP_DETECT_2_STRT_ADDR UINT8_C(0x00) + +/*! @name BMI270_LEGACY feature output start addresses */ +#define BMI270_LEGACY_STEP_CNT_OUT_STRT_ADDR UINT8_C(0x00) +#define BMI270_LEGACY_STEP_ACT_OUT_STRT_ADDR UINT8_C(0x04) +#define BMI270_LEGACY_ORIENT_HIGH_G_OUT_STRT_ADDR UINT8_C(0x06) +#define BMI270_LEGACY_GYR_USER_GAIN_OUT_STRT_ADDR UINT8_C(0x08) +#define BMI270_LEGACY_GYRO_CROSS_SENSE_STRT_ADDR UINT8_C(0x0C) +#define BMI270_LEGACY_NVM_VFRM_OUT_STRT_ADDR UINT8_C(0x0E) + +/*! @name Defines maximum number of pages */ +#define BMI270_LEGACY_MAX_PAGE_NUM UINT8_C(8) + +/*! @name Defines maximum number of feature input configurations */ +#define BMI270_LEGACY_MAX_FEAT_IN UINT8_C(23) + +/*! @name Defines maximum number of feature outputs */ +#define BMI270_LEGACY_MAX_FEAT_OUT UINT8_C(8) + +/*! @name Mask definitions for feature interrupt status bits */ +#define BMI270_LEGACY_SIG_MOT_STATUS_MASK UINT8_C(0x01) +#define BMI270_LEGACY_STEP_CNT_STATUS_MASK UINT8_C(0x02) +#define BMI270_LEGACY_HIGH_G_STATUS_MASK UINT8_C(0x04) +#define BMI270_LEGACY_LOW_G_STATUS_MASK UINT8_C(0x04) +#define BMI270_LEGACY_TAP_STATUS_MASK UINT8_C(0x08) +#define BMI270_LEGACY_FLAT_STATUS_MASK UINT8_C(0x10) +#define BMI270_LEGACY_NO_MOT_STATUS_MASK UINT8_C(0x20) +#define BMI270_LEGACY_ANY_MOT_STATUS_MASK UINT8_C(0x40) +#define BMI270_LEGACY_ORIENT_STATUS_MASK UINT8_C(0x80) +#define BMI270_LEGACY_SINGLE_TAP_MASK UINT8_C(0x20) +#define BMI270_LEGACY_DOUBLE_TAP_MASK UINT8_C(0x40) +#define BMI270_LEGACY_TRIPLE_TAP_MASK UINT8_C(0x80) + +/*! @name Status register for tap */ +#define BMI270_LEGACY_TAP_STATUS_REG UINT8_C(0x20) + +/*! @name Macros for high-g interrupt axis/sign */ +#define BMI270_LEGACY_HIGH_G_DETECT_X UINT8_C(0x08) +#define BMI270_LEGACY_HIGH_G_DETECT_Y UINT8_C(0x10) +#define BMI270_LEGACY_HIGH_G_DETECT_Z UINT8_C(0x20) +#define BMI270_LEGACY_HIGH_G_DETECT_SIGN UINT8_C(0x40) + +/*! @name Mask definitions for feature interrupt mapping bits */ +#define BMI270_LEGACY_INT_SIG_MOT_MASK UINT8_C(0x01) +#define BMI270_LEGACY_INT_STEP_COUNTER_MASK UINT8_C(0x02) +#define BMI270_LEGACY_INT_STEP_DETECTOR_MASK UINT8_C(0x02) +#define BMI270_LEGACY_INT_STEP_ACTIVITY_MASK UINT8_C(0x02) +#define BMI270_LEGACY_INT_HIGH_G_MASK UINT8_C(0x04) +#define BMI270_LEGACY_INT_LOW_G_MASK UINT8_C(0x04) +#define BMI270_LEGACY_INT_TAP_MASK UINT8_C(0x08) +#define BMI270_LEGACY_INT_FLAT_MASK UINT8_C(0x10) +#define BMI270_LEGACY_INT_NO_MOT_MASK UINT8_C(0x20) +#define BMI270_LEGACY_INT_ANY_MOT_MASK UINT8_C(0x40) +#define BMI270_LEGACY_INT_ORIENT_MASK UINT8_C(0x80) +#define BMI270_LEGACY_INT_SINGLE_TAP_MASK UINT8_C(0x20) +#define BMI270_LEGACY_INT_DOUBLE_TAP_MASK UINT8_C(0x40) +#define BMI270_LEGACY_INT_TRIPLE_TAP_MASK UINT8_C(0x80) + +/*! @name Defines maximum number of feature interrupts */ +#define BMI270_LEGACY_MAX_INT_MAP UINT8_C(14) + +/***************************************************************************/ + +/*! BMI270_LEGACY User Interface function prototypes + ****************************************************************************/ + +/** + * \ingroup bmi270_legacy + * \defgroup bmi270_legacyApiInit Initialization + * @brief Initialize the sensor and device structure + */ + +/*! + * \ingroup bmi270_legacyApiInit + * \page bmi270_legacy_api_bmi270_legacy_init bmi270_legacy_init + * \code + * int8_t bmi270_legacy_init(struct bmi2_dev *dev); + * \endcode + * @details This API: + * 1) updates the device structure with address of the configuration file. + * 2) Initializes BMI270_LEGACY sensor. + * 3) Writes the configuration file. + * 4) Updates the feature offset parameters in the device structure. + * 5) Updates the maximum number of pages, in the device structure. + * + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_init(struct bmi2_dev *dev); + +/** + * \ingroup bmi270_legacy + * \defgroup bmi270_legacyApiSensor Feature Set + * @brief Enable / Disable features of the sensor + */ + +/*! + * \ingroup bmi270_legacyApiSensor + * \page bmi270_legacy_api_bmi270_legacy_sensor_enable bmi270_legacy_sensor_enable + * \code + * int8_t bmi270_legacy_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev); + * \endcode + * @details This API selects the sensors/features to be enabled. + * + * @param[in] sens_list : Pointer to select the sensor/feature. + * @param[in] n_sens : Number of sensors selected. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @note Sensors/features that can be enabled. + * + *@verbatim + * sens_list | Values + * ----------------------------|----------- + * BMI2_ACCEL | 0 + * BMI2_GYRO | 1 + * BMI2_AUX | 2 + * BMI2_SIG_MOTION | 3 + * BMI2_ANY_MOTION | 4 + * BMI2_NO_MOTION | 5 + * BMI2_STEP_DETECTOR | 6 + * BMI2_STEP_COUNTER | 7 + * BMI2_STEP_ACTIVITY | 8 + * BMI2_GYRO_GAIN_UPDATE | 9 + * BMI2_ORIENTATION | 14 + * BMI2_HIGH_G | 15 + * BMI2_LOW_G | 16 + * BMI2_FLAT | 17 + * BMI2_SINGLE_TAP | 25 + * BMI2_DOUBLE_TAP | 26 + * BMI2_TRIPLE_TAP | 27 + * BMI2_TEMP | 31 + *@endverbatim + * + * @note : + * example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO}; + * uint8_t n_sens = 2; + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev); + +/*! + * \ingroup bmi270_legacyApiSensor + * \page bmi270_legacy_api_bmi270_legacy_sensor_disable bmi270_legacy_sensor_disable + * \code + * int8_t bmi270_legacy_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev); + * \endcode + * @details This API selects the sensors/features to be disabled. + * + * @param[in] sens_list : Pointer to select the sensor/feature. + * @param[in] n_sens : Number of sensors selected. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @note Sensors/features that can be disabled. + * + *@verbatim + * sens_list | Values + * ----------------------------|----------- + * BMI2_ACCEL | 0 + * BMI2_GYRO | 1 + * BMI2_AUX | 2 + * BMI2_SIG_MOTION | 3 + * BMI2_ANY_MOTION | 4 + * BMI2_NO_MOTION | 5 + * BMI2_STEP_DETECTOR | 6 + * BMI2_STEP_COUNTER | 7 + * BMI2_STEP_ACTIVITY | 8 + * BMI2_GYRO_GAIN_UPDATE | 9 + * BMI2_ORIENTATION | 14 + * BMI2_HIGH_G | 15 + * BMI2_LOW_G | 16 + * BMI2_FLAT | 17 + * BMI2_SINGLE_TAP | 25 + * BMI2_DOUBLE_TAP | 26 + * BMI2_TRIPLE_TAP | 27 + * BMI2_TEMP | 31 + *@endverbatim + * + * @note : + * example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO}; + * uint8_t n_sens = 2; + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev); + +/** + * \ingroup bmi270_legacy + * \defgroup bmi270_legacyApiSensorC Sensor Configuration + * @brief Enable / Disable feature configuration of the sensor + */ + +/*! + * \ingroup bmi270_legacyApiSensorC + * \page bmi270_legacy_api_bmi270_legacy_set_sensor_config bmi270_legacy_set_sensor_config + * \code + * int8_t bmi270_legacy_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev); + * \endcode + * @details This API sets the sensor/feature configuration. + * + * @param[in] sens_cfg : Structure instance of bmi2_sens_config. + * @param[in] n_sens : Number of sensors selected. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @note Sensors/features that can be configured + * + *@verbatim + * sens_list | Values + * ----------------------------|----------- + * BMI2_SIG_MOTION | 3 + * BMI2_ANY_MOTION | 4 + * BMI2_NO_MOTION | 5 + * BMI2_STEP_DETECTOR | 6 + * BMI2_STEP_COUNTER | 7 + * BMI2_STEP_ACTIVITY | 8 + * BMI2_ORIENTATION | 14 + * BMI2_HIGH_G | 15 + * BMI2_LOW_G | 16 + * BMI2_FLAT | 17 + * BMI2_TAP | 28 + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev); + +/*! + * \ingroup bmi270_legacyApiSensorC + * \page bmi270_legacy_api_bmi270_legacy_get_sensor_config bmi270_legacy_get_sensor_config + * \code + * int8_t bmi270_legacy_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev); + * \endcode + * @details This API gets the sensor/feature configuration. + * + * @param[in] sens_cfg : Structure instance of bmi2_sens_config. + * @param[in] n_sens : Number of sensors selected. + * @param[in, out] dev : Structure instance of bmi2_dev. + * + * @note Sensors/features whose configurations can be read. + * + *@verbatim + * sens_list | Values + * ----------------------------|----------- + * BMI2_SIG_MOTION | 3 + * BMI2_ANY_MOTION | 4 + * BMI2_NO_MOTION | 5 + * BMI2_STEP_DETECTOR | 6 + * BMI2_STEP_COUNTER | 7 + * BMI2_STEP_ACTIVITY | 8 + * BMI2_ORIENTATION | 14 + * BMI2_HIGH_G | 15 + * BMI2_LOW_G | 16 + * BMI2_FLAT | 17 + * BMI2_TAP | 28 + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev); + +/** + * \ingroup bmi270_legacy + * \defgroup bmi270_legacyApiSensorD Feature Sensor Data + * @brief Get feature sensor data + */ + +/*! + * \ingroup bmi270_legacyApiSensorD + * \page bmi270_legacy_api_bmi270_legacy_get_feature_data bmi270_legacy_get_feature_data + * \code + * int8_t bmi270_legacy_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev); + * \endcode + * @details This API gets the feature data. + * + * @param[out] feature_data : Structure instance of bmi2_feat_sensor_data. + * @param[in] n_sens : Number of sensors selected. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @note Sensors/features whose data can be read + * + *@verbatim + * sens_list | Values + * ---------------------|----------- + * BMI2_STEP_COUNTER | 7 + * BMI2_STEP_ACTIVITY | 8 + * BMI2_ORIENTATION | 14 + * BMI2_HIGH_G | 15 + * BMI2_NVM_STATUS | 38 + * BMI2_VFRM_STATUS | 39 + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev); + +/** + * \ingroup bmi270_legacy + * \defgroup bmi270_legacyApiGyroUG Gyro User Gain + * @brief Set / Get Gyro User Gain of the sensor + */ + +/*! + * \ingroup bmi270_legacyApiGyroUG + * \page bmi270_legacy_api_bmi270_legacy_update_gyro_user_gain bmi270_legacy_update_gyro_user_gain + * \code + * int8_t bmi270_legacy_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev); + * \endcode + * @details This API updates the gyroscope user-gain. + * + * @param[in] user_gain : Structure that stores user-gain configurations. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev); + +/*! + * \ingroup bmi270_legacyApiGyroUG + * \page bmi270_legacy_api_bmi270_legacy_read_gyro_user_gain bmi270_legacy_read_gyro_user_gain + * \code + * int8_t bmi270_legacy_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, const struct bmi2_dev *dev); + * \endcode + * @details This API reads the compensated gyroscope user-gain values. + * + * @param[out] gyr_usr_gain : Structure that stores gain values. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev); + +/*! + * \ingroup bmi270_legacyApiInt + * \page bmi270_legacy_api_bmi270_legacy_map_feat_int bmi270_legacy_map_feat_int + * \code + * int8_t bmi270_legacy_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev) + * \endcode + * @details This API maps/unmaps feature interrupts to that of interrupt pins. + * + * @param[in] sens_int : Structure instance of bmi2_sens_int_config. + * @param[in] n_sens : Number of interrupts to be mapped. + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi270_legacy_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev); + +/******************************************************************************/ +/*! @name C++ Guard Macros */ +/******************************************************************************/ +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* _BMI270_LEGACY_H_ */ diff --git a/bmi270_legacy_examples/accel_foc/Makefile b/bmi270_legacy_examples/accel_foc/Makefile new file mode 100644 index 0000000..f8f2229 --- /dev/null +++ b/bmi270_legacy_examples/accel_foc/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accel_foc.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/accel_foc/accel_foc.c b/bmi270_legacy_examples/accel_foc/accel_foc.c new file mode 100644 index 0000000..af7d4e1 --- /dev/null +++ b/bmi270_legacy_examples/accel_foc/accel_foc.c @@ -0,0 +1,729 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include +#include +#include +#include + +#include "bmi270_legacy.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macro Definitions */ + +#define ACCEL_SAMPLE_COUNT UINT8_C(100) + +/******************************************************************************/ +/*! Global Variable Declaration */ + +/* Structure to store temporary axes data values */ +struct temp_axes_val +{ + /* X data */ + int32_t x; + + /* Y data */ + int32_t y; + + /* Z data */ + int32_t z; +}; + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used perform accel foc and determine limits based on range + * + * @param[in] range : Range of Accel + * @param[in] input_axis : Axis selected for Accel FOC + * @param[in,out] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t perform_foc_range_test(uint8_t range, uint8_t input_axis, struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to determine if average accel FOC data is within limits + * + * @param[in] range : Value of Accel range + * @param[in] avg_accel_foc_data : Average Accel FOC value + * @param[in] reference : Reference LSB based on Accel Range + * @param[in] foc_sign : Input sign of performed Accel FOC + * @param[in] min_val : Minimum acceptable LSB limit + * @param[in] max_val : Maximum acceptable LSB limit + * + * @return Status of execution. + */ +static int8_t accel_foc_report(uint8_t range, + int16_t avg_accel_foc_data, + int16_t reference, + uint8_t foc_sign, + int16_t min_val, + int16_t max_val); + +/*! + * @brief This internal API is to collect and verify accel sensor data + * + * @param[in] range : Value of Accel range + * @param[in] reference : Reference LSB based on Accel Range + * @param[in] matched_axis : Input Axis to perform Accel FOC + * @param[in] foc_sign : Input sign to perform Accel FOC + * @param[in,out] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t verify_accel_foc_data(uint8_t range, + int16_t reference, + int8_t matched_axis, + uint8_t foc_sign, + struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to calculate noise level for Accel FOC data + * + * @param[in] matched_axis : Input Axis to perform accel FOC + * @param[in] accel_foc_data : Array of Accel FOC data + * @param[in] avg_accel_foc_data : Average Accel FOC data + * + * @return Status of execution. + */ +static void calculate_noise(int8_t matched_axis, + struct bmi2_sens_axes_data *accel_foc_data, + struct bmi2_sens_axes_data avg_accel_foc_data); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + uint8_t try = 0, j = 0; + int8_t rslt; + uint8_t sens_list = BMI2_ACCEL; + struct bmi2_sens_config sens_cfg = { 0 }; + uint8_t data = 0, range, input_axis = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + printf("Functional test for accel foc start..\n\n"); + + printf("Choose the axis for accel FOC to be done\n"); + printf("Press '1' to choose X axis\n"); + printf("Press '2' to choose Y axis\n"); + printf("Press '3' to choose Z axis\n"); + + printf("Press '4' to choose -X axis\n"); + printf("Press '5' to choose -Y axis\n"); + printf("Press '6' to choose -Z axis\n"); + + while (1) + { + scanf("%hu", (short unsigned int *)&input_axis); + if (input_axis > 0 && input_axis < 7) + { + break; + } + } + + if (input_axis == 1) + { + printf("The choosen input axis for FOC is : X\n"); + } + else if (input_axis == 2) + { + printf("The choosen input axis for FOC is : Y\n"); + } + else if (input_axis == 3) + { + printf("The choosen input axis for FOC is : Z\n"); + } + else if (input_axis == 4) + { + printf("The choosen input axis for FOC is : -X\n"); + } + else if (input_axis == 5) + { + printf("The choosen input axis for FOC is : -Y\n"); + } + else if (input_axis == 6) + { + printf("The choosen input axis for FOC is : -Z\n"); + } + + printf("Confirm your chosen axis and the sensor keeping position are same before doing FOC\n"); + + for (j = 0; j < 2; j++) + { + try = 0; + + if (j == 1) + { + printf("Keep sensor in wrong position and press 5\n"); + } + else if (j == 0) + { + printf("Keep sensor in right position and press 5\n"); + } + + while (1) + { + scanf("%hu", (short unsigned int *)&try); + if (try == 5) + { + break; + } + } + + for (range = BMI2_ACC_RANGE_2G; range <= BMI2_ACC_RANGE_16G; range++) + { + /****************************************************************/ + /* Initialize by enabling configuration load */ + printf("#########################################################\n\n"); + + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + sens_cfg.type = BMI2_ACCEL; + + /* Testing with different settings other than the default configurations + * Default is : 50Hz ODR and 2g RANGE + * Note - Change accel_conf.range for testing in different range values + */ + sens_cfg.cfg.acc.odr = BMI2_ACC_ODR_50HZ; + sens_cfg.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /****************************************************************/ + sens_cfg.cfg.acc.range = range; + + /* Set the configuration details */ + rslt = bmi270_legacy_set_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Get the configuration details to verify whether the configured values are set */ + rslt = bmi270_legacy_get_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("ODR = %d, RANGE = %d, BANDWIDTH = %d\n", + sens_cfg.cfg.acc.odr, + sens_cfg.cfg.acc.range, + sens_cfg.cfg.acc.bwp); + + /* Perform FOC for different ranges */ + rslt = perform_foc_range_test(range, input_axis, &dev); + + if ((j == 1) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - Wrong position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_OK)) + { + printf("\n######### Valid input - Right position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 1) && (rslt == BMI2_OK)) + { + printf("\n######### Invalid input - Right position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Wrong position #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - Right position #########\n\n"); + printf("\n######### Before FOC is better than after FOC #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((j == 1) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Right position #########\n\n"); + printf("\n######### Before FOC is better than after FOC #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + } + + /* Disable offset compensation */ + rslt = bmi2_get_regs(BMI2_NV_CONF_ADDR, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + data = BMI2_SET_BIT_VAL0(data, BMI2_NV_ACC_OFFSET); + + rslt = bmi2_set_regs(BMI2_NV_CONF_ADDR, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Get the accelerometer configuration details to verify whether it is reverted back to the configured ones */ + rslt = bmi270_legacy_get_sensor_config(&sens_cfg, 1, &dev); + bmi2_error_codes_print_result(rslt); + } + + bmi2_coines_deinit(); + + return rslt; +} + +static int8_t accel_foc_report(uint8_t range, + int16_t avg_accel_foc_data, + int16_t reference, + uint8_t foc_sign, + int16_t min_val, + int16_t max_val) +{ + int8_t rslt = BMI2_OK; + int16_t diff_after = 0; + + if (foc_sign == 0) + { + if ((avg_accel_foc_data >= (min_val)) && (avg_accel_foc_data <= (max_val))) + { + if (avg_accel_foc_data >= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** PASS | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d in range\n", avg_accel_foc_data); + rslt = BMI2_OK; + } + else + { + if (avg_accel_foc_data >= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** FAIL | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d not in range\n", avg_accel_foc_data); + rslt = BMI2_E_OUT_OF_RANGE; + } + } + + if (foc_sign == 1) + { + if ((avg_accel_foc_data <= (min_val)) && (avg_accel_foc_data >= (max_val))) + { + if (avg_accel_foc_data <= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** PASS | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d in range\n", avg_accel_foc_data); + rslt = BMI2_OK; + } + else + { + if (avg_accel_foc_data <= reference) + { + diff_after = avg_accel_foc_data - reference; + } + else + { + diff_after = reference - avg_accel_foc_data; + } + + printf("\n# ********** FAIL | Difference = %d **********\n", diff_after); + printf("\n# Avg_FOC %d not in range\n", avg_accel_foc_data); + rslt = BMI2_E_OUT_OF_RANGE; + } + } + + return rslt; +} + +static void calculate_noise(int8_t matched_axis, + struct bmi2_sens_axes_data *accel_foc_data, + struct bmi2_sens_axes_data avg_accel_foc_data) +{ + uint16_t variance = 0; + uint16_t noise_level = 0; + uint16_t index = 0; + + if (matched_axis == 'X') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].x - avg_accel_foc_data.x) * (accel_foc_data[index].x - avg_accel_foc_data.x)); + } + } + else if (matched_axis == 'Y') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].y - avg_accel_foc_data.y) * (accel_foc_data[index].y - avg_accel_foc_data.y)); + } + } + else if (matched_axis == 'Z') + { + for (index = 0; index < ACCEL_SAMPLE_COUNT; index++) + { + variance += + ((accel_foc_data[index].z - avg_accel_foc_data.z) * (accel_foc_data[index].z - avg_accel_foc_data.z)); + } + } + + noise_level = sqrt(variance); + + printf("\n# ********** NOISE LEVEL = %d **********\n", noise_level); +} + +static int8_t verify_accel_foc_data(uint8_t range, + int16_t reference, + int8_t matched_axis, + uint8_t foc_sign, + struct bmi2_dev *bmi2_dev) +{ + int8_t rslt = BMI2_E_INVALID_STATUS; + uint8_t i; + uint16_t reg_status = 0; + int16_t xl, yl, zl; + int16_t xh, yh, zh; + int16_t min_val = 0; + int16_t max_val = 0; + struct bmi2_sens_axes_data accel_foc_data[ACCEL_SAMPLE_COUNT] = { { 0 } }; + struct temp_axes_val temp_foc_data = { 0 }; + struct bmi2_sens_axes_data avg_accel_foc_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Setting initial values */ + xl = yl = zl = 32767; + xh = yh = zh = -32768; + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read accelerometer values before/after FOC */ + for (i = 0; i < ACCEL_SAMPLE_COUNT; i++) + { + while (1) + { + /* To get the data ready interrupt status */ + rslt = bmi2_get_int_status(®_status, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read accelerometer data based on data ready interrupt */ + if ((rslt == BMI2_OK) && (reg_status & BMI2_ACC_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + memcpy(&accel_foc_data[i], &sensor_data.acc, sizeof(struct bmi2_sens_axes_data)); + + printf("X[%d] = %5d, Y[%d] = %5d, Z[%d] = %5d\n", + i, + accel_foc_data[i].x, + i, + accel_foc_data[i].y, + i, + accel_foc_data[i].z); + + if (xl > accel_foc_data[i].x) + { + xl = accel_foc_data[i].x; + } + + if (xh < accel_foc_data[i].x) + { + xh = accel_foc_data[i].x; + } + + if (yl > accel_foc_data[i].y) + { + yl = accel_foc_data[i].y; + } + + if (yh < accel_foc_data[i].y) + { + yh = accel_foc_data[i].y; + } + + if (zl > accel_foc_data[i].z) + { + zl = accel_foc_data[i].z; + } + + if (zh < accel_foc_data[i].z) + { + zh = accel_foc_data[i].z; + } + + temp_foc_data.x += accel_foc_data[i].x; + temp_foc_data.y += accel_foc_data[i].y; + temp_foc_data.z += accel_foc_data[i].z; + break; + + } + } + } + + /* Taking average values to calculate percentage deviation */ + avg_accel_foc_data.x = (int16_t)(temp_foc_data.x / ACCEL_SAMPLE_COUNT); + avg_accel_foc_data.y = (int16_t)(temp_foc_data.y / ACCEL_SAMPLE_COUNT); + avg_accel_foc_data.z = (int16_t)(temp_foc_data.z / ACCEL_SAMPLE_COUNT); + + printf("********* MIN & MAX VALUES ********\n"); + + printf("XL = %5d YL = %5d ZL = %5d\n", xl, yl, zl); + printf("XH = %5d YH = %5d ZH = %5d\n", xh, yh, zh); + + printf("***** AVERAGE AFTER FOC *****\n"); + printf("Avg-X = %d Avg-Y = %d Avg-Z = %d\n", + avg_accel_foc_data.x, + avg_accel_foc_data.y, + avg_accel_foc_data.z); + + /* Calculate noise level */ + calculate_noise(matched_axis, accel_foc_data, avg_accel_foc_data); + + /* "zero-g offset" of accel is +/- 20 mg for all ranges as per datasheet */ + if (range == 0) + { + /* Min and Max limits for Range 2G */ + min_val = BMI2_ACC_2G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_2G_MAX_NOISE_LIMIT; + } + else if (range == 1) + { + /* Min and Max limits for Range 4G */ + min_val = BMI2_ACC_4G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_4G_MAX_NOISE_LIMIT; + } + else if (range == 2) + { + /* Min and Max limits for Range 8G */ + min_val = BMI2_ACC_8G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_8G_MAX_NOISE_LIMIT; + } + else if (range == 3) + { + /* Min and Max limits for Range 16G */ + min_val = BMI2_ACC_16G_MIN_NOISE_LIMIT; + max_val = BMI2_ACC_16G_MAX_NOISE_LIMIT; + } + + if ((matched_axis == 'X') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.x, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.x, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'Y') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.y, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.y, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'Z') && (foc_sign == 0)) + { + rslt = accel_foc_report(range, avg_accel_foc_data.z, reference, foc_sign, min_val, max_val); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %u Max_Value : %u\n", + range, + avg_accel_foc_data.z, + reference, + min_val, + max_val); + } + else if ((matched_axis == 'X') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.x, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.x, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + else if ((matched_axis == 'Y') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.y, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.y, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + else if ((matched_axis == 'Z') && (foc_sign == 1)) + { + rslt = + accel_foc_report(range, avg_accel_foc_data.z, (reference * (-1)), foc_sign, (min_val * (-1)), + (max_val * (-1))); + printf("Range : %d Avg_FOC-X : %d Reference : %d Min_Value : %d Max_Value : %d\n", + range, + avg_accel_foc_data.z, + (reference * (-1)), + (min_val * (-1)), + (max_val * (-1))); + } + + return rslt; +} + +/* Perform FOC for different range and resolutions */ +static int8_t perform_foc_range_test(uint8_t range, uint8_t input_axis, struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + int8_t matched_axis = 0; + int16_t reference = 0; + + /* Set accel foc axis and it's sign (x, y, z, sign)*/ + struct bmi2_accel_foc_g_value g_value_foc = { 0, 0, 0, 0 }; + + if (input_axis == 1) + { + g_value_foc.x = 1; + g_value_foc.y = 0; + g_value_foc.z = 0; + g_value_foc.sign = 0; + } + else if (input_axis == 2) + { + g_value_foc.x = 0; + g_value_foc.y = 1; + g_value_foc.z = 0; + g_value_foc.sign = 0; + } + else if (input_axis == 3) + { + g_value_foc.x = 0; + g_value_foc.y = 0; + g_value_foc.z = 1; + g_value_foc.sign = 0; + } + else if (input_axis == 4) + { + g_value_foc.x = 1; + g_value_foc.y = 0; + g_value_foc.z = 0; + g_value_foc.sign = 1; + } + else if (input_axis == 5) + { + g_value_foc.x = 0; + g_value_foc.y = 1; + g_value_foc.z = 0; + g_value_foc.sign = 1; + } + else if (input_axis == 6) + { + g_value_foc.x = 0; + g_value_foc.y = 0; + g_value_foc.z = 1; + g_value_foc.sign = 1; + } + + switch (range) + { + /* Reference LSB value of 2G */ + case 0: + reference = BMI2_ACC_FOC_2G_REF; + break; + + /* Reference LSB value of 4G */ + case 1: + reference = BMI2_ACC_FOC_4G_REF; + break; + + /* Reference LSB value of 8G */ + case 2: + reference = BMI2_ACC_FOC_8G_REF; + break; + + /* Reference LSB value of 16G */ + case 3: + reference = BMI2_ACC_FOC_16G_REF; + break; + } + + if (g_value_foc.x == 1) + { + matched_axis = 'X'; + } + else if (g_value_foc.y == 1) + { + matched_axis = 'Y'; + } + else if (g_value_foc.z == 1) + { + matched_axis = 'Z'; + } + + if (g_value_foc.sign == 1) + { + printf("MATCHED AXIS is = -%c\n", matched_axis); + } + else + { + printf("MATCHED AXIS is = %c\n", matched_axis); + } + + printf("\n\n# Before FOC\n"); + rslt = verify_accel_foc_data(range, reference, matched_axis, g_value_foc.sign, bmi2_dev); + + printf("\n\n######### Perform Accel FOC #########\n\n"); + + /* Perform accelerometer FOC */ + rslt = bmi2_perform_accel_foc(&g_value_foc, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Provide delay after performing FOC */ + bmi2_dev->delay_us(40000, bmi2_dev->intf_ptr); + + printf("\n\n# After FOC\n"); + rslt = verify_accel_foc_data(range, reference, matched_axis, g_value_foc.sign, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + return rslt; +} diff --git a/bmi270_legacy_examples/accel_gyro/Makefile b/bmi270_legacy_examples/accel_gyro/Makefile new file mode 100644 index 0000000..1bb4d8f --- /dev/null +++ b/bmi270_legacy_examples/accel_gyro/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accel_gyro.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/accel_gyro/accel_gyro.c b/bmi270_legacy_examples/accel_gyro/accel_gyro.c new file mode 100644 index 0000000..3f9b6a8 --- /dev/null +++ b/bmi270_legacy_examples/accel_gyro/accel_gyro.c @@ -0,0 +1,264 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * + * @param[in] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Accel values in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to define limit to print accel data. */ + uint8_t limit = 10; + + /* Assign accel and gyro sensor to variable. */ + uint8_t sensor_list[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Sensor initialization configuration. */ + struct bmi2_dev bmi2_dev; + + /* Create an instance of sensor data structure. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Initialize the interrupt status of accel and gyro. */ + uint16_t int_status = 0; + + uint8_t indx = 1; + + float x = 0, y = 0, z = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&bmi2_dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Accel and gyro configuration settings. */ + rslt = set_accel_gyro_config(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: Accel and Gyro enable must be done after setting configurations */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Loop to print accel and gyro data when interrupt occurs. */ + while (indx <= limit) + { + /* To get the data ready interrupt status of accel and gyro. */ + rslt = bmi2_get_int_status(&int_status, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 10 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) + { + /* Get accel and gyro data for x, y and z axis. */ + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("\n******* Accel(Raw and m/s2) Gyro(Raw and dps) data : %d *******\n", indx); + + printf("\nAcc_x = %d\t", sensor_data.acc.x); + printf("Acc_y = %d\t", sensor_data.acc.y); + printf("Acc_z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z= %d\n", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("Gyro_DPS_X = %4.2f, Gyro_DPS_Y = %4.2f, Gyro_DPS_Z = %4.2f\n", x, y, z); + + indx++; + } + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accelerometer and gyro configuration. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Set Output Data Rate */ + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_200HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples. + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[ACCEL].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* The user can change the following configuration parameters according to their requirement. */ + /* Set Output Data Rate */ + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_200HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[GYRO].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[GYRO].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the accel and gyro configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} diff --git a/bmi270_legacy_examples/accelerometer/Makefile b/bmi270_legacy_examples/accelerometer/Makefile new file mode 100644 index 0000000..2d1f509 --- /dev/null +++ b/bmi270_legacy_examples/accelerometer/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accelerometer.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/accelerometer/accelerometer.c b/bmi270_legacy_examples/accelerometer/accelerometer.c new file mode 100644 index 0000000..4b84268 --- /dev/null +++ b/bmi270_legacy_examples/accelerometer/accelerometer.c @@ -0,0 +1,200 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel. + * + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_accel_config(struct bmi2_dev *dev); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Gravity. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to define limit to print accel data. */ + uint8_t limit = 20; + + /* Assign accel sensor to variable. */ + uint8_t sensor_list = BMI2_ACCEL; + + /* Create an instance of sensor data structure. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Initialize the interrupt status of accel. */ + uint16_t int_status = 0; + + uint8_t indx = 0; + float x = 0, y = 0, z = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Accel configuration settings. */ + rslt = set_accel_config(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: + * Accel enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(&sensor_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel raw data and gravity data in m/s^2 \n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (indx <= limit) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print the status for 10 samples. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get accelerometer data for x, y and z axis. */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("\nAcc_X = %d\t", sensor_data.acc.x); + printf("Acc_Y = %d\t", sensor_data.acc.y); + printf("Acc_Z = %d\t", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, dev.resolution); + + /* Print the data in m/s2. */ + printf("Acc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); + + indx++; + } + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel. + */ +static int8_t set_accel_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accelerometer configuration. */ + struct bmi2_sens_config config; + + /* Configure the type of feature. */ + config.type = BMI2_ACCEL; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Output Data Rate */ + config.cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config.cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples. + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config.cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the accel configurations. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} diff --git a/bmi270_legacy_examples/any_motion/Makefile b/bmi270_legacy_examples/any_motion/Makefile new file mode 100644 index 0000000..5b2992e --- /dev/null +++ b/bmi270_legacy_examples/any_motion/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= any_motion.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/any_motion/any_motion.c b/bmi270_legacy_examples/any_motion/any_motion.c new file mode 100644 index 0000000..3134ece --- /dev/null +++ b/bmi270_legacy_examples/any_motion/any_motion.c @@ -0,0 +1,136 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for any-motion. + * + * @param[in] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_feature_config(struct bmi2_dev *bmi2_dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Accel sensor and any-motion feature are listed in array. */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_ANY_MOTION }; + + /* Variable to get any-motion interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_ANY_MOTION, .hw_int_pin = BMI2_INT1 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Set feature configurations for any-motion. */ + rslt = set_feature_config(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the feature interrupt for any-motion. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Move the board in any direction\n"); + + /* Loop to print the any-motion interrupt status. */ + do + { + /* Clear the buffer. */ + int_status = 0; + + /* To get the interrupt status of any-motion. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of any-motion. */ + if (int_status & BMI270_LEGACY_ANY_MOT_STATUS_MASK) + { + printf("Any-motion interrupt is generated\n"); + break; + } + } while (rslt == BMI2_OK); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for any-motion. + */ +static int8_t set_feature_config(struct bmi2_dev *bmi2_dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Configure the type of any-motion feature. */ + config.type = BMI2_ANY_MOTION; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* 1LSB equals 20ms. Default is 100ms, setting to 80ms. */ + config.cfg.any_motion.duration = 0x04; + + /* 1LSB equals to 0.48mg. Default is 83mg, setting to 50mg. */ + config.cfg.any_motion.threshold = 0x68; + + /* Set new configurations. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/aux_fifo_full_header_mode/Makefile b/bmi270_legacy_examples/aux_fifo_full_header_mode/Makefile new file mode 100644 index 0000000..760101f --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_full_header_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_full_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c b/bmi270_legacy_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c new file mode 100644 index 0000000..3175c87 --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_full_header_mode/aux_fifo_full_header_mode.c @@ -0,0 +1,462 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro, 8 Aux and 1 header, + * totaling to 21) which equals to 97. + * + * Extra frames to parse sensortime data + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(120) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(120) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(120) + +/*! Macro to read sensortime byte in FIFO. */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(220) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_legacy will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", + (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_legacy_examples/aux_fifo_full_headerless_mode/Makefile b/bmi270_legacy_examples/aux_fifo_full_headerless_mode/Makefile new file mode 100644 index 0000000..5cc39a8 --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_full_headerless_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_full_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c b/bmi270_legacy_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c new file mode 100644 index 0000000..fa133be --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_full_headerless_mode/aux_fifo_full_headerless_mode.c @@ -0,0 +1,455 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro, 8 Aux and 1 header, + * totaling to 21) which equals to 97. + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(97) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(97) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(97) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_legacy will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in headerless mode\n"); + + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &aux_bmi2_dev); + } + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_legacy_examples/aux_fifo_watermark_header_mode/Makefile b/bmi270_legacy_examples/aux_fifo_watermark_header_mode/Makefile new file mode 100644 index 0000000..eeab3c2 --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_watermark_header_mode/Makefile @@ -0,0 +1,24 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_watermark_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP20 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c b/bmi270_legacy_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c new file mode 100644 index 0000000..cae1b7b --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_watermark_header_mode/aux_fifo_watermark_header_mode.c @@ -0,0 +1,476 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6, + * aux_frame_len = 8, header_byte = 1. + * fifo_accel_frame_count = (650 / (6 + 6 + 8 + 1 )) = 30 frames + * NOTE: Extra frames are read in order to get sensor time + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(50) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(50) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(50) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*! Macro to read sensortime byte in FIFO */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(250) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_legacy will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", + (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_legacy_examples/aux_fifo_watermark_headerless_mode/Makefile b/bmi270_legacy_examples/aux_fifo_watermark_headerless_mode/Makefile new file mode 100644 index 0000000..98001b4 --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_watermark_headerless_mode/Makefile @@ -0,0 +1,24 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= aux_fifo_watermark_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP20 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c b/bmi270_legacy_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c new file mode 100644 index 0000000..f486a56 --- /dev/null +++ b/bmi270_legacy_examples/aux_fifo_watermark_headerless_mode/aux_fifo_watermark_headerless_mode.c @@ -0,0 +1,468 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "bmm150.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6, aux_frame_len = 8. + * fifo_accel_frame_count = (650 / (6 + 6 + 8 )) = 32 frames + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(32) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(32) + +/*! Number of aux frames to be extracted from FIFO. */ +#define BMI2_FIFO_AUX_FRAME_COUNT UINT8_C(32) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/******************************************************************************/ +/*! Functions */ + +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + uint16_t index = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + uint16_t aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Array of aux frames */ + struct bmi2_aux_fifo_data fifo_aux_data[BMI2_FIFO_AUX_FRAME_COUNT] = { { { 0 } } }; + + uint16_t fifo_length = 0; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE]; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_legacy will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_50HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in headerless mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_ENABLE, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &aux_bmi2_dev); + } + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + aux_frame_length = BMI2_FIFO_AUX_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + aux_bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nFIFO aux frames requested : %d \n", aux_frame_length); + + /* Parse the FIFO data to extract aux data from the FIFO buffer. */ + rslt = bmi2_extract_aux(fifo_aux_data, &aux_frame_length, &fifoframe, &aux_bmi2_dev); + printf("\nFIFO aux frames extracted : %d \n", aux_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_gyro_data[index].x, + fifo_gyro_data[index].y, fifo_gyro_data[index].z); + } + + printf("\nExtracted aux frames\n"); + + /* Print the parsed aux data from the FIFO buffer. */ + for (index = 0; index < aux_frame_length; index++) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(fifo_aux_data[index].data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + printf("AUX[%d] Mag_uT_X : %ld\t Mag_uT_Y : %ld\t Mag_uT_Z : %ld\n", + index, + (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, + (long unsigned int)mag_data.z); + } + + try++; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_legacy_examples/axis_remap/Makefile b/bmi270_legacy_examples/axis_remap/Makefile new file mode 100644 index 0000000..f7ea25e --- /dev/null +++ b/bmi270_legacy_examples/axis_remap/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= axis_remap.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/axis_remap/axis_remap.c b/bmi270_legacy_examples/axis_remap/axis_remap.c new file mode 100644 index 0000000..4c27a70 --- /dev/null +++ b/bmi270_legacy_examples/axis_remap/axis_remap.c @@ -0,0 +1,505 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include + +#include "bmi270_legacy.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel. + * + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_accel_config(struct bmi2_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Status of api are returned to this variable. */ + int8_t rslt; + + struct bmi2_remap remapped_axis = { 0 }; + + /* Initialize the interrupt status of accel. */ + uint16_t int_status = 0; + + /* Select sensors for enable and setting */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_GYRO }; + + char data_array[13][12] = + { { 0 }, { "BMI2_X" }, { "BMI2_Y" }, { 0 }, { "BMI2_Z" }, { 0 }, { 0 }, { 0 }, { 0 }, { "BMI2_NEG_X" }, + { "BMI2_NEG_Y" }, { 0 }, { "BMI2_NEG_Z" } }; + + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize the sensor by enabling write configuration */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Accel configuration settings. */ + rslt = set_accel_config(&dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + printf("\nAXIS_REMAP_FUNC_TEST 1\n"); + printf("Get default values of re-mapped axes sensor data\n"); + + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + + printf("Expected Re-mapped x value = BMI2_X\n"); + printf("Expected Re-mapped y value = BMI2_Y\n"); + printf("Expected Re-mapped z value = BMI2_Z\n"); + + if ((remapped_axis.x == BMI2_X) && (remapped_axis.y == BMI2_Y) && (remapped_axis.z == BMI2_Z)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 1 Failed\n"); + exit(COINES_E_FAILURE); + } + + printf("Print un-mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 2\n"); + printf("Get sensor data of re-mapped axes\n"); + + remapped_axis.x = BMI2_NEG_Y; + remapped_axis.y = BMI2_Z; + remapped_axis.z = BMI2_NEG_X; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_NEG_Y\n"); + printf("Expected Re-mapped y value = BMI2_Z\n"); + printf("Expected Re-mapped z value = BMI2_NEG_X\n"); + + if ((remapped_axis.x == BMI2_NEG_Y) && (remapped_axis.y == BMI2_Z) && (remapped_axis.z == BMI2_NEG_X)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 2 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 3\n"); + printf("Get sensor data of re-mapped axes - 2nd combination\n"); + + remapped_axis.x = BMI2_NEG_Z; + remapped_axis.y = BMI2_NEG_X; + remapped_axis.z = BMI2_Y; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_NEG_Z\n"); + printf("Expected Re-mapped y value = BMI2_NEG_X\n"); + printf("Expected Re-mapped z value = BMI2_Y\n"); + + if ((remapped_axis.x == BMI2_NEG_Z) && (remapped_axis.y == BMI2_NEG_X) && (remapped_axis.z == BMI2_Y)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 3 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 4\n"); + printf("Get sensor data of re-mapped axes - 3rd combination\n"); + + remapped_axis.x = BMI2_Y; + remapped_axis.y = BMI2_Z; + remapped_axis.z = BMI2_X; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_Y\n"); + printf("Expected Re-mapped y value = BMI2_Z\n"); + printf("Expected Re-mapped z value = BMI2_X\n"); + + if ((remapped_axis.x == BMI2_Y) && (remapped_axis.y == BMI2_Z) && (remapped_axis.z == BMI2_X)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 4 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + printf("\nAXIS_REMAP_FUNC_TEST 5\n"); + printf("Get sensor data of re-mapped axes - 4th combination\n"); + + remapped_axis.x = BMI2_NEG_X; + remapped_axis.y = BMI2_NEG_Y; + remapped_axis.z = BMI2_NEG_Z; + + rslt = bmi2_set_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + rslt = bmi2_get_remap_axes(&remapped_axis, &dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + printf("Re-mapped x value = %s\n", data_array[remapped_axis.x]); + printf("Re-mapped y value = %s\n", data_array[remapped_axis.y]); + printf("Re-mapped z value = %s\n", data_array[remapped_axis.z]); + } + + printf("Expected Re-mapped x value = BMI2_NEG_X\n"); + printf("Expected Re-mapped y value = BMI2_NEG_Y\n"); + printf("Expected Re-mapped z value = BMI2_NEG_Z\n"); + + if ((remapped_axis.x == BMI2_NEG_X) && (remapped_axis.y == BMI2_NEG_Y) && (remapped_axis.z == BMI2_NEG_Z)) + { + printf(">> PASS\n"); + } + else + { + printf("AXIS_REMAP_FUNC_TEST 5 Failed\n"); + exit(COINES_E_FAILURE); + } + } + + printf("Print mapped data\n"); + + /* Loop to print the accel data when interrupt occurs. */ + while (1) + { + /* To get the status of accel data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the accel data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_ACC_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Accel :: X : %d Y : %d Z :%d\n", sensor_data.acc.x, sensor_data.acc.y, sensor_data.acc.z); + + break; + } + } + + /* Loop to print the gyro data when interrupt occurs. */ + while (1) + { + /* To get the status of gyro data ready interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the gyro data ready interrupt status and print 1 sample. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get sensor data */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro :: X : %d Y : %d Z :%d\n", sensor_data.gyr.x, sensor_data.gyr.y, sensor_data.gyr.z); + break; + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel. + */ +static int8_t set_accel_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accelerometer configuration. */ + struct bmi2_sens_config config; + + /* Configure the type of feature. */ + config.type = BMI2_ACCEL; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Output Data Rate. By default ODR is set as 100Hz for accel. */ + config.cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config.cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples. + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config.cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the accel configurations. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, dev); + } + + return rslt; +} diff --git a/examples/bmi270_context/common/common.c b/bmi270_legacy_examples/common/common.c similarity index 94% rename from examples/bmi270_context/common/common.c rename to bmi270_legacy_examples/common/common.c index afff37b..0298c30 100644 --- a/examples/bmi270_context/common/common.c +++ b/bmi270_legacy_examples/common/common.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,7 +8,7 @@ #include #include -#include "coines.h" +#include "common.h" #include "bmi2_defs.h" /******************************************************************************/ @@ -123,7 +123,15 @@ int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) bmi->intf = BMI2_I2C_INTF; bmi->read = bmi2_i2c_read; bmi->write = bmi2_i2c_write; - coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + + /* SDO to Ground */ + coines_set_pin_config(COINES_SHUTTLE_PIN_22, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* Make CSB pin HIGH */ + coines_set_pin_config(COINES_SHUTTLE_PIN_21, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + coines_delay_msec(100); + + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE); } /* Bus configuration : SPI */ else if (intf == BMI2_SPI_INTF) @@ -151,11 +159,11 @@ int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) /* Assign to NULL to load the default config file. */ bmi->config_file_ptr = NULL; - coines_delay_usec(10000); + coines_delay_msec(100); coines_set_shuttleboard_vdd_vddio_config(3300, 3300); - coines_delay_usec(10000); + coines_delay_msec(200); } else { @@ -368,5 +376,14 @@ void bmi2_error_codes_print_result(int8_t rslt) */ void bmi2_coines_deinit(void) { + fflush(stdout); + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Coines interface reset */ + coines_soft_reset(); + coines_delay_msec(100); + coines_close_comm_intf(COINES_COMM_INTF_USB); } diff --git a/examples/bmi270/common/common.h b/bmi270_legacy_examples/common/common.h similarity index 95% rename from examples/bmi270/common/common.h rename to bmi270_legacy_examples/common/common.h index 763983d..c165102 100644 --- a/examples/bmi270/common/common.h +++ b/bmi270_legacy_examples/common/common.h @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -14,6 +14,7 @@ extern "C" { #include #include "bmi2.h" +#include "coines.h" /*! * @brief Function for reading the sensor's registers through I2C bus. @@ -79,7 +80,7 @@ BMI2_INTF_RETURN_TYPE bmi2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the * APIs. * - * @param[in] period_us : The required wait time in microsecond. + * @param[in] period : The required wait time in microsecond. * @param[in] intf_ptr : Interface pointer * * @return void. diff --git a/examples/bmi270_maximum_fifo/component_retrim/Makefile b/bmi270_legacy_examples/component_retrim/Makefile similarity index 88% rename from examples/bmi270_maximum_fifo/component_retrim/Makefile rename to bmi270_legacy_examples/component_retrim/Makefile index 0729972..802d0c0 100644 --- a/examples/bmi270_maximum_fifo/component_retrim/Makefile +++ b/bmi270_legacy_examples/component_retrim/Makefile @@ -8,7 +8,7 @@ COMMON_LOCATION ?= .. C_SRCS += \ $(API_LOCATION)/bmi2.c \ -$(API_LOCATION)/bmi270_maximum_fifo.c \ +$(API_LOCATION)/bmi270_legacy.c \ $(COMMON_LOCATION)/common/common.c INCLUDEPATHS += \ diff --git a/examples/bmi270_maximum_fifo/component_retrim/component_retrim.c b/bmi270_legacy_examples/component_retrim/component_retrim.c similarity index 74% rename from examples/bmi270_maximum_fifo/component_retrim/component_retrim.c rename to bmi270_legacy_examples/component_retrim/component_retrim.c index ea24ab2..ce19c47 100644 --- a/examples/bmi270_maximum_fifo/component_retrim/component_retrim.c +++ b/bmi270_legacy_examples/component_retrim/component_retrim.c @@ -1,5 +1,5 @@ /**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause **/ @@ -7,17 +7,17 @@ /******************************************************************************/ /*! Header Files */ #include -#include "bmi270_maximum_fifo.h" +#include "bmi270_legacy.h" #include "common.h" /******************************************************************************/ -/*! Functions */ +/*! Function */ /* This function starts the execution of program. */ int main(void) { /* Sensor initialization configuration. */ - struct bmi2_dev bmi2_dev; + struct bmi2_dev dev; /* Status of api are returned to this variable. */ int8_t rslt; @@ -26,17 +26,17 @@ int main(void) * For I2C : BMI2_I2C_INTF * For SPI : BMI2_SPI_INTF */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); bmi2_error_codes_print_result(rslt); - /* Initialize bmi270_maximum_fifo. */ - rslt = bmi270_maximum_fifo_init(&bmi2_dev); + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { /* This API runs the CRT process. */ - rslt = bmi2_do_crt(&bmi2_dev); + rslt = bmi2_do_crt(&dev); bmi2_error_codes_print_result(rslt); /* Do not move the board while doing CRT. If so, it will throw an abort error. */ diff --git a/bmi270_legacy_examples/fifo_full_header_mode/Makefile b/bmi270_legacy_examples/fifo_full_header_mode/Makefile new file mode 100644 index 0000000..31e2f5b --- /dev/null +++ b/bmi270_legacy_examples/fifo_full_header_mode/Makefile @@ -0,0 +1,20 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= fifo_full_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP30 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/fifo_full_header_mode/fifo_full_header_mode.c b/bmi270_legacy_examples/fifo_full_header_mode/fifo_full_header_mode.c new file mode 100644 index 0000000..de015c7 --- /dev/null +++ b/bmi270_legacy_examples/fifo_full_header_mode/fifo_full_header_mode.c @@ -0,0 +1,307 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO. */ +#define BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro and 1 header, + * totaling to 13) which equals to 157. + * + * Extra frames to parse sensortime data + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(185) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(185) + +/*! Macro to read sensortime byte in FIFO. */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(220) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * @param[in] dev : Structure instance of bmi2_dev. + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + uint16_t index = 0; + uint16_t fifo_length = 0; + uint16_t config = 0; + + uint8_t try = 1; + + /* To read sensortime, extra bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Variable to get fifo full interrupt status. */ + uint16_t int_status = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Array of accelerometer frames -> Total bytes = + * 157 * (6 axes bytes) = 942 bytes */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames -> Total bytes = + * 157 * (6 axes bytes) = 942 bytes */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + /* Accel and gyro sensor are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Configuration settings for accel and gyro. */ + rslt = set_accel_gyro_config(&dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_sel, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_get_fifo_config(&config, &dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra bytes are added to fifo user length. */ + fifoframe.length = BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN, BMI2_ENABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &dev); + bmi2_error_codes_print_result(rslt); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + index, + fifo_gyro_data[index].x, + fifo_gyro_data[index].y, + fifo_gyro_data[index].z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + } + + try++; + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accel and gyro configurations. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[0].type = BMI2_ACCEL; + config[1].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Accel configuration settings. */ + /* Output Data Rate */ + config[0].cfg.acc.odr = BMI2_ACC_ODR_50HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[0].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Gyro configuration settings. */ + /* Output data Rate */ + config[1].cfg.gyr.odr = BMI2_GYR_ODR_50HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope Bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[1].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[1].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set new configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/fifo_full_headerless_mode/Makefile b/bmi270_legacy_examples/fifo_full_headerless_mode/Makefile new file mode 100644 index 0000000..ae25f37 --- /dev/null +++ b/bmi270_legacy_examples/fifo_full_headerless_mode/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= fifo_full_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c b/bmi270_legacy_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c new file mode 100644 index 0000000..d891c82 --- /dev/null +++ b/bmi270_legacy_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c @@ -0,0 +1,293 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) + +/*! Length of data to be read from FIFO */ +#define BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(2048)/ Total frames(6 Accel, 6 Gyro totaling to + * 12) which equals to 170. + */ +#define BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT UINT8_C(169) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT UINT8_C(169) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * @param[in] dev : Structure instance of bmi2_dev. + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + uint16_t index = 0; + uint16_t fifo_length = 0; + + uint8_t try = 1; + + /* Variable to get fifo full interrupt status. */ + uint16_t int_status = 0; + + uint16_t accel_frame_length = BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Array of accelerometer frames -> Total bytes = + * 150 * (6 axes bytes) = 900 bytes */ + struct bmi2_sens_axes_data fifo_accel_data[BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames -> Total bytes = + * 150 * (6 axes bytes) = 900 bytes */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + /* Accel and gyro sensor are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Configuration settings for accel and gyro. */ + rslt = set_accel_gyro_config(&dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_sel, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + fifoframe.length = BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is FIFO mode. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN, BMI2_ENABLE, &dev); + bmi2_error_codes_print_result(rslt); + + printf("FIFO is configured in headerless mode\n"); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &dev); + } + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &dev); + bmi2_error_codes_print_result(rslt); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + rslt = bmi2_get_fifo_length(&fifo_length, &dev); + bmi2_error_codes_print_result(rslt); + + accel_frame_length = BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT; + gyro_frame_length = BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT; + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + index, + fifo_gyro_data[index].x, + fifo_gyro_data[index].y, + fifo_gyro_data[index].z); + } + } + + try++; + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accel and gyro configurations. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[0].type = BMI2_ACCEL; + config[1].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Accel configuration settings. */ + /* Output Data Rate. By default ODR is set as 100Hz for accel. */ + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[0].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Gyro configuration settings. */ + /* Output data Rate. Default ODR is 200Hz, setting to 100Hz. */ + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope Bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[1].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[1].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set new configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/fifo_watermark_header_mode/Makefile b/bmi270_legacy_examples/fifo_watermark_header_mode/Makefile new file mode 100644 index 0000000..0110efe --- /dev/null +++ b/bmi270_legacy_examples/fifo_watermark_header_mode/Makefile @@ -0,0 +1,20 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= fifo_watermark_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP30 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c b/bmi270_legacy_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c new file mode 100644 index 0000000..0d1034f --- /dev/null +++ b/bmi270_legacy_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c @@ -0,0 +1,324 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1200) + +/*! Length of data to be read from FIFO */ +#define BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1200) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6 header_byte = 1. + * fifo_accel_frame_count = (650 / (6 + 6 + 1 )) = 50 frames + * NOTE: Extra frames are read in order to get sensor time + */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(70) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(70) + +/*! Setting a watermark level in FIFO */ +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/*! Macro to read sensortime byte in FIFO */ +#define SENSORTIME_OVERHEAD_BYTE UINT8_C(150) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * @param[in] dev : Structure instance of bmi2_dev. + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to index bytes. */ + uint16_t index = 0; + + uint16_t fifo_length = 0; + + uint16_t accel_frame_length; + + uint16_t gyro_frame_length; + + uint8_t try = 1; + + /* To read sensortime, extra bytes are added to fifo buffer */ + uint16_t fifo_buffer_size = BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Array of accelerometer frames -> Total bytes = + * 55 * (6 axes bytes) = 330 bytes */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames -> Total bytes = + * 55 * (6 axes bytes) = 330 bytes */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + /* Accel and gyro sensor are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Variable to get fifo water-mark interrupt status. */ + uint16_t int_status = 0; + + uint16_t watermark = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Configuration settings for accel and gyro. */ + rslt = set_accel_gyro_config(&dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + + /* Enable accel and gyro sensor. */ + rslt = bmi270_legacy_sensor_enable(sensor_sel, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra bytes are added to fifo user length. */ + fifoframe.length = BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN, BMI2_ENABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &dev); + bmi2_error_codes_print_result(rslt); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the status of FIFO watermark interrupt. */ + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + rslt = bmi2_get_fifo_wm(&watermark, &dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level : %d\n", watermark); + + rslt = bmi2_get_fifo_length(&fifo_length, &dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nExracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + index, + fifo_gyro_data[index].x, + fifo_gyro_data[index].y, + fifo_gyro_data[index].z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("Skipped frame count = %d\n", fifoframe.skipped_frame_count); + printf("Sensor time(in seconds) = %.4lf s\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accel and gyro configurations. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[0].type = BMI2_ACCEL; + config[1].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Accel configuration settings. */ + /* Output Data Rate */ + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[0].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Gyro configuration settings. */ + /* Output data Rate */ + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope Bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[1].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[1].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set new configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/fifo_watermark_headerless_mode/Makefile b/bmi270_legacy_examples/fifo_watermark_headerless_mode/Makefile new file mode 100644 index 0000000..9a6ac98 --- /dev/null +++ b/bmi270_legacy_examples/fifo_watermark_headerless_mode/Makefile @@ -0,0 +1,20 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= fifo_watermark_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP30 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c b/bmi270_legacy_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c new file mode 100644 index 0000000..16f87bb --- /dev/null +++ b/bmi270_legacy_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c @@ -0,0 +1,318 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(800) + +/*! Length of data to be read from FIFO */ +#define BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH UINT16_C(800) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! + * Calculation: + * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6. + * fifo_accel_frame_count = (650 / (6 + 6 )) = 54 frames + */ +#define BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT UINT8_C(55) + +/*! Setting a watermark level in FIFO */ +#define BMI270_LEGACY_FIFO_WATERMARK_LEVEL UINT16_C(650) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * @param[in] dev : Structure instance of bmi2_dev. + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to index bytes. */ + uint16_t index = 0; + + uint16_t fifo_length = 0; + + uint16_t accel_frame_length = BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT; + + uint8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI270_LEGACY_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Array of accelerometer frames -> Total bytes = + * 50 * (6 axes bytes) = 300 bytes */ + struct bmi2_sens_axes_data fifo_accel_data[BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames -> Total bytes = + * 50 * (6 axes bytes) = 300 bytes */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + /* Accel and gyro sensor are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Variable to get fifo water-mark interrupt status. */ + uint16_t int_status = 0; + + uint16_t watermark = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Configuration settings for accel and gyro. */ + rslt = set_accel_gyro_config(&dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_sel, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + fifoframe.length = BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is FIFO mode. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN, BMI2_ENABLE, &dev); + bmi2_error_codes_print_result(rslt); + + printf("FIFO is configured in headerless mode\n"); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &dev); + } + + /* FIFO water-mark interrupt is enabled. */ + fifoframe.data_int_map = BMI2_FWM_INT; + + /* Map water-mark interrupt to the required interrupt pin. */ + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Set water-mark level. */ + fifoframe.wm_lvl = BMI270_LEGACY_FIFO_WATERMARK_LEVEL; + + fifoframe.length = BMI270_LEGACY_FIFO_RAW_DATA_USER_LENGTH; + + /* Set the water-mark level if water-mark interrupt is mapped. */ + rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &dev); + bmi2_error_codes_print_result(rslt); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the status of FIFO watermark interrupt. */ + if ((rslt == BMI2_OK) && (int_status & BMI2_FWM_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + rslt = bmi2_get_fifo_wm(&watermark, &dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level : %d\n", watermark); + + rslt = bmi2_get_fifo_length(&fifo_length, &dev); + bmi2_error_codes_print_result(rslt); + + accel_frame_length = BMI270_LEGACY_FIFO_ACCEL_FRAME_COUNT; + gyro_frame_length = BMI270_LEGACY_FIFO_GYRO_FRAME_COUNT; + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nExracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + index, + fifo_gyro_data[index].x, + fifo_gyro_data[index].y, + fifo_gyro_data[index].z); + } + } + + try++; + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accel and gyro configurations. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[0].type = BMI2_ACCEL; + config[1].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameter according to their requirement. */ + /* Accel configuration settings. */ + /* Output Data Rate. By default ODR is set as 100Hz for accel. */ + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[0].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Gyro configuration settings. */ + /* Output Data Rate. Default ODR is 200Hz, setting to 100Hz. */ + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope Bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[1].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[1].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set new configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 2, dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/flat/Makefile b/bmi270_legacy_examples/flat/Makefile new file mode 100644 index 0000000..1034aa7 --- /dev/null +++ b/bmi270_legacy_examples/flat/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= flat.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/flat/flat.c b/bmi270_legacy_examples/flat/flat.c new file mode 100644 index 0000000..ad83e13 --- /dev/null +++ b/bmi270_legacy_examples/flat/flat.c @@ -0,0 +1,95 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Function */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Structure to define the feature configuration. */ + struct bmi2_sens_config config; + + /* Accel sensor and flat feature are listed in array. */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_FLAT }; + + /* Variable to get flat interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_FLAT, .hw_int_pin = BMI2_INT1 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_FLAT; + + if (rslt == BMI2_OK) + { + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the feature interrupt for flat. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Keep the board flat \n"); + + /* Loop to get flat interrupt status. */ + do + { + /* Clear buffer. */ + int_status = 0; + + /* To get the interrupt status of flat. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of flat. */ + if (int_status & BMI270_LEGACY_FLAT_STATUS_MASK) + { + printf("Flat interrupt is generated\n"); + break; + } + } while (rslt == BMI2_OK); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} diff --git a/bmi270_legacy_examples/g_detection/Makefile b/bmi270_legacy_examples/g_detection/Makefile new file mode 100644 index 0000000..8f0b9a8 --- /dev/null +++ b/bmi270_legacy_examples/g_detection/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= g_detection.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/g_detection/g_detection.c b/bmi270_legacy_examples/g_detection/g_detection.c new file mode 100644 index 0000000..098a265 --- /dev/null +++ b/bmi270_legacy_examples/g_detection/g_detection.c @@ -0,0 +1,178 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Function */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config[2]; + + /* Accel sensor and high-g feature are listed in array. */ + uint8_t high_g_sens_list[2] = { BMI2_ACCEL, BMI2_HIGH_G }; + + /* Accel sensor and low-g feature are listed in array. */ + uint8_t low_g_sens_list[2] = { BMI2_ACCEL, BMI2_LOW_G }; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_feat_sensor_data sensor_data = { 0 }; + + /* Variable to get high-g and low-g interrupt status. */ + uint16_t int_status = 0; + + /* Variables to store the output of high-g. */ + uint8_t high_g_out = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config high_g_int = { .type = BMI2_HIGH_G, .hw_int_pin = BMI2_INT1 }; + struct bmi2_sens_int_config low_g_int = { .type = BMI2_LOW_G, .hw_int_pin = BMI2_INT2 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable high-g feature. */ + rslt = bmi270_legacy_sensor_enable(high_g_sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config[0].type = BMI2_HIGH_G; + config[1].type = BMI2_LOW_G; + + if (rslt == BMI2_OK) + { + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 2, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map high_g feature interrupt to interrupt pin. */ + rslt = bmi270_legacy_map_feat_int(&high_g_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Sensor type of sensor to get data */ + sensor_data.type = BMI2_HIGH_G; + + /* To generate high-g interrupt */ + printf("\n\nMove the board fast towards upward direction\n"); + + do + { + /* Clear the buffer. */ + int_status = 0; + + /* To get the interrupt status of high-g. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of high-g. */ + if (int_status & BMI270_LEGACY_HIGH_G_STATUS_MASK) + { + printf("High-g interrupt is generated\n"); + + rslt = bmi270_legacy_get_feature_data(&sensor_data, 1, &dev); + + high_g_out = sensor_data.sens_data.high_g_output; + + printf("The high-g output : 0x%x \n", high_g_out); + + if (high_g_out & BMI270_LEGACY_HIGH_G_DETECT_X) + { + printf("High-g detected on X-Axis\n"); + } + + if (high_g_out & BMI270_LEGACY_HIGH_G_DETECT_Y) + { + printf("High-g detected on Y-Axis\n"); + } + + if (high_g_out & BMI270_LEGACY_HIGH_G_DETECT_Z) + { + printf("High-g detected on Z-Axis\n"); + } + + if (high_g_out & BMI270_LEGACY_HIGH_G_DETECT_SIGN) + { + printf("High-g detected on negative axis\n"); + } + + if ((high_g_out & BMI270_LEGACY_HIGH_G_DETECT_SIGN) == BMI2_DISABLE) + { + printf("High-g detected on positive axis\n"); + } + else if ((high_g_out & BMI270_LEGACY_HIGH_G_DETECT_SIGN) & + (~(high_g_out & BMI270_LEGACY_HIGH_G_DETECT_SIGN))) + { + printf("High-g detected on positive axis\n"); + } + + break; + } + } while (rslt == BMI2_OK); + + /* Disable high-g feature. */ + rslt = bmi270_legacy_sensor_disable(high_g_sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Enable low-g feature. */ + rslt = bmi270_legacy_sensor_enable(low_g_sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Map low_g feature interrupt to interrupt pin. */ + rslt = bmi270_legacy_map_feat_int(&low_g_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* To generate low-g interrupt */ + printf("\n\nDrop the board in free fall\n"); + + do + { + /* Clear the buffer. */ + int_status = 0; + + /* To get the interrupt status of low-g. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of low-g. */ + if (int_status & BMI270_LEGACY_LOW_G_STATUS_MASK) + { + printf("Low-g interrupt is generated\n"); + break; + } + } while (rslt == BMI2_OK); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} diff --git a/bmi270_legacy_examples/gyro/Makefile b/bmi270_legacy_examples/gyro/Makefile new file mode 100644 index 0000000..72e17f3 --- /dev/null +++ b/bmi270_legacy_examples/gyro/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= gyro.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/gyro/gyro.c b/bmi270_legacy_examples/gyro/gyro.c new file mode 100644 index 0000000..1e507f1 --- /dev/null +++ b/bmi270_legacy_examples/gyro/gyro.c @@ -0,0 +1,197 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for gyro. + * + * @param[in] dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_gyro_config(struct bmi2_dev *dev); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to define limit to print gyro data. */ + uint8_t limit = 10; + + uint8_t indx = 0; + float x = 0, y = 0, z = 0; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Create an instance of sensor data structure. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Assign gyro sensor to variable. */ + uint8_t sens_list = BMI2_GYRO; + + /* Initialize the interrupt status of gyro. */ + uint16_t int_status = 0; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Gyro configuration settings. */ + rslt = set_gyro_config(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + printf("Gyro raw data and DPS data\n"); + + /* Loop to print gyro data when interrupt occurs. */ + while (indx <= limit) + { + /* To get the data ready interrupt status of gyro. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 10 samples. */ + if (int_status & BMI2_GYR_DRDY_INT_MASK) + { + /* Get gyro data for x, y and z axis. */ + rslt = bmi2_get_sensor_data(&sensor_data, &dev); + bmi2_error_codes_print_result(rslt); + + printf("\nGyro Data set : %d\n", indx); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z = %d\r\n", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, dev.resolution); + + /* Print the data in dps. */ + printf("Gyr_DPS_X = %4.2f, Gyr_DPS_Y = %4.2f, Gyr_DPS_Z = %4.2f\n", x, y, z); + + indx++; + } + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for gyro. + */ +static int8_t set_gyro_config(struct bmi2_dev *dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Configure the type of feature. */ + config.type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* The user can change the following configuration parameters according to their requirement. */ + /* Output Data Rate */ + config.cfg.gyr.odr = BMI2_GYR_ODR_200HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config.cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config.cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config.cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config.cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the gyro configurations. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT2, dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} diff --git a/bmi270_legacy_examples/gyro_foc/Makefile b/bmi270_legacy_examples/gyro_foc/Makefile new file mode 100644 index 0000000..3dc2bc2 --- /dev/null +++ b/bmi270_legacy_examples/gyro_foc/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= gyro_foc.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/gyro_foc/gyro_foc.c b/bmi270_legacy_examples/gyro_foc/gyro_foc.c new file mode 100644 index 0000000..eb24135 --- /dev/null +++ b/bmi270_legacy_examples/gyro_foc/gyro_foc.c @@ -0,0 +1,305 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include +#include +#include + +#include "bmi270_legacy.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macro Definitions */ + +#define GYRO_SAMPLE_COUNT UINT8_C(100) + +/******************************************************************************/ +/*! Global Variable Declaration */ + +/* Structure to store temporary axes data values */ +struct temp_axes_val +{ + /* X data */ + int32_t x; + + /* Y data */ + int32_t y; + + /* Z data */ + int32_t z; +}; + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is to perform gyro FOC + * + * @param[in,out] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t perform_gyro_foc_test(struct bmi2_dev *bmi2_dev); + +/*! + * @brief This internal API is to determind if gyro FOC data is within defined limits + * + * @param[in,out] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t verify_gyro_foc_data(struct bmi2_dev *bmi2_dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + uint8_t try = 0, iteration = 0; + int8_t rslt; + uint8_t sens_list = BMI2_GYRO; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + printf("Functional test for gyro foc start..\n"); + + /* Perform FOC for different ranges */ + for (iteration = 0; iteration < 2; iteration++) + { + rslt = 0; + try = 0; + + if (iteration == 0) + { + printf("Shake the sensor and press 5\n"); + } + else if (iteration > 0) + { + printf("Keep sensor stable in right position and press 5\n"); + } + + while (1) + { + scanf("%hu", (short unsigned int *)&try); + if (try == 5) + { + break; + } + } + + /* Initialize the sensor */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + /* Enable gyroscope */ + rslt = bmi270_legacy_sensor_enable(&sens_list, 1, &dev); + bmi2_error_codes_print_result(rslt); + + rslt = perform_gyro_foc_test(&dev); + + if ((iteration == 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Valid input - sensor is shaking #########\n\n"); + if (rslt != BMI2_E_OUT_OF_RANGE) + { + printf("rslt != BMI2_E_OUT_OF_RANGE\n"); + break; + } + } + else if ((iteration > 0) && (rslt == BMI2_OK)) + { + printf("\n######### Valid input - Sensor is not shaking #########\n\n"); + bmi2_error_codes_print_result(rslt); + } + else if ((iteration == 0) && (rslt == BMI2_OK)) + { + printf("\n######### Invalid input - sensor is not shaking #########\n\n"); + if (rslt == BMI2_OK) + { + printf("rslt == BMI2_OK\n"); + break; + } + } + else if ((iteration > 0) && (rslt == BMI2_E_OUT_OF_RANGE)) + { + printf("\n######### Invalid input - Sensor is shaking #########\n\n"); + if (rslt == BMI2_E_OUT_OF_RANGE) + { + printf("rslt == BMI2_E_OUT_OF_RANGE\n"); + break; + } + } + else if (rslt == BMI2_E_OUT_OF_RANGE) + { + bmi2_error_codes_print_result(rslt); + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +static int8_t verify_gyro_foc_data(struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + struct bmi2_sens_axes_data gyr_foc_data[GYRO_SAMPLE_COUNT] = { { 0 } }; + struct temp_axes_val temp_foc_data = { 0 }; + struct bmi2_sens_axes_data avg_foc_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; + uint16_t drdy_status = 0; + uint8_t i; + + /* Read gyroscope values before/after FOC */ + for (i = 0; i < GYRO_SAMPLE_COUNT; i++) + { + while (1) + { + /* To get the data ready interrupt status of gyro. */ + rslt = bmi2_get_int_status(&drdy_status, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read gyroscope data based on data ready interrupt */ + if ((rslt == BMI2_OK) && (drdy_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + memcpy(&gyr_foc_data[i], &sensor_data.gyr, sizeof(struct bmi2_sens_axes_data)); + + printf("X[%d] = %5d, Y[%d] = %5d, Z[%d] = %5d\n", + i, + gyr_foc_data[i].x, + i, + gyr_foc_data[i].y, + i, + gyr_foc_data[i].z); + + temp_foc_data.x += gyr_foc_data[i].x; + temp_foc_data.y += gyr_foc_data[i].y; + temp_foc_data.z += gyr_foc_data[i].z; + break; + } + } + } + + /* Taking average values to calculate percentage deviation */ + avg_foc_data.x = (int16_t)(temp_foc_data.x / GYRO_SAMPLE_COUNT); + avg_foc_data.y = (int16_t)(temp_foc_data.y / GYRO_SAMPLE_COUNT); + avg_foc_data.z = (int16_t)(temp_foc_data.z / GYRO_SAMPLE_COUNT); + + printf("# Average GYRO Axes FOC\n"); + + printf("\n# Avg_X = %5d \t Avg_Y = %5d \t Avg_Z = %5d\n", avg_foc_data.x, avg_foc_data.y, avg_foc_data.z); + + /* The measurement result should be 0 +/- 1dps */ + if (((avg_foc_data.x >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.x <= BMI2_GYRO_FOC_2000_DPS_REF)) && + ((avg_foc_data.y >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.y <= (BMI2_GYRO_FOC_2000_DPS_REF))) && + ((avg_foc_data.z >= -(BMI2_GYRO_FOC_2000_DPS_REF)) && (avg_foc_data.z <= BMI2_GYRO_FOC_2000_DPS_REF))) + { + printf("\n### Gyro Axes data within range ###\n"); + rslt = BMI2_OK; + } + else + { + printf("\n### Gyro Axes data out of range ###\n"); + rslt = BMI2_E_OUT_OF_RANGE; + } + + return rslt; +} + +/* Perform FOC for different ranges*/ +static int8_t perform_gyro_foc_test(struct bmi2_dev *bmi2_dev) +{ + int8_t rslt; + struct bmi2_sens_config config = { 0 }; + + uint8_t sens_list = BMI2_GYRO; + + /* Initialize the sensor */ + rslt = bmi270_legacy_init(bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_GYRO; + + rslt = bmi270_legacy_get_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Set Output Data Rate to 25Hz */ + config.cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config.cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Set Gyroscope bandwidth to CIC mode */ + config.cfg.gyr.bwp = BMI2_GYR_CIC_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config.cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config.cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set the gyro configurations. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Enable gyroscope */ + rslt = bmi270_legacy_sensor_enable(&sens_list, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("# BWP : %d ODR : %d Range : %d\n", config.cfg.gyr.bwp, config.cfg.gyr.odr, config.cfg.gyr.range); + + printf("\n# Before GYRO FOC\n"); + + rslt = verify_gyro_foc_data(bmi2_dev); + + printf("\n\n########## Perform GYRO FOC ##########\n\n"); + + /* Perform gyroscope FOC */ + rslt = bmi2_perform_gyro_foc(bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Provide delay after performing FOC */ + bmi2_dev->delay_us(40000, bmi2_dev->intf_ptr); + + if (rslt == BMI2_OK) + { + printf("\n# After GYRO FOC\n"); + + rslt = verify_gyro_foc_data(bmi2_dev); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/no_motion/Makefile b/bmi270_legacy_examples/no_motion/Makefile new file mode 100644 index 0000000..bb4f6ac --- /dev/null +++ b/bmi270_legacy_examples/no_motion/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= no_motion.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/no_motion/no_motion.c b/bmi270_legacy_examples/no_motion/no_motion.c new file mode 100644 index 0000000..cf3dab9 --- /dev/null +++ b/bmi270_legacy_examples/no_motion/no_motion.c @@ -0,0 +1,135 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for no-motion. + * + * @param[in] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_feature_config(struct bmi2_dev *bmi2_dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Accel sensor and no-motion feature are listed in array. */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_NO_MOTION }; + + /* Variable to get no-motion interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_NO_MOTION, .hw_int_pin = BMI2_INT1 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Set feature configurations for no-motion. */ + rslt = set_feature_config(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the feature interrupt for no-motion. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + printf("Do not move the board\n"); + + /* Loop to get no-motion interrupt. */ + do + { + /* Clear buffer. */ + int_status = 0; + + /* To get the interrupt status of no-motion. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of no-motion. */ + if (int_status & BMI270_LEGACY_NO_MOT_STATUS_MASK) + { + printf("No-motion interrupt is generated\n"); + break; + } + } while (rslt == BMI2_OK); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for no-motion. + */ +static int8_t set_feature_config(struct bmi2_dev *bmi2_dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Configure the type of feature. */ + config.type = BMI2_NO_MOTION; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* 1LSB equals 20ms. Default is 100ms, setting to 80ms. */ + config.cfg.no_motion.duration = 0x04; + + /* 1LSB equals to 0.48mg. Default is 83mg, setting to 50mg. */ + config.cfg.no_motion.threshold = 0x68; + + /* Set new configurations. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/orient/Makefile b/bmi270_legacy_examples/orient/Makefile new file mode 100644 index 0000000..e033823 --- /dev/null +++ b/bmi270_legacy_examples/orient/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= orient.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/orient/orient.c b/bmi270_legacy_examples/orient/orient.c new file mode 100644 index 0000000..b6c0ce8 --- /dev/null +++ b/bmi270_legacy_examples/orient/orient.c @@ -0,0 +1,158 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/**\name Orientation output macros */ +#define BMI270_LEGACY_FACE_UP UINT8_C(0x00) +#define BMI270_LEGACY_FACE_DOWN UINT8_C(0x01) + +#define BMI270_LEGACY_PORTRAIT_UP_RIGHT UINT8_C(0x00) +#define BMI270_LEGACY_LANDSCAPE_LEFT UINT8_C(0x01) +#define BMI270_LEGACY_PORTRAIT_UP_DOWN UINT8_C(0x02) +#define BMI270_LEGACY_LANDSCAPE_RIGHT UINT8_C(0x03) + +/******************************************************************************/ +/*! Function */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variables to store the output of orientation. */ + uint8_t orientation_out = 0; + uint8_t orientation_faceup_down = 0; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_feat_sensor_data sensor_data = { 0 }; + + /* Accel sensor and orientation feature are listed in array. */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_ORIENTATION }; + + /* Variable to get orientation interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_ORIENTATION, .hw_int_pin = BMI2_INT2 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_ORIENTATION; + + if (rslt == BMI2_OK) + { + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Set orientation configurations */ + config.cfg.orientation.ud_en = 0x01; + config.cfg.orientation.mode = 0x02; + config.cfg.orientation.blocking = 0x01; + config.cfg.orientation.theta = 0x33; + config.cfg.orientation.hysteresis = 0x80; + + rslt = bmi270_legacy_set_sensor_config(&config, 1, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the feature interrupt for orientation. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Move the sensor at different orientations to get orientation interrupt. */ + printf("Move the board at different orientations\n"); + + /* Sensor type of sensor to get data */ + sensor_data.type = BMI2_ORIENTATION; + + while (1) + { + /* To get the interrupt status of orientation. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of orientation. */ + if ((rslt == BMI2_OK) && (int_status & BMI270_LEGACY_ORIENT_STATUS_MASK)) + { + printf("Orientation interrupt is generated\n"); + rslt = bmi270_legacy_get_feature_data(&sensor_data, 1, &dev); + + orientation_out = sensor_data.sens_data.orient_output.portrait_landscape; + orientation_faceup_down = sensor_data.sens_data.orient_output.faceup_down; + + printf("The Orientation output is %d \n", orientation_out); + printf("The Orientation faceup/down output is %d\n", orientation_faceup_down); + + switch (orientation_out) + { + case BMI270_LEGACY_LANDSCAPE_LEFT: + printf("Orientation state is landscape left\n"); + break; + case BMI270_LEGACY_LANDSCAPE_RIGHT: + printf("Orientation state is landscape right\n"); + break; + case BMI270_LEGACY_PORTRAIT_UP_DOWN: + printf("Orientation state is portrait upside down\n"); + break; + case BMI270_LEGACY_PORTRAIT_UP_RIGHT: + printf("Orientation state is portrait upright\n"); + break; + } + + switch (orientation_faceup_down) + { + case BMI270_LEGACY_FACE_UP: + printf("Orientation state is face up\n"); + break; + case BMI270_LEGACY_FACE_DOWN: + printf("Orientation state is face down\n"); + break; + } + + break; + } + } + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} diff --git a/bmi270_legacy_examples/read_aux_data_mode/Makefile b/bmi270_legacy_examples/read_aux_data_mode/Makefile new file mode 100644 index 0000000..084279a --- /dev/null +++ b/bmi270_legacy_examples/read_aux_data_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_aux_data_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/read_aux_data_mode/read_aux_data_mode.c b/bmi270_legacy_examples/read_aux_data_mode/read_aux_data_mode.c new file mode 100644 index 0000000..2c4a597 --- /dev/null +++ b/bmi270_legacy_examples/read_aux_data_mode/read_aux_data_mode.c @@ -0,0 +1,409 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_legacy will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL, AND GYRO DATA IN DATA MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK) && + (int_status & BMI2_AUX_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(sensor_data.aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in data mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in data mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_legacy_examples/read_aux_manual_mode/Makefile b/bmi270_legacy_examples/read_aux_manual_mode/Makefile new file mode 100644 index 0000000..9134a63 --- /dev/null +++ b/bmi270_legacy_examples/read_aux_manual_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_aux_manual_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/read_aux_manual_mode/read_aux_manual_mode.c b/bmi270_legacy_examples/read_aux_manual_mode/read_aux_manual_mode.c new file mode 100644 index 0000000..c576d41 --- /dev/null +++ b/bmi270_legacy_examples/read_aux_manual_mode/read_aux_manual_mode.c @@ -0,0 +1,408 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* Array of eight bytes to store x, y, z and r axis aux data. */ + uint8_t aux_data[8] = { 0 }; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270_legacy will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim register */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.manual_en = BMI2_ENABLE; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi270_legacy_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi270_legacy_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL AND GYRO DATA IN MANUAL MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + } + + /* Read aux data from the bmm150 data registers. */ + rslt = bmi2_read_aux_man_mode(BMM150_REG_DATA_X_LSB, aux_data, 8, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_legacy_examples/sig_motion/Makefile b/bmi270_legacy_examples/sig_motion/Makefile new file mode 100644 index 0000000..d90c51b --- /dev/null +++ b/bmi270_legacy_examples/sig_motion/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= sig_motion.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/sig_motion/sig_motion.c b/bmi270_legacy_examples/sig_motion/sig_motion.c new file mode 100644 index 0000000..559580a --- /dev/null +++ b/bmi270_legacy_examples/sig_motion/sig_motion.c @@ -0,0 +1,93 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Function */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Accel sensor and significant-motion feature are listed in array. */ + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_SIG_MOTION }; + + /* Variable to get significant-motion interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_SIG_MOTION, .hw_int_pin = BMI2_INT1 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(sens_list, 2, &dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_SIG_MOTION; + + if (rslt == BMI2_OK) + { + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the feature interrupt for significant-motion. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* By default the significant-motion interrupt occurs when the sensor is in motion for about 5 seconds. + * */ + printf("Move the board for 5 secs in any direction\n"); + + do + { + /* To get the interrupt status of significant-motion. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of significant-motion. */ + if (int_status & BMI270_LEGACY_SIG_MOT_STATUS_MASK) + { + printf("Significant motion interrupt is generated\n"); + break; + } + } while (rslt == BMI2_OK); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} diff --git a/bmi270_legacy_examples/step_activity/Makefile b/bmi270_legacy_examples/step_activity/Makefile new file mode 100644 index 0000000..bcd1b54 --- /dev/null +++ b/bmi270_legacy_examples/step_activity/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= step_activity.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/step_activity/step_activity.c b/bmi270_legacy_examples/step_activity/step_activity.c new file mode 100644 index 0000000..b8d60f3 --- /dev/null +++ b/bmi270_legacy_examples/step_activity/step_activity.c @@ -0,0 +1,110 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Functions */ +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev bmi2_dev; + + /* Structure to define the type of sensor and their respective data. */ + struct bmi2_feat_sensor_data sensor_data = { 0 }; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Accel sensor and step activity feature are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_STEP_ACTIVITY }; + + /* Type of sensor to get step activity data. */ + sensor_data.type = BMI2_STEP_ACTIVITY; + + /* Variable to get step activity interrupt status. */ + uint16_t int_status = 0; + + uint16_t loop = 10; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_STEP_ACTIVITY, .hw_int_pin = BMI2_INT2 }; + + /* The step activities are listed in array. */ + const char *activity_output[4] = { "BMI2_STILL", "BMI2_WALK", "BMI2_RUN", "BMI2_UNKNOWN" }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensor. */ + rslt = bmi270_legacy_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of sensor. */ + config.type = BMI2_STEP_ACTIVITY; + + if (rslt == BMI2_OK) + { + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the feature interrupt for step activity. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("\nMove the board in steps to perform step activity:\n"); + + /* Loop to get step activity. */ + while (loop) + { + /* To get the interrupt status of step detector. */ + rslt = bmi2_get_int_status(&int_status, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of step detector. */ + if (int_status & BMI270_LEGACY_INT_STEP_ACTIVITY_MASK) + { + printf("Step detected\n"); + + /* Get step activity output. */ + rslt = bmi270_legacy_get_feature_data(&sensor_data, 1, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Print the step activity output. */ + printf("Step activity = %s\n", activity_output[sensor_data.sens_data.activity_output]); + + loop--; + } + } + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} diff --git a/bmi270_legacy_examples/step_counter/Makefile b/bmi270_legacy_examples/step_counter/Makefile new file mode 100644 index 0000000..2cde6f9 --- /dev/null +++ b/bmi270_legacy_examples/step_counter/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= step_counter.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/step_counter/step_counter.c b/bmi270_legacy_examples/step_counter/step_counter.c new file mode 100644 index 0000000..7a5e911 --- /dev/null +++ b/bmi270_legacy_examples/step_counter/step_counter.c @@ -0,0 +1,148 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for step counter. + * + * @param[in] bmi2_dev : Structure instance of bmi2_dev. + * + * @return Status of execution. + */ +static int8_t set_feature_config(struct bmi2_dev *bmi2_dev); + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_feat_sensor_data sensor_data = { 0 }; + + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Accel sensor and step counter feature are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_STEP_COUNTER }; + + /* Variable to get step counter interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_STEP_COUNTER, .hw_int_pin = BMI2_INT2 }; + + /* Type of sensor to get step counter data. */ + sensor_data.type = BMI2_STEP_COUNTER; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensor. */ + rslt = bmi270_legacy_sensor_enable(sensor_sel, 2, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Set the feature configuration for step counter. */ + rslt = set_feature_config(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the step counter feature interrupt. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Move the board in steps for 20 times to get step counter interrupt. */ + printf("Move the board in steps\n"); + + /* Loop to get number of steps counted. */ + do + { + /* To get the interrupt status of the step counter. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of the step counter. */ + if (int_status & BMI270_LEGACY_STEP_CNT_STATUS_MASK) + { + printf("Step counter interrupt occurred when watermark level (20 steps) is reached\n"); + + /* Get step counter output. */ + rslt = bmi270_legacy_get_feature_data(&sensor_data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Print the step counter output. */ + printf("No of steps counted = %lu\n", + (unsigned long int)sensor_data.sens_data.step_counter_output); + + break; + } + } while (rslt == BMI2_OK); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for step counter. + */ +static int8_t set_feature_config(struct bmi2_dev *bmi2_dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Configure the type of sensor. */ + config.type = BMI2_STEP_COUNTER; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Setting water-mark level to 1 for step counter to get interrupt after 20 step counts. Every 20 steps once + * output triggers. */ + config.cfg.step_counter.watermark_level = 1; + + printf("Step counter watermark level set to 1 (20 steps)\n"); + + /* Set new configuration. */ + rslt = bmi270_legacy_set_sensor_config(&config, 1, bmi2_dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_legacy_examples/tap/Makefile b/bmi270_legacy_examples/tap/Makefile new file mode 100644 index 0000000..358a0fb --- /dev/null +++ b/bmi270_legacy_examples/tap/Makefile @@ -0,0 +1,18 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= tap.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_legacy.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_legacy_examples/tap/tap.c b/bmi270_legacy_examples/tap/tap.c new file mode 100644 index 0000000..e6b1e30 --- /dev/null +++ b/bmi270_legacy_examples/tap/tap.c @@ -0,0 +1,116 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_legacy.h" +#include "common.h" + +/******************************************************************************/ +/*! Function */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + uint8_t data = 0; + uint8_t loop = 10; + + /* Sensor initialization configuration. */ + struct bmi2_dev dev; + + /* Structure to define the type of sensor and its configurations. */ + struct bmi2_sens_config config; + + /* Accel sensor and tap feature are listed in array. */ + uint8_t sens_list[4] = { BMI2_ACCEL, BMI2_SINGLE_TAP, BMI2_DOUBLE_TAP, BMI2_TRIPLE_TAP }; + + /* Variable to get tap interrupt status. */ + uint16_t int_status = 0; + + /* Select features and their pins to be mapped to. */ + struct bmi2_sens_int_config sens_int = { .type = BMI2_TAP, .hw_int_pin = BMI2_INT1 }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&dev, BMI2_SPI_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_legacy. */ + rslt = bmi270_legacy_init(&dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Enable the selected sensors. */ + rslt = bmi270_legacy_sensor_enable(sens_list, 4, &dev); + bmi2_error_codes_print_result(rslt); + + /* Configure the type of feature. */ + config.type = BMI2_TAP; + + if (rslt == BMI2_OK) + { + /* Get default configurations for the type of feature selected. */ + rslt = bmi270_legacy_get_sensor_config(&config, 1, &dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* Map the tap feature interrupt. */ + rslt = bmi270_legacy_map_feat_int(&sens_int, 1, &dev); + bmi2_error_codes_print_result(rslt); + + /* Tap the board to get interrupt. */ + printf("Tap the board\n"); + + do + { + /* Clear the buffer. */ + int_status = 0; + + /* To get the interrupt status of tap. */ + rslt = bmi2_get_int_status(&int_status, &dev); + bmi2_error_codes_print_result(rslt); + + /* To check the interrupt status of tap. */ + if (int_status & BMI270_LEGACY_TAP_STATUS_MASK) + { + printf("Tap interrupt is generated\n"); + rslt = bmi2_get_regs(BMI270_LEGACY_TAP_STATUS_REG, &data, 1, &dev); + bmi2_error_codes_print_result(rslt); + + if (data & BMI270_LEGACY_SINGLE_TAP_MASK) + { + printf("Single tap asserted\n"); + } + + if (data & BMI270_LEGACY_DOUBLE_TAP_MASK) + { + printf("Double tap asserted\n"); + } + + if (data & BMI270_LEGACY_TRIPLE_TAP_MASK) + { + printf("Triple tap asserted\n"); + } + + loop--; + } + } while (loop > 0); + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} diff --git a/examples/bmi270_maximum_fifo/accel/Makefile b/bmi270_max_fifo_examples/accel/Makefile similarity index 100% rename from examples/bmi270_maximum_fifo/accel/Makefile rename to bmi270_max_fifo_examples/accel/Makefile diff --git a/examples/bmi270_maximum_fifo/accel/accel.c b/bmi270_max_fifo_examples/accel/accel.c similarity index 87% rename from examples/bmi270_maximum_fifo/accel/accel.c rename to bmi270_max_fifo_examples/accel/accel.c index c32a43a..4ebe099 100644 --- a/examples/bmi270_maximum_fifo/accel/accel.c +++ b/bmi270_max_fifo_examples/accel/accel.c @@ -59,7 +59,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Initialize the interrupt status of accel. */ uint16_t int_status = 0; @@ -80,18 +80,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the accel sensor. */ - rslt = bmi2_sensor_enable(&sensor_list, 1, &bmi2_dev); + /* Accel configuration settings. */ + rslt = set_accel_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Accel configuration settings. */ - rslt = set_accel_config(&bmi2_dev); + /* NOTE: + * Accel enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(&sensor_list, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Assign accel sensor. */ - sensor_data.type = BMI2_ACCEL; printf("Accel and m/s2 data \n"); printf("Accel data collected at 2G Range with 16-bit resolution\n"); @@ -106,16 +106,16 @@ int main(void) if (int_status & BMI2_ACC_DRDY_INT_MASK) { /* Get accelerometer data for x, y and z axis. */ - rslt = bmi2_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("\nAcc_X = %d\t", sensor_data.sens_data.acc.x); - printf("Acc_Y = %d\t", sensor_data.sens_data.acc.y); - printf("Acc_Z = %d\r\n", sensor_data.sens_data.acc.z); + printf("\nAcc_X = %d\t", sensor_data.acc.x); + printf("Acc_Y = %d\t", sensor_data.acc.y); + printf("Acc_Z = %d\r\n", sensor_data.acc.z); /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data.sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data.sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data.sens_data.acc.z, 2, bmi2_dev.resolution); + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); /* Print the data in m/s2. */ printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); diff --git a/examples/bmi270_maximum_fifo/accel_gyro/Makefile b/bmi270_max_fifo_examples/accel_gyro/Makefile similarity index 100% rename from examples/bmi270_maximum_fifo/accel_gyro/Makefile rename to bmi270_max_fifo_examples/accel_gyro/Makefile diff --git a/examples/bmi270_maximum_fifo/accel_gyro/accel_gyro.c b/bmi270_max_fifo_examples/accel_gyro/accel_gyro.c similarity index 83% rename from examples/bmi270_maximum_fifo/accel_gyro/accel_gyro.c rename to bmi270_max_fifo_examples/accel_gyro/accel_gyro.c index b77ea1d..457e464 100644 --- a/examples/bmi270_maximum_fifo/accel_gyro/accel_gyro.c +++ b/bmi270_max_fifo_examples/accel_gyro/accel_gyro.c @@ -75,7 +75,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data[2] = { { 0 } }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Initialize the interrupt status of accel and gyro. */ uint16_t int_status = 0; @@ -97,20 +97,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the accel and gyro sensor. */ - rslt = bmi2_sensor_enable(sensor_list, 2, &bmi2_dev); + /* Accel and gyro configuration settings. */ + rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Accel and gyro configuration settings. */ - rslt = set_accel_gyro_config(&bmi2_dev); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_list, 2, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Assign accel and gyro sensor. */ - sensor_data[ACCEL].type = BMI2_ACCEL; - sensor_data[GYRO].type = BMI2_GYRO; - /* Loop to print accel and gyro data when interrupt occurs. */ while (indx <= limit) { @@ -122,31 +120,31 @@ int main(void) if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) { /* Get accel and gyro data for x, y and z axis. */ - rslt = bmi2_get_sensor_data(sensor_data, 2, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); printf("\n******* Accel(Raw and m/s2) Gyro(Raw and dps) data : %d *******\n", indx); - printf("\nAcc_x = %d\t", sensor_data[ACCEL].sens_data.acc.x); - printf("Acc_y = %d\t", sensor_data[ACCEL].sens_data.acc.y); - printf("Acc_z = %d", sensor_data[ACCEL].sens_data.acc.z); + printf("\nAcc_x = %d\t", sensor_data.acc.x); + printf("Acc_y = %d\t", sensor_data.acc.y); + printf("Acc_z = %d", sensor_data.acc.z); /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.z, 2, bmi2_dev.resolution); + x = lsb_to_mps2(sensor_data.acc.x, 2, bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, bmi2_dev.resolution); /* Print the data in m/s2. */ printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); - printf("\nGyr_X = %d\t", sensor_data[GYRO].sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data[GYRO].sens_data.gyr.y); - printf("Gyr_Z= %d\n", sensor_data[GYRO].sens_data.gyr.z); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z= %d\n", sensor_data.gyr.z); /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.z, 2000, bmi2_dev.resolution); + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); /* Print the data in dps. */ printf("Gyro_DPS_X = %4.2f, Gyro_DPS_Y = %4.2f, Gyro_DPS_Z = %4.2f\n", x, y, z); @@ -264,5 +262,5 @@ static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { float half_scale = ((float)(1 << bit_width) / 2.0f); - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); + return (dps / ((half_scale))) * (val); } diff --git a/bmi270_max_fifo_examples/common/common.c b/bmi270_max_fifo_examples/common/common.c new file mode 100644 index 0000000..0298c30 --- /dev/null +++ b/bmi270_max_fifo_examples/common/common.c @@ -0,0 +1,389 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "common.h" +#include "bmi2_defs.h" + +/******************************************************************************/ +/*! Macro definitions */ +#define BMI2XY_SHUTTLE_ID UINT16_C(0x1B8) + +/*! Macro that defines read write length */ +#define READ_WRITE_LEN UINT8_C(46) + +/******************************************************************************/ +/*! Static variable definition */ + +/*! Variable that holds the I2C device address or SPI chip selection */ +static uint8_t dev_addr; + +/******************************************************************************/ +/*! User interface functions */ + +/*! + * I2C read function map to COINES platform + */ +BMI2_INTF_RETURN_TYPE bmi2_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_i2c(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +/*! + * I2C write function map to COINES platform + */ +BMI2_INTF_RETURN_TYPE bmi2_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_i2c(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +/*! + * SPI read function map to COINES platform + */ +BMI2_INTF_RETURN_TYPE bmi2_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_spi(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +/*! + * SPI write function map to COINES platform + */ +BMI2_INTF_RETURN_TYPE bmi2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_spi(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +/*! + * Delay function map to COINES platform + */ +void bmi2_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Function to select the interface between SPI and I2C. + * Also to initialize coines platform + */ +int8_t bmi2_interface_init(struct bmi2_dev *bmi, uint8_t intf) +{ + int8_t rslt = BMI2_OK; + struct coines_board_info board_info; + + if (bmi != NULL) + { + int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB); + if (result < COINES_SUCCESS) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(result); + } + + result = coines_get_board_info(&board_info); + +#if defined(PC) + setbuf(stdout, NULL); +#endif + + if (result == COINES_SUCCESS) + { + if ((board_info.shuttle_id != BMI2XY_SHUTTLE_ID)) + { + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + } + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Bus configuration : I2C */ + if (intf == BMI2_I2C_INTF) + { + printf("I2C Interface \n"); + + /* To initialize the user I2C function */ + dev_addr = BMI2_I2C_PRIM_ADDR; + bmi->intf = BMI2_I2C_INTF; + bmi->read = bmi2_i2c_read; + bmi->write = bmi2_i2c_write; + + /* SDO to Ground */ + coines_set_pin_config(COINES_SHUTTLE_PIN_22, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* Make CSB pin HIGH */ + coines_set_pin_config(COINES_SHUTTLE_PIN_21, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + coines_delay_msec(100); + + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE); + } + /* Bus configuration : SPI */ + else if (intf == BMI2_SPI_INTF) + { + printf("SPI Interface \n"); + + /* To initialize the user SPI function */ + dev_addr = COINES_SHUTTLE_PIN_7; + bmi->intf = BMI2_SPI_INTF; + bmi->read = bmi2_spi_read; + bmi->write = bmi2_spi_write; + coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + } + + /* Assign device address to interface pointer */ + bmi->intf_ptr = &dev_addr; + + /* Configure delay in microseconds */ + bmi->delay_us = bmi2_delay_us; + + /* Configure max read/write length (in bytes) ( Supported length depends on target machine) */ + bmi->read_write_len = READ_WRITE_LEN; + + /* Assign to NULL to load the default config file. */ + bmi->config_file_ptr = NULL; + + coines_delay_msec(100); + + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + + coines_delay_msec(200); + } + else + { + rslt = BMI2_E_NULL_PTR; + } + + return rslt; + +} + +/*! + * @brief Prints the execution status of the APIs. + */ +void bmi2_error_codes_print_result(int8_t rslt) +{ + switch (rslt) + { + case BMI2_OK: + + /* Do nothing */ + break; + + case BMI2_W_FIFO_EMPTY: + printf("Warning [%d] : FIFO empty\r\n", rslt); + break; + case BMI2_W_PARTIAL_READ: + printf("Warning [%d] : FIFO partial read\r\n", rslt); + break; + case BMI2_E_NULL_PTR: + printf( + "Error [%d] : Null pointer error. It occurs when the user tries to assign value (not address) to a pointer," " which has been initialized to NULL.\r\n", + rslt); + break; + + case BMI2_E_COM_FAIL: + printf( + "Error [%d] : Communication failure error. It occurs due to read/write operation failure and also due " "to power failure during communication\r\n", + rslt); + break; + + case BMI2_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMI2_E_INVALID_SENSOR: + printf( + "Error [%d] : Invalid sensor error. It occurs when there is a mismatch in the requested feature with the " "available one\r\n", + rslt); + break; + + case BMI2_E_SELF_TEST_FAIL: + printf( + "Error [%d] : Self-test failed error. It occurs when the validation of accel self-test data is " "not satisfied\r\n", + rslt); + break; + + case BMI2_E_INVALID_INT_PIN: + printf( + "Error [%d] : Invalid interrupt pin error. It occurs when the user tries to configure interrupt pins " "apart from INT1 and INT2\r\n", + rslt); + break; + + case BMI2_E_OUT_OF_RANGE: + printf( + "Error [%d] : Out of range error. It occurs when the data exceeds from filtered or unfiltered data from " "fifo and also when the range exceeds the maximum range for accel and gyro while performing FOC\r\n", + rslt); + break; + + case BMI2_E_ACC_INVALID_CFG: + printf( + "Error [%d] : Invalid Accel configuration error. It occurs when there is an error in accel configuration" " register which could be one among range, BW or filter performance in reg address 0x40\r\n", + rslt); + break; + + case BMI2_E_GYRO_INVALID_CFG: + printf( + "Error [%d] : Invalid Gyro configuration error. It occurs when there is a error in gyro configuration" "register which could be one among range, BW or filter performance in reg address 0x42\r\n", + rslt); + break; + + case BMI2_E_ACC_GYR_INVALID_CFG: + printf( + "Error [%d] : Invalid Accel-Gyro configuration error. It occurs when there is a error in accel and gyro" " configuration registers which could be one among range, BW or filter performance in reg address 0x40 " "and 0x42\r\n", + rslt); + break; + + case BMI2_E_CONFIG_LOAD: + printf( + "Error [%d] : Configuration load error. It occurs when failure observed while loading the configuration " "into the sensor\r\n", + rslt); + break; + + case BMI2_E_INVALID_PAGE: + printf( + "Error [%d] : Invalid page error. It occurs due to failure in writing the correct feature configuration " "from selected page\r\n", + rslt); + break; + + case BMI2_E_SET_APS_FAIL: + printf( + "Error [%d] : APS failure error. It occurs due to failure in write of advance power mode configuration " "register\r\n", + rslt); + break; + + case BMI2_E_AUX_INVALID_CFG: + printf( + "Error [%d] : Invalid AUX configuration error. It occurs when the auxiliary interface settings are not " "enabled properly\r\n", + rslt); + break; + + case BMI2_E_AUX_BUSY: + printf( + "Error [%d] : AUX busy error. It occurs when the auxiliary interface buses are engaged while configuring" " the AUX\r\n", + rslt); + break; + + case BMI2_E_REMAP_ERROR: + printf( + "Error [%d] : Remap error. It occurs due to failure in assigning the remap axes data for all the axes " "after change in axis position\r\n", + rslt); + break; + + case BMI2_E_GYR_USER_GAIN_UPD_FAIL: + printf( + "Error [%d] : Gyro user gain update fail error. It occurs when the reading of user gain update status " "fails\r\n", + rslt); + break; + + case BMI2_E_SELF_TEST_NOT_DONE: + printf( + "Error [%d] : Self-test not done error. It occurs when the self-test process is ongoing or not " "completed\r\n", + rslt); + break; + + case BMI2_E_INVALID_INPUT: + printf("Error [%d] : Invalid input error. It occurs when the sensor input validity fails\r\n", rslt); + break; + + case BMI2_E_INVALID_STATUS: + printf("Error [%d] : Invalid status error. It occurs when the feature/sensor validity fails\r\n", rslt); + break; + + case BMI2_E_CRT_ERROR: + printf("Error [%d] : CRT error. It occurs when the CRT test has failed\r\n", rslt); + break; + + case BMI2_E_ST_ALREADY_RUNNING: + printf( + "Error [%d] : Self-test already running error. It occurs when the self-test is already running and " "another has been initiated\r\n", + rslt); + break; + + case BMI2_E_CRT_READY_FOR_DL_FAIL_ABORT: + printf( + "Error [%d] : CRT ready for download fail abort error. It occurs when download in CRT fails due to wrong " "address location\r\n", + rslt); + break; + + case BMI2_E_DL_ERROR: + printf( + "Error [%d] : Download error. It occurs when write length exceeds that of the maximum burst length\r\n", + rslt); + break; + + case BMI2_E_PRECON_ERROR: + printf( + "Error [%d] : Pre-conditional error. It occurs when precondition to start the feature was not " "completed\r\n", + rslt); + break; + + case BMI2_E_ABORT_ERROR: + printf("Error [%d] : Abort error. It occurs when the device was shaken during CRT test\r\n", rslt); + break; + + case BMI2_E_WRITE_CYCLE_ONGOING: + printf( + "Error [%d] : Write cycle ongoing error. It occurs when the write cycle is already running and another " "has been initiated\r\n", + rslt); + break; + + case BMI2_E_ST_NOT_RUNING: + printf( + "Error [%d] : Self-test is not running error. It occurs when self-test running is disabled while it's " "running\r\n", + rslt); + break; + + case BMI2_E_DATA_RDY_INT_FAILED: + printf( + "Error [%d] : Data ready interrupt error. It occurs when the sample count exceeds the FOC sample limit " "and data ready status is not updated\r\n", + rslt); + break; + + case BMI2_E_INVALID_FOC_POSITION: + printf( + "Error [%d] : Invalid FOC position error. It occurs when average FOC data is obtained for the wrong" " axes\r\n", + rslt); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } +} + +/*! + * @brief Deinitializes coines platform + * + * @return void. + */ +void bmi2_coines_deinit(void) +{ + fflush(stdout); + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_msec(100); + + /* Coines interface reset */ + coines_soft_reset(); + coines_delay_msec(100); + + coines_close_comm_intf(COINES_COMM_INTF_USB); +} diff --git a/bmi270_max_fifo_examples/common/common.h b/bmi270_max_fifo_examples/common/common.h new file mode 100644 index 0000000..c165102 --- /dev/null +++ b/bmi270_max_fifo_examples/common/common.h @@ -0,0 +1,123 @@ +/**\ + * Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +#ifndef _COMMON_H +#define _COMMON_H + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "bmi2.h" +#include "coines.h" + +/*! + * @brief Function for reading the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Pointer to the data buffer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI2_INTF_RET_SUCCESS -> Success + * @retval != BMI2_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI2_INTF_RETURN_TYPE bmi2_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through I2C bus. + * + * @param[in] reg_addr : Register address. + * @param[in] reg_data : Pointer to the data buffer whose value is to be written. + * @param[in] length : No of bytes to write. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI2_INTF_RET_SUCCESS -> Success + * @retval != BMI2_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI2_INTF_RETURN_TYPE bmi2_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for reading the sensor's registers through SPI bus. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Pointer to the data buffer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI2_INTF_RET_SUCCESS -> Success + * @retval != BMI2_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI2_INTF_RETURN_TYPE bmi2_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through SPI bus. + * + * @param[in] reg_addr : Register address. + * @param[in] reg_data : Pointer to the data buffer whose data has to be written. + * @param[in] length : No of bytes to write. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI2_INTF_RET_SUCCESS -> Success + * @retval != BMI2_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI2_INTF_RETURN_TYPE bmi2_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + * + */ +void bmi2_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief Function to select the interface between SPI and I2C. + * + * @param[in] bma : Structure instance of bmi2_dev + * @param[in] intf : Interface selection parameter + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +int8_t bmi2_interface_init(struct bmi2_dev *bma, uint8_t intf); + +/*! + * @brief Prints the execution status of the APIs. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +void bmi2_error_codes_print_result(int8_t rslt); + +/*! + * @brief Deinitializes coines platform + * + * @return void. + */ +void bmi2_coines_deinit(void); + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* _COMMON_H */ diff --git a/bmi270_max_fifo_examples/fifo_full_header_mode/Makefile b/bmi270_max_fifo_examples/fifo_full_header_mode/Makefile new file mode 100644 index 0000000..b60e0c2 --- /dev/null +++ b/bmi270_max_fifo_examples/fifo_full_header_mode/Makefile @@ -0,0 +1,20 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= fifo_full_header_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_maximum_fifo.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP30 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_max_fifo_examples/fifo_full_header_mode/fifo_full_header_mode.c b/bmi270_max_fifo_examples/fifo_full_header_mode/fifo_full_header_mode.c new file mode 100644 index 0000000..15e5455 --- /dev/null +++ b/bmi270_max_fifo_examples/fifo_full_header_mode/fifo_full_header_mode.c @@ -0,0 +1,306 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_maximum_fifo.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +/*! Buffer size allocated to store raw FIFO data. */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(6144) + +/*! Length of data to be read from FIFO. */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(6144) + +/*! Number of accel frames to be extracted from FIFO. */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(6144)/ Total frames(6 Accel, 6 Gyro and 1 header, + * totaling to 13) which equals to 472. + * + * Added extra frames to parse sensortime + */ + +/*! Number of accel frames to be extracted from FIFO */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT16_C(550) + +/*! Number of gyro frames to be extracted from FIFO. */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT16_C(550) + +/*! Macro to read sensortime byte in FIFO. */ +#define SENSORTIME_OVERHEAD_BYTE UINT16_C(800) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * @param[in] dev : Structure instance of bmi2_dev. + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev); + +/******************************************************************************/ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + uint16_t index = 0; + uint16_t fifo_length = 0; + uint16_t config = 0; + + /* To read sensortime, extra 3 bytes are added to fifo buffer. */ + uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; + + /* Variable to get fifo full interrupt status. */ + uint16_t int_status = 0; + + uint16_t accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + uint16_t gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + int8_t try = 1; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[fifo_buffer_size]; + + /* Sensor initialization configuration. */ + struct bmi2_dev bmi2_dev; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + /* Accel and gyro sensor are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_maximum_fifo. */ + rslt = bmi270_maximum_fifo_init(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configuration settings for accel and gyro. */ + rslt = set_accel_gyro_config(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_get_fifo_config(&config, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + /* To read sensortime, extra 3 bytes are added to fifo user length. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH + SENSORTIME_OVERHEAD_BYTE; + + /* Set FIFO configuration by enabling accel, gyro and timestamp. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is in FIFO mode. + * NOTE 3: Sensortime is enabled by default */ + printf("FIFO is configured in header mode\n"); + rslt = bmi2_set_fifo_config(BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN, BMI2_ENABLE, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + index, + fifo_gyro_data[index].x, + fifo_gyro_data[index].y, + fifo_gyro_data[index].z); + } + + /* Print control frames like sensor time and skipped frame count. */ + printf("\nSkipped frame count = %d\n", fifoframe.skipped_frame_count); + + printf("Sensor time(in seconds) = %.4lf s\r\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); + + try++; + } + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accel and gyro configurations. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[0].type = BMI2_ACCEL; + config[1].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi2_get_sensor_config(config, 2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Accel configuration settings. */ + /* Set Output Data Rate */ + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[0].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Gyro configuration settings. */ + /* Set Output Data Rate */ + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope Bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[1].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[1].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set new configurations. */ + rslt = bmi2_set_sensor_config(config, 2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/bmi270_max_fifo_examples/fifo_full_headerless_mode/Makefile b/bmi270_max_fifo_examples/fifo_full_headerless_mode/Makefile new file mode 100644 index 0000000..803f6f8 --- /dev/null +++ b/bmi270_max_fifo_examples/fifo_full_headerless_mode/Makefile @@ -0,0 +1,20 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= fifo_full_headerless_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_maximum_fifo.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(COMMON_LOCATION)/common + +TARGET = MCU_APP30 + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_max_fifo_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c b/bmi270_max_fifo_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c new file mode 100644 index 0000000..46c49cc --- /dev/null +++ b/bmi270_max_fifo_examples/fifo_full_headerless_mode/fifo_full_headerless_mode.c @@ -0,0 +1,293 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_maximum_fifo.h" +#include "common.h" + +/******************************************************************************/ +/*! Macros */ + +/*! Buffer size allocated to store raw FIFO data */ +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(6144) + +/*! Length of data to be read from FIFO */ +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(6144) + +/*! Number of accel frames to be extracted from FIFO */ + +/*! Calculation for frame count: Total frame count = Fifo buffer size(6144)/ Total frames(6 Accel, 6 Gyro totaling to + * 12) which equals to 512. + */ + +/*! Number of accel frames to be extracted from FIFO */ +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT16_C(512) + +/*! Number of gyro frames to be extracted from FIFO */ +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT16_C(512) + +/******************************************************************************/ +/*! Static Function Declaration */ + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + * @param[in] dev : Structure instance of bmi2_dev. + * @return Status of execution. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *dev); + +/******************************************************************************/ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + uint16_t index = 0; + + uint16_t fifo_length = 0; + + uint8_t try = 1; + + /* Variable to get fifo full interrupt status. */ + uint16_t int_status = 0; + + uint16_t accel_frame_length; + + uint16_t gyro_frame_length; + + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ + uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Sensor initialization configuration. */ + struct bmi2_dev bmi2_dev; + + /* Array of accelerometer frames */ + struct bmi2_sens_axes_data fifo_accel_data[BMI2_FIFO_ACCEL_FRAME_COUNT] = { { 0 } }; + + /* Array of gyro frames */ + struct bmi2_sens_axes_data fifo_gyro_data[BMI2_FIFO_GYRO_FRAME_COUNT] = { { 0 } }; + + /* Initialize FIFO frame structure. */ + struct bmi2_fifo_frame fifoframe = { 0 }; + + /* Accel and gyro sensor are listed in array. */ + uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_GYRO }; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_maximum_fifo. */ + rslt = bmi270_maximum_fifo_init(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configuration settings for accel and gyro. */ + rslt = set_accel_gyro_config(&bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Before setting FIFO, disable the advance power save mode. */ + rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initially disable all configurations in fifo. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ALL_EN, BMI2_DISABLE, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Update FIFO structure. */ + /* Mapping the buffer to store the fifo data. */ + fifoframe.data = fifo_data; + + /* Length of FIFO frame. */ + fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; + + /* Set FIFO configuration by enabling accel, gyro. + * NOTE 1: The header mode is enabled by default. + * NOTE 2: By default the FIFO operating mode is FIFO mode. */ + rslt = bmi2_set_fifo_config(BMI2_FIFO_ACC_EN | BMI2_FIFO_GYR_EN, BMI2_ENABLE, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("FIFO is configured in headerless mode\n"); + + /* To enable headerless mode, disable the header. */ + if (rslt == BMI2_OK) + { + rslt = bmi2_set_fifo_config(BMI2_FIFO_HEADER_EN, BMI2_DISABLE, &bmi2_dev); + } + + /* Map FIFO full interrupt. */ + fifoframe.data_int_map = BMI2_FFULL_INT; + rslt = bmi2_map_data_int(fifoframe.data_int_map, BMI2_INT1, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + while (try <= 10) + { + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if ((rslt == BMI2_OK) && (int_status & BMI2_FFULL_INT_STATUS_MASK)) + { + printf("\nIteration : %d\n", try); + + rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; + gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + bmi2_dev.dummy_byte; + + printf("\nFIFO data bytes available : %d \n", fifo_length); + printf("\nFIFO data bytes requested : %d \n", fifoframe.length); + + /* Read FIFO data. */ + rslt = bmi2_read_fifo_data(&fifoframe, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Read FIFO data on interrupt. */ + rslt = bmi2_get_int_status(&int_status, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nFIFO accel frames requested : %d \n", accel_frame_length); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer. */ + rslt = bmi2_extract_accel(fifo_accel_data, &accel_frame_length, &fifoframe, &bmi2_dev); + printf("\nFIFO accel frames extracted : %d \n", accel_frame_length); + + printf("\nFIFO gyro frames requested : %d \n", gyro_frame_length); + + /* Parse the FIFO data to extract gyro data from the FIFO buffer. */ + rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); + printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); + + printf("\nExtracted accel frames\n"); + + /* Print the parsed accelerometer data from the FIFO buffer. */ + for (index = 0; index < accel_frame_length; index++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", index, fifo_accel_data[index].x, + fifo_accel_data[index].y, fifo_accel_data[index].z); + } + + printf("\nExtracted gyro frames\n"); + + /* Print the parsed gyro data from the FIFO buffer. */ + for (index = 0; index < gyro_frame_length; index++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + index, + fifo_gyro_data[index].x, + fifo_gyro_data[index].y, + fifo_gyro_data[index].z); + } + } + + try++; + } + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This internal API is used to set configurations for accel and gyro. + */ +static int8_t set_accel_gyro_config(struct bmi2_dev *bmi2_dev) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Structure to define accel and gyro configurations. */ + struct bmi2_sens_config config[2]; + + /* Configure the type of feature. */ + config[0].type = BMI2_ACCEL; + config[1].type = BMI2_GYRO; + + /* Get default configurations for the type of feature selected. */ + rslt = bmi2_get_sensor_config(config, 2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + /* NOTE: The user can change the following configuration parameters according to their requirement. */ + /* Accel configuration settings. */ + /* Set Output Data Rate */ + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + + /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ + config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* The bandwidth parameter is used to configure the number of sensor samples that are averaged + * if it is set to 2, then 2^(bandwidth parameter) samples + * are averaged, resulting in 4 averaged samples + * Note1 : For more information, refer the datasheet. + * Note2 : A higher number of averaged samples will result in a lower noise level of the signal, but + * this has an adverse effect on the power consumed. + */ + config[0].cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4; + + /* Enable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + * For more info refer datasheet. + */ + config[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + + /* Gyro configuration settings. */ + /* Set Output Data Rate */ + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + + /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ + config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + + /* Gyroscope Bandwidth parameters. By default the gyro bandwidth is in normal mode. */ + config[1].cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE; + + /* Enable/Disable the noise performance mode for precision yaw rate sensing + * There are two modes + * 0 -> Ultra low power mode(Default) + * 1 -> High performance mode + */ + config[1].cfg.gyr.noise_perf = BMI2_POWER_OPT_MODE; + + /* Enable/Disable the filter performance mode where averaging of samples + * will be done based on above set bandwidth and ODR. + * There are two modes + * 0 -> Ultra low power mode + * 1 -> High performance mode(Default) + */ + config[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + + /* Set new configurations. */ + rslt = bmi2_set_sensor_config(config, 2, bmi2_dev); + bmi2_error_codes_print_result(rslt); + } + + return rslt; +} diff --git a/examples/bmi270_maximum_fifo/fifo_watermark_header_mode/Makefile b/bmi270_max_fifo_examples/fifo_watermark_header_mode/Makefile similarity index 94% rename from examples/bmi270_maximum_fifo/fifo_watermark_header_mode/Makefile rename to bmi270_max_fifo_examples/fifo_watermark_header_mode/Makefile index 131538f..180a9ef 100644 --- a/examples/bmi270_maximum_fifo/fifo_watermark_header_mode/Makefile +++ b/bmi270_max_fifo_examples/fifo_watermark_header_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270_maximum_fifo/fifo_watermark_header_mode/fifo_watermark_header_mode.c b/bmi270_max_fifo_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c similarity index 86% rename from examples/bmi270_maximum_fifo/fifo_watermark_header_mode/fifo_watermark_header_mode.c rename to bmi270_max_fifo_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c index f031379..e1203bf 100644 --- a/examples/bmi270_maximum_fifo/fifo_watermark_header_mode/fifo_watermark_header_mode.c +++ b/bmi270_max_fifo_examples/fifo_watermark_header_mode/fifo_watermark_header_mode.c @@ -14,29 +14,29 @@ /*! Macros */ /*! Buffer size allocated to store raw FIFO data */ -#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(6144) /*! Length of data to be read from FIFO */ -#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(6144) /*! Number of accel frames to be extracted from FIFO */ /*! * Calculation: - * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6 header_byte = 1. - * fifo_accel_frame_count = (650 / (6 + 6 + 1 )) = 50 frames + * fifo_watermark_level = 4050, accel_frame_len = 6, gyro_frame_len = 6 header_byte = 1. + * fifo_accel_frame_count = (4050 / (6 + 6 + 1 )) = 311 frames * NOTE: Extra frames are read in order to get sensor time */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT16_C(400) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT16_C(400) /*! Setting a watermark level in FIFO */ -#define BMI270_FIFO_WATERMARK_LEVEL UINT16_C(650) +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(4050) /*! Macro to read sensortime byte in FIFO */ -#define SENSORTIME_OVERHEAD_BYTE UINT8_C(3) +#define SENSORTIME_OVERHEAD_BYTE UINT16_C(800) /******************************************************************************/ /*! Static Function Declaration */ @@ -57,9 +57,6 @@ int main(void) /* Status of api are returned to this variable. */ int8_t rslt; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - /* Variable to index bytes. */ uint16_t index = 0; @@ -74,7 +71,9 @@ int main(void) /* To read sensortime, extra 3 bytes are added to fifo buffer */ uint16_t fifo_buffer_size = BMI2_FIFO_RAW_DATA_BUFFER_SIZE + SENSORTIME_OVERHEAD_BYTE; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[fifo_buffer_size]; /* Sensor initialization configuration. */ @@ -110,14 +109,16 @@ int main(void) rslt = bmi270_maximum_fifo_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi2_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -150,16 +151,12 @@ int main(void) bmi2_error_codes_print_result(rslt); /* Set water-mark level. */ - fifoframe.wm_lvl = BMI270_FIFO_WATERMARK_LEVEL; + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; /* Set the water-mark level if water-mark interrupt is mapped. */ rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &bmi2_dev); bmi2_error_codes_print_result(rslt); - rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - printf("\nFIFO watermark level is %d\n", watermark); - while (try <= 10) { /* Read FIFO data on interrupt. */ @@ -171,7 +168,9 @@ int main(void) { printf("\nIteration : %d\n", try); - printf("\nWatermark interrupt occurred\n"); + rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level is %d\n", watermark); rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -179,6 +178,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + SENSORTIME_OVERHEAD_BYTE + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -204,18 +206,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len + header_byte)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH + 1)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -225,11 +217,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { @@ -242,7 +229,7 @@ int main(void) /* Print control frames like sensor time and skipped frame count. */ printf("Skipped frame count = %d\n", fifoframe.skipped_frame_count); - printf("Sensor time = %lu\r\n", fifoframe.sensor_time); + printf("Sensor time(in seconds) = %.4lf s\r\n", (fifoframe.sensor_time * BMI2_SENSORTIME_RESOLUTION)); try++; } @@ -278,7 +265,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *dev) /* NOTE: The user can change the following configuration parameters according to their requirement. */ /* Accel configuration settings. */ /* Set Output Data Rate */ - config[0].cfg.acc.odr = BMI2_ACC_ODR_25HZ; + config[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; /* Gravity range of the sensor (+/- 2G, 4G, 8G, 16G). */ config[0].cfg.acc.range = BMI2_ACC_RANGE_2G; @@ -303,7 +290,7 @@ static int8_t set_accel_gyro_config(struct bmi2_dev *dev) /* Gyro configuration settings. */ /* Set Output Data Rate */ - config[1].cfg.gyr.odr = BMI2_GYR_ODR_25HZ; + config[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; /* Gyroscope Angular Rate Measurement Range.By default the range is 2000dps. */ config[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; diff --git a/examples/bmi270_maximum_fifo/fifo_watermark_headerless_mode/Makefile b/bmi270_max_fifo_examples/fifo_watermark_headerless_mode/Makefile similarity index 94% rename from examples/bmi270_maximum_fifo/fifo_watermark_headerless_mode/Makefile rename to bmi270_max_fifo_examples/fifo_watermark_headerless_mode/Makefile index 9790a92..8b00f76 100644 --- a/examples/bmi270_maximum_fifo/fifo_watermark_headerless_mode/Makefile +++ b/bmi270_max_fifo_examples/fifo_watermark_headerless_mode/Makefile @@ -15,4 +15,6 @@ INCLUDEPATHS += \ $(API_LOCATION) \ $(COMMON_LOCATION)/common +TARGET = MCU_APP30 + include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi270_maximum_fifo/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c b/bmi270_max_fifo_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c similarity index 87% rename from examples/bmi270_maximum_fifo/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c rename to bmi270_max_fifo_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c index 541ff11..dff32d4 100644 --- a/examples/bmi270_maximum_fifo/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c +++ b/bmi270_max_fifo_examples/fifo_watermark_headerless_mode/fifo_watermark_headerless_mode.c @@ -14,25 +14,25 @@ /*! Macros */ /*! Buffer size allocated to store raw FIFO data */ -#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(4500) /*! Length of data to be read from FIFO */ -#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(2048) +#define BMI2_FIFO_RAW_DATA_USER_LENGTH UINT16_C(4500) /*! Number of accel frames to be extracted from FIFO */ /*! * Calculation: - * fifo_watermark_level = 650, accel_frame_len = 6, gyro_frame_len = 6. - * fifo_accel_frame_count = (650 / (6 + 6 )) = 54 frames + * fifo_watermark_level = 4050, accel_frame_len = 6, gyro_frame_len = 6. + * fifo_accel_frame_count = (4050 / (6 + 6 )) = 337 frames */ -#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_ACCEL_FRAME_COUNT UINT16_C(337) /*! Number of gyro frames to be extracted from FIFO */ -#define BMI2_FIFO_GYRO_FRAME_COUNT UINT8_C(55) +#define BMI2_FIFO_GYRO_FRAME_COUNT UINT16_C(337) /*! Setting a watermark level in FIFO */ -#define BMI270_FIFO_WATERMARK_LEVEL UINT16_C(650) +#define BMI2_FIFO_WATERMARK_LEVEL UINT16_C(4050) /******************************************************************************/ /*! Static Function Declaration */ @@ -56,9 +56,6 @@ int main(void) /* Variable to index bytes. */ uint16_t index = 0; - /* Variable to store the available frame length count in FIFO */ - uint8_t frame_count; - uint16_t fifo_length = 0; uint16_t accel_frame_length; @@ -67,7 +64,9 @@ int main(void) uint8_t try = 1; - /* Number of bytes of FIFO data. */ + /* Number of bytes of FIFO data + * NOTE : Dummy byte (for SPI Interface) required for FIFO data read must be given as part of array size + */ uint8_t fifo_data[BMI2_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; /* Sensor initialization configuration. */ @@ -103,14 +102,16 @@ int main(void) rslt = bmi270_maximum_fifo_init(&bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Enable accel and gyro sensor. */ - rslt = bmi2_sensor_enable(sensor_sel, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - /* Configuration settings for accel and gyro. */ rslt = set_accel_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); + /* NOTE: + * Accel and Gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_sel, 2, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + /* Before setting FIFO, disable the advance power save mode. */ rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -148,7 +149,7 @@ int main(void) bmi2_error_codes_print_result(rslt); /* Set water-mark level. */ - fifoframe.wm_lvl = BMI270_FIFO_WATERMARK_LEVEL; + fifoframe.wm_lvl = BMI2_FIFO_WATERMARK_LEVEL; fifoframe.length = BMI2_FIFO_RAW_DATA_USER_LENGTH; @@ -156,10 +157,6 @@ int main(void) rslt = bmi2_set_fifo_wm(fifoframe.wm_lvl, &bmi2_dev); bmi2_error_codes_print_result(rslt); - rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - printf("\nFIFO watermark level is %d\n", watermark); - while (try <= 10) { /* Read FIFO data on interrupt. */ @@ -171,7 +168,9 @@ int main(void) { printf("\nIteration : %d\n", try); - printf("\nWatermark interrupt occurred\n"); + rslt = bmi2_get_fifo_wm(&watermark, &bmi2_dev); + bmi2_error_codes_print_result(rslt); + printf("\nFIFO watermark level is %d\n", watermark); rslt = bmi2_get_fifo_length(&fifo_length, &bmi2_dev); bmi2_error_codes_print_result(rslt); @@ -179,6 +178,9 @@ int main(void) accel_frame_length = BMI2_FIFO_ACCEL_FRAME_COUNT; gyro_frame_length = BMI2_FIFO_GYRO_FRAME_COUNT; + /* Updating FIFO length to be read based on available length and dummy byte updation */ + fifoframe.length = fifo_length + bmi2_dev.dummy_byte; + printf("\nFIFO data bytes available : %d \n", fifo_length); printf("\nFIFO data bytes requested : %d \n", fifoframe.length); @@ -204,18 +206,8 @@ int main(void) rslt = bmi2_extract_gyro(fifo_gyro_data, &gyro_frame_length, &fifoframe, &bmi2_dev); printf("\nFIFO gyro frames extracted : %d \n", gyro_frame_length); - /* Calculating the frame count from the available bytes in FIFO - * frame_length = (available_fifo_bytes / (acc_frame_len + gyro_frame_len)) */ - frame_count = (fifo_length / (BMI2_FIFO_ACC_GYR_LENGTH)); - printf("\nAvailable frame count from available bytes: %d\n", frame_count); - printf("\nExracted accel frames\n"); - if (accel_frame_length > frame_count) - { - accel_frame_length = frame_count; - } - /* Print the parsed accelerometer data from the FIFO buffer. */ for (index = 0; index < accel_frame_length; index++) { @@ -225,11 +217,6 @@ int main(void) printf("\nExtracted gyro frames\n"); - if (gyro_frame_length > frame_count) - { - gyro_frame_length = frame_count; - } - /* Print the parsed gyro data from the FIFO buffer. */ for (index = 0; index < gyro_frame_length; index++) { diff --git a/examples/bmi270_maximum_fifo/gyro/Makefile b/bmi270_max_fifo_examples/gyro/Makefile similarity index 100% rename from examples/bmi270_maximum_fifo/gyro/Makefile rename to bmi270_max_fifo_examples/gyro/Makefile diff --git a/examples/bmi270_maximum_fifo/gyro/gyro.c b/bmi270_max_fifo_examples/gyro/gyro.c similarity index 85% rename from examples/bmi270_maximum_fifo/gyro/gyro.c rename to bmi270_max_fifo_examples/gyro/gyro.c index 8b56f08..6a2f8e3 100644 --- a/examples/bmi270_maximum_fifo/gyro/gyro.c +++ b/bmi270_max_fifo_examples/gyro/gyro.c @@ -54,7 +54,7 @@ int main(void) struct bmi2_dev bmi2_dev; /* Create an instance of sensor data structure. */ - struct bmi2_sensor_data sensor_data = { 0 }; + struct bmi2_sens_data sensor_data = { { 0 } }; /* Assign gyro sensor to variable. */ uint8_t sens_list = BMI2_GYRO; @@ -75,18 +75,18 @@ int main(void) if (rslt == BMI2_OK) { - /* Enable the selected sensors. */ - rslt = bmi2_sensor_enable(&sens_list, 1, &bmi2_dev); + /* Gyro configuration settings. */ + rslt = set_gyro_config(&bmi2_dev); bmi2_error_codes_print_result(rslt); if (rslt == BMI2_OK) { - /* Gyro configuration settings. */ - rslt = set_gyro_config(&bmi2_dev); + /* NOTE: + * Gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(&sens_list, 1, &bmi2_dev); bmi2_error_codes_print_result(rslt); - /* Select gyro sensor. */ - sensor_data.type = BMI2_GYRO; printf("Gyro and DPS data\n"); printf("Gyro data collected at Range 2000 dps with 16-bit resolution\n"); @@ -101,17 +101,17 @@ int main(void) if (int_status & BMI2_GYR_DRDY_INT_MASK) { /* Get gyro data for x, y and z axis. */ - rslt = bmi2_get_sensor_data(&sensor_data, 1, &bmi2_dev); + rslt = bmi2_get_sensor_data(&sensor_data, &bmi2_dev); bmi2_error_codes_print_result(rslt); - printf("\nGyr_X = %d\t", sensor_data.sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data.sens_data.gyr.y); - printf("Gyr_Z = %d\r\n", sensor_data.sens_data.gyr.z); + printf("\nGyr_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Z = %d\r\n", sensor_data.gyr.z); /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data.sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data.sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data.sens_data.gyr.z, 2000, bmi2_dev.resolution); + x = lsb_to_dps(sensor_data.gyr.x, 2000, bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, bmi2_dev.resolution); /* Print the data in dps. */ printf("Gyr_DPS_X = %4.2f, Gyr_DPS_Y = %4.2f, Gyr_DPS_Z = %4.2f\n", x, y, z); @@ -191,5 +191,5 @@ static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) { float half_scale = ((float)(1 << bit_width) / 2.0f); - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); + return (dps / ((half_scale))) * (val); } diff --git a/bmi270_max_fifo_examples/read_aux_data_mode/Makefile b/bmi270_max_fifo_examples/read_aux_data_mode/Makefile new file mode 100644 index 0000000..9b09cfe --- /dev/null +++ b/bmi270_max_fifo_examples/read_aux_data_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_aux_data_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_maximum_fifo.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_max_fifo_examples/read_aux_data_mode/read_aux_data_mode.c b/bmi270_max_fifo_examples/read_aux_data_mode/read_aux_data_mode.c new file mode 100644 index 0000000..f3dbb83 --- /dev/null +++ b/bmi270_max_fifo_examples/read_aux_data_mode/read_aux_data_mode.c @@ -0,0 +1,409 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_maximum_fifo.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/*******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in data mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_maximum_fifo. */ + rslt = bmi270_maximum_fifo_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim regiter */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi2_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi2_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + rslt = bmi2_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Disable manual mode so that the data mode is enabled. */ + config[AUX].cfg.aux.manual_en = BMI2_DISABLE; + + /* Set the aux configurations. */ + rslt = bmi2_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL, AND GYRO DATA IN DATA MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK) && + (int_status & BMI2_AUX_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(sensor_data.aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in data mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in data mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_max_fifo_examples/read_aux_manual_mode/Makefile b/bmi270_max_fifo_examples/read_aux_manual_mode/Makefile new file mode 100644 index 0000000..78c7356 --- /dev/null +++ b/bmi270_max_fifo_examples/read_aux_manual_mode/Makefile @@ -0,0 +1,23 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_aux_manual_mode.c + +API_LOCATION ?= ../.. + +COMMON_LOCATION ?= .. + +BMM150_SOURCE ?= ../../../bmm150 + +C_SRCS += \ +$(API_LOCATION)/bmi2.c \ +$(API_LOCATION)/bmi270_maximum_fifo.c \ +$(BMM150_SOURCE)/bmm150.c \ +$(COMMON_LOCATION)/common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +$(BMM150_SOURCE) \ +$(COMMON_LOCATION)/common + + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/bmi270_max_fifo_examples/read_aux_manual_mode/read_aux_manual_mode.c b/bmi270_max_fifo_examples/read_aux_manual_mode/read_aux_manual_mode.c new file mode 100644 index 0000000..70c6fef --- /dev/null +++ b/bmi270_max_fifo_examples/read_aux_manual_mode/read_aux_manual_mode.c @@ -0,0 +1,408 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi270_maximum_fifo.h" +#include "bmm150.h" +#include "coines.h" +#include "common.h" + +/******************************************************************************/ +/*! Macro definition */ + +/*! Macros to select the sensors */ +#define ACCEL UINT8_C(0x00) +#define GYRO UINT8_C(0x01) +#define AUX UINT8_C(0x02) + +/*! Macro define limit to print data */ +#define SAMPLE_COUNT UINT8_C(20) + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*****************************************************************************/ +/*! Structure declaration */ + +/* Sensor initialization configuration. */ +struct bmi2_dev aux_bmi2_dev; + +/******************************************************************************/ +/*! Functions */ + +/** + * aux_i2c_read - Reads data from auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the read data. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/** + * aux_i2c_write - Writes data to the auxiliary sensor in manual mode. + * + * @param[in] reg_addr : Register address. + * @param[out] reg_data : Aux data pointer to store the data being written. + * @param[in] length : No of bytes to read. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + */ +static void aux_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Value in meter per second squared. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Value in degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This API is used to print the execution status. + * + * @param[in] rslt : Error code returned by the API whose execution status has to be printed. + * + * @return void. + */ +static void bmm150_error_codes_print_result(int8_t rslt); + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable. */ + int8_t rslt; + + /* Variable to select the pull-up resistor which is set to trim register */ + uint8_t regdata; + + /* Variable to define limit to print aux data. */ + uint8_t limit = SAMPLE_COUNT; + + /* Variable to print data set count of aux data. */ + uint8_t count = 1; + + /* Accel, Gyro and Aux sensors are listed in array. */ + uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; + + /* Initialize the interrupt status of accel, gyro and aux. */ + uint16_t int_status = 0; + + /* Sensor initialization configuration. */ + struct bmm150_dev aux_bmm150_dev; + + /* bmm150 settings configuration */ + struct bmm150_settings settings; + + /* bmm150 magnetometer data */ + struct bmm150_mag_data mag_data; + + /* Structure to define the type of the sensor and its configurations. */ + struct bmi2_sens_config config[3]; + + /* Structure to define type of sensor and their respective data. */ + struct bmi2_sens_data sensor_data = { { 0 } }; + + /* Variables to define read the accel and gyro data in float */ + float x = 0, y = 0, z = 0; + + config[ACCEL].type = BMI2_ACCEL; + config[GYRO].type = BMI2_GYRO; + config[AUX].type = BMI2_AUX; + + /* Array of eight bytes to store x, y, z and r axis aux data. */ + uint8_t aux_data[8] = { 0 }; + + /* To enable the i2c interface settings for bmm150. */ + uint8_t aux_bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; + aux_bmm150_dev.intf_ptr = &aux_bmm150_dev_addr; + aux_bmm150_dev.read = aux_i2c_read; + aux_bmm150_dev.write = aux_i2c_write; + aux_bmm150_dev.delay_us = aux_delay_us; + + /* As per datasheet, aux interface with bmi270 will support only for I2C */ + aux_bmm150_dev.intf = BMM150_I2C_INTF; + + /* Interface reference is given as a parameter + * For I2C : BMI2_I2C_INTF + * For SPI : BMI2_SPI_INTF + */ + rslt = bmi2_interface_init(&aux_bmi2_dev, BMI2_I2C_INTF); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmi270_maximum_fifo. */ + rslt = bmi270_maximum_fifo_init(&aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Pull-up resistor 2k is set to the trim register */ + regdata = BMI2_ASDA_PUPSEL_2K; + rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Get default configurations for the type of feature selected. */ + rslt = bmi2_get_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Configurations for accel. */ + config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; + + /* Configurations for gyro. */ + config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; + config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + /* Configurations for aux. */ + config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; + config[AUX].cfg.aux.aux_en = BMI2_ENABLE; + config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; + config[AUX].cfg.aux.manual_en = BMI2_ENABLE; + config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; + config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; + config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; + + /* Set new configurations for accel, gyro and aux. */ + rslt = bmi2_set_sensor_config(config, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* NOTE: + * Accel and gyro enable must be done after setting configurations + */ + rslt = bmi2_sensor_enable(sensor_list, 3, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* Initialize bmm150. */ + rslt = bmm150_init(&aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Set the power mode to normal mode. */ + settings.pwr_mode = BMM150_POWERMODE_NORMAL; + rslt = bmm150_set_op_mode(&settings, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + + /* Map data ready interrupt to interrupt pin. */ + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + printf("MAGNETOMETER, ACCEL AND GYRO DATA IN MANUAL MODE\n"); + +#ifdef BMM150_USE_FIXED_POINT + printf("Magnetometer data contains fraction part (last 4 bits) and decimal part\n\n"); +#endif + + if (aux_bmm150_dev.chip_id == BMM150_CHIP_ID) + { + printf("\nValid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + + while (1) + { + /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ + aux_bmi2_dev.delay_us(50000, aux_bmi2_dev.intf_ptr); + + /* To get the data ready interrupt status of accel, gyro and aux */ + rslt = bmi2_get_int_status(&int_status, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + /* To check the data ready interrupt status and print the status for 20 samples. */ + if ((int_status & BMI2_ACC_DRDY_INT_MASK) && (int_status & BMI2_GYR_DRDY_INT_MASK)) + { + rslt = bmi2_get_sensor_data(&sensor_data, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + + if (rslt == BMI2_OK) + { + printf("\nData set : %d", count); + + printf("\nAcc_Raw_X = %d\t", sensor_data.acc.x); + printf("Acc_Raw_Y = %d\t", sensor_data.acc.y); + printf("Acc_Raw_Z = %d", sensor_data.acc.z); + + /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ + x = lsb_to_mps2(sensor_data.acc.x, 2, aux_bmi2_dev.resolution); + y = lsb_to_mps2(sensor_data.acc.y, 2, aux_bmi2_dev.resolution); + z = lsb_to_mps2(sensor_data.acc.z, 2, aux_bmi2_dev.resolution); + + /* Print the data in m/s2. */ + printf("\nAcc_ms2_X = %4.2f\t Acc_ms2_Y = %4.2f\t Acc_ms2_Z = %4.2f\n", x, y, z); + + printf("\nGyr_Raw_X = %d\t", sensor_data.gyr.x); + printf("Gyr_Raw_Y = %d\t", sensor_data.gyr.y); + printf("Gyr_Raw_Z = %d", sensor_data.gyr.z); + + /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ + x = lsb_to_dps(sensor_data.gyr.x, 2000, aux_bmi2_dev.resolution); + y = lsb_to_dps(sensor_data.gyr.y, 2000, aux_bmi2_dev.resolution); + z = lsb_to_dps(sensor_data.gyr.z, 2000, aux_bmi2_dev.resolution); + + /* Print the data in dps. */ + printf("\nGyro_DPS_X = %4.2f\t Gyro_DPS_Y = %4.2f\t Gyro_DPS_Z = %4.2f\n", x, y, z); + } + + /* Read aux data from the bmm150 data registers. */ + rslt = bmi2_read_aux_man_mode(BMM150_REG_DATA_X_LSB, aux_data, 8, &aux_bmi2_dev); + bmi2_error_codes_print_result(rslt); + if (rslt == BMI2_OK) + { + /* Compensating the raw auxiliary data available from the BMM150 API. */ + rslt = bmm150_aux_mag_data(aux_data, &mag_data, &aux_bmm150_dev); + bmm150_error_codes_print_result(rslt); + printf("\nMag_uT_X = %ld\t Mag_uT_Y = %ld\t Mag_uT_Z = %ld\n", (long unsigned int)mag_data.x, + (long unsigned int)mag_data.y, (long unsigned int)mag_data.z); + } + + count++; + limit--; + + if (limit == 0) + { + break; + } + } + } + } + else + { + printf("\nInvalid BMM150 (Aux) sensor - Chip ID : 0x%x\n", aux_bmm150_dev.chip_id); + } + + bmi2_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function reads the data from auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_read_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * @brief This function writes the data to auxiliary sensor in manual mode. + */ +static int8_t aux_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) +{ + int8_t rslt; + + rslt = bmi2_write_aux_man_mode(reg_addr, reg_data, length, &aux_bmi2_dev); + + return rslt; +} + +/*! + * Delay function map to COINES platform + */ +static void aux_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (GRAVITY_EARTH * val * g_range) / half_scale; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale))) * (val); +} + +/*! + * @brief Prints the execution status of the APIs. + */ +static void bmm150_error_codes_print_result(int8_t rslt) +{ + if (rslt != BMM150_OK) + { + switch (rslt) + { + case BMM150_E_NULL_PTR: + printf("Error [%d] : Null pointer error.", rslt); + printf( + "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); + break; + + case BMM150_E_COM_FAIL: + printf("Error [%d] : Communication failure error.", rslt); + printf( + "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); + break; + + case BMM150_E_DEV_NOT_FOUND: + printf("Error [%d] : Device not found error. It occurs when the device chip id is incorrectly read\r\n", + rslt); + break; + + case BMM150_E_INVALID_CONFIG: + printf("Error [%d] : Invalid sensor configuration.", rslt); + printf(" It occurs when there is a mismatch in the requested feature with the available one\r\n"); + break; + + default: + printf("Error [%d] : Unknown error code\r\n", rslt); + break; + } + } +} diff --git a/bmi270_maximum_fifo.c b/bmi270_maximum_fifo.c index cfa89a5..8dd0b7c 100644 --- a/bmi270_maximum_fifo.c +++ b/bmi270_maximum_fifo.c @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi270_maximum_fifo.c -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ diff --git a/bmi270_maximum_fifo.h b/bmi270_maximum_fifo.h index e912a96..d427aad 100644 --- a/bmi270_maximum_fifo.h +++ b/bmi270_maximum_fifo.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi270_maximum_fifo.h -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ diff --git a/bmi2_defs.h b/bmi2_defs.h index 08f89d6..af92d13 100644 --- a/bmi2_defs.h +++ b/bmi2_defs.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. +* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved. * * BSD-3-Clause * @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi2_defs.h -* @date 2020-11-04 -* @version v2.63.1 +* @date 2021-09-30 +* @version v2.71.8 * */ @@ -127,6 +127,9 @@ #define BMI2_TRUE UINT8_C(1) #define BMI2_FALSE UINT8_C(0) +/*! @name Macro to define maximum length of read */ +#define BMI2_MAX_LEN UINT8_C(128) + /*! @name To define sensor interface success code */ #define BMI2_INTF_RET_SUCCESS INT8_C(0) @@ -172,6 +175,15 @@ /*! @name To define warnings for FIFO activity */ #define BMI2_W_FIFO_EMPTY INT8_C(1) #define BMI2_W_PARTIAL_READ INT8_C(2) +#define BMI2_W_DUMMY_BYTE INT8_C(3) + +/*! @name Macros to define dummy frame header FIFO headerless mode */ +#define BMI2_FIFO_HEADERLESS_DUMMY_ACC UINT8_C(0x01) +#define BMI2_FIFO_HEADERLESS_DUMMY_GYR UINT8_C(0x02) +#define BMI2_FIFO_HEADERLESS_DUMMY_AUX UINT8_C(0x03) +#define BMI2_FIFO_HEADERLESS_DUMMY_BYTE_1 UINT8_C(0x7F) +#define BMI2_FIFO_HEADERLESS_DUMMY_BYTE_2 UINT8_C(0x00) +#define BMI2_FIFO_HEADERLESS_DUMMY_BYTE_3 UINT8_C(0x80) /*! @name Bit wise to define information */ #define BMI2_I_MIN_VALUE UINT8_C(1) @@ -183,6 +195,7 @@ #define BMI2_AUX_X_LSB_ADDR UINT8_C(0x04) #define BMI2_ACC_X_LSB_ADDR UINT8_C(0x0C) #define BMI2_GYR_X_LSB_ADDR UINT8_C(0x12) +#define BMI2_SENSORTIME_ADDR UINT8_C(0x18) #define BMI2_EVENT_ADDR UINT8_C(0x1B) #define BMI2_INT_STATUS_0_ADDR UINT8_C(0x1C) #define BMI2_INT_STATUS_1_ADDR UINT8_C(0x1D) @@ -190,18 +203,18 @@ #define BMI2_SYNC_COMMAND_ADDR UINT8_C(0x1E) #define BMI2_GYR_CAS_GPIO0_ADDR UINT8_C(0x1E) #define BMI2_INTERNAL_STATUS_ADDR UINT8_C(0x21) -#define BMI2_FIFO_LENGTH_0_ADDR UINT8_C(0X24) -#define BMI2_FIFO_DATA_ADDR UINT8_C(0X26) +#define BMI2_FIFO_LENGTH_0_ADDR UINT8_C(0x24) +#define BMI2_FIFO_DATA_ADDR UINT8_C(0x26) #define BMI2_FEAT_PAGE_ADDR UINT8_C(0x2F) #define BMI2_FEATURES_REG_ADDR UINT8_C(0x30) #define BMI2_ACC_CONF_ADDR UINT8_C(0x40) #define BMI2_GYR_CONF_ADDR UINT8_C(0x42) #define BMI2_AUX_CONF_ADDR UINT8_C(0x44) -#define BMI2_FIFO_DOWNS_ADDR UINT8_C(0X45) -#define BMI2_FIFO_WTM_0_ADDR UINT8_C(0X46) -#define BMI2_FIFO_WTM_1_ADDR UINT8_C(0X47) -#define BMI2_FIFO_CONFIG_0_ADDR UINT8_C(0X48) -#define BMI2_FIFO_CONFIG_1_ADDR UINT8_C(0X49) +#define BMI2_FIFO_DOWNS_ADDR UINT8_C(0x45) +#define BMI2_FIFO_WTM_0_ADDR UINT8_C(0x46) +#define BMI2_FIFO_WTM_1_ADDR UINT8_C(0x47) +#define BMI2_FIFO_CONFIG_0_ADDR UINT8_C(0x48) +#define BMI2_FIFO_CONFIG_1_ADDR UINT8_C(0x49) #define BMI2_AUX_DEV_ID_ADDR UINT8_C(0x4B) #define BMI2_AUX_IF_CONF_ADDR UINT8_C(0x4C) #define BMI2_AUX_RD_ADDR UINT8_C(0x4D) @@ -218,17 +231,17 @@ #define BMI2_INIT_ADDR_1 UINT8_C(0x5C) #define BMI2_INIT_DATA_ADDR UINT8_C(0x5E) #define BMI2_AUX_IF_TRIM UINT8_C(0x68) -#define BMI2_GYR_CRT_CONF_ADDR UINT8_C(0X69) +#define BMI2_GYR_CRT_CONF_ADDR UINT8_C(0x69) #define BMI2_NVM_CONF_ADDR UINT8_C(0x6A) -#define BMI2_IF_CONF_ADDR UINT8_C(0X6B) -#define BMI2_ACC_SELF_TEST_ADDR UINT8_C(0X6D) +#define BMI2_IF_CONF_ADDR UINT8_C(0x6B) +#define BMI2_ACC_SELF_TEST_ADDR UINT8_C(0x6D) #define BMI2_GYR_SELF_TEST_AXES_ADDR UINT8_C(0x6E) -#define BMI2_SELF_TEST_MEMS_ADDR UINT8_C(0X6F) +#define BMI2_SELF_TEST_MEMS_ADDR UINT8_C(0x6F) #define BMI2_NV_CONF_ADDR UINT8_C(0x70) -#define BMI2_ACC_OFF_COMP_0_ADDR UINT8_C(0X71) -#define BMI2_GYR_OFF_COMP_3_ADDR UINT8_C(0X74) -#define BMI2_GYR_OFF_COMP_6_ADDR UINT8_C(0X77) -#define BMI2_GYR_USR_GAIN_0_ADDR UINT8_C(0X78) +#define BMI2_ACC_OFF_COMP_0_ADDR UINT8_C(0x71) +#define BMI2_GYR_OFF_COMP_3_ADDR UINT8_C(0x74) +#define BMI2_GYR_OFF_COMP_6_ADDR UINT8_C(0x77) +#define BMI2_GYR_USR_GAIN_0_ADDR UINT8_C(0x78) #define BMI2_PWR_CONF_ADDR UINT8_C(0x7C) #define BMI2_PWR_CTRL_ADDR UINT8_C(0x7D) #define BMI2_CMD_REG_ADDR UINT8_C(0x7E) @@ -246,8 +259,12 @@ /*! @name BMI2 sensor data bytes */ -#define BMI2_ACC_GYR_NUM_BYTES UINT8_C(6) #define BMI2_AUX_NUM_BYTES UINT8_C(8) +#define BMI2_ACC_NUM_BYTES UINT8_C(6) +#define BMI2_GYR_NUM_BYTES UINT8_C(6) +#define BMI2_ACC_GYR_NUM_BYTES UINT8_C(12) +#define BMI2_AUX_ACC_NUM_BYTES UINT8_C(14) +#define BMI2_ACC_GYR_AUX_NUM_BYTES UINT8_C(20) #define BMI2_CRT_CONFIG_FILE_SIZE UINT16_C(2048) #define BMI2_FEAT_SIZE_IN_BYTES UINT8_C(16) #define BMI2_ACC_CONFIG_LENGTH UINT8_C(2) @@ -380,6 +397,9 @@ #define BMI2_Y_AXIS UINT8_C(1) #define BMI2_Z_AXIS UINT8_C(2) +/*! @name Macro for delay to read internal status */ +#define BMI2_INTERNAL_STATUS_READ_DELAY_MS UINT32_C(140000) + /******************************************************************************/ /*! @name Sensor Macro Definitions */ /******************************************************************************/ @@ -434,6 +454,14 @@ #define BMI2_ACTIVITY_RECOGNITION_SETTINGS UINT8_C(45) #define BMI2_OIS_OUTPUT UINT8_C(46) #define BMI2_CONFIG_ID UINT8_C(47) +#define BMI2_EXT_TCO UINT8_C(48) +#define BMI2_LPD UINT8_C(49) +#define BMI2_LAPTOP_POSITION_DETECTOR_1 UINT8_C(50) +#define BMI2_LAPTOP_POSITION_DETECTOR_2 UINT8_C(51) +#define BMI2_LAPTOP_POSITION_DETECTOR_3 UINT8_C(52) +#define BMI2_LAPTOP_POSITION_DETECTOR_4 UINT8_C(53) +#define BMI2_WRIST_GESTURE_WH_1 UINT8_C(54) +#define BMI2_WRIST_GESTURE_WH_2 UINT8_C(55) /*! @name Bit wise for selecting BMI2 sensors/features */ #define BMI2_ACCEL_SENS_SEL (1) @@ -469,6 +497,8 @@ #define BMI2_WRIST_WEAR_WAKE_UP_WH_SEL (1 << BMI2_WRIST_WEAR_WAKE_UP_WH) #define BMI2_PRIMARY_OIS_SEL (1 << BMI2_PRIMARY_OIS) #define BMI2_FREE_FALL_DET_SEL (1 << BMI2_FREE_FALL_DET) +#define BMI2_EXT_TCO_SEL ((uint64_t)1 << BMI2_EXT_TCO) +#define BMI2_LPD_SEL ((uint64_t)1 << BMI2_LPD) /*! @name Mask definitions for BMI2 wake-up feature configuration for bmi260 */ #define BMI2_WAKEUP_SENSITIVITY_MASK UINT8_C(0x0E) @@ -616,7 +646,7 @@ /*! @name Mask definitions for BMI2 step-counter/detector feature configuration */ #define BMI2_STEP_COUNT_WM_LEVEL_MASK UINT16_C(0x03FF) #define BMI2_STEP_COUNT_RST_CNT_MASK UINT16_C(0x0400) -#define BMI2_STEP_BUFFER_SIZE_MASK UINT16_C(0XFF00) +#define BMI2_STEP_BUFFER_SIZE_MASK UINT16_C(0xFF00) #define BMI2_STEP_COUNT_INT_MASK UINT8_C(0x02) #define BMI2_STEP_ACT_INT_MASK UINT8_C(0x04) @@ -624,7 +654,7 @@ * configuration */ #define BMI2_STEP_COUNT_RST_CNT_POS UINT8_C(0x0A) -#define BMI2_STEP_BUFFER_SIZE_POS UINT8_C(0X08) +#define BMI2_STEP_BUFFER_SIZE_POS UINT8_C(0x08) /*! @name Mask definitions for BMI2 gyroscope user gain feature * configuration @@ -753,6 +783,9 @@ #define BMI2_WRIST_WAKE_UP_ANGLE_PU_POS UINT16_C(0x0008) #define BMI2_WRIST_WAKE_UP_MIN_DUR_QUITE_POS UINT16_C(0x0008) +/*! @name Mask definition for BMI2 EXT TCO configuration */ +#define BMI2_EXT_TCO_MASK UINT8_C(0x01) + /*! @name Macros to define values of BMI2 axis and its sign for re-map * settings */ @@ -790,23 +823,51 @@ #define BMI2_CRT_MIN_BURST_WORD_LENGTH UINT8_C(2) #define BMI2_CRT_MAX_BURST_WORD_LENGTH UINT16_C(255) +/* Reference value with positive and negative noise range in lsb */ + +/* + * For Gyro FOC, axes values after FOC must be 0 +/- 1 dps + * + * In 2000 dps, 1 dps is 16.384 (~16) + * In 1000 dps, 1 dps is 32.768 (~33) + * In 500 dps, 1 dps is 65.536 (~66) + * In 250 dps, 1 dps is 131.072 (~131) + * In 125 dps, 1 dps is 262.144 (~262) + */ +#define BMI2_GYRO_FOC_2000_DPS_REF UINT16_C(16) +#define BMI2_GYRO_FOC_1000_DPS_REF UINT16_C(33) +#define BMI2_GYRO_FOC_500_DPS_REF UINT16_C(66) +#define BMI2_GYRO_FOC_250_DPS_REF UINT16_C(131) +#define BMI2_GYRO_FOC_125_DPS_REF UINT16_C(262) + +/* Reference value with positive and negative noise range in lsb */ + +/* + * As per datasheet, Zero-g offset : +/- 20mg + * + * In range 2G, 1G is 16384. so, 16384 x 20 x (10 ^ -3) = 328 + * In range 4G, 1G is 8192. so, 8192 x 20 x (10 ^ -3) = 164 + * In range 8G, 1G is 4096. so, 4096 x 20 x (10 ^ -3) = 82 + * In range 16G, 1G is 2048. so, 2048 x 20 x (10 ^ -3) = 41 + */ #define BMI2_ACC_FOC_2G_REF UINT16_C(16384) #define BMI2_ACC_FOC_4G_REF UINT16_C(8192) #define BMI2_ACC_FOC_8G_REF UINT16_C(4096) #define BMI2_ACC_FOC_16G_REF UINT16_C(2048) -#define BMI2_GYRO_FOC_NOISE_LIMIT_NEGATIVE INT8_C(-20) -#define BMI2_GYRO_FOC_NOISE_LIMIT_POSITIVE INT8_C(20) +#define BMI2_ACC_FOC_2G_OFFSET UINT16_C(328) +#define BMI2_ACC_FOC_4G_OFFSET UINT16_C(164) +#define BMI2_ACC_FOC_8G_OFFSET UINT16_C(82) +#define BMI2_ACC_FOC_16G_OFFSET UINT16_C(41) -/* reference value with positive and negative noise range in lsb */ -#define BMI2_ACC_2G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_2G_REF + UINT16_C(255)) -#define BMI2_ACC_2G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_2G_REF - UINT16_C(255)) -#define BMI2_ACC_4G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_4G_REF + UINT16_C(255)) -#define BMI2_ACC_4G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_4G_REF - UINT16_C(255)) -#define BMI2_ACC_8G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_8G_REF + UINT16_C(255)) -#define BMI2_ACC_8G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_8G_REF - UINT16_C(255)) -#define BMI2_ACC_16G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_16G_REF + UINT16_C(255)) -#define BMI2_ACC_16G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_16G_REF - UINT16_C(255)) +#define BMI2_ACC_2G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_2G_REF + BMI2_ACC_FOC_2G_OFFSET) +#define BMI2_ACC_2G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_2G_REF - BMI2_ACC_FOC_2G_OFFSET) +#define BMI2_ACC_4G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_4G_REF + BMI2_ACC_FOC_4G_OFFSET) +#define BMI2_ACC_4G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_4G_REF - BMI2_ACC_FOC_4G_OFFSET) +#define BMI2_ACC_8G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_8G_REF + BMI2_ACC_FOC_8G_OFFSET) +#define BMI2_ACC_8G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_8G_REF - BMI2_ACC_FOC_8G_OFFSET) +#define BMI2_ACC_16G_MAX_NOISE_LIMIT (BMI2_ACC_FOC_16G_REF + BMI2_ACC_FOC_16G_OFFSET) +#define BMI2_ACC_16G_MIN_NOISE_LIMIT (BMI2_ACC_FOC_16G_REF - BMI2_ACC_FOC_16G_OFFSET) #define BMI2_FOC_SAMPLE_LIMIT UINT8_C(128) @@ -898,7 +959,7 @@ #define BMI2_ACC_SELF_TEST_AMP_POS UINT8_C(0x03) /*! @name MASK definition for gyro self test status */ -#define BMI2_GYR_ST_AXES_DONE_MASK UINT8_C(0X01) +#define BMI2_GYR_ST_AXES_DONE_MASK UINT8_C(0x01) #define BMI2_GYR_AXIS_X_OK_MASK UINT8_C(0x02) #define BMI2_GYR_AXIS_Y_OK_MASK UINT8_C(0x04) #define BMI2_GYR_AXIS_Z_OK_MASK UINT8_C(0x08) @@ -1031,6 +1092,9 @@ #define BMI2_FIFO_GYR_EN UINT16_C(0x8000) #define BMI2_FIFO_ALL_EN UINT16_C(0xE000) +/*! @name Sensortime resolution in seconds */ +#define BMI2_SENSORTIME_RESOLUTION 0.0000390625f + /*! @name FIFO sensor data lengths */ #define BMI2_FIFO_ACC_LENGTH UINT8_C(6) #define BMI2_FIFO_GYR_LENGTH UINT8_C(6) @@ -1698,8 +1762,8 @@ struct bmi2_ois_output int16_t ois_gyro_z; }; -/*! @name Union to define BMI2 sensor data */ -union bmi2_sens_data +/*! @name Structure to define BMI2 sensor data */ +struct bmi2_sens_data { /*! Accelerometer axes data */ struct bmi2_sens_axes_data acc; @@ -1710,6 +1774,13 @@ union bmi2_sens_data /*! Auxiliary sensor data */ uint8_t aux_data[BMI2_AUX_NUM_BYTES]; + /*! Sensor time */ + uint32_t sens_time; +}; + +/*! @name Union to define BMI2 feature data */ +union bmi2_feature_data +{ /*! Step counter output */ uint32_t step_counter_output; @@ -1745,13 +1816,13 @@ union bmi2_sens_data }; /*! @name Structure to define type of sensor and their respective data */ -struct bmi2_sensor_data +struct bmi2_feat_sensor_data { /*! Defines the type of sensor */ uint8_t type; /*! Defines various sensor data */ - union bmi2_sens_data sens_data; + union bmi2_feature_data sens_data; }; /*! @name Structure to define accelerometer configuration */ @@ -1826,7 +1897,7 @@ struct bmi2_aux_config /*! @name Structure to define any-motion configuration */ struct bmi2_any_motion_config { - /*! Duration in 50Hz samples(20msec) */ + /*! Duration */ uint16_t duration; /*! Acceleration slope threshold */ @@ -1845,7 +1916,7 @@ struct bmi2_any_motion_config /*! @name Structure to define no-motion configuration */ struct bmi2_no_motion_config { - /*! Duration in 50Hz samples(20msec) */ + /*! Duration */ uint16_t duration; /*! Acceleration slope threshold */ @@ -1880,6 +1951,13 @@ struct bmi2_sig_motion_config uint16_t param_5; }; +/*! @name Structure to define EXT TCO configuration */ +struct bmi2_ext_tco +{ + /*! Enable(1) / Disable(0) hardware compensation. */ + uint8_t hw_comp_enable; +}; + /*! @name Structure to define step counter/detector/activity configuration */ struct bmi2_step_config { @@ -1909,46 +1987,19 @@ struct bmi2_gyro_user_gain_config /*! @name Structure to define wake-up configuration */ struct bmi2_wake_up_config { - /*! Wake-up sensitivity for bmi261 */ + /*! Wake-up sensitivity */ uint16_t sensitivity; - /*! Tap feature for BMI261 + /*! * For Single tap, single_tap_en = 1 * For Double tap, single_tap_en = 0 */ uint16_t single_tap_en; - - /*! Enable -> Filtered tap data, Disable -> Unfiltered data */ - uint16_t data_reg_en; - - /*! Scaling factor of threshold */ - uint16_t tap_sens_thres; - - /*! Maximum duration between each taps */ - uint16_t max_gest_dur; - - /*! Minimum quite time between the two gesture detection */ - uint16_t quite_time_after_gest; - - /*! Wait time */ - uint16_t wait_for_timeout; - - /*! Axis selection */ - uint16_t axis_sel; }; /*! @name Structure to define tap configuration */ struct bmi2_tap_config { - /*! Tap sensitivity */ - uint16_t sensitivity; - - /*! Tap feature. - * For Single tap, single_tap_en = 1 - * For Double tap, single_tap_en = 0 - */ - uint16_t single_tap_en; - /*! Enable -> Filtered tap data, Disable -> Unfiltered data */ uint16_t data_reg_en; @@ -2034,7 +2085,7 @@ struct bmi2_flat_config /*! Hysteresis for theta flat detection */ uint16_t hysteresis; - /*! Holds the duration in 50Hz samples(20msec) */ + /*! Holds the duration */ uint16_t hold_time; }; @@ -2061,51 +2112,149 @@ struct bmi2_wrist_gest_config /*! @name Structure to define wrist wear wake-up configuration */ struct bmi2_wrist_wear_wake_up_config { - /*! Cosine of min expected attitude change of the device within 1 second time window when - * moving within focus position. - * The parameter is scaled by 2048 i.e. 2048 * cos(angle). Range is 1024 to 1774. - * Default is 1448. */ + /*! Cosine of minimum expected attitude change of the device + * within 1 second time window when moving within focus position. + * The parameter is scaled by 2048 i.e. 2048 * cos(angle). + * Range is 1024 to 1774. Default is 1448. + */ uint16_t min_angle_focus; - /*! Cosine of min expected attitude change of the device within 1 second time window when - * moving from non-focus to focus position. - * The parameter is scaled by 2048 i.e. 2048 * cos(angle). Range is 1448 to 1856. - * Default value is 1774. */ + /*! Cosine of minimum expected attitude change of the device + * within 1 second time window when moving from non-focus to focus position. + * The parameter is scaled by 2048 i.e. 2048 * cos(angle). + * Range is 1448 to 1856. Default value is 1774. + */ uint16_t min_angle_nonfocus; - /*! Sine of the max allowed downward tilt angle in landscape right direction of the device, - * when it is in focus position - * (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). Range is 700 to 1024. - * Default value is 1024. */ + /*! Sine of the maximum allowed downward tilt angle in + * landscape right direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). + * Range is 700 to 1024. Default value is 1024. + */ uint16_t max_tilt_lr; - /*! Sine of the max allowed downward tilt angle in landscape left direction of the device, - * when it is in focus position - * (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). Range is 700 to - * 1024. Default value is 700. */ + /*! Sine of the maximum allowed downward tilt angle in + * landscape left direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). + * Range is 700 to 1024. Default value is 700. + */ uint16_t max_tilt_ll; - /*! Sine of the max allowed backward tilt angle in portrait down direction of the device, - * when it is in focus position - * (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). Range is 0 to179. - * Default value is 179. */ + /*! Sine of the maximum allowed backward tilt angle in + * portrait down direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). + * Range is 0 to179. Default value is 179. + */ uint16_t max_tilt_pd; - /*! Sine of the maximum allowed forward tilt angle in portrait up direction of the - * device, when it is in focus position - * (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). Range is 1774 to 1978. - * Default value is 1925. */ + /*! Sine of the maximum allowed forward tilt angle in + * portrait up direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 2048 i.e. 2048 * sin(angle). + * Range is 1774 to 1978. Default value is 1925. + */ uint16_t max_tilt_pu; }; +/*! @name Structure to define wrist wear wake-up configuration for wearable configuration */ +struct bmi2_wrist_wear_wake_up_wh_config +{ + /*! Cosine of minimum expected attitude change of the device + * within 1 second time window when moving within focus position. + * The parameter is scaled by 2048 i.e. 2048 * cos(angle). + * Range is 1024 to 1774. Default is 1774. + */ + uint16_t min_angle_focus; + + /*! Cosine of minimum expected attitude change of the device + * within 1 second time window when moving from non-focus to focus position. + * The parameter is scaled by 2048 i.e. 2048 * cos(angle). + * Range is 1448 to 1856. Default value is 1522. + */ + uint16_t min_angle_nonfocus; + + /*! Sine of the maximum allowed tilt angle in + * landscape right direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). + * Range is 88 to 128. Default value is 128. + */ + uint8_t angle_landscape_right; + + /*! Sine of the maximum allowed tilt angle in + * landscape left direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). + * Range is 88 to 128. Default value is 128. + */ + uint8_t angle_landscape_left; + + /*! Sine of the maximum allowed backward tilt angle in + * portrait down direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). + * Range is 0 to179. Default value is 22. + */ + uint8_t angle_portrait_down; + + /*! Sine of the maximum allowed forward tilt angle in + * portrait up direction of the device, when it is in focus position + * (i.e. user is able to comfortably look at the dial of wear device). + * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). + * Range is 222 to 247. Default value is 241. + */ + uint8_t angle_portrait_up; + + /*! Minimum duration the arm should be moved while performing gesture. + * Range: 1 to 10, resolution = 20 ms + * Default 2(40 ms) + */ + uint8_t min_dur_moved; + + /*! Minimum duration the arm should be static between two consecutive gestures. + * Range: 1 to 10, resolution = 20 ms + * Default 2(40 ms) + */ + uint8_t min_dur_quite; +}; + +/*! @name Structure to define primary OIS configuration */ +struct bmi2_primary_ois_config +{ + /*! Low pass filter control */ + uint8_t lp_filter_enabled; + + /*! Lp filter cut-off frequency */ + uint8_t lp_filter_config; + + /*! Enable gyroscope on OIS interface in registers + * OIS_DATA_6 till OIS_DATA_11 with minimum group delay at 6.4KHz ODR + */ + uint8_t gyr_en; + + /*! Enable accelerometer on OIS interface in registers + * OIS_DATA_0 till OIS_DATA_5 with minimum group delay at 1.6KHz ODR + */ + uint8_t acc_en; +}; + +/*! @name Structure to configure free-fall detection settings */ +struct bmi2_free_fall_det_config +{ + /*! free-fall accel settings */ + uint16_t freefall_accel_settings[BMI2_FREE_FALL_ACCEL_SET_PARAMS]; +}; + /*! @name Structure to define wrist gesture configuration for wearable variant */ struct bmi2_wrist_gest_w_config { - /*! Wearable arm (left or right) */ + /*! Device in left (0) or right (1) arm. + * By default, the wearable device is assumed to be in left arm + * i.e. default value is 0. + */ uint8_t device_position; /*! Minimum threshold for flick peak on y-axis */ @@ -2140,75 +2289,94 @@ struct bmi2_wrist_gest_w_config uint16_t max_duration_jiggle_peaks; }; -/*! @name Structure to define wrist wear wake-up configuration for wearable configuration */ -struct bmi2_wrist_wear_wake_up_wh_config +/*! @name Structure to configure Laptop position recognition settings for bmi260lpd */ +struct bmi2_lpd_config { - /*! Cosine of min expected attitude change of the device within 1 second time window when - * moving within focus position. - * The parameter is scaled by 2048 i.e. 2048 * cos(angle). Range is 1024 to 1774. - * Default is 1448. */ - uint16_t min_angle_focus; + /*! Sets the bit for filtered data enable */ + uint8_t flit_data_enable; - /*! Cosine of min expected attitude change of the device within 1 second time window when - * moving from non-focus to focus position. - * The parameter is scaled by 2048 i.e. 2048 * cos(angle). Range is 1448 to 1856. - * Default value is 1774. */ - uint16_t min_angle_nonfocus; + /*! lpd enable bit */ + uint8_t lpd_enable; - /*! Sine of the max allowed downward tilt angle in landscape right direction of the device, - * when it is in focus position (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). Range is 88 to 128. - * Default value is 128. */ - uint8_t angle_lr; - - /*! Sine of the max allowed downward tilt angle in landscape left direction of the device, - * when it is in focus position (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). Range is 88 to 128. - * Default value is 128. */ - uint8_t angle_ll; - - /*! Sine of the max allowed backward tilt angle in portrait down direction of the device, - * when it is in focus position (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). Range is 0 to 179. - * Default value is 22. */ - uint8_t angle_pd; - - /*! Sine of the maximum allowed forward tilt angle in portrait up direction of the device, - * when it is in focus position (i.e. user is able to comfortably look at the dial of wear device). - * The configuration parameter is scaled by 256 i.e. 256 * sin(angle). Range is 222 to 247. - * Default value is 241. */ - uint8_t angle_pu; - - /*! Minimum duration the arm should be moved while performing gesture. Range: 1 to 10, - * resolution = 20 ms. - * Default 2(40 ms)*/ - uint8_t min_dur_mov; - - /*! Minimum duration the arm should be static between two consecutive gestures. Range: 1 to - * 10, resolution = 20 ms - * Default 2(40 ms)*/ - uint8_t min_dur_quite; -}; + /*! Sets angle for portrait oriented in bag cases */ + uint8_t portrait_theta; -/*! @name Structure to define primary OIS configuration */ -struct bmi2_primary_ois_config -{ - uint8_t lp_filter_enable; + /*! Sets Hysteresis for portrait oriented in bag theta detection */ + uint8_t portrait_hysteresis; - uint8_t lp_filter_config; + /*! Sets angle for landscape oriented in bag cases */ + uint8_t landscape_theta; + + /*! Sets Hysteresis for landscape oriented in bag theta detection */ + uint8_t landscape_hysteresis; + + /*! Sets angle for flat oriented in bag cases */ + uint8_t flat_posture_theta; + + /*! Sets Hysteresis for landscape oriented in bag theta detection */ + uint8_t flat_posture_hysteresis; - uint8_t primary_ois_reserved; + /*! Sets blocking mode, if blocking mode is set no interrupt will be triggered */ + uint8_t blocking_mode; - uint8_t primary_ois_gyro_en; + /*! Sets the hold time for which the condition has to be respected */ + uint8_t hold_time; - uint8_t primary_ois_accel_en; + /*! Sets threshold slope for block mode conditions */ + uint8_t blockingslope_thres; + + /*! Segment size for which the predictors are computed on */ + uint16_t segment_size; + + /* Post processing enable for the lap status detected */ + uint16_t post_processing_enable; + + /* Minimum threshold of the Gini's diversity index for accepting position */ + uint16_t mingdithreshold_acc; + + /* Minimum threshold of the Gini's diversity index for rejecting position */ + uint16_t mingdithreshold_rej; + + /* Buffer size for the post processing of the position detected */ + uint16_t output_buffersize; + + /* Minimum segments classified with moderate confidence as belonging to certain position */ + uint16_t minseg_moderateconf; }; -/*! @name Structure to configure free-fall detection settings */ -struct bmi2_free_fall_det_config +/*! @name Structure to configure wrist gesture configuration */ +struct bmi2_wrist_gesture_config { - /*! free-fall accel settings */ - uint16_t freefall_accel_settings[BMI2_FREE_FALL_ACCEL_SET_PARAMS]; + /* Minimum threshold for flick peak on y-axis */ + uint16_t min_flick_peak_y_threshold; + + /* Minimum threshold for flick peak on z-axis */ + uint16_t min_flick_peak_z_threshold; + + /* Maximum expected value of positive gravitational acceleration on x-axis when arm is in focus pose */ + uint16_t gravity_bounds_x_pos; + + /* Maximum expected value of negative gravitational acceleration on x-axis when arm is in focus pose */ + uint16_t gravity_bounds_x_neg; + + /* Maximum expected value of negaitive gravitational acceleration on y-axis when arm is in focus pose */ + uint16_t gravity_bounds_y_neg; + + /* Maximum expected value of negaitive gravitational acceleration on z-axis when arm is in focus pose */ + uint16_t gravity_bounds_z_neg; + + /* Exponential smoothing coefficient for adaptive peak threshold decay */ + uint16_t flick_peak_decay_coeff; + + /* Exponential smoothing coefficient for acceleration mean estimation */ + uint16_t lp_mean_filter_coeff; + + /* Maximum duration between 2 peaks of jiggle in samples */ + uint16_t max_duration_jiggle_peaks; + + /* Device in left (0) or right (1) arm. By default, the wearable device is assumed to be in left arm i.e. default + * value is 0. */ + uint16_t device_position; }; /*! @name Union to define the sensor configurations */ @@ -2232,6 +2400,9 @@ union bmi2_sens_config_types /*! Sig_motion configuration */ struct bmi2_sig_motion_config sig_motion; + /*! EXT TCO configuration */ + struct bmi2_ext_tco ext_tco; + /*! Step counter parameter configuration */ uint16_t step_counter_params[BMI2_STEP_CNT_N_PARAMS]; @@ -2242,7 +2413,7 @@ union bmi2_sens_config_types struct bmi2_gyro_user_gain_config gyro_gain_update; /*! Wake-up configuration */ - struct bmi2_wake_up_config tap; + struct bmi2_wake_up_config wake_up_conf; /*! Tap configuration */ struct bmi2_tap_config tap_conf; @@ -2276,6 +2447,12 @@ union bmi2_sens_config_types /* Free-fall detection configurations */ struct bmi2_free_fall_det_config free_fall_det; + + /* Laptop position detection configurations */ + struct bmi2_lpd_config lap_pos_det; + + /* Structure to configure wrist gesture configurations */ + struct bmi2_wrist_gesture_config wrist_g_config; }; /*! @name Structure to define the type of the sensor and its configurations */ @@ -2434,20 +2611,26 @@ struct bmi2_accel_foc_g_value /*! @name Structure to configure activity recognition settings */ struct bmi2_act_recg_sett { - /*! Activity recognition register 1 */ - uint8_t act_rec_1 : 1; + /*! Enable/Disable post processing of the activity detected by the classifier */ + uint8_t pp_en; - /*! Activity recognition register 2 */ - uint16_t act_rec_2; + /*! Minimum threshold of the Gini's diversity index (GDI) for + * accepting and adding activity detected by the classifier to activity buffer + */ + uint16_t min_gdi_thres; - /*! Activity recognition register 3 */ - uint16_t act_rec_3; + /*! Maximum threshold of the Gini's diversity index (GDI) for + * rejecting the activity detected by the classifier + */ + uint16_t max_gdi_thres; - /*! Activity recognition register 4 */ - uint8_t act_rec_4 : 4; + /*! Buffer size for post processing of the activity detected by the classifier */ + uint8_t buf_size; - /*! Activity recognition register 5 */ - uint8_t act_rec_5 : 4; + /*! Minimum segments classified with moderate confidence as belonging + * to a certain activity type to be added to activity buffer. + */ + uint8_t min_seg_conf; }; /*! @name Structure to configure activity recognition settings for bmi270hc */ diff --git a/examples/bmi270/read_aux_data_mode/read_aux_data_mode.c b/examples/bmi270/read_aux_data_mode/read_aux_data_mode.c deleted file mode 100644 index a542f97..0000000 --- a/examples/bmi270/read_aux_data_mode/read_aux_data_mode.c +++ /dev/null @@ -1,327 +0,0 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -/******************************************************************************/ -/*! Header Files */ -#include -#include "bmi270.h" -#include "bmm150.h" -#include "coines.h" -#include "common.h" - -/******************************************************************************/ -/*! Macro definition */ - -/*! Macros to select the sensors */ -#define ACCEL UINT8_C(0x00) -#define GYRO UINT8_C(0x01) -#define AUX UINT8_C(0x02) - -/*! Earth's gravity in m/s^2 */ -#define GRAVITY_EARTH (9.80665f) - -/*****************************************************************************/ -/*! Structure declaration */ - -/* Sensor initialization configuration. */ -struct bmi2_dev bmi2_dev; - -/*******************************************************************************/ -/*! Functions */ - -/** - * user_aux_read - Reads data from auxiliary sensor in manual mode. - * - * @param[in] reg_addr : Register address. - * @param[out] aux_data : Aux data pointer to store the read data. - * @param[in] length : No of bytes to read. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -static int8_t user_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint32_t len, void *intf_ptr); - -/** - * user_aux_write - Writes data to the auxiliary sensor in manual mode. - * - * @param[in] reg_addr : Register address. - * @param[out] aux_data : Aux data pointer to store the data being written. - * @param[in] length : No of bytes to read. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -static int8_t user_aux_write(uint8_t reg_addr, const uint8_t *aux_data, uint32_t len, void *intf_ptr); - -/*! - * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the - * APIs. - * - * @param[in] period_us : The required wait time in microsecond. - * @param[in] intf_ptr : Interface pointer - * - * @return void. - */ -static void user_delay_us(uint32_t period, void *intf_ptr); - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - * - * @param[in] val : LSB from each axis. - * @param[in] g_range : Gravity range. - * @param[in] bit_width : Resolution for accel. - * - * @return Gravity. - */ -static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - * - * @param[in] val : LSB from each axis. - * @param[in] dps : Degree per second. - * @param[in] bit_width : Resolution for gyro. - * - * @return Degree per second. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); - -/* This function starts the execution of program. */ -int main(void) -{ - /* Status of api are returned to this variable. */ - int8_t rslt; - - /* Variable to select the pull-up resistor which is set to trim register */ - uint8_t regdata; - - /* Variable to define limit to print aux data. */ - uint8_t limit = 20; - - /* Accel, Gyro and Aux sensors are listed in array. */ - uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; - - /* Structure to define the type of the sensor and its configurations. */ - struct bmi2_sens_config config[3]; - - /* Sensor initialization configuration. */ - struct bmm150_dev bmm150_dev; - - /* bmm150 settings configuration */ - struct bmm150_settings settings; - - /* bmm150 magnetometer data */ - struct bmm150_mag_data mag_data; - - /* Structure to define type of sensor and their respective data. */ - struct bmi2_sensor_data sensor_data[3]; - - /* Variables to define read the accel and gyro data in float */ - float x = 0, y = 0, z = 0; - - config[ACCEL].type = BMI2_ACCEL; - config[GYRO].type = BMI2_GYRO; - config[AUX].type = BMI2_AUX; - - /* To enable the i2c interface settings for bmm150. */ - uint8_t bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; - bmm150_dev.intf_ptr = &bmm150_dev_addr; - bmm150_dev.read = user_aux_read; - bmm150_dev.write = user_aux_write; - bmm150_dev.delay_us = user_delay_us; - - /* As per datasheet, aux interface with bmi270 will support only for I2C */ - bmm150_dev.intf = BMM150_I2C_INTF; - - sensor_data[ACCEL].type = BMI2_ACCEL; - sensor_data[GYRO].type = BMI2_GYRO; - sensor_data[AUX].type = BMI2_AUX; - - /* Interface reference is given as a parameter - * For I2C : BMI2_I2C_INTF - * For SPI : BMI2_SPI_INTF - */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); - bmi2_error_codes_print_result(rslt); - - /* Initialize bmi270. */ - rslt = bmi270_init(&bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Pull-up resistor 2k is set to the trim regiter */ - regdata = BMI2_ASDA_PUPSEL_2K; - rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Enable the accel, gyro and aux sensor. */ - rslt = bmi270_sensor_enable(sensor_list, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Get default configurations for the type of feature selected. */ - rslt = bmi270_get_sensor_config(config, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Configurations for accel. */ - config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; - config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; - config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; - config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; - - /* Configurations for gyro. */ - config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; - config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; - config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; - config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; - config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; - config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; - - /* Configurations for aux. */ - config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; - config[AUX].cfg.aux.aux_en = BMI2_ENABLE; - config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; - config[AUX].cfg.aux.manual_en = BMI2_ENABLE; - config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; - config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; - config[AUX].cfg.aux.read_addr = BMM150_REG_DATA_X_LSB; - - /* Set new configurations for accel, gyro and aux. */ - rslt = bmi270_set_sensor_config(config, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Initialize bmm150. */ - rslt = bmm150_init(&bmm150_dev); - bmi2_error_codes_print_result(rslt); - - /* Set the power mode to normal mode. */ - settings.pwr_mode = BMM150_POWERMODE_NORMAL; - rslt = bmm150_set_op_mode(&settings, &bmm150_dev); - bmi2_error_codes_print_result(rslt); - - rslt = bmi270_get_sensor_config(config, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Disable manual mode so that the data mode is enabled. */ - config[AUX].cfg.aux.manual_en = BMI2_DISABLE; - - /* Set the aux configurations. */ - rslt = bmi270_set_sensor_config(config, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - printf("MAGNETOMETER, ACCEL, AND GYRO DATA IN DATA MODE\n"); - - if (bmm150_dev.chip_id == BMM150_CHIP_ID) - { - while (limit--) - { - /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ - bmi2_dev.delay_us(50000, bmi2_dev.intf_ptr); - - rslt = bmi270_get_sensor_data(sensor_data, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - if (rslt == BMI2_OK) - { - printf("\nAcc_x = %d\t", sensor_data[ACCEL].sens_data.acc.x); - printf("Acc_y = %d\t", sensor_data[ACCEL].sens_data.acc.y); - printf("Acc_z = %d", sensor_data[ACCEL].sens_data.acc.z); - - /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.z, 2, bmi2_dev.resolution); - - /* Print the data in m/s2. */ - printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); - - printf("\nGyr_X = %d\t", sensor_data[GYRO].sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data[GYRO].sens_data.gyr.y); - printf("Gyr_Z= %d", sensor_data[GYRO].sens_data.gyr.z); - - /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.z, 2000, bmi2_dev.resolution); - - /* Print the data in dps. */ - printf("\nGyro_DPS_X = %4.2f, Gyro_DPS_Y = %4.2f, Gyro_DPS_Z = %4.2f\n", x, y, z); - - /* Compensating the raw auxiliary data available from the BMM150 API. */ - rslt = bmm150_aux_mag_data(sensor_data[AUX].sens_data.aux_data, &mag_data, &bmm150_dev); - bmi2_error_codes_print_result(rslt); - printf("\nMag_x_axis = %d \t Mag_y_axis = %d \t Mag_z_axis = %d \t\n", - mag_data.x, - mag_data.y, - mag_data.z); - } - } - } - - bmi2_coines_deinit(); - - return rslt; -} - -/*! - * @brief This function reads the data from auxiliary sensor in manual mode. - */ -static int8_t user_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt; - - /* Discarding the parameter id as it is redundant */ - rslt = bmi2_read_aux_man_mode(reg_addr, aux_data, len, &bmi2_dev); - - return rslt; -} - -/*! - * @brief This function writes the data to auxiliary sensor in manual mode. - */ -static int8_t user_aux_write(uint8_t reg_addr, const uint8_t *aux_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt; - - /* Discarding the parameter id as it is redundant */ - rslt = bmi2_write_aux_man_mode(reg_addr, aux_data, len, &bmi2_dev); - - return rslt; -} - -/*! - * Delay function map to COINES platform - */ -static void user_delay_us(uint32_t period, void *intf_ptr) -{ - coines_delay_usec(period); -} - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - */ -static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) -{ - float half_scale = ((float)(1 << bit_width) / 2.0f); - - return (GRAVITY_EARTH * val * g_range) / half_scale; -} - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) -{ - float half_scale = ((float)(1 << bit_width) / 2.0f); - - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); -} diff --git a/examples/bmi270/read_aux_manual_mode/read_aux_manual_mode.c b/examples/bmi270/read_aux_manual_mode/read_aux_manual_mode.c deleted file mode 100644 index ced8f59..0000000 --- a/examples/bmi270/read_aux_manual_mode/read_aux_manual_mode.c +++ /dev/null @@ -1,322 +0,0 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -/******************************************************************************/ -/*! Header Files */ -#include -#include "bmi270.h" -#include "bmm150.h" -#include "coines.h" -#include "common.h" - -/******************************************************************************/ -/*! Macro definition */ - -/*! Macros to select the sensors */ -#define ACCEL UINT8_C(0x00) -#define GYRO UINT8_C(0x01) -#define AUX UINT8_C(0x02) - -/*! Earth's gravity in m/s^2 */ -#define GRAVITY_EARTH (9.80665f) - -/*****************************************************************************/ -/*! Structure declaration */ - -/* Sensor initialization configuration. */ -struct bmi2_dev bmi2_dev; - -/******************************************************************************/ -/*! Functions */ - -/** - * user_aux_read - Reads data from auxiliary sensor in manual mode. - * - * @param[in] reg_addr : Register address. - * @param[out] aux_data : Aux data pointer to store the read data. - * @param[in] length : No of bytes to read. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -static int8_t user_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint32_t len, void *intf_ptr); - -/** - * user_aux_write - Writes data to the auxiliary sensor in manual mode. - * - * @param[in] reg_addr : Register address. - * @param[out] aux_data : Aux data pointer to store the data being written. - * @param[in] length : No of bytes to read. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -static int8_t user_aux_write(uint8_t reg_addr, const uint8_t *aux_data, uint32_t len, void *intf_ptr); - -/*! - * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the - * APIs. - * - * @param[in] period_us : The required wait time in microsecond. - * @param[in] intf_ptr : Interface pointer - * - * @return void. - */ -static void user_delay_us(uint32_t period, void *intf_ptr); - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - * - * @param[in] val : LSB from each axis. - * @param[in] g_range : Gravity range. - * @param[in] bit_width : Resolution for accel. - * - * @return Gravity. - */ -static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width); - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - * - * @param[in] val : LSB from each axis. - * @param[in] dps : Degree per second. - * @param[in] bit_width : Resolution for gyro. - * - * @return Degree per second. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); - -/* This function starts the execution of program. */ -int main(void) -{ - /* Status of api are returned to this variable. */ - int8_t rslt; - - /* Variable to select the pull-up resistor which is set to trim register */ - uint8_t regdata; - - /* Variable to define limit to print aux data. */ - uint8_t limit = 20; - - /* Accel, Gyro and Aux sensors are listed in array. */ - uint8_t sensor_list[3] = { BMI2_ACCEL, BMI2_GYRO, BMI2_AUX }; - - /* Sensor initialization configuration. */ - struct bmm150_dev bmm150_dev; - - /* bmm150 settings configuration */ - struct bmm150_settings settings; - - /* bmm150 magnetometer data */ - struct bmm150_mag_data mag_data; - - /* Structure to define the type of the sensor and its configurations. */ - struct bmi2_sens_config config[3]; - - /* Structure to define type of sensor and their respective data. */ - struct bmi2_sensor_data sensor_data[2]; - - /* Variables to define read the accel and gyro data in float */ - float x = 0, y = 0, z = 0; - - config[ACCEL].type = BMI2_ACCEL; - config[GYRO].type = BMI2_GYRO; - config[AUX].type = BMI2_AUX; - - sensor_data[ACCEL].type = BMI2_ACCEL; - sensor_data[GYRO].type = BMI2_GYRO; - - /* Array of eight bytes to store x, y, z and r axis aux data. */ - uint8_t aux_data[8] = { 0 }; - - /* To enable the i2c interface settings for bmm150. */ - uint8_t bmm150_dev_addr = BMM150_DEFAULT_I2C_ADDRESS; - bmm150_dev.intf_ptr = &bmm150_dev_addr; - bmm150_dev.read = user_aux_read; - bmm150_dev.write = user_aux_write; - bmm150_dev.delay_us = user_delay_us; - - /* As per datasheet, aux interface with bmi270 will support only for I2C */ - bmm150_dev.intf = BMM150_I2C_INTF; - - /* Interface reference is given as a parameter - * For I2C : BMI2_I2C_INTF - * For SPI : BMI2_SPI_INTF - */ - rslt = bmi2_interface_init(&bmi2_dev, BMI2_I2C_INTF); - bmi2_error_codes_print_result(rslt); - - /* Initialize bmi270. */ - rslt = bmi270_init(&bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Pull-up resistor 2k is set to the trim register */ - regdata = BMI2_ASDA_PUPSEL_2K; - rslt = bmi2_set_regs(BMI2_AUX_IF_TRIM, ®data, 1, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Enable the accel, gyro and aux sensor. */ - rslt = bmi270_sensor_enable(sensor_list, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Get default configurations for the type of feature selected. */ - rslt = bmi270_get_sensor_config(config, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Configurations for accel. */ - config[ACCEL].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; - config[ACCEL].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; - config[ACCEL].cfg.acc.odr = BMI2_ACC_ODR_100HZ; - config[ACCEL].cfg.acc.range = BMI2_ACC_RANGE_2G; - - /* Configurations for gyro. */ - config[GYRO].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; - config[GYRO].cfg.gyr.noise_perf = BMI2_GYR_RANGE_2000; - config[GYRO].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; - config[GYRO].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; - config[GYRO].cfg.gyr.range = BMI2_GYR_RANGE_2000; - config[GYRO].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; - - /* Configurations for aux. */ - config[AUX].cfg.aux.odr = BMI2_AUX_ODR_100HZ; - config[AUX].cfg.aux.aux_en = BMI2_ENABLE; - config[AUX].cfg.aux.i2c_device_addr = BMM150_DEFAULT_I2C_ADDRESS; - config[AUX].cfg.aux.manual_en = BMI2_ENABLE; - config[AUX].cfg.aux.fcu_write_en = BMI2_ENABLE; - config[AUX].cfg.aux.man_rd_burst = BMI2_AUX_READ_LEN_3; - - /* Set new configurations for accel, gyro and aux. */ - rslt = bmi270_set_sensor_config(config, 3, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - /* Initialize bmm150. */ - rslt = bmm150_init(&bmm150_dev); - bmi2_error_codes_print_result(rslt); - - /* Set the power mode to normal mode. */ - settings.pwr_mode = BMM150_POWERMODE_NORMAL; - rslt = bmm150_set_op_mode(&settings, &bmm150_dev); - bmi2_error_codes_print_result(rslt); - - printf("MAGNETOMETER, ACCEL AND GYRO DATA IN MANUAL MODE\n"); - - if (bmm150_dev.chip_id == BMM150_CHIP_ID) - { - while (limit--) - { - /* Delay has been added to get aux, accel and gyro data at the interval of every 0.05 second. */ - bmi2_dev.delay_us(50000, bmi2_dev.intf_ptr); - - rslt = bmi270_get_sensor_data(sensor_data, 2, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - - if (rslt == BMI2_OK) - { - printf("\nAcc_x = %d\t", sensor_data[ACCEL].sens_data.acc.x); - printf("Acc_y = %d\t", sensor_data[ACCEL].sens_data.acc.y); - printf("Acc_z = %d", sensor_data[ACCEL].sens_data.acc.z); - - /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.x, 2, bmi2_dev.resolution); - y = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.y, 2, bmi2_dev.resolution); - z = lsb_to_mps2(sensor_data[ACCEL].sens_data.acc.z, 2, bmi2_dev.resolution); - - /* Print the data in m/s2. */ - printf("\nAcc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); - - printf("\nGyr_X = %d\t", sensor_data[GYRO].sens_data.gyr.x); - printf("Gyr_Y = %d\t", sensor_data[GYRO].sens_data.gyr.y); - printf("Gyr_Z = %d", sensor_data[GYRO].sens_data.gyr.z); - - /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.x, 2000, bmi2_dev.resolution); - y = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.y, 2000, bmi2_dev.resolution); - z = lsb_to_dps(sensor_data[GYRO].sens_data.gyr.z, 2000, bmi2_dev.resolution); - - /* Print the data in dps. */ - printf("\nGyro_DPS_X = %4.2f, Gyro_DPS_Y = %4.2f, Gyro_DPS_Z = %4.2f\n", x, y, z); - } - - /* Read aux data from the bmm150 data registers. */ - rslt = bmi2_read_aux_man_mode(BMM150_REG_DATA_X_LSB, aux_data, 8, &bmi2_dev); - bmi2_error_codes_print_result(rslt); - if (rslt == BMI2_OK) - { - /* Compensating the raw auxiliary data available from the BMM150 API. */ - rslt = bmm150_aux_mag_data(aux_data, &mag_data, &bmm150_dev); - bmi2_error_codes_print_result(rslt); - printf("Mag_x_axis = %d \t Mag_y_axis = %d \t Mag_z_axis = %d \t\n", mag_data.x, mag_data.y, - mag_data.z); - } - } - } - - bmi2_coines_deinit(); - - return rslt; -} - -/*! - * @brief This function reads the data from auxiliary sensor in manual mode. - */ -int8_t user_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt; - - /* Discarding the parameter id as it is redundant */ - rslt = bmi2_read_aux_man_mode(reg_addr, aux_data, len, &bmi2_dev); - - return rslt; -} - -/*! - * @brief This function writes the data to auxiliary sensor in manual mode. - */ -int8_t user_aux_write(uint8_t reg_addr, const uint8_t *aux_data, uint32_t len, void *intf_ptr) -{ - int8_t rslt; - - /* Discarding the parameter id as it is redundant */ - rslt = bmi2_write_aux_man_mode(reg_addr, aux_data, len, &bmi2_dev); - - return rslt; -} - -/*! - * Delay function map to COINES platform - */ -static void user_delay_us(uint32_t period, void *intf_ptr) -{ - coines_delay_usec(period); -} - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - */ -static float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width) -{ - float half_scale = ((float)(1 << bit_width) / 2.0f); - - return (GRAVITY_EARTH * val * g_range) / half_scale; -} - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) -{ - float half_scale = ((float)(1 << bit_width) / 2.0f); - - return (dps / ((half_scale) + BMI2_GYR_RANGE_2000)) * (val); -} diff --git a/examples/bmi2_ois/common/common.c b/examples/bmi2_ois/common/common.c deleted file mode 100644 index 1a43947..0000000 --- a/examples/bmi2_ois/common/common.c +++ /dev/null @@ -1,153 +0,0 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -/******************************************************************************/ -#include -#include -#include - -#include "coines.h" -#include "common.h" - -/******************************************************************************/ -/*! Global declaration */ - -/*! Device address for primary and secondary interface */ -static uint8_t ois_dev_addr; - -/******************************************************************************/ -/*! Functions */ - -/*! - * SPI read function map to COINES platform - */ -int8_t bmi2_ois_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) -{ - uint8_t dev_addr = *(uint8_t*)intf_ptr; - - return coines_read_spi(dev_addr, reg_addr, reg_data, (uint16_t)len); -} - -/*! - * SPI write function map to COINES platform - */ -int8_t bmi2_ois_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) -{ - uint8_t dev_addr = *(uint8_t*)intf_ptr; - - return coines_write_spi(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); -} - -/*! - * Delay function map to COINES platform - */ -void bmi2_ois_delay_us(uint32_t period, void *intf_ptr) -{ - coines_delay_usec(period); -} - -/******************************************************************************/ -int8_t bmi2_ois_init(struct bmi2_ois_dev *ois_dev) -{ - int8_t rslt; - - if (ois_dev != NULL) - { - int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB); - if (result < COINES_SUCCESS) - { - printf( - "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" - " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); - exit(result); - } - - coines_set_shuttleboard_vdd_vddio_config(0, 0); - coines_delay_msec(100); - - printf("SPI Interface \n"); - - /* To initialize the user SPI function */ - ois_dev_addr = COINES_SHUTTLE_PIN_8; /*COINES_SHUTTLE_PIN_7 */ - ois_dev->ois_read = bmi2_ois_spi_read; - ois_dev->ois_write = bmi2_ois_spi_write; - - /* Assign device address to interface pointer */ - ois_dev->intf_ptr = &ois_dev_addr; - - /* Configure delay in microseconds */ - ois_dev->ois_delay_us = bmi2_ois_delay_us; - - /* SDO pin is made low for selecting I2C address 0x76*/ - coines_set_pin_config(COINES_SHUTTLE_PIN_8, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); - - /* coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); */ - coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_7_5_MHZ, COINES_SPI_MODE0); - coines_delay_msec(10); - - /* PS pin is made high for selecting I2C protocol (gyroscope)*/ - coines_set_pin_config(COINES_SHUTTLE_PIN_9, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); - - coines_delay_usec(10000); - - coines_set_shuttleboard_vdd_vddio_config(3300, 3300); - - coines_delay_usec(10000); - - } - else - { - rslt = BMI2_OIS_E_NULL_PTR; - } - - return rslt; -} - -/******************************************************************************/ - -/*! - * @brief This internal API prints the execution status - */ -void bmi2_ois_error_codes_print_result(const char api_name[], int8_t rslt) -{ - if (rslt != BMI2_OIS_OK) - { - printf("%s\t", api_name); - - if (rslt == BMI2_OIS_E_NULL_PTR) - { - printf("Error [%d] : Null pointer error.\r\n", rslt); - printf( - "It occurs when the user tries to assign value (not address) to a pointer, which has been initialized to NULL.\r\n"); - } - else if (rslt == BMI2_OIS_E_COM_FAIL) - { - printf("Error [%d] : Communication failure error.\r\n", rslt); - printf( - "It occurs due to read/write operation failure and also due to power failure during communication\r\n"); - } - else if (rslt == BMI2_OIS_E_INVALID_SENSOR) - { - printf( - "Error [%d] : Invalid sensor error. It occurs when there is a mismatch in the requested feature with the available one\r\n", - rslt); - } - else - { - printf("Error [%d] : Unknown error code\r\n", rslt); - } - } -} - -/*! - * @brief Deinitializes coines platform - * - * @return void. - */ -void bmi2_ois_coines_deinit(void) -{ - coines_close_comm_intf(COINES_COMM_INTF_USB); -} diff --git a/examples/bmi2_ois/common/common.h b/examples/bmi2_ois/common/common.h deleted file mode 100644 index 82a843b..0000000 --- a/examples/bmi2_ois/common/common.h +++ /dev/null @@ -1,92 +0,0 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -#ifndef _COMMON_H -#define _COMMON_H - -/*! CPP guard */ -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "bmi2_ois.h" - -/*! - * @brief Function for reading the sensor's registers through SPI bus. - * - * @param[in] reg_addr : Register address. - * @param[out] reg_data : Pointer to the data buffer to store the read data. - * @param[in] length : No of bytes to read. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval = BMI2_INTF_RET_SUCCESS -> Success - * @retval != BMI2_INTF_RET_SUCCESS -> Failure Info - * - */ -int8_t bmi2_ois_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); - -/*! - * @brief Function for writing the sensor's registers through SPI bus. - * - * @param[in] reg_addr : Register address. - * @param[in] reg_data : Pointer to the data buffer whose data has to be written. - * @param[in] length : No of bytes to write. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval = BMI2_INTF_RET_SUCCESS -> Success - * @retval != BMI2_INTF_RET_SUCCESS -> Failure Info - * - */ -int8_t bmi2_ois_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); - -/*! - * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the - * APIs. - * - * @param[in] period_us : The required wait time in microsecond. - * @param[in] intf_ptr : Interface pointer - * - * @return void. - * - */ -void bmi2_ois_delay_us(uint32_t period, void *intf_ptr); - -/*! - * @brief Function to initialize device structure and coines platform - * - * @param[in] bma : Structure instance of bmi2_dev - * - * @return Status of execution - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -int8_t bmi2_ois_init(struct bmi2_ois_dev *ois_dev); - -/*! - * @brief Prints the execution status of the APIs. - * - * @param[in] api_name : API name with return status - * @param[in] rslt : Error code returned by the API whose execution status has to be printed. - * - * @return void. - */ -void bmi2_ois_error_codes_print_result(const char api_name[], int8_t rslt); - -/*! - * @brief Deinitializes coines platform - * - * @return void. - */ -void bmi2_ois_coines_deinit(void); - -#ifdef __cplusplus -} -#endif /* End of CPP guard */ - -#endif /* End _COMMON_H */ diff --git a/examples/bmi2_ois/ois_accel_gyro/Makefile b/examples/bmi2_ois/ois_accel_gyro/Makefile deleted file mode 100644 index 65cd946..0000000 --- a/examples/bmi2_ois/ois_accel_gyro/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -COINES_INSTALL_PATH ?= ../../../.. - -EXAMPLE_FILE ?= ois_accel_gyro.c - -API_LOCATION ?= ../.. - -COMMON_LOCATION ?= .. - -C_SRCS += \ -$(API_LOCATION)/bmi2.c \ -$(API_LOCATION)/bmi2_ois.c \ -$(COMMON_LOCATION)/common.c - -INCLUDEPATHS += \ -$(API_LOCATION) \ -$(COMMON_LOCATION)/common - -include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/bmi2_ois/ois_accel_gyro/ois_accel_gyro.c b/examples/bmi2_ois/ois_accel_gyro/ois_accel_gyro.c deleted file mode 100644 index bdb9d8f..0000000 --- a/examples/bmi2_ois/ois_accel_gyro/ois_accel_gyro.c +++ /dev/null @@ -1,118 +0,0 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -/******************************************************************************/ -#include - -#include "bmi2_ois.h" -#include "bmi2_ois_common.h" - -/******************************************************************************/ -/*! Macro definition */ - -/*! Macro that holds the total number of accel x,y and z axes sample counts to be printed */ -#define ACCEL_GYRO_SAMPLE_COUNT UINT8_C(50) - -/******************************************************************************/ -/*! Functions */ - -int main(void) -{ - int8_t rslt; - - struct bmi2_ois_dev ois_dev; - - int8_t idx; - - /* To store the gyroscope cross sensitivity value */ - int16_t ois_gyr_cross_sens_zx = 0; - - /* Array to enable sensor through OIS interface */ - uint8_t sens_sel[2] = { BMI2_OIS_ACCEL, BMI2_OIS_GYRO }; - - /* Variable that holds the accel and gyro sample count */ - uint8_t n_data = ACCEL_GYRO_SAMPLE_COUNT; - - /* Initialize the device structure */ - rslt = bmi2_ois_init(&ois_dev); - bmi2_ois_error_codes_print_result("bmi2_ois_init", rslt); - - /* Get configurations for OIS */ - rslt = bmi2_ois_get_config(&ois_dev); - bmi2_ois_error_codes_print_result("bmi2_ois_get_config", rslt); - - /* OIS configurations */ - ois_dev.acc_en = BMI2_OIS_ENABLE; - ois_dev.gyr_en = BMI2_OIS_ENABLE; - ois_dev.lp_filter_en = BMI2_OIS_ENABLE; - - /* Set configurations for OIS */ - rslt = bmi2_ois_set_config(&ois_dev); - bmi2_ois_error_codes_print_result("bmi2_ois_set_config", rslt); - - /* Get configurations for OIS */ - rslt = bmi2_ois_get_config(&ois_dev); - bmi2_ois_error_codes_print_result("bmi2_ois_get_config", rslt); - - if (rslt == BMI2_OIS_OK) - { - for (idx = 0; idx < n_data; idx++) - { - ois_dev.ois_delay_us(156, ois_dev.intf_ptr); - - /* Accel ODR is 1600hz and gyro ODR is 6400hz.Delay required for - * accel 156us and 625us for gyro. - * taken modules from accel and gyro ODR which results every 4th sample accel and gyro - * read happens, rest of three samples gyro data alone will be read */ - if (idx % 4 == 0) - { - /* Get OIS accelerometer and gyro data through OIS interface - * @note for sensor which support gyro cross axes sensitivity pass the - * gyr_cross_sens_zx from the bmi2_dev structure */ - rslt = bmi2_ois_read_data(sens_sel, 2, &ois_dev, ois_gyr_cross_sens_zx); - bmi2_ois_error_codes_print_result("bmi2_ois_read_data", rslt); - - if (rslt == BMI2_OIS_OK) - { - printf("\n"); - - /* Print accelerometer data */ - printf("OIS Accel x-axis = %d ", ois_dev.acc_data.x); - printf("OIS Accel y-axis = %d ", ois_dev.acc_data.y); - printf("OIS Accel z-axis = %d \n", ois_dev.acc_data.z); - - /* Print gyro data */ - printf("OIS Gyro x-axis = %d ", ois_dev.gyr_data.x); - printf("OIS Gyro y-axis = %d ", ois_dev.gyr_data.y); - printf("OIS Gyro z-axis = %d \n", ois_dev.gyr_data.z); - - printf("\n"); - } - } - else - { - /* Get OIS gyro data through OIS interface - * @note for sensor which support gyro cross axes sensitivity pass the - * gyr_cross_sens_zx from the bmi2_dev structure */ - rslt = bmi2_ois_read_data(&sens_sel[1], 1, &ois_dev, ois_gyr_cross_sens_zx); - bmi2_ois_error_codes_print_result("bmi2_ois_read_data", rslt); - if (rslt == BMI2_OIS_OK) - { - /* Print gyro data */ - printf("OIS Gyro x-axis = %d ", ois_dev.gyr_data.x); - printf("OIS Gyro y-axis = %d ", ois_dev.gyr_data.y); - printf("OIS Gyro z-axis = %d ", ois_dev.gyr_data.z); - - printf("\n"); - } - } - } - } - - bmi2_ois_coines_deinit(); - - return rslt; -}