2006 lines
61 KiB
C
2006 lines
61 KiB
C
/**
|
|
* 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 bmp5.c
|
|
* @date 2021-08-27
|
|
* @version v1.0.5
|
|
*
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
|
|
/*! Header files
|
|
****************************************************************************/
|
|
#include "bmp5.h"
|
|
|
|
/***************************************************************************/
|
|
|
|
/*! Global Variable
|
|
****************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
/*! Local Function Prototypes
|
|
******************************************************************************/
|
|
|
|
/*!
|
|
* @brief This internal API is used to validate the device pointer for
|
|
* null conditions.
|
|
*
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t null_ptr_check(const struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to validate the chip id of the sensor.
|
|
*
|
|
* @param[in] chip_id : Variable that hold the chip id from register.
|
|
* @param[in,out] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t validate_chip_id(uint8_t chip_id, struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to validate the post power-up procedure.
|
|
*
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t power_up_check(struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to check if sensor is in deepstandby mode.
|
|
*
|
|
* @param[out] powermode : To store whether sensor is in deepstanby mode.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t check_deepstandby_mode(enum bmp5_powermode* powermode,
|
|
struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to set sensor in deep standby powermode.
|
|
*
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_deep_standby_mode(struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to set sensor in standby or
|
|
* normal or forced or continous powermode.
|
|
*
|
|
* @param[in] powermode : Select desired powermode.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_power_mode(enum bmp5_powermode powermode,
|
|
struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to set sensor in standby powermode when
|
|
* powermode is deepstandby mode.
|
|
*
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_standby_mode(struct bmp5_dev* dev);
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/*!
|
|
* @brief This internal API is used to calculate the power of a value.
|
|
*
|
|
* @param[in] base : Base for power calculation.
|
|
* @param[in] resolution : Exponent for power calculation.
|
|
*
|
|
* @return the calculated power
|
|
* @retval the power value
|
|
*/
|
|
static uint32_t power(uint8_t base, uint8_t resolution);
|
|
|
|
#endif
|
|
|
|
/*!
|
|
* @brief This internal API is used to set the IIR for temperature and pressure.
|
|
*
|
|
* @param[in] iir_cfg : Structure instance of bmp5_iir_config.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_iir_config(const struct bmp5_iir_config* iir_cfg,
|
|
struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to set fifo threshold based on the frame
|
|
* type selected.
|
|
*
|
|
* @param[in,out] reg_data : Stores the register data.
|
|
* @param[in] fifo : Structure instance of bmp5_fifo.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_fifo_threshold(uint8_t* reg_data,
|
|
const struct bmp5_fifo* fifo);
|
|
|
|
/*!
|
|
* @brief This internal API sets the configuration for IIR of fifo.
|
|
*
|
|
* @param[in] set_fifo_iir_t : Variable to store the fifo IIR value for
|
|
* temperature.
|
|
* @param[in] set_fifo_iir_p : Variable to store the fifo IIR value for
|
|
* pressure.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_fifo_iir_config(uint8_t set_fifo_iir_t,
|
|
uint8_t set_fifo_iir_p, struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to unpack the fifo data and store it in the
|
|
* bmp5_sensor_data structure.
|
|
*
|
|
* @param[out] sensor_data : Stores the pressure and temperature data in
|
|
* bmp5_sensor_data structure.
|
|
* @param[in,out] data_index : Contains the beginning of set of bytes parsed to
|
|
* unpack.
|
|
* @param[in] fifo : Structure instance of bmp5_fifo.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t unpack_sensor_data(struct bmp5_sensor_data* sensor_data,
|
|
uint16_t* data_index,
|
|
const struct bmp5_fifo* fifo);
|
|
|
|
/*!
|
|
* @brief This internal API sets the IIR configuration and count limit of OOR
|
|
* pressure.
|
|
*
|
|
* @param[in] set_oor_iir_p : Variable to store the OOR IIR value for
|
|
* pressure.
|
|
* @param[in] set_count_limit : Variable to store the OOR count limit value for
|
|
* pressure.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_oor_iir_count_limit(uint8_t set_oor_iir_p,
|
|
uint8_t set_count_limit,
|
|
struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to read the nvm data.
|
|
*
|
|
* @param[out] nvm_data : Variable to store nvm data.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t get_nvm_data(uint16_t* nvm_data, struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to get the nvm status (NVM ready interrupt,
|
|
* NVM error interrupt and NVM command error interrupt).
|
|
*
|
|
* @param[out] nvm_status : Variable to store nvm status.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @note : Below are values of nvm_status possible.
|
|
*
|
|
* nvm_status | Functionality
|
|
* ---------------------|----------------------------
|
|
* BMP5_INT_NVM_RDY | NVM ready status
|
|
* BMP5_INT_NVM_ERR | NVM error status
|
|
* BMP5_NVM_CMD_ERR | NVM command error status
|
|
*
|
|
* @return Result of API execution status.
|
|
* @return 0 -> Success
|
|
* @return < 0 -> Fail
|
|
*/
|
|
static int8_t get_nvm_status(uint8_t* nvm_status, struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to write the nvm address and prog_en.
|
|
*
|
|
* @param[out] nvm_addr : Variable that holds the nvm address.
|
|
* @param[in] prog_en : Variable that holds the prog_en value.
|
|
* @param[in,out] curr_pwrmode : Stores current powermode.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t nvm_write_addr(uint8_t nvm_addr, uint8_t prog_en,
|
|
enum bmp5_powermode* curr_pwrmode,
|
|
struct bmp5_dev* dev);
|
|
|
|
/*!
|
|
* @brief This internal API is used to set the nvm address and prog_enable based
|
|
* on NVM read/write selected.
|
|
*
|
|
* @param[out] nvm_addr : Variable that holds the nvm address.
|
|
* @param[in] prog_en : Variable that holds the prog_en value.
|
|
* @param[in] dev : Structure instance of bmp5_dev.
|
|
*
|
|
* @return Result of API execution status
|
|
* @retval 0 -> Success
|
|
* @retval <0 -> Fail
|
|
*/
|
|
static int8_t set_nvm_addr(uint8_t nvm_addr, uint8_t prog_en,
|
|
struct bmp5_dev* dev);
|
|
|
|
/***************************************************************************/
|
|
|
|
/*! Local Function Definitions
|
|
****************************************************************************/
|
|
|
|
/*!
|
|
* @brief This API is the entry point.
|
|
* It performs the selection of I2C/I3C/SPI read mechanism according to the
|
|
* selected interface and reads the chip-id of the sensor.
|
|
*/
|
|
int8_t bmp5_init(struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
uint8_t chip_id;
|
|
|
|
/* Check for null pointer in the device structure */
|
|
rslt = null_ptr_check(dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
if (dev->intf == BMP5_SPI_INTF) {
|
|
/* Performing a single read via SPI of registers,
|
|
* e.g. registers CHIP_ID, before the actual
|
|
* SPI communication with the device.
|
|
*/
|
|
rslt = bmp5_get_regs(BMP5_REG_CHIP_ID, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Read chip_id */
|
|
rslt = bmp5_get_regs(BMP5_REG_CHIP_ID, &chip_id, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
if (chip_id != 0) {
|
|
/* Validate post power-up procedure */
|
|
rslt = power_up_check(dev);
|
|
} else {
|
|
rslt = BMP5_E_INVALID_CHIP_ID;
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = validate_chip_id(chip_id, dev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the data from the given register address of the sensor.
|
|
*/
|
|
int8_t bmp5_get_regs(uint8_t reg_addr, uint8_t* reg_data, uint32_t len,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
/* Check for null pointer in the device structure */
|
|
rslt = null_ptr_check(dev);
|
|
|
|
/* Proceed if null check is fine */
|
|
if ((rslt == BMP5_OK) && (reg_data != NULL)) {
|
|
if (dev->intf == BMP5_SPI_INTF) {
|
|
/* If interface selected is SPI */
|
|
reg_addr = reg_addr | BMP5_SPI_RD_MASK;
|
|
}
|
|
|
|
/* Read the data from the reg_addr */
|
|
dev->intf_rslt = dev->read(reg_addr, reg_data, len, dev->intf_ptr);
|
|
|
|
if (dev->intf_rslt != BMP5_INTF_RET_SUCCESS) {
|
|
/* Failure case */
|
|
rslt = BMP5_E_COM_FAIL;
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API writes the given data to the register address
|
|
* of the sensor.
|
|
*/
|
|
int8_t bmp5_set_regs(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t idx = 0;
|
|
|
|
/* Check for null pointer in the device structure */
|
|
rslt = null_ptr_check(dev);
|
|
|
|
/* Proceed if null check is fine */
|
|
if ((rslt == BMP5_OK) && (reg_data != NULL)) {
|
|
if (dev->intf == BMP5_SPI_INTF) {
|
|
/* Write the data to the reg_addr */
|
|
do {
|
|
dev->intf_rslt =
|
|
dev->write((reg_addr + idx), ®_data[idx], 1, dev->intf_ptr);
|
|
idx++;
|
|
} while ((idx < len) && (dev->intf_rslt == BMP5_INTF_RET_SUCCESS));
|
|
} else if ((dev->intf == BMP5_I2C_INTF) || (dev->intf == BMP5_I3C_INTF)) {
|
|
/* Write the data to the reg_addr */
|
|
dev->intf_rslt = dev->write(reg_addr, reg_data, len, dev->intf_ptr);
|
|
}
|
|
|
|
if (dev->intf_rslt != BMP5_INTF_RET_SUCCESS) {
|
|
/* Failure case */
|
|
rslt = BMP5_E_COM_FAIL;
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API performs the soft reset of the sensor.
|
|
*/
|
|
int8_t bmp5_soft_reset(struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
uint8_t por_status;
|
|
uint8_t data = BMP5_SOFT_RESET_CMD;
|
|
|
|
/* Reset the device */
|
|
rslt = bmp5_set_regs(BMP5_REG_CMD, &data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Soft-reset execution takes 2 ms, we'll wait a little longer */
|
|
dev->delay_us(BMP5_DELAY_US_SOFT_RESET * 3, dev->intf_ptr);
|
|
|
|
if (dev->intf == BMP5_SPI_INTF) {
|
|
/* Performing a single read via SPI of registers,
|
|
* e.g. registers CHIP_ID, before the actual
|
|
* SPI communication with the device.
|
|
*/
|
|
rslt = bmp5_get_regs(BMP5_REG_CHIP_ID, ®_data, 1, dev);
|
|
}
|
|
|
|
#if 0 // Suggestion by Bosch to fix init problem with checking INT_STATUS.por
|
|
// bit
|
|
if (rslt == BMP5_OK)
|
|
{
|
|
rslt = bmp5_get_interrupt_status(&por_status, dev);
|
|
|
|
if (rslt == BMP5_OK)
|
|
{
|
|
if (por_status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE)
|
|
{
|
|
rslt = BMP5_OK;
|
|
}
|
|
else
|
|
{
|
|
rslt = BMP5_E_POR_SOFTRESET;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
(void)por_status; // Avoid compiler warning-as-error
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to get interrupt status.
|
|
*/
|
|
int8_t bmp5_get_interrupt_status(uint8_t* int_status, struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
if (int_status != NULL) {
|
|
rslt = bmp5_get_regs(BMP5_REG_INT_STATUS, int_status, 1, dev);
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to get powermode of the sensor.
|
|
*/
|
|
int8_t bmp5_get_power_mode(enum bmp5_powermode* powermode,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t deep_dis;
|
|
uint8_t reg_data;
|
|
uint8_t pwrmode;
|
|
|
|
if (powermode != NULL) {
|
|
/* Read the power mode register */
|
|
rslt = bmp5_get_regs(BMP5_REG_ODR_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
pwrmode = BMP5_GET_BITS_POS_0(reg_data, BMP5_POWERMODE);
|
|
|
|
switch (pwrmode) {
|
|
case BMP5_POWERMODE_STANDBY:
|
|
|
|
/* Getting deep disable status */
|
|
deep_dis = BMP5_GET_BITSLICE(reg_data, BMP5_DEEP_DISABLE);
|
|
|
|
/* Checking deepstandby status only when powermode is in standby mode
|
|
*/
|
|
|
|
/* If deep_dis = 0(BMP5_DEEP_ENABLED) then deepstandby mode is
|
|
* enabled. If deep_dis = 1(BMP5_DEEP_DISABLED) then deepstandby mode
|
|
* is disabled
|
|
*/
|
|
if (deep_dis == BMP5_DEEP_ENABLED) {
|
|
rslt = check_deepstandby_mode(powermode, dev);
|
|
} else {
|
|
*powermode = BMP5_POWERMODE_STANDBY;
|
|
}
|
|
|
|
break;
|
|
case BMP5_POWERMODE_NORMAL:
|
|
*powermode = BMP5_POWERMODE_NORMAL;
|
|
break;
|
|
case BMP5_POWERMODE_FORCED:
|
|
*powermode = BMP5_POWERMODE_FORCED;
|
|
break;
|
|
case BMP5_POWERMODE_CONTINOUS:
|
|
*powermode = BMP5_POWERMODE_CONTINOUS;
|
|
break;
|
|
default:
|
|
rslt = BMP5_E_INVALID_POWERMODE;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to set powermode of the sensor.
|
|
*/
|
|
int8_t bmp5_set_power_mode(enum bmp5_powermode powermode,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
enum bmp5_powermode lst_pwrmode;
|
|
|
|
/* Existing power mode of the device is received in lst_pwrmode */
|
|
rslt = bmp5_get_power_mode(&lst_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* If the sensor is not in standby mode set the device to
|
|
* standby mode.
|
|
*/
|
|
if (lst_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
/* Device should be set to standby before transiting to
|
|
* forced mode or normal mode or continous mode.
|
|
*/
|
|
rslt = set_power_mode(BMP5_POWERMODE_STANDBY, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Give t_standby(as per data sheet) time for device to go into standby
|
|
* mode */
|
|
dev->delay_us(BMP5_DELAY_US_STANDBY, dev->intf_ptr);
|
|
}
|
|
}
|
|
|
|
/* Set the desired power mode */
|
|
if (rslt == BMP5_OK) {
|
|
switch (powermode) {
|
|
case BMP5_POWERMODE_DEEP_STANDBY:
|
|
rslt = set_deep_standby_mode(dev);
|
|
break;
|
|
case BMP5_POWERMODE_STANDBY:
|
|
|
|
/* Since switching between powermodes require sensor to be in standby
|
|
* mode it is performed above. So it is not explicitly performed here.
|
|
*/
|
|
break;
|
|
case BMP5_POWERMODE_NORMAL:
|
|
case BMP5_POWERMODE_FORCED:
|
|
case BMP5_POWERMODE_CONTINOUS:
|
|
rslt = set_power_mode(powermode, dev);
|
|
break;
|
|
default:
|
|
rslt = BMP5_E_INVALID_POWERMODE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API reads the temperature(deg C) or both pressure(Pa) and
|
|
* temperature(deg C) data from the sensor and store it in the bmp5_sensor_data
|
|
* structure instance passed by the user.
|
|
*/
|
|
int8_t bmp5_get_sensor_data(
|
|
struct bmp5_sensor_data* sensor_data,
|
|
const struct bmp5_osr_odr_press_config* osr_odr_press_cfg,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data[6] = {0};
|
|
int32_t raw_data_t;
|
|
uint32_t raw_data_p;
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_TEMP_DATA_XLSB, reg_data, 6, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
raw_data_t = (int32_t)(((uint32_t)reg_data[2] << 16) |
|
|
((uint16_t)reg_data[1] << 8) | reg_data[0]);
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/* Division by 2^16(whose equivalent value is 65536) is performed to get
|
|
* temperature data and followed by fixed point digit precision in deg C
|
|
*/
|
|
sensor_data->temperature =
|
|
(int64_t)((raw_data_t / (int64_t)65536.0) *
|
|
(power(10, BMP5_FIXED_POINT_DIGIT_PRECISION)));
|
|
#else
|
|
|
|
/* Division by 2^16(whose equivalent value is 65536) is performed to get
|
|
* temperature data in deg C */
|
|
sensor_data->temperature = (float)(raw_data_t / 65536.0);
|
|
#endif
|
|
|
|
if (osr_odr_press_cfg->press_en == BMP5_ENABLE) {
|
|
raw_data_p = (uint32_t)(((uint32_t)reg_data[5] << 16) |
|
|
((uint16_t)reg_data[4] << 8) | reg_data[3]);
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/* Division by 2^6(whose equivalent value is 64) is performed to get
|
|
* pressure data and followed by fixed point digit precision in Pa
|
|
*/
|
|
sensor_data->pressure =
|
|
(uint64_t)((raw_data_p / (int64_t)64.0) *
|
|
(power(10, BMP5_FIXED_POINT_DIGIT_PRECISION)));
|
|
#else
|
|
|
|
/* Division by 2^6(whose equivalent value is 64) is performed to get
|
|
* pressure data in Pa */
|
|
sensor_data->pressure = (float)(raw_data_p / 64.0);
|
|
#endif
|
|
} else {
|
|
sensor_data->pressure = 0.0;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to enable the interrupts(drdy interrupt, fifo full
|
|
* interrupt, fifo threshold enable and pressure data out of range interrupt).
|
|
*/
|
|
int8_t bmp5_int_source_select(
|
|
const struct bmp5_int_source_select* int_source_select,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
|
|
if (int_source_select != NULL) {
|
|
rslt = bmp5_get_regs(BMP5_REG_INT_SOURCE, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_INT_DRDY_EN,
|
|
int_source_select->drdy_en);
|
|
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_FIFO_FULL_EN,
|
|
int_source_select->fifo_full_en);
|
|
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_FIFO_THRES_EN,
|
|
int_source_select->fifo_thres_en);
|
|
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_OOR_PRESS_EN,
|
|
int_source_select->oor_press_en);
|
|
|
|
rslt = bmp5_set_regs(BMP5_REG_INT_SOURCE, ®_data, 1, dev);
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to configure the interrupt settings.
|
|
*/
|
|
int8_t bmp5_configure_interrupt(enum bmp5_intr_mode int_mode,
|
|
enum bmp5_intr_polarity int_pol,
|
|
enum bmp5_intr_drive int_od,
|
|
enum bmp5_intr_en_dis int_en,
|
|
struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt;
|
|
|
|
/* Variable to get interrupt configuration */
|
|
uint8_t reg_data = 0;
|
|
|
|
/* Variable to set interrupt source */
|
|
uint8_t int_source = 0;
|
|
|
|
/* Variable to get interrupt status */
|
|
uint8_t int_status = 0;
|
|
|
|
/* Get interrupt configuration */
|
|
rslt = bmp5_get_regs(BMP5_REG_INT_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Any change between latched/pulsed mode has to be applied while interrupt
|
|
* is disabled */
|
|
/* Step 1 : Turn off all INT sources (INT_SOURCE -> 0x00) */
|
|
rslt = bmp5_set_regs(BMP5_REG_INT_SOURCE, &int_source, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Step 2 : Read the INT_STATUS register to clear the status */
|
|
rslt = bmp5_get_regs(BMP5_REG_INT_STATUS, &int_status, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Step 3 : Set the desired mode in INT_CONFIG.int_mode */
|
|
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_INT_MODE, int_mode);
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_POL, int_pol);
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_OD, int_od);
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_EN, int_en);
|
|
|
|
/* Finally transfer the interrupt configurations */
|
|
rslt = bmp5_set_regs(BMP5_REG_INT_CONFIG, ®_data, 1, dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the configuration for oversampling of temperature,
|
|
* oversampling of pressure and ODR configuration along with pressure enable.
|
|
*/
|
|
int8_t bmp5_get_osr_odr_press_config(
|
|
struct bmp5_osr_odr_press_config* osr_odr_press_cfg, struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt;
|
|
|
|
/* Variable to store OSR and ODR config */
|
|
uint8_t reg_data[2];
|
|
|
|
if (osr_odr_press_cfg != NULL) {
|
|
/* Get OSR and ODR configuration in burst read */
|
|
rslt = bmp5_get_regs(BMP5_REG_OSR_CONFIG, reg_data, 2, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
osr_odr_press_cfg->osr_t = BMP5_GET_BITS_POS_0(reg_data[0], BMP5_TEMP_OS);
|
|
osr_odr_press_cfg->osr_p = BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_OS);
|
|
osr_odr_press_cfg->press_en =
|
|
BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_EN);
|
|
osr_odr_press_cfg->odr = BMP5_GET_BITSLICE(reg_data[1], BMP5_ODR);
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the configuration for oversampling temperature,
|
|
* oversampling of pressure and ODR configuration along with pressure enable.
|
|
*
|
|
* @note If ODR is set to a value higher than 5Hz then powermode is set as
|
|
* standby mode, as ODR value greater than 5HZ without disabling deep-standby
|
|
* mode makes powermode invalid.
|
|
*/
|
|
int8_t bmp5_set_osr_odr_press_config(
|
|
const struct bmp5_osr_odr_press_config* osr_odr_press_cfg,
|
|
struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt = 0;
|
|
|
|
/* Variable to set ODR and OSR config */
|
|
uint8_t reg_data[2] = {0};
|
|
|
|
if (osr_odr_press_cfg != NULL) {
|
|
/* If ODR is set to a value higher than 5Hz then powermode is set as standby
|
|
* mode, as ODR value greater than 5HZ without disabling deep-standby mode
|
|
* makes powermode invalid. NOTE: Register value for 5Hz is greater compared
|
|
* to ODRs higher than it. Thus in this below condition odr is checked
|
|
* whether less than 5Hz macro.
|
|
*/
|
|
if (osr_odr_press_cfg->odr < BMP5_ODR_05_HZ) {
|
|
rslt = set_standby_mode(dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_regs(BMP5_REG_OSR_CONFIG, reg_data, 2, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data[0] = BMP5_SET_BITS_POS_0(reg_data[0], BMP5_TEMP_OS,
|
|
osr_odr_press_cfg->osr_t);
|
|
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_PRESS_OS,
|
|
osr_odr_press_cfg->osr_p);
|
|
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_PRESS_EN,
|
|
osr_odr_press_cfg->press_en);
|
|
reg_data[1] =
|
|
BMP5_SET_BITSLICE(reg_data[1], BMP5_ODR, osr_odr_press_cfg->odr);
|
|
|
|
/* Set ODR and OSR configuration */
|
|
rslt = bmp5_set_regs(BMP5_REG_OSR_CONFIG, reg_data, 2, dev);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the configuration for IIR of temperature and pressure.
|
|
*/
|
|
int8_t bmp5_get_iir_config(struct bmp5_iir_config* iir_cfg,
|
|
struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt;
|
|
|
|
/* Variable to get IIR config */
|
|
uint8_t reg_data[2];
|
|
|
|
if (iir_cfg != NULL) {
|
|
/* Get IIR configuration */
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_CONFIG, reg_data, 2, dev);
|
|
|
|
iir_cfg->shdw_set_iir_t =
|
|
BMP5_GET_BITSLICE(reg_data[0], BMP5_SHDW_SET_IIR_TEMP);
|
|
iir_cfg->shdw_set_iir_p =
|
|
BMP5_GET_BITSLICE(reg_data[0], BMP5_SHDW_SET_IIR_PRESS);
|
|
iir_cfg->iir_flush_forced_en =
|
|
BMP5_GET_BITSLICE(reg_data[0], BMP5_IIR_FLUSH_FORCED_EN);
|
|
|
|
iir_cfg->set_iir_t = BMP5_GET_BITS_POS_0(reg_data[1], BMP5_SET_IIR_TEMP);
|
|
iir_cfg->set_iir_p = BMP5_GET_BITSLICE(reg_data[1], BMP5_SET_IIR_PRESS);
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the configuration for IIR of temperature and pressure.
|
|
*
|
|
* @note If IIR value for both temperature and pressure is set a value other
|
|
* than bypass then powermode is set as standby mode, as IIR with value other
|
|
* than bypass without disabling deep-standby mode makes powermode invalid.
|
|
*/
|
|
int8_t bmp5_set_iir_config(const struct bmp5_iir_config* iir_cfg,
|
|
struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt = 0;
|
|
|
|
/* Variable to store existing powermode */
|
|
enum bmp5_powermode curr_pwrmode;
|
|
|
|
if (iir_cfg != NULL) {
|
|
/* If IIR value for both temperature and pressure is set a value other than
|
|
* bypass then powermode is set as standby mode, as IIR with value other
|
|
* than bypass without disabling deep-standby mode makes powermode invalid.
|
|
*/
|
|
if ((iir_cfg->set_iir_t != BMP5_IIR_FILTER_BYPASS) ||
|
|
(iir_cfg->set_iir_p != BMP5_IIR_FILTER_BYPASS)) {
|
|
rslt = set_standby_mode(dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_power_mode(&curr_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* IIR configuration is writable only during STANDBY mode(as per
|
|
* datasheet) */
|
|
if (curr_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
/* If sensor is not in standby mode, set sensor in standby mode */
|
|
rslt = bmp5_set_power_mode(BMP5_POWERMODE_STANDBY, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = set_iir_config(iir_cfg, dev);
|
|
}
|
|
|
|
/* If previous mode is not standbymode return sensor to that previous
|
|
* mode after setting iir configuration
|
|
*/
|
|
if (rslt == BMP5_OK) {
|
|
/* Since IIR works only in standby mode we are not re-writing to
|
|
* deepstandby mode as deep standby mode resets the IIR settings to
|
|
* default
|
|
*/
|
|
if ((curr_pwrmode != BMP5_POWERMODE_STANDBY) &&
|
|
(curr_pwrmode != BMP5_POWERMODE_DEEP_STANDBY)) {
|
|
rslt = bmp5_set_power_mode(curr_pwrmode, dev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the configuration for effective OSR of temperature,
|
|
* effective OSR of pressure and ODR valid status.
|
|
*/
|
|
int8_t bmp5_get_osr_odr_eff(struct bmp5_osr_odr_eff* osr_odr_eff,
|
|
struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt;
|
|
|
|
/* Variable to store effective OSR */
|
|
uint8_t reg_data;
|
|
|
|
if (osr_odr_eff != NULL) {
|
|
/* Get effective OSR configuration and ODR valid status */
|
|
rslt = bmp5_get_regs(BMP5_REG_OSR_EFF, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
osr_odr_eff->osr_t_eff = BMP5_GET_BITS_POS_0(reg_data, BMP5_OSR_TEMP_EFF);
|
|
osr_odr_eff->osr_p_eff = BMP5_GET_BITSLICE(reg_data, BMP5_OSR_PRESS_EFF);
|
|
osr_odr_eff->odr_is_valid =
|
|
BMP5_GET_BITSLICE(reg_data, BMP5_ODR_IS_VALID);
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API used to get the configurations of fifo from the sensor.
|
|
*/
|
|
int8_t bmp5_get_fifo_configuration(struct bmp5_fifo* fifo,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt = 0;
|
|
uint8_t reg_data;
|
|
|
|
if (fifo != NULL) {
|
|
/* Get the fifo congifurations */
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
fifo->threshold = BMP5_GET_BITS_POS_0(reg_data, BMP5_FIFO_THRESHOLD);
|
|
fifo->mode = BMP5_GET_BITSLICE(reg_data, BMP5_FIFO_MODE);
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_SEL, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
fifo->frame_sel = BMP5_GET_BITS_POS_0(reg_data, BMP5_FIFO_FRAME_SEL);
|
|
fifo->dec_sel = BMP5_GET_BITSLICE(reg_data, BMP5_FIFO_DEC_SEL);
|
|
}
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
fifo->set_fifo_iir_t =
|
|
BMP5_GET_BITSLICE(reg_data, BMP5_SET_FIFO_IIR_TEMP);
|
|
fifo->set_fifo_iir_p =
|
|
BMP5_GET_BITSLICE(reg_data, BMP5_SET_FIFO_IIR_PRESS);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API used to set the configurations of fifo in the sensor.
|
|
*
|
|
* @note If Fifo frame selection is enabled then powermode is set as standby
|
|
* mode, as fifo frame selection enabled without disabling deep-standby mode
|
|
* makes powermode invalid.
|
|
*/
|
|
int8_t bmp5_set_fifo_configuration(const struct bmp5_fifo* fifo,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt = 0;
|
|
uint8_t reg_data;
|
|
uint8_t set_fifo_iir_t, set_fifo_iit_p;
|
|
|
|
if (fifo != NULL) {
|
|
/* If Fifo frame selection is enabled then powermode is set as standby mode,
|
|
* as fifo frame selection enabled without disabling deep-standby mode makes
|
|
* powermode invalid.
|
|
*/
|
|
if (fifo->frame_sel != BMP5_DISABLE) {
|
|
rslt = set_standby_mode(dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
set_fifo_iir_t = fifo->set_fifo_iir_t;
|
|
set_fifo_iit_p = fifo->set_fifo_iir_p;
|
|
|
|
rslt = set_fifo_iir_config(set_fifo_iir_t, set_fifo_iit_p, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Get the fifo congifurations */
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_FIFO_MODE, fifo->mode);
|
|
|
|
rslt = set_fifo_threshold(®_data, fifo);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Set the fifo congifurations */
|
|
rslt = bmp5_set_regs(BMP5_REG_FIFO_CONFIG, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_SEL, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_FIFO_FRAME_SEL,
|
|
fifo->frame_sel);
|
|
reg_data =
|
|
BMP5_SET_BITSLICE(reg_data, BMP5_FIFO_DEC_SEL, fifo->dec_sel);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Set the fifo congifurations */
|
|
rslt = bmp5_set_regs(BMP5_REG_FIFO_SEL, ®_data, 1, dev);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to get the length of fifo from the sensor.
|
|
*/
|
|
int8_t bmp5_get_fifo_len(uint16_t* fifo_len, struct bmp5_fifo* fifo,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
|
|
if ((fifo != NULL) && (fifo_len != NULL)) {
|
|
/* Get the fifo frame count */
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_COUNT, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
fifo->fifo_count = BMP5_GET_BITS_POS_0(reg_data, BMP5_FIFO_COUNT);
|
|
|
|
if ((fifo->frame_sel == BMP5_FIFO_TEMPERATURE_DATA) ||
|
|
(fifo->frame_sel == BMP5_FIFO_PRESSURE_DATA)) {
|
|
/* Maximum of 32 frames if either one of temperature or pressure is
|
|
* selected and each frame comprises of 3 bytes of data
|
|
*/
|
|
*fifo_len = fifo->fifo_count * 3;
|
|
} else if (fifo->frame_sel == BMP5_FIFO_PRESS_TEMP_DATA) {
|
|
/* Maximum of 16 frames if both temperature and pressure is selected
|
|
* and each frame comprises of 6 bytes of data
|
|
*/
|
|
*fifo_len = fifo->fifo_count * 6;
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to get the fifo data from the sensor.
|
|
*/
|
|
int8_t bmp5_get_fifo_data(struct bmp5_fifo* fifo, struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint16_t fifo_len;
|
|
|
|
if (fifo != NULL) {
|
|
/* Get the fifo length */
|
|
rslt = bmp5_get_fifo_len(&fifo_len, fifo, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
if (fifo->length > fifo_len) {
|
|
fifo->length = fifo_len;
|
|
}
|
|
|
|
/* Read the fifo data */
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_DATA, fifo->data, fifo->length, dev);
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API extract the temperature and/or pressure data from the fifo
|
|
* data which is already read from the fifo.
|
|
*/
|
|
int8_t bmp5_extract_fifo_data(const struct bmp5_fifo* fifo,
|
|
struct bmp5_sensor_data* sensor_data) {
|
|
int8_t rslt = 0;
|
|
uint8_t idx = 0;
|
|
uint16_t data_indx;
|
|
|
|
/* Proceed if null check is fine */
|
|
if ((fifo != NULL) && (sensor_data != NULL)) {
|
|
for (data_indx = 0;
|
|
(data_indx < fifo->length) && (rslt != BMP5_E_FIFO_FRAME_EMPTY);) {
|
|
/* Inside unpack_sensor_data function, data_index is incremented */
|
|
rslt = unpack_sensor_data(&sensor_data[idx], &data_indx, fifo);
|
|
idx++;
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API gets the configuration for out-of-range pressure threshold,
|
|
* range count limit and IIR.
|
|
*/
|
|
int8_t bmp5_get_oor_configuration(
|
|
struct bmp5_oor_press_configuration* oor_press_config,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data[4];
|
|
|
|
if (oor_press_config != NULL) {
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_CONFIG, ®_data[0], 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
oor_press_config->oor_sel_iir_p =
|
|
BMP5_GET_BITSLICE(reg_data[0], BMP5_OOR_SEL_IIR_PRESS);
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_OOR_THR_P_LSB, reg_data, 4, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
oor_press_config->oor_thr_p =
|
|
reg_data[0] | (reg_data[1] << 8) |
|
|
((reg_data[3] & BMP5_OOR_THR_P_XMSB_REG_MSK) << 16);
|
|
oor_press_config->oor_range_p = reg_data[2];
|
|
oor_press_config->cnt_lim =
|
|
BMP5_GET_BITSLICE(reg_data[3], BMP5_OOR_COUNT_LIMIT);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API sets the configuration for out-of-range pressure threshold,
|
|
* range count limit and IIR.
|
|
*/
|
|
int8_t bmp5_set_oor_configuration(
|
|
const struct bmp5_oor_press_configuration* oor_press_config,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data[4];
|
|
uint8_t thres_xmsb;
|
|
uint8_t set_oor_iir_p, set_count_limit;
|
|
|
|
if (oor_press_config != NULL) {
|
|
set_oor_iir_p = oor_press_config->oor_sel_iir_p;
|
|
set_count_limit = oor_press_config->cnt_lim;
|
|
|
|
rslt = set_oor_iir_count_limit(set_oor_iir_p, set_count_limit, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Get the OOR congifurations */
|
|
rslt = bmp5_get_regs(BMP5_REG_OOR_THR_P_LSB, reg_data, 4, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data[0] = BMP5_SET_BITS_POS_0(reg_data[0], BMP5_OOR_THR_P_LSB,
|
|
oor_press_config->oor_thr_p);
|
|
reg_data[1] =
|
|
(uint8_t)(BMP5_SET_BITS_POS_0(reg_data[1], BMP5_OOR_THR_P_MSB,
|
|
oor_press_config->oor_thr_p) >>
|
|
8);
|
|
reg_data[2] = oor_press_config->oor_range_p;
|
|
thres_xmsb =
|
|
BMP5_GET_BITSLICE(oor_press_config->oor_thr_p, BMP5_OOR_THR_P_XMSB);
|
|
reg_data[3] = BMP5_SET_BITS_POS_0(reg_data[3], BMP5_OOR_THR_P_XMSB_REG,
|
|
thres_xmsb);
|
|
|
|
/* Set the OOR congifurations */
|
|
rslt = bmp5_set_regs(BMP5_REG_OOR_THR_P_LSB, reg_data, 4, dev);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to perform NVM read.
|
|
*/
|
|
int8_t bmp5_nvm_read(uint8_t nvm_addr, uint16_t* nvm_data,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
|
|
/* Variable to store existing powermode */
|
|
enum bmp5_powermode curr_pwrmode;
|
|
|
|
if (nvm_data != NULL) {
|
|
rslt = nvm_write_addr(nvm_addr, BMP5_DISABLE, &curr_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* First NVM command for user read sequence */
|
|
reg_data = BMP5_NVM_FIRST_CMND;
|
|
rslt = bmp5_set_regs(BMP5_REG_CMD, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Read enable NVM command for user read sequence */
|
|
reg_data = BMP5_NVM_READ_ENABLE_CMND;
|
|
rslt = bmp5_set_regs(BMP5_REG_CMD, ®_data, 1, dev);
|
|
|
|
/* Delay required for NVM ready status to change to 1 before NVM read */
|
|
dev->delay_us(BMP5_DELAY_US_NVM_READY_READ, dev->intf_ptr);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = get_nvm_data(nvm_data, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* If previous mode is not standbymode return sensor to that previous mode
|
|
* after performing NVM
|
|
*/
|
|
if (curr_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
rslt = bmp5_set_power_mode(curr_pwrmode, dev);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to perform NVM write.
|
|
*/
|
|
int8_t bmp5_nvm_write(uint8_t nvm_addr, const uint16_t* nvm_data,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
uint8_t nvm_status = 0;
|
|
|
|
uint8_t reg_data = 0;
|
|
|
|
uint8_t nvmdata[2];
|
|
|
|
/* Variable to store existing powermode */
|
|
enum bmp5_powermode curr_pwrmode;
|
|
|
|
if (nvm_data != NULL) {
|
|
rslt = nvm_write_addr(nvm_addr, BMP5_ENABLE, &curr_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Write data to be written to NVM address */
|
|
rslt = bmp5_get_regs(BMP5_REG_NVM_DATA_LSB, nvmdata, 2, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
nvmdata[0] = (uint8_t)(*nvm_data & BMP5_NVM_DATA_LSB_MSK);
|
|
nvmdata[1] = (uint8_t)((*nvm_data & BMP5_NVM_DATA_MSB_MSK) >> 8);
|
|
|
|
rslt = bmp5_set_regs(BMP5_REG_NVM_DATA_LSB, nvmdata, 2, dev);
|
|
}
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* First NVM command for user write sequence */
|
|
reg_data = BMP5_NVM_FIRST_CMND;
|
|
rslt = bmp5_set_regs(BMP5_REG_CMD, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Write enable NVM command for user write sequence */
|
|
reg_data = BMP5_NVM_WRITE_ENABLE_CMND;
|
|
rslt = bmp5_set_regs(BMP5_REG_CMD, ®_data, 1, dev);
|
|
|
|
/* Delay required for NVM ready status to change to 1 */
|
|
dev->delay_us(BMP5_DELAY_US_NVM_READY_WRITE, dev->intf_ptr);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Check if NVM ready status = 1, NVM error status = 0 and NVM command
|
|
* error status = 0 */
|
|
rslt = get_nvm_status(&nvm_status, dev);
|
|
|
|
if ((nvm_status & BMP5_INT_NVM_RDY) &&
|
|
(!(nvm_status & BMP5_INT_NVM_ERR)) &&
|
|
(!(nvm_status & BMP5_INT_NVM_CMD_ERR))) {
|
|
/* Reset NVM prog_en */
|
|
reg_data = BMP5_SET_BIT_VAL_0(reg_data, BMP5_NVM_PROG_EN);
|
|
|
|
rslt = bmp5_set_regs(BMP5_REG_NVM_ADDR, ®_data, 1, dev);
|
|
} else {
|
|
rslt = BMP5_E_NVM_NOT_READY;
|
|
}
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* If previous mode is not standbymode return sensor to that previous mode
|
|
* after performing NVM
|
|
*/
|
|
if (curr_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
rslt = bmp5_set_power_mode(curr_pwrmode, dev);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/****************** Static 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 bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) ||
|
|
(dev->delay_us == NULL)) {
|
|
/* Device structure pointer is not valid */
|
|
rslt = BMP5_E_NULL_PTR;
|
|
} else {
|
|
/* Device structure is fine */
|
|
rslt = BMP5_OK;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to validate the chip id of the sensor.
|
|
*/
|
|
static int8_t validate_chip_id(uint8_t chip_id, struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
if (chip_id == BMP5_CHIP_ID || chip_id == BMP585_CHIP_ID) {
|
|
/* Updating chip_id in device structure */
|
|
dev->chip_id = chip_id;
|
|
rslt = BMP5_OK;
|
|
} else {
|
|
rslt = BMP5_E_DEV_NOT_FOUND;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to validate the post power-up procedure.
|
|
*/
|
|
static int8_t power_up_check(struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t nvm_status;
|
|
uint8_t por_status;
|
|
|
|
rslt = get_nvm_status(&nvm_status, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Check if nvm_rdy status = 1 and nvm_err status = 0 to proceed */
|
|
if ((nvm_status & BMP5_INT_NVM_RDY) && (!(nvm_status & BMP5_INT_NVM_ERR))) {
|
|
rslt = bmp5_get_interrupt_status(&por_status, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Check if por/soft-reset complete status = 1 to proceed */
|
|
if (por_status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE) {
|
|
rslt = BMP5_OK;
|
|
} else {
|
|
rslt = BMP5_E_POWER_UP;
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_POWER_UP;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to check if sensor is in deepstandby mode.
|
|
*/
|
|
static int8_t check_deepstandby_mode(enum bmp5_powermode* powermode,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t fifo_frame_sel;
|
|
struct bmp5_iir_config iir_cfg = {0};
|
|
struct bmp5_osr_odr_press_config osr_odr_press_cfg = {0};
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_SEL, &fifo_frame_sel, 1, dev);
|
|
fifo_frame_sel = BMP5_GET_BITS_POS_0(fifo_frame_sel, BMP5_FIFO_FRAME_SEL);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_osr_odr_press_config(&osr_odr_press_cfg, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_iir_config(&iir_cfg, dev);
|
|
}
|
|
}
|
|
|
|
/* As per datasheet odr should be less than 5Hz. But register value for 5Hz is
|
|
* less than 4Hz and so, thus in this below condition odr is checked whether
|
|
* greater than 5Hz macro.
|
|
*/
|
|
if ((osr_odr_press_cfg.odr > BMP5_ODR_05_HZ) &&
|
|
(fifo_frame_sel == BMP5_DISABLE) &&
|
|
(iir_cfg.set_iir_t == BMP5_IIR_FILTER_BYPASS) &&
|
|
(iir_cfg.set_iir_p == BMP5_IIR_FILTER_BYPASS)) {
|
|
*powermode = BMP5_POWERMODE_DEEP_STANDBY;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to set sensor in deep standby mode.
|
|
*/
|
|
static int8_t set_deep_standby_mode(struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_ODR_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Setting deep_dis = 0(BMP5_DEEP_ENABLED) enables the deep standby mode */
|
|
reg_data = BMP5_SET_BIT_VAL_0(reg_data, BMP5_DEEP_DISABLE);
|
|
|
|
/* Set ODR less then 5Hz - ODR used is 1Hz */
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_ODR, BMP5_ODR_01_HZ);
|
|
|
|
/* Write the value to the odr config register(0x37) */
|
|
rslt = bmp5_set_regs(BMP5_REG_ODR_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_IIR, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Set iir_t and iir_p as Bypass(0x00) */
|
|
|
|
/* The register holds only iir_t and iir_p and the last 2 bits are
|
|
* reserved. Thus using the macro BMP5_IIR_BYPASS(0xC0) the register
|
|
* value is set as zero.
|
|
*/
|
|
reg_data = reg_data & BMP5_IIR_BYPASS;
|
|
|
|
/* Write the value to the IIR register(0x31) */
|
|
rslt = bmp5_set_regs(BMP5_REG_DSP_IIR, ®_data, 1, dev);
|
|
}
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
rslt = bmp5_get_regs(BMP5_REG_FIFO_SEL, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Disable fifo frame selct */
|
|
reg_data = BMP5_SET_BIT_VAL_0(reg_data, BMP5_FIFO_FRAME_SEL);
|
|
|
|
/* Write the value to the fifo select register(0x18) */
|
|
rslt = bmp5_set_regs(BMP5_REG_FIFO_SEL, ®_data, 1, dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to set sensor in standby or normal or forced
|
|
* or continous powermode.
|
|
*/
|
|
static int8_t set_power_mode(enum bmp5_powermode powermode,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data;
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_ODR_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Setting deep_dis = 1(BMP5_DEEP_DISABLED) disables the deep standby mode
|
|
*/
|
|
reg_data =
|
|
BMP5_SET_BITSLICE(reg_data, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED);
|
|
|
|
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_POWERMODE, powermode);
|
|
|
|
rslt = bmp5_set_regs(BMP5_REG_ODR_CONFIG, ®_data, 1, dev);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to set sensor in standby powermode when
|
|
* powermode is deepstandby mode.
|
|
*/
|
|
static int8_t set_standby_mode(struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
enum bmp5_powermode pwrmode;
|
|
|
|
rslt = bmp5_get_power_mode(&pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
if (pwrmode == BMP5_POWERMODE_DEEP_STANDBY) {
|
|
rslt = bmp5_set_power_mode(BMP5_POWERMODE_STANDBY, dev);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/*!
|
|
* @brief This internal API is used to calculate the power of a value.
|
|
*/
|
|
static uint32_t power(uint8_t base, uint8_t resolution) {
|
|
/* Initialize loop */
|
|
uint8_t loop = 1;
|
|
|
|
/* Initialize variable to store the power of 2 value */
|
|
uint32_t value = 1;
|
|
|
|
for (; loop <= resolution; loop++) {
|
|
value = (uint32_t)(value * base);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
#endif
|
|
|
|
/*!
|
|
* @brief This internal API is used to set the IIR for temperature and pressure.
|
|
*/
|
|
static int8_t set_iir_config(const struct bmp5_iir_config* iir_cfg,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
/* Variable to set IIR config */
|
|
uint8_t reg_data[2];
|
|
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_CONFIG, reg_data, 2, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_SHDW_SET_IIR_TEMP,
|
|
iir_cfg->shdw_set_iir_t);
|
|
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_SHDW_SET_IIR_PRESS,
|
|
iir_cfg->shdw_set_iir_p);
|
|
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_IIR_FLUSH_FORCED_EN,
|
|
iir_cfg->iir_flush_forced_en);
|
|
|
|
reg_data[1] = iir_cfg->set_iir_t;
|
|
reg_data[1] =
|
|
BMP5_SET_BITSLICE(reg_data[1], BMP5_SET_IIR_PRESS, iir_cfg->set_iir_p);
|
|
|
|
/* Set IIR configuration */
|
|
rslt = bmp5_set_regs(BMP5_REG_DSP_CONFIG, reg_data, 2, dev);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API sets the configuration for IIR of fifo.
|
|
*/
|
|
static int8_t set_fifo_iir_config(uint8_t set_fifo_iir_t,
|
|
uint8_t set_fifo_iir_p,
|
|
struct bmp5_dev* dev) {
|
|
/* Variable to store the function result */
|
|
int8_t rslt;
|
|
|
|
/* Variable to set fifo IIR config */
|
|
uint8_t reg_data = 0;
|
|
|
|
/* Variable to store existing powermode */
|
|
enum bmp5_powermode curr_pwrmode;
|
|
|
|
rslt = bmp5_get_power_mode(&curr_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Fifo IIR configuration is writable only during STANDBY mode(as per
|
|
* datasheet) */
|
|
if (curr_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
/* If sensor is not in standby mode, set sensor in standby mode */
|
|
rslt = bmp5_set_power_mode(BMP5_POWERMODE_STANDBY, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Get fifo IIR configuration */
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data =
|
|
BMP5_SET_BITSLICE(reg_data, BMP5_SET_FIFO_IIR_TEMP, set_fifo_iir_t);
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_SET_FIFO_IIR_PRESS,
|
|
set_fifo_iir_p);
|
|
|
|
/* Set fifo IIR configuration */
|
|
rslt = bmp5_set_regs(BMP5_REG_DSP_CONFIG, ®_data, 1, dev);
|
|
}
|
|
}
|
|
|
|
/* If previous mode is not standbymode return sensor to that previous mode
|
|
* after setting fifo iir configuration
|
|
*/
|
|
if (rslt == BMP5_OK) {
|
|
/* Since fifo IIR works only in standby mode we are not re-writing to
|
|
* deepstandby mode as deep standby mode resets the fifo IIR settings to
|
|
* default
|
|
*/
|
|
if ((curr_pwrmode != BMP5_POWERMODE_STANDBY) &&
|
|
(curr_pwrmode != BMP5_POWERMODE_DEEP_STANDBY)) {
|
|
rslt = bmp5_set_power_mode(curr_pwrmode, dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to set fifo threshold based on the frame
|
|
* type selected.
|
|
*/
|
|
static int8_t set_fifo_threshold(uint8_t* reg_data,
|
|
const struct bmp5_fifo* fifo) {
|
|
int8_t rslt = 0;
|
|
|
|
if ((fifo->frame_sel == BMP5_FIFO_TEMPERATURE_DATA) ||
|
|
(fifo->frame_sel == BMP5_FIFO_PRESSURE_DATA)) {
|
|
/* If Pressure or Temperature is selected, maximum 31 frames can be set as
|
|
* threshold */
|
|
if (fifo->threshold <= BMP5_FIFO_MAX_THRESHOLD_P_MODE) {
|
|
reg_data[0] = BMP5_SET_BITS_POS_0(reg_data[0], BMP5_FIFO_THRESHOLD,
|
|
fifo->threshold);
|
|
} else {
|
|
rslt = BMP5_E_INVALID_THRESHOLD;
|
|
}
|
|
} else if (fifo->frame_sel == BMP5_FIFO_PRESS_TEMP_DATA) {
|
|
/* If both pressure and temperature is selected, maximum 15 frames can be
|
|
* set as threshold */
|
|
if (fifo->threshold <= BMP5_FIFO_MAX_THRESHOLD_P_T_MODE) {
|
|
reg_data[0] = BMP5_SET_BITS_POS_0(reg_data[0], BMP5_FIFO_THRESHOLD,
|
|
fifo->threshold);
|
|
} else {
|
|
rslt = BMP5_E_INVALID_THRESHOLD;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to unpack the fifo data and store it in the
|
|
* bmp5_sensor_data structure.
|
|
*/
|
|
static int8_t unpack_sensor_data(struct bmp5_sensor_data* sensor_data,
|
|
uint16_t* data_index,
|
|
const struct bmp5_fifo* fifo) {
|
|
int8_t rslt = 0;
|
|
int32_t raw_data_t;
|
|
uint32_t raw_data_p;
|
|
|
|
switch (fifo->frame_sel) {
|
|
case BMP5_FIFO_TEMPERATURE_DATA:
|
|
|
|
/* Check if fifo frame is empty */
|
|
if (!((fifo->data[*data_index] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 1] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 2] == BMP5_FIFO_EMPTY))) {
|
|
raw_data_t = (int32_t)((uint32_t)fifo->data[*data_index + 2] << 16 |
|
|
(uint16_t)fifo->data[*data_index + 1] << 8 |
|
|
fifo->data[*data_index]);
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/* Division by 2^16(whose equivalent value is 65536) is performed to get
|
|
* temperature data and followed by fixed point digit precision in deg C
|
|
*/
|
|
sensor_data->temperature =
|
|
(int64_t)((raw_data_t / (int64_t)65536.0) *
|
|
(power(10, BMP5_FIXED_POINT_DIGIT_PRECISION)));
|
|
#else
|
|
|
|
/* Division by 2^16(whose equivalent value is 65536) is performed to get
|
|
* temperature data in deg C */
|
|
sensor_data->temperature = (float)(raw_data_t / 65536.0);
|
|
#endif
|
|
|
|
sensor_data->pressure = 0.0;
|
|
*data_index += 3;
|
|
} else {
|
|
rslt = BMP5_E_FIFO_FRAME_EMPTY;
|
|
|
|
/* Move the data index to the last byte to mark completion */
|
|
*data_index = fifo->length;
|
|
}
|
|
|
|
break;
|
|
case BMP5_FIFO_PRESSURE_DATA:
|
|
|
|
/* Check if fifo frame is empty */
|
|
if (!((fifo->data[*data_index] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 1] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 2] == BMP5_FIFO_EMPTY))) {
|
|
raw_data_p = (uint32_t)((uint32_t)fifo->data[(*data_index) + 2] << 16 |
|
|
(uint16_t)fifo->data[(*data_index) + 1] << 8 |
|
|
fifo->data[*data_index]);
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/* Division by 2^6(whose equivalent value is 64) is performed to get
|
|
* pressure data and followed by fixed point digit precision in Pa
|
|
*/
|
|
sensor_data->pressure =
|
|
(uint64_t)((raw_data_p / (uint64_t)64.0) *
|
|
(power(10, BMP5_FIXED_POINT_DIGIT_PRECISION)));
|
|
#else
|
|
|
|
/* Division by 2^6(whose equivalent value is 64) is performed to get
|
|
* pressure data in Pa */
|
|
sensor_data->pressure = (float)(raw_data_p / 64.0);
|
|
#endif
|
|
|
|
sensor_data->temperature = 0.0;
|
|
*data_index += 3;
|
|
} else {
|
|
rslt = BMP5_E_FIFO_FRAME_EMPTY;
|
|
|
|
/* Move the data index to the last byte to mark completion */
|
|
*data_index = fifo->length;
|
|
}
|
|
|
|
break;
|
|
case BMP5_FIFO_PRESS_TEMP_DATA:
|
|
if (!((fifo->data[*data_index] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 1] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 2] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 3] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 4] == BMP5_FIFO_EMPTY) &&
|
|
(fifo->data[*data_index + 5] == BMP5_FIFO_EMPTY))) {
|
|
raw_data_t = (int32_t)((uint32_t)fifo->data[*data_index + 2] << 16 |
|
|
(uint16_t)fifo->data[*data_index + 1] << 8 |
|
|
fifo->data[*data_index]);
|
|
|
|
raw_data_p = (uint32_t)((uint32_t)fifo->data[(*data_index) + 5] << 16 |
|
|
(uint16_t)fifo->data[(*data_index) + 4] << 8 |
|
|
fifo->data[*data_index + 3]);
|
|
|
|
#ifdef BMP5_USE_FIXED_POINT
|
|
|
|
/* Division by 2^16(whose equivalent value is 65536) is performed to get
|
|
* temperature data and followed by fixed point digit precision in deg C
|
|
*/
|
|
sensor_data->temperature =
|
|
(int64_t)((raw_data_t / (int64_t)65536.0) *
|
|
(power(10, BMP5_FIXED_POINT_DIGIT_PRECISION)));
|
|
|
|
/* Division by 2^6(whose equivalent value is 64) is performed to get
|
|
* pressure data and followed by fixed point digit precision in Pa
|
|
*/
|
|
sensor_data->pressure =
|
|
(uint64_t)((raw_data_p / (uint64_t)64.0) *
|
|
(power(10, BMP5_FIXED_POINT_DIGIT_PRECISION)));
|
|
#else
|
|
|
|
/* Division by 2^16(whose equivalent value is 65536) is performed to get
|
|
* temperature data in deg C */
|
|
sensor_data->temperature = (float)(raw_data_t / 65536.0);
|
|
|
|
/* Division by 2^6(whose equivalent value is 64) is performed to get
|
|
* pressure data in Pa */
|
|
sensor_data->pressure = (float)(raw_data_p / 64.0);
|
|
#endif
|
|
|
|
*data_index += 6;
|
|
} else {
|
|
rslt = BMP5_E_FIFO_FRAME_EMPTY;
|
|
|
|
/* Move the data index to the last byte to mark completion */
|
|
*data_index = fifo->length;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
sensor_data->pressure = 0.0;
|
|
sensor_data->temperature = 0.0;
|
|
break;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API sets the IIR configuration and count limit of OOR
|
|
* pressure.
|
|
*/
|
|
static int8_t set_oor_iir_count_limit(uint8_t set_oor_iir_p,
|
|
uint8_t set_count_limit,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t reg_data = 0;
|
|
|
|
/* Variable to store existing powermode */
|
|
enum bmp5_powermode curr_pwrmode;
|
|
|
|
rslt = bmp5_get_power_mode(&curr_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* OOR IIR configuration and count limit is writable only during STANDBY
|
|
* mode(as per datasheet) */
|
|
if (curr_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
/* If sensor is not in standby mode, set sensor in standby mode */
|
|
rslt = bmp5_set_power_mode(BMP5_POWERMODE_STANDBY, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Get OOR pressure IIR configuration */
|
|
rslt = bmp5_get_regs(BMP5_REG_DSP_CONFIG, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data =
|
|
BMP5_SET_BITSLICE(reg_data, BMP5_OOR_SEL_IIR_PRESS, set_oor_iir_p);
|
|
|
|
/* Set OOR pressure IIR configuration */
|
|
rslt = bmp5_set_regs(BMP5_REG_DSP_CONFIG, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Get OOR pressure count limit */
|
|
rslt = bmp5_get_regs(BMP5_REG_OOR_CONFIG, ®_data, 1, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
reg_data =
|
|
BMP5_SET_BITSLICE(reg_data, BMP5_OOR_COUNT_LIMIT, set_count_limit);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Set OOR pressure count limit */
|
|
rslt = bmp5_set_regs(BMP5_REG_OOR_CONFIG, ®_data, 1, dev);
|
|
}
|
|
}
|
|
|
|
/* If previous mode is not standbymode return sensor to that previous mode
|
|
* after setting oor iir configuration and count limit
|
|
*/
|
|
if (rslt == BMP5_OK) {
|
|
/* Since oor IIR and count limit works only in standby mode we are not
|
|
* re-writing to deepstandby mode as deep standby mode resets the oor iir
|
|
* configuration and count limit to default
|
|
*/
|
|
if ((curr_pwrmode != BMP5_POWERMODE_STANDBY) &&
|
|
(curr_pwrmode != BMP5_POWERMODE_DEEP_STANDBY)) {
|
|
rslt = bmp5_set_power_mode(curr_pwrmode, dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to write the nvm address and prog_en.
|
|
*/
|
|
static int8_t nvm_write_addr(uint8_t nvm_addr, uint8_t prog_en,
|
|
enum bmp5_powermode* curr_pwrmode,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
if ((nvm_addr >= BMP5_NVM_START_ADDR) && (nvm_addr <= BMP5_NVM_END_ADDR)) {
|
|
/* Get current powermode */
|
|
rslt = bmp5_get_power_mode(curr_pwrmode, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* NVM write can be performed only during STANDBY mode */
|
|
if (*curr_pwrmode != BMP5_POWERMODE_STANDBY) {
|
|
/* If sensor is not in standby mode, set sensor in standby mode */
|
|
rslt = bmp5_set_power_mode(BMP5_POWERMODE_STANDBY, dev);
|
|
}
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Write the NVM address and set NVM prog_en with respect to NVM
|
|
* read/write selected. */
|
|
rslt = set_nvm_addr(nvm_addr, prog_en, dev);
|
|
}
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NVM_INVALID_ADDR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to set the nvm address and prog_enable based
|
|
* on NVM read/write selected.
|
|
*/
|
|
static int8_t set_nvm_addr(uint8_t nvm_addr, uint8_t prog_en,
|
|
struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t nvm_status;
|
|
uint8_t reg_data;
|
|
|
|
/* Check if NVM ready status = 1 */
|
|
rslt = get_nvm_status(&nvm_status, dev);
|
|
|
|
if (nvm_status & BMP5_INT_NVM_RDY) {
|
|
rslt = bmp5_get_regs(BMP5_REG_NVM_ADDR, ®_data, 1, dev);
|
|
|
|
if (rslt == BMP5_OK) {
|
|
/* Write the NVM address */
|
|
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_NVM_ADDR, nvm_addr);
|
|
|
|
if (prog_en == BMP5_ENABLE) {
|
|
/* Set bit nvm_prog_en as 1 if NVM write is selected */
|
|
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_NVM_PROG_EN, prog_en);
|
|
} else {
|
|
/* Set bit nvm_prog_en as 0 if NVM read is selected */
|
|
reg_data = BMP5_SET_BIT_VAL_0(reg_data, BMP5_NVM_PROG_EN);
|
|
}
|
|
|
|
rslt = bmp5_set_regs(BMP5_REG_NVM_ADDR, ®_data, 1, dev);
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NVM_NOT_READY;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This internal API is used to read the nvm data.
|
|
*/
|
|
static int8_t get_nvm_data(uint16_t* nvm_data, struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
uint8_t nvm_status;
|
|
uint8_t nvmdata[2];
|
|
|
|
if (nvm_data != NULL) {
|
|
rslt = get_nvm_status(&nvm_status, dev);
|
|
|
|
/* Check if NVM ready status = 1, NVM error status = 0 and NVM command error
|
|
* status = 0 */
|
|
if ((nvm_status & BMP5_INT_NVM_RDY) && (!(nvm_status & BMP5_INT_NVM_ERR)) &&
|
|
(!(nvm_status & BMP5_INT_NVM_CMD_ERR))) {
|
|
/* Read the NVM data from the register address */
|
|
rslt = bmp5_get_regs(BMP5_REG_NVM_DATA_LSB, nvmdata, 2, dev);
|
|
|
|
(*nvm_data) = (uint16_t)((nvmdata[1] << 8) | nvmdata[0]);
|
|
} else {
|
|
rslt = BMP5_E_NVM_NOT_READY;
|
|
}
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
/*!
|
|
* @brief This API is used to get nvm status.
|
|
*/
|
|
static int8_t get_nvm_status(uint8_t* nvm_status, struct bmp5_dev* dev) {
|
|
int8_t rslt;
|
|
|
|
if (nvm_status != NULL) {
|
|
rslt = bmp5_get_regs(BMP5_REG_STATUS, nvm_status, 1, dev);
|
|
} else {
|
|
rslt = BMP5_E_NULL_PTR;
|
|
}
|
|
|
|
return rslt;
|
|
}
|