2017-05-09 13:59:35 +02:00
|
|
|
/**\mainpage
|
|
|
|
*
|
2016-06-22 14:23:09 +02:00
|
|
|
****************************************************************************
|
2017-05-09 13:59:35 +02:00
|
|
|
* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
|
|
|
* File : bme680.c
|
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* Date: 5 May 2017
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* Revision : 2.2.0 $
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
|
|
|
* Usage: Sensor Driver for BME680 sensor
|
|
|
|
*
|
|
|
|
****************************************************************************
|
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* \section Disclaimer
|
|
|
|
*
|
|
|
|
* Common:
|
|
|
|
* Bosch Sensortec products are developed for the consumer goods industry.
|
|
|
|
* They may only be used within the parameters of the respective valid
|
|
|
|
* product data sheet. Bosch Sensortec products are provided with the
|
|
|
|
* express understanding that there is no warranty of fitness for a
|
|
|
|
* particular purpose.They are not fit for use in life-sustaining,
|
|
|
|
* safety or security sensitive systems or any system or device
|
|
|
|
* that may lead to bodily harm or property damage if the system
|
|
|
|
* or device malfunctions. In addition,Bosch Sensortec products are
|
|
|
|
* not fit for use in products which interact with motor vehicle systems.
|
|
|
|
* The resale and or use of products are at the purchasers own risk and
|
|
|
|
* his own responsibility. The examination of fitness for the intended use
|
|
|
|
* is the sole responsibility of the Purchaser.
|
|
|
|
*
|
|
|
|
* The purchaser shall indemnify Bosch Sensortec from all third party
|
|
|
|
* claims, including any claims for incidental, or consequential damages,
|
|
|
|
* arising from any product use not covered by the parameters of
|
|
|
|
* the respective valid product data sheet or not approved by
|
|
|
|
* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
|
|
|
|
* connection with such claims.
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* The purchaser must monitor the market for the purchased products,
|
|
|
|
* particularly with regard to product safety and inform Bosch Sensortec
|
|
|
|
* without delay of all security relevant incidents.
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* Engineering Samples are marked with an asterisk (*) or (e).
|
|
|
|
* Samples may vary from the valid technical specifications of the product
|
|
|
|
* series. They are therefore not intended or fit for resale to third
|
|
|
|
* parties or for use in end products. Their sole purpose is internal
|
|
|
|
* client testing. The testing of an engineering sample may in no way
|
|
|
|
* replace the testing of a product series. Bosch Sensortec assumes
|
|
|
|
* no liability for the use of engineering samples.
|
|
|
|
* By accepting the engineering samples, the Purchaser agrees to indemnify
|
|
|
|
* Bosch Sensortec from all claims arising from the use of engineering
|
|
|
|
* samples.
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* Special:
|
|
|
|
* This software module (hereinafter called "Software") and any information
|
|
|
|
* on application-sheets (hereinafter called "Information") is provided
|
|
|
|
* free of charge for the sole purpose to support your application work.
|
|
|
|
* The Software and Information is subject to the following
|
|
|
|
* terms and conditions:
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* The Software is specifically designed for the exclusive use for
|
|
|
|
* Bosch Sensortec products by personnel who have special experience
|
|
|
|
* and training. Do not use this Software if you do not have the
|
|
|
|
* proper experience or training.
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* This Software package is provided `` as is `` and without any expressed
|
|
|
|
* or implied warranties,including without limitation, the implied warranties
|
|
|
|
* of merchantability and fitness for a particular purpose.
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
2017-05-09 13:59:35 +02:00
|
|
|
* Bosch Sensortec and their representatives and agents deny any liability
|
|
|
|
* for the functional impairment
|
|
|
|
* of this Software in terms of fitness, performance and safety.
|
|
|
|
* Bosch Sensortec and their representatives and agents shall not be liable
|
|
|
|
* for any direct or indirect damages or injury, except as
|
|
|
|
* otherwise stipulated in mandatory applicable law.
|
|
|
|
*
|
|
|
|
* The Information provided is believed to be accurate and reliable.
|
|
|
|
* Bosch Sensortec assumes no responsibility for the consequences of use
|
|
|
|
* of such Information nor for any infringement of patents or
|
2016-06-22 14:23:09 +02:00
|
|
|
* other rights of third parties which may result from its use.
|
|
|
|
* No license is granted by implication or otherwise under any patent or
|
2017-05-09 13:59:35 +02:00
|
|
|
* patent rights of Bosch. Specifications mentioned in the Information are
|
|
|
|
* subject to change without notice.
|
2016-06-22 14:23:09 +02:00
|
|
|
**************************************************************************/
|
|
|
|
/*! \file bme680.c
|
|
|
|
\brief BME680 Sensor Driver Support source File */
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Header files
|
|
|
|
****************************************************************************/
|
|
|
|
#include "bme680.h"
|
|
|
|
#include "bme680_calculations.h"
|
|
|
|
#include "bme680_internal.h"
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Macros, Enums, Constants
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
File globals, typedefs
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* Static function declarations */
|
|
|
|
static enum bme680_return_type bme680_get_calib_param(struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static void bme680_scale_to_multiplication_factor(u16 *duration_u16);
|
|
|
|
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
static void bme680_buffer_restruct_burst_write(u8 arr[], u8 reg_addr,
|
|
|
|
u8 data_size, u8 arr_size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static u8 bme680_find_largest_index(u8 *meas_index);
|
|
|
|
|
|
|
|
static enum bme680_return_type bme680_set_memory_page(u8 memory_page_u8,
|
|
|
|
struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static void bme680_align_sensor_type_uncomp_data(u8 *a_data_u8, u8 index,
|
|
|
|
u8 offset, u8 sensor_type,
|
|
|
|
struct bme680_uncomp_field_data *uncomp_data);
|
|
|
|
|
|
|
|
static void bme680_packing_calib_param(u8 *a_data_u8, struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static void bme680_copy_ordered_sensor_field_data(
|
|
|
|
struct bme680_uncomp_field_data *sensor_data,
|
|
|
|
u8 latest, u8 recent, u8 old, u8 sensor_type,
|
|
|
|
struct bme680_uncomp_field_data *temp_sensor_data);
|
|
|
|
|
|
|
|
static void bme680_get_latest_recent_old_field_index(
|
|
|
|
struct bme680_uncomp_field_data *sensor_data,
|
|
|
|
struct bme680_t *bme680);
|
|
|
|
|
|
|
|
#ifdef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
static enum bme680_return_type bme680_get_field_specific_uncomp_data(
|
|
|
|
u8 field_index, u8 sensor_type, u8 *a_data_u8, struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static enum bme680_return_type bme680_Temp_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static enum bme680_return_type bme680_Pressure_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static enum bme680_return_type bme680_Humidity_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680);
|
|
|
|
|
|
|
|
static enum bme680_return_type bme680_Gas_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Function definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the
|
|
|
|
* the chip id and calibration data of the BME680 sensor
|
|
|
|
* chip id is read in the register 0xD0/0x50(I2C/SPI) from bit 0 to 7
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @note Structure with the below data to be filled
|
|
|
|
* before passing to this function.
|
|
|
|
* @note Device address( applicable only for I2C, bypassed for SPI)
|
|
|
|
* @note Bus interface functions.
|
|
|
|
* @note Delay function
|
|
|
|
* @note With the above data properly set, Chip id will be read from the sensor
|
|
|
|
*
|
|
|
|
* @note While changing the parameter of the bme680_t
|
|
|
|
* @note consider the following point:
|
|
|
|
* Changing the reference value of the parameter
|
|
|
|
* will change the local copy or local reference
|
|
|
|
* make sure your changes will not
|
|
|
|
* affect the reference value of the parameter
|
|
|
|
* (Better case don't change the reference value of the parameter)
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return Either the results of bus communication status or
|
|
|
|
* chip_id fail status
|
|
|
|
* @retval 0 -> Success both bus communication & chip_id
|
|
|
|
* @retval any negative value -> Bus communication failed
|
|
|
|
* -4 -> chip_id corrupted and bus communication ok
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_init(struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 data_u8 = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
/* assign the pointer*/
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/*SPI address 0x45*/
|
|
|
|
/* read the chip id*/
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_PAGE0_SPI_ID_REG,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
} else if (BME680_I2C_INTERFACE == bme680->interface) {
|
|
|
|
/* read the chip id*/
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_PAGE0_I2C_ID_REG,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
}
|
|
|
|
bme680->chip_id = data_u8;
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
if (BME680_CHIP_ID == bme680->chip_id) {
|
|
|
|
/* read the calibration values*/
|
|
|
|
com_status = bme680_get_calib_param(bme680);
|
|
|
|
} else {
|
|
|
|
com_status = BME680_CHIP_ID_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to retrieve the calibration
|
|
|
|
* data from the image registers of the sensor.
|
|
|
|
*
|
|
|
|
* @note Registers 8Ah to A1h for calibration data 1 to 24
|
|
|
|
* from bit 0 to 7
|
|
|
|
* @note Registers E1h to F0h for calibration data 25 to 40
|
|
|
|
* from bit 0 to 7
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static enum bme680_return_type bme680_get_calib_param(struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* array of data holding the calibration values*/
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 v_data_u8 = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
u8 a_data_u8[BME680_CALIB_PARAM_SIZE];
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
for (; index < BME680_CALIB_PARAM_SIZE; index++)
|
2017-05-09 13:59:35 +02:00
|
|
|
a_data_u8[index] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
/* check the bme680 structure pointer as NULL*/
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(
|
|
|
|
BME680_PAGE0_INTERFACE_SPI, bme680);
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
/* read the pressure and temperature
|
|
|
|
calibration data*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_CALIB_SPI_ADDR_1,
|
|
|
|
a_data_u8,
|
|
|
|
BME680_CALIB_DATA_LENGTH_GAS);
|
|
|
|
/* read the humidity and gas
|
|
|
|
calibration data*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_CALIB_SPI_ADDR_2,
|
|
|
|
(a_data_u8 +
|
|
|
|
BME680_CALIB_DATA_LENGTH_GAS),
|
|
|
|
BME680_CALIB_DATA_LENGTH);
|
|
|
|
}
|
|
|
|
} else if (BME680_I2C_INTERFACE == bme680->interface) {
|
|
|
|
/* read the pressure and temperature
|
|
|
|
calibration data*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_CALIB_I2C_ADDR_1,
|
|
|
|
a_data_u8,
|
|
|
|
BME680_CALIB_DATA_LENGTH_GAS);
|
|
|
|
/* read the humidity and gas
|
|
|
|
calibration data*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_CALIB_I2C_ADDR_2,
|
|
|
|
(a_data_u8 +
|
|
|
|
BME680_CALIB_DATA_LENGTH_GAS),
|
|
|
|
BME680_CALIB_DATA_LENGTH);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
com_status = BME680_COMM_RES_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
/*read TPGH calibration*/
|
|
|
|
bme680_packing_calib_param(a_data_u8, bme680);
|
|
|
|
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(BME680_PAGE1_INTERFACE_SPI,
|
|
|
|
bme680);
|
|
|
|
}
|
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_RES_HEAT_RANGE,
|
|
|
|
&v_data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
bme680->cal_param.res_heat_range = BME680_GET_REG(v_data_u8,
|
|
|
|
BME680_MASK_RES_HEAT_RANGE,
|
|
|
|
BME680_SHIFT_RES_HEAT_RANGE);
|
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_RES_HEAT_VAL,
|
|
|
|
&v_data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
bme680->cal_param.res_heat_val = v_data_u8;
|
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_RANGE_SWITCHING_ERR,
|
|
|
|
&v_data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
bme680->cal_param.range_switching_error = BME680_GET_REG(
|
|
|
|
(s8)v_data_u8,
|
|
|
|
(s8)BME680_MASK_RANGE_ERR,
|
|
|
|
BME680_SHIFT_RANGE_ERR);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to write the data to
|
|
|
|
* the given register
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param addr_u8 -> Address of the register
|
|
|
|
* @param data_u8 -> The data to write to the register
|
|
|
|
* @param len_u8 -> No of bytes to write
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_write_reg(u8 addr_u8, u8 *data_u8, u8 len_u8,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_write(
|
|
|
|
bme680->dev_addr,
|
|
|
|
addr_u8,
|
|
|
|
data_u8,
|
|
|
|
len_u8);
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to reads the data from
|
|
|
|
* the given register
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param addr_u8 -> Address of the register
|
|
|
|
* @param data_u8 -> Pointer to store the
|
|
|
|
* received data from the register
|
|
|
|
* @param len_u8 -> No of bytes to read
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_read_reg(u8 addr_u8, u8 *data_u8, u8 len_u8,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
|
|
|
addr_u8,
|
|
|
|
data_u8,
|
|
|
|
len_u8);
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the new data0
|
|
|
|
* @note Field-0(new_data_0),
|
|
|
|
* Field-1(new_data_1) and Field-2(new_data_2)
|
|
|
|
* @note Page-1
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param new_data_u8: The value of new data
|
|
|
|
* @param field_u8: The value of field selection for new data
|
|
|
|
* field | value
|
|
|
|
* -----------|-------------
|
|
|
|
* 0 | BME680_FIELD_ZERO
|
|
|
|
* 1 | BME680_FIELD_ONE
|
|
|
|
* 2 | BME680_FIELD_TWO
|
|
|
|
*
|
|
|
|
* field | Register
|
|
|
|
* -------------------|------------
|
|
|
|
* BME680_FIELD_ZERO | 0x1D bit 7
|
|
|
|
* BME680_FIELD_ONE | 0x2E bit 7
|
|
|
|
* BME680_FIELD_TWO | 0x3F bit 7
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_get_new_data(u8 *new_data_u8, u8 field_u8,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(
|
|
|
|
BME680_PAGE1_INTERFACE_SPI,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BME680_I2C_INTERFACE == bme680->interface)
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
switch (field_u8) {
|
|
|
|
case BME680_FIELD_ZERO:
|
|
|
|
/* read field0 new data zero*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0,
|
|
|
|
new_data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case BME680_FIELD_ONE:
|
|
|
|
/* read field1 new data one*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
(BME680_ADDR_FIELD_0 +
|
|
|
|
BME680_FIELD_ONE_OFFSET),
|
|
|
|
new_data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case BME680_FIELD_TWO:
|
|
|
|
/* read field2 new data two*/
|
|
|
|
com_status =
|
|
|
|
(enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
(BME680_ADDR_FIELD_0 +
|
|
|
|
BME680_FIELD_TWO_OFFSET),
|
|
|
|
new_data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
com_status = BME680_COMM_RES_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (BME680_COMM_RES_OK == com_status)
|
|
|
|
*new_data_u8 = BME680_GET_REG(*new_data_u8,
|
|
|
|
BME680_MASK_NEW_DATA,
|
|
|
|
BME680_SHIFT_NEW_DATA);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the uncompensated
|
|
|
|
* sensor data from Field-0, Field-1, Field-2 and page-1
|
|
|
|
*
|
|
|
|
* @param uncomp_data:
|
|
|
|
* Pointer to store the value of uncompensated sensor
|
|
|
|
* data of pressure, temperature, humidity and gas
|
|
|
|
*
|
|
|
|
* @param field_count : total no of field data which needs
|
|
|
|
* to be read from the sensor
|
|
|
|
*
|
|
|
|
* @note:
|
|
|
|
* field_count = 1 : only latest field data out of 3 fields
|
|
|
|
* field_count = 2 : latest and recent field data out of 3 field
|
|
|
|
* field_count = 3 : All 3 latest, recent and old field data
|
|
|
|
*
|
|
|
|
* @param sensor_type : Type of sensor
|
|
|
|
* e.g; BME680_PRESSURE,BME680_TEMPERATURE,BME680_HUMIDITY
|
|
|
|
* BME680_GAS,BME680_ALL
|
|
|
|
*
|
|
|
|
* @note: if "BME680_SPECIFIC_FIELD_DATA_READ_ENABLED" is not defined in
|
|
|
|
* bme680.h then for any sensor_type function will perform
|
|
|
|
* read operation for BME680_ALL.
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
* @note error code is returned when data readout is attempted
|
|
|
|
* in sleep mode or when field_count is not in the below range
|
|
|
|
* it must be 1<= field_count <= 3
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_get_uncomp_data(
|
|
|
|
struct bme680_uncomp_field_data *uncomp_data, u8 field_count,
|
|
|
|
u8 sensor_type, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
u8 a_data_u8[BME680_LEN_ALL_FIELD_SIZE];
|
|
|
|
struct bme680_uncomp_field_data temp_sensor_data[BME680_THREE];
|
|
|
|
|
|
|
|
#ifdef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
|
|
|
|
/*Array to store the new_data status of all 3 fields*/
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 new_data[BME680_THREE] = {0, 0,
|
|
|
|
0};
|
2016-06-22 14:23:09 +02:00
|
|
|
#endif
|
|
|
|
/*clear the the latest, recent and old field index*/
|
2017-05-09 13:59:35 +02:00
|
|
|
bme680->latest_field_index = 0;
|
|
|
|
bme680->recent_field_index = 0;
|
|
|
|
bme680->old_field_index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
if ((field_count < BME680_PRESENT_DATA_FIELD
|
|
|
|
|| field_count > BME680_ALL_DATA_FIELD)
|
|
|
|
|| (BME680_SLEEP_MODE == bme680->last_set_mode)) {
|
|
|
|
com_status = BME680_COMM_RES_ERROR;
|
|
|
|
} else {
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
}
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
#ifndef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
sensor_type = BME680_ALL;
|
|
|
|
field_count = BME680_ALL_DATA_FIELD;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (BME680_FORCED_MODE == bme680->last_set_mode) {
|
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0, a_data_u8,
|
|
|
|
BME680_SINGLE_FIELD_LENGTH);
|
|
|
|
field_count = BME680_PRESENT_DATA_FIELD;
|
|
|
|
} else {
|
|
|
|
#ifdef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
|
|
|
|
/*read status field of all 3 filed and extract the new_data
|
|
|
|
flag status.*/
|
|
|
|
com_status = bme680_read_status_fields(uncomp_data, a_data_u8,
|
|
|
|
new_data, bme680);
|
|
|
|
|
|
|
|
/*get the latest, recent and old field index*/
|
|
|
|
bme680_get_latest_recent_old_field_index(uncomp_data, bme680);
|
|
|
|
|
|
|
|
|
|
|
|
/*By default read latest field data */
|
|
|
|
if (BME680_TRUE == new_data[bme680->latest_field_index]) {
|
|
|
|
com_status =
|
|
|
|
bme680_get_field_specific_uncomp_data(
|
|
|
|
bme680->latest_field_index,
|
|
|
|
sensor_type,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
}
|
|
|
|
if (BME680_PRESENT_AND_PREVIOUS_DATA_FIELD == field_count) {
|
|
|
|
/* read recent field data */
|
|
|
|
if (BME680_TRUE ==
|
|
|
|
new_data[bme680->recent_field_index]) {
|
|
|
|
com_status =
|
|
|
|
bme680_get_field_specific_uncomp_data(
|
|
|
|
bme680->recent_field_index,
|
|
|
|
sensor_type,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (BME680_ALL_DATA_FIELD == field_count) {
|
|
|
|
|
|
|
|
/* read recent field data */
|
|
|
|
if (BME680_TRUE ==
|
|
|
|
new_data[bme680->recent_field_index]) {
|
|
|
|
com_status =
|
|
|
|
bme680_get_field_specific_uncomp_data(
|
|
|
|
bme680->recent_field_index,
|
|
|
|
sensor_type,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read old field data */
|
|
|
|
if (BME680_TRUE ==
|
|
|
|
new_data[bme680->old_field_index]) {
|
|
|
|
com_status =
|
|
|
|
bme680_get_field_specific_uncomp_data(
|
|
|
|
bme680->old_field_index,
|
|
|
|
sensor_type,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (BME680_ALL == sensor_type) {
|
|
|
|
/*read uncompensated sensor data of field 0,1,2*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0, a_data_u8,
|
|
|
|
BME680_LEN_ALL_FIELD_SIZE);
|
|
|
|
}
|
|
|
|
(uncomp_data + 0)->status.meas_index = a_data_u8[1];
|
|
|
|
(uncomp_data + 1)->status.meas_index = a_data_u8[18];
|
|
|
|
(uncomp_data + 2)->status.meas_index = a_data_u8[35];
|
|
|
|
|
|
|
|
/*get the latest, recent and old field index*/
|
|
|
|
bme680_get_latest_recent_old_field_index(uncomp_data, bme680);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
bme680_align_uncomp_data(a_data_u8,
|
|
|
|
field_count,
|
|
|
|
sensor_type,
|
|
|
|
uncomp_data,
|
|
|
|
bme680);
|
|
|
|
if (BME680_FORCED_MODE != bme680->last_set_mode) {
|
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index <
|
2016-06-22 14:23:09 +02:00
|
|
|
BME680_ALL_DATA_FIELD; index++)
|
|
|
|
temp_sensor_data[index] =
|
|
|
|
*(uncomp_data + index);
|
|
|
|
|
|
|
|
|
|
|
|
bme680_copy_ordered_sensor_field_data(
|
|
|
|
uncomp_data, bme680->latest_field_index,
|
|
|
|
bme680->recent_field_index,
|
|
|
|
bme680->old_field_index, sensor_type,
|
|
|
|
temp_sensor_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
#ifdef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the uncompensated
|
|
|
|
* data according to sensor type
|
|
|
|
* @note Field-0, Field-1 and Field-2
|
|
|
|
* @note Page-1
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param field_index : index of the field which needs
|
|
|
|
* to be read from the sensor
|
|
|
|
*
|
|
|
|
* @param sensor_type : Type of sensor
|
|
|
|
* e.g; BME680_PRESSURE,BME680_TEMPERATURE,BME680_HUMIDITY
|
|
|
|
* BME680_GAS,BME680_ALL
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to store read data.
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_get_field_specific_uncomp_data(
|
|
|
|
u8 field_index, u8 sensor_type, u8 *a_data_u8, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
|
|
|
|
|
|
|
|
if (BME680_PRESSURE == sensor_type ||
|
|
|
|
BME680_TEMPERATURE == sensor_type ||
|
|
|
|
BME680_HUMIDITY == sensor_type) {
|
|
|
|
|
|
|
|
com_status = bme680_Temp_field_specific_uncomp_read(
|
|
|
|
field_index,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
switch (sensor_type) {
|
|
|
|
case BME680_PRESSURE:
|
|
|
|
com_status = bme680_Pressure_field_specific_uncomp_read(
|
|
|
|
field_index,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case BME680_HUMIDITY:
|
|
|
|
com_status = bme680_Humidity_field_specific_uncomp_read(
|
|
|
|
field_index,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (BME680_GAS == sensor_type) {
|
|
|
|
|
|
|
|
com_status = bme680_Gas_field_specific_uncomp_read(field_index,
|
|
|
|
a_data_u8,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
} else if (BME680_ALL == sensor_type) {
|
|
|
|
/*read uncompensated sensor data of field 0,1,2*/
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0,
|
|
|
|
a_data_u8,
|
|
|
|
BME680_LEN_ALL_FIELD_SIZE);
|
|
|
|
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the uncompensated
|
|
|
|
* Temperature for specific Field type.
|
|
|
|
* Field-0, Field-1 and Field-2
|
|
|
|
*
|
|
|
|
* @param field_index : index of the field which needs
|
|
|
|
* to be read from the sensor
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to store read data.
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_Temp_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* local buffer length is 5 and it's the maximum */
|
|
|
|
u8 temp_data_u8[BME680_THREE];
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0; count < BME680_THREE; count++)
|
|
|
|
temp_data_u8[count] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
/*read uncompensated Temperature of field 0*/
|
|
|
|
if (BME680_FIELD_INDEX0 == field_index) {
|
|
|
|
/*read the 3 byte of T1 data form 0x22*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0_TEMP1,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_TEMPERATURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
5,6 & 7 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_TEMPERATURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[5 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read the 3 byte of T2 data form 0x27*/
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0_TEMP2,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_TEMPERATURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
10,11 & 12 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_TEMPERATURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[10 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Temperature of field 1*/
|
|
|
|
} else if (BME680_FIELD_INDEX1 == field_index) {
|
|
|
|
|
|
|
|
/*read the 3 byte of T1 data form 0x33*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_1_TEMP1,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_TEMPERATURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
22,23 & 24 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_TEMPERATURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[22 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read the 3 byte of T2 data form 0x38*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_1_TEMP2,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_TEMPERATURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
27,28 & 29 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_TEMPERATURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[27 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Temperature of field 2*/
|
|
|
|
} else if (BME680_FIELD_INDEX2 == field_index) {
|
|
|
|
|
|
|
|
/*read the 3 byte of T1 data form 0x44*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_2_TEMP1,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_TEMPERATURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
39,40 & 41 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_TEMPERATURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[39 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read the 3 byte of T2 data form 0x49*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_2_TEMP2,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_TEMPERATURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
44,45 & 46 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_TEMPERATURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[44 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the uncompensated
|
|
|
|
* Pressure for specific Field type.
|
|
|
|
* Field-0, Field-1 and Field-2
|
|
|
|
*
|
|
|
|
* @param field_index : index of the field which needs
|
|
|
|
* to be read from the sensor
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to store read data.
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_Pressure_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* local buffer length is 5 and it's the maximum */
|
|
|
|
u8 temp_data_u8[BME680_THREE];
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0; count < BME680_THREE; count++)
|
|
|
|
temp_data_u8[count] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
/*read uncompensated Pressure of field 0*/
|
|
|
|
if (BME680_FIELD_INDEX0 == field_index) {
|
|
|
|
/*read the 3 byte of P data form 0x1F*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0_PRESS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_PRESSURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
2,3 & 4 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_PRESSURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[2 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Pressure of field 1*/
|
|
|
|
} else if (BME680_FIELD_INDEX1 == field_index) {
|
|
|
|
|
|
|
|
/*read the 3 byte of P data
|
|
|
|
form 0x30*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_1_PRESS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_PRESSURE_DATA_LEN);
|
|
|
|
/*Assign data to the
|
|
|
|
reserved index
|
|
|
|
19,20 & 21 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_PRESSURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[19 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Pressure of field 2*/
|
|
|
|
} else if (BME680_FIELD_INDEX2 == field_index) {
|
|
|
|
|
|
|
|
/*read the 3 byte of P data
|
|
|
|
form 0x41*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_2_PRESS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_PRESSURE_DATA_LEN);
|
|
|
|
/*Assign data to the reserved
|
|
|
|
index 36,37 & 38 of the input
|
|
|
|
buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_PRESSURE_DATA_LEN; count++)
|
|
|
|
a_data_u8[36 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the uncompensated
|
|
|
|
* Humidity for specific Field type.
|
|
|
|
* Field-0, Field-1 and Field-2
|
|
|
|
*
|
|
|
|
* @param field_index : index of the field which needs
|
|
|
|
* to be read from the sensor
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to store read data.
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_Humidity_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* local buffer length is 5 and it's the maximum */
|
|
|
|
u8 temp_data_u8[BME680_TWO];
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0; count < BME680_TWO; count++)
|
|
|
|
temp_data_u8[count] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
/*read uncompensated Humidity of field 0*/
|
|
|
|
if (BME680_FIELD_INDEX0 == field_index) {
|
|
|
|
/*read the 2 byte of H data form 0x25*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0_HUM,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_HUMIDITY_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
8 & 9 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_HUMIDITY_DATA_LEN; count++)
|
|
|
|
a_data_u8[8 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Humidity of field 1*/
|
|
|
|
} else if (BME680_FIELD_INDEX1 == field_index) {
|
|
|
|
|
|
|
|
/*read the 2 byte of H data form 0x36*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_1_HUM,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_HUMIDITY_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
25 & 26 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_HUMIDITY_DATA_LEN; count++)
|
|
|
|
a_data_u8[25 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Humidity of field 2*/
|
|
|
|
} else if (BME680_FIELD_INDEX2 == field_index) {
|
|
|
|
|
|
|
|
/*read the 2 byte of H data form 0x47*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_2_HUM,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_HUMIDITY_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
42 & 43 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_HUMIDITY_DATA_LEN; count++)
|
|
|
|
a_data_u8[42 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the uncompensated
|
|
|
|
* Gas for specific Field type.
|
|
|
|
* Field-0, Field-1 and Field-2
|
|
|
|
*
|
|
|
|
* @param field_index : index of the field which needs
|
|
|
|
* to be read from the sensor
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to store read data.
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_Gas_field_specific_uncomp_read(
|
|
|
|
u8 field_index, u8 *a_data_u8, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* local buffer length is 5 and it's the maximum */
|
|
|
|
u8 temp_data_u8[BME680_TWO];
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0; count < BME680_TWO; count++)
|
|
|
|
temp_data_u8[count] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
/*read uncompensated Gas of field 0*/
|
|
|
|
if (BME680_FIELD_INDEX0 == field_index) {
|
|
|
|
/*Default field_0 required*/
|
|
|
|
/*read the 2 byte of G data form 0x2A*/
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0_GAS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_GAS_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
13,14 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_GAS_DATA_LEN; count++)
|
|
|
|
a_data_u8[13 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Gas of field 1*/
|
|
|
|
} else if (BME680_FIELD_INDEX1 == field_index) {
|
|
|
|
|
|
|
|
/*read the 2 byte of G data form 0x3B*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_1_GAS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_GAS_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
30,31 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_GAS_DATA_LEN; count++)
|
|
|
|
a_data_u8[30 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
/*read uncompensated Gas of field 2*/
|
|
|
|
} else if (BME680_FIELD_INDEX2 == field_index) {
|
|
|
|
|
|
|
|
/*read the 2 byte of G data form 0x4C*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_2_GAS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_GAS_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
47,48 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_GAS_DATA_LEN; count++)
|
|
|
|
a_data_u8[47 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to get the
|
|
|
|
* Operational Mode from the sensor in the
|
|
|
|
* register 0x74 bit 0 and 1
|
|
|
|
*
|
|
|
|
* @param power_mode_u8 : Pointer to store the received value
|
|
|
|
* of power mode
|
|
|
|
* value | mode
|
|
|
|
* -----------|------------------
|
|
|
|
* 0x00 | BME680_SLEEP_MODE
|
|
|
|
* 0x01 | BME680_FORCED_MODE
|
|
|
|
* 0x02 | BME680_PARALLEL_MODE
|
|
|
|
* 0x03 | BME680_SEQUENTIAL_MODE
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_get_power_mode(u8 *power_mode_u8,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 data_u8 = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
/* read power mode*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
|
|
|
BME680_ADDR_OP_MODE,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
*power_mode_u8 = BME680_GET_REG(data_u8,
|
|
|
|
BME680_MASK_OP_MODE,
|
|
|
|
BME680_SHIFT_OP_MODE);
|
|
|
|
/* updating power mode in global structure*/
|
|
|
|
if (bme680->last_set_mode != BME680_FORCED_MODE)
|
|
|
|
bme680->last_set_mode = *power_mode_u8;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to set the
|
|
|
|
* Operational Mode of the sensor in the
|
|
|
|
* register 0x74 bit 0 and 1
|
|
|
|
*
|
|
|
|
* @param power_mode_u8 : The value of power mode
|
|
|
|
* value | mode
|
|
|
|
* -------------|------------------
|
|
|
|
* 0x00 | BME680_SLEEP_MODE
|
|
|
|
* 0x01 | BME680_FORCED_MODE
|
|
|
|
* 0x02 | BME680_PARALLEL_MODE
|
|
|
|
* 0x03 | BME680_SEQUENTIAL_MODE
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_set_power_mode(u8 power_mode_u8,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 data_u8 = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
/* write power mode*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
|
|
|
BME680_ADDR_OP_MODE,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
data_u8 = BME680_SET_REG(data_u8, power_mode_u8,
|
|
|
|
BME680_MASK_OP_MODE, BME680_SHIFT_OP_MODE);
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_write(bme680->dev_addr,
|
|
|
|
BME680_ADDR_OP_MODE,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_WRITE_DATA_LENGTH);
|
|
|
|
}
|
|
|
|
/* updating power mode in global structure*/
|
|
|
|
if (BME680_COMM_RES_OK == com_status)
|
|
|
|
bme680->last_set_mode = power_mode_u8;
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to set the sensor configuration
|
|
|
|
*
|
|
|
|
* @param sens_conf : structure pointer which points to
|
|
|
|
* bme680_sens_conf structure passed by the user.
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @note reference input values from user are below
|
|
|
|
*
|
|
|
|
* heatr_ctrl = BME680_HEATR_CTRL_ENABLE;
|
|
|
|
* odr = BME680_ODR_20MS;
|
|
|
|
* run_gas = BME680_RUN_GAS_ENABLE;
|
|
|
|
* nb_conv = 0x01;
|
|
|
|
* osrs_hum = BME680_OSRS_1X;
|
|
|
|
* osrs_pres = BME680_OSRS_1X;
|
|
|
|
* osrs_temp = BME680_OSRS_1X;
|
|
|
|
* filter = BME680_FILTER_COEFF_1;
|
|
|
|
* spi_3w = BME680_SPI_3W_DISABLE;
|
|
|
|
* intr = BME680_SPI_3W_INTR_DISABLE
|
|
|
|
*
|
|
|
|
* @note nb_conv parameter is specific to power mode
|
|
|
|
* refer data sheet for detailed info.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_set_sensor_config(
|
|
|
|
struct bme680_sens_conf *sens_conf, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
u8 data_u8[(BME680_SENS_CONF_LEN*2)-1];
|
|
|
|
u8 index;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(
|
|
|
|
BME680_PAGE1_INTERFACE_SPI, bme680);
|
|
|
|
}
|
|
|
|
if (BME680_I2C_INTERFACE == bme680->interface)
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
for (index = 0; index < (BME680_SENS_CONF_LEN * 2) - 2;
|
|
|
|
index++)
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_SENSOR_CONFIG,
|
|
|
|
data_u8,
|
|
|
|
(BME680_SENS_CONF_LEN));
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
data_u8[BME680_INDEX_CTRL_GAS_0] =
|
|
|
|
(sens_conf->heatr_ctrl & 0x01)
|
|
|
|
<< BME680_SHIFT_HEATR_CTRL;
|
|
|
|
|
|
|
|
data_u8[BME680_INDEX_CTRL_GAS_1] =
|
|
|
|
((sens_conf->odr & 0x08) << BME680_SHIFT_ODR_3)
|
|
|
|
| ((sens_conf->run_gas & 0x01) <<
|
|
|
|
BME680_SHIFT_RUN_GAS) |
|
|
|
|
(sens_conf->nb_conv & 0x0F);
|
|
|
|
|
|
|
|
data_u8[BME680_INDEX_CTRL_HUM] =
|
|
|
|
((sens_conf->intr & 0x01) <<
|
|
|
|
BME680_SHIFT_SPI_3W_INT) |
|
|
|
|
(sens_conf->osrs_hum & 0x07);
|
|
|
|
|
|
|
|
data_u8[BME680_INDEX_CTRL_MEAS] =
|
|
|
|
((sens_conf->osrs_pres & 0x07) <<
|
|
|
|
BME680_SHIFT_OSRS_PRES) |
|
|
|
|
((sens_conf->osrs_temp & 0x07) <<
|
|
|
|
BME680_SHIFT_OSRS_TEMP) |
|
|
|
|
(data_u8[BME680_INDEX_CTRL_MEAS] & 0x03);
|
|
|
|
|
|
|
|
data_u8[BME680_INDEX_CONFIG] =
|
|
|
|
(((sens_conf->odr) & 0x07) <<
|
|
|
|
BME680_SHIFT_ODR_2_0) |
|
|
|
|
((sens_conf->filter & 0x07) <<
|
|
|
|
BME680_SHIFT_FILTER) |
|
|
|
|
(sens_conf->spi_3w & 0x01);
|
|
|
|
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
bme680_buffer_restruct_burst_write(data_u8,
|
|
|
|
0x70,
|
|
|
|
BME680_SENS_CONF_LEN,
|
|
|
|
(BME680_SENS_CONF_LEN * 2)-1);
|
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_write(bme680->dev_addr,
|
|
|
|
BME680_ADDR_SENSOR_CONFIG,
|
|
|
|
data_u8,
|
|
|
|
(BME680_SENS_CONF_LEN * 2)-1);
|
|
|
|
#else
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_write(bme680->dev_addr,
|
|
|
|
BME680_ADDR_SENSOR_CONFIG,
|
|
|
|
data_u8,
|
|
|
|
BME680_SENS_CONF_LEN);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to get the sensor configuration
|
|
|
|
*
|
|
|
|
* @param sens_conf : structure pointer which points to
|
|
|
|
* bme680_sens_conf structure passed by the user to store the
|
|
|
|
* received configuration
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @note reference output values from the sensor are below
|
|
|
|
*
|
|
|
|
* heatr_ctrl = BME680_HEATR_CTRL_ENABLE;
|
|
|
|
* odr = BME680_ODR_20MS;
|
|
|
|
* run_gas = BME680_RUN_GAS_ENABLE;
|
|
|
|
* nb_conv = 0x01;
|
|
|
|
* osrs_hum = BME680_OSRS_1X;
|
|
|
|
* osrs_pres = BME680_OSRS_1X;
|
|
|
|
* osrs_temp = BME680_OSRS_1X;
|
|
|
|
* filter = BME680_FILTER_COEFF_1;
|
|
|
|
* spi_3w = BME680_SPI_3W_DISABLE;
|
|
|
|
* intr = BME680_SPI_3W_INTR_DISABLE
|
|
|
|
*
|
|
|
|
* @note actual settings may differ as configured by user earlier using
|
|
|
|
* bme680_set_sensor_config function.
|
|
|
|
* @note nb_conv parameter is specific to power mode
|
|
|
|
* refer data sheet for detailed info.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_get_sensor_config(
|
|
|
|
struct bme680_sens_conf *sens_conf, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
u8 data_u8[BME680_SENS_CONF_LEN];
|
|
|
|
u8 index;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(
|
|
|
|
BME680_PAGE1_INTERFACE_SPI, bme680);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (BME680_I2C_INTERFACE == bme680->interface)
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
for (index = 0; index < BME680_SENS_CONF_LEN ; index++)
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_SENSOR_CONFIG,
|
|
|
|
data_u8,
|
|
|
|
BME680_SENS_CONF_LEN);
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
sens_conf->heatr_ctrl = (enum bme680_heatr_ctrl)
|
|
|
|
BME680_GET_REG(data_u8[BME680_INDEX_CTRL_GAS_0],
|
|
|
|
BME680_MASK_HEATR_CTRL,
|
|
|
|
BME680_SHIFT_HEATR_CTRL);
|
|
|
|
sens_conf->run_gas = (enum bme680_run_gas)
|
|
|
|
BME680_GET_REG(data_u8[BME680_INDEX_CTRL_GAS_1],
|
|
|
|
BME680_MASK_RUN_GAS,
|
|
|
|
BME680_SHIFT_RUN_GAS);
|
|
|
|
sens_conf->nb_conv = BME680_GET_REG(
|
|
|
|
data_u8[BME680_INDEX_CTRL_GAS_1],
|
|
|
|
BME680_MASK_PROF_INDEX,
|
|
|
|
BME680_SHIFT_PROF_INDEX);
|
|
|
|
sens_conf->odr = (enum bme680_odr)((BME680_GET_REG(
|
|
|
|
data_u8[BME680_INDEX_CTRL_GAS_1],
|
|
|
|
BME680_MASK_ODR_3,
|
|
|
|
BME680_SHIFT_ODR_3)) | (BME680_GET_REG(
|
|
|
|
data_u8[BME680_INDEX_CONFIG],
|
|
|
|
BME680_MASK_ODR_2_0,
|
|
|
|
BME680_SHIFT_ODR_2_0)));
|
|
|
|
sens_conf->osrs_hum = (enum bme680_osrs_x)
|
|
|
|
BME680_GET_REG(data_u8[BME680_INDEX_CTRL_HUM],
|
|
|
|
BME680_MASK_OSRS_HUM,
|
|
|
|
BME680_SHIFT_OSRS_HUM);
|
|
|
|
sens_conf->intr = (enum bme680_spi_3w_intr)
|
|
|
|
BME680_GET_REG(data_u8[BME680_INDEX_CTRL_HUM],
|
|
|
|
BME680_MASK_SPI_3W_INT,
|
|
|
|
BME680_SHIFT_SPI_3W_INT);
|
|
|
|
sens_conf->osrs_pres = (enum bme680_osrs_x)
|
|
|
|
BME680_GET_REG(data_u8[BME680_INDEX_CTRL_MEAS],
|
|
|
|
BME680_MASK_OSRS_PRES,
|
|
|
|
BME680_SHIFT_OSRS_PRES);
|
|
|
|
|
|
|
|
sens_conf->osrs_temp = (enum bme680_osrs_x)
|
|
|
|
BME680_GET_REG(data_u8[BME680_INDEX_CTRL_MEAS],
|
|
|
|
BME680_MASK_OSRS_TEMP,
|
|
|
|
BME680_SHIFT_OSRS_TEMP);
|
|
|
|
sens_conf->filter = (enum bme680_filter)BME680_GET_REG(
|
|
|
|
data_u8[BME680_INDEX_CONFIG],
|
|
|
|
BME680_MASK_FILTER,
|
|
|
|
BME680_SHIFT_FILTER);
|
|
|
|
sens_conf->spi_3w = (enum bme680_spi_3w)BME680_GET_REG(
|
|
|
|
data_u8[BME680_INDEX_CONFIG],
|
|
|
|
BME680_MASK_SPI_3W_EN,
|
|
|
|
BME680_SHIFT_SPI_3W_EN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used for setting gas heater configuration
|
2017-05-09 13:59:35 +02:00
|
|
|
* of the sensor from register 5A to 6E address
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
|
|
|
* @param heatr_conf : structure pointer of Heater configuration
|
|
|
|
* structure
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @note reference input values from user are below
|
|
|
|
*
|
|
|
|
* heater_temp - target temperature (200 to 400 deg cls)
|
|
|
|
* heatr_dur - heater duration ( 1 to 4032 ms)
|
|
|
|
* heatr_dur_shared - wait time for parallel mode
|
|
|
|
* profile_cnt - user configurable profiles(1 to 10)
|
|
|
|
*
|
|
|
|
* @note heatr_dur and heatr_duration share behaviour varies
|
|
|
|
* between parallel and other modes.
|
|
|
|
* kindly refer data-sheet
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_set_gas_heater_config(
|
|
|
|
struct bme680_heater_conf *heatr_conf, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
u8 data_u8[(BME680_SENS_HEATR_CONF_LEN << 1)-1] = {0};
|
|
|
|
u8 index;
|
|
|
|
u8 power_mode = 0;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(
|
|
|
|
BME680_PAGE1_INTERFACE_SPI, bme680);
|
|
|
|
} else if (BME680_I2C_INTERFACE == bme680->interface)
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
/* get power mode to identify parallel or other modes */
|
|
|
|
com_status = bme680_get_power_mode(&power_mode, bme680);
|
|
|
|
for (index = 0; index < heatr_conf->profile_cnt;
|
|
|
|
index++) {
|
2017-05-09 13:59:35 +02:00
|
|
|
|
2016-06-22 14:23:09 +02:00
|
|
|
#ifdef FIXED_POINT_COMPENSATION
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index] =
|
2016-06-22 14:23:09 +02:00
|
|
|
bme680_convert_temperature_to_resistance_int32(
|
|
|
|
heatr_conf->heater_temp[index],
|
|
|
|
25, bme680);
|
|
|
|
#else
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index] =
|
2016-06-22 14:23:09 +02:00
|
|
|
bme680_convert_temperature_to_resistance_double(
|
|
|
|
heatr_conf->heater_temp[index],
|
|
|
|
25, bme680);
|
|
|
|
#endif
|
|
|
|
if (power_mode != BME680_PARALLEL_MODE)
|
|
|
|
bme680_scale_to_multiplication_factor(
|
|
|
|
&heatr_conf->heatr_dur[index]);
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index + 10] = heatr_conf->heatr_dur[index];
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
if (BME680_PARALLEL_MODE == power_mode) {
|
|
|
|
heatr_conf->heatr_dur_shared =
|
|
|
|
(heatr_conf->heatr_dur_shared * 1000) /
|
|
|
|
BME680_GAS_WAIT_STEP_SIZE;
|
|
|
|
bme680_scale_to_multiplication_factor(
|
|
|
|
&heatr_conf->heatr_dur_shared);
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[20] = heatr_conf->heatr_dur_shared;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
bme680_buffer_restruct_burst_write(data_u8,
|
|
|
|
BME680_ADDR_SENS_CONF_START,
|
|
|
|
BME680_SENS_HEATR_CONF_LEN,
|
|
|
|
(BME680_SENS_HEATR_CONF_LEN << 1)-1);
|
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_write(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_SENS_CONF_START,
|
|
|
|
data_u8,
|
|
|
|
(BME680_SENS_HEATR_CONF_LEN << 1)-1);
|
|
|
|
#else
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_write(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_SENS_CONF_START,
|
|
|
|
data_u8,
|
|
|
|
BME680_SENS_HEATR_CONF_LEN);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to convert the gas duration
|
|
|
|
* according to multiplication factor of the sensor
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* gas_wait_X(5:0) define 64 timer values
|
|
|
|
* gas_wait_X(7:6) define a multiplication factor
|
|
|
|
*
|
|
|
|
* gas_wait_X (7:6) | multiplication factor
|
|
|
|
* ------------------|------------------------------
|
|
|
|
* 00 | 1
|
|
|
|
* 01 | 4
|
|
|
|
* 10 | 16
|
|
|
|
* 11 | 64
|
|
|
|
*
|
|
|
|
* @param duration_u16 : pointer to store the
|
|
|
|
* the converted gas duration
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void bme680_scale_to_multiplication_factor(u16 *duration_u16)
|
|
|
|
{
|
|
|
|
|
|
|
|
u8 factor = 0;
|
|
|
|
|
|
|
|
while ((*duration_u16) > BME680_GAS_WAIT_MAX_TIMER_VALUE) {
|
|
|
|
(*duration_u16) = (*duration_u16) >> 2;
|
|
|
|
factor += 1;
|
|
|
|
}
|
|
|
|
(*duration_u16) = (*duration_u16) + (factor * 64);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to rearrange the buffer
|
|
|
|
* according to burst write configuration of BME680 sensor
|
|
|
|
*
|
|
|
|
* @param arr : interface buffer for SPI or I2C
|
|
|
|
* @param reg_addr : register address to write
|
|
|
|
* @param data_size : no of bytes of data to write
|
|
|
|
* @param arr_size : size of the array
|
|
|
|
*
|
|
|
|
* @return none
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#ifndef __KERNEL__
|
|
|
|
static void bme680_buffer_restruct_burst_write(u8 arr[], u8 reg_addr,
|
|
|
|
u8 data_size, u8 arr_size)
|
|
|
|
{
|
|
|
|
s8 index, sub_index = 0;
|
|
|
|
|
|
|
|
for (index = 0 ; index < (data_size - 1); index++) {
|
|
|
|
arr[arr_size - 1 - sub_index] = arr[data_size - index - 1];
|
|
|
|
arr[arr_size - 2 - sub_index] = reg_addr + data_size - 1;
|
|
|
|
--reg_addr;
|
|
|
|
sub_index += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the sensor heater
|
2017-05-09 13:59:35 +02:00
|
|
|
* configuration from register 5A to 6E address
|
2016-06-22 14:23:09 +02:00
|
|
|
*
|
|
|
|
* @param heatr_conf : structure pointer of Heater
|
|
|
|
* configuration structure
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @note reference output values from the sensor are below
|
|
|
|
*
|
|
|
|
* heater_temp - target temperature (200 to 400 deg cls)
|
|
|
|
* heatr_dur - heater duration ( 1 to 4032 ms)
|
|
|
|
* heatr_dur_shared - wait time for parallel mode
|
|
|
|
*
|
|
|
|
* @note heatr_dur and heatr_duration share behaviour varies
|
|
|
|
* between parallel and other modes.
|
|
|
|
* kindly refer data-sheet
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
* @note if error code is -5 = BME680_PROFILE_CNT_ERROR
|
|
|
|
* means profile count is not set by user.
|
|
|
|
* it must be set before calling this function.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_get_gas_heater_config(
|
|
|
|
struct bme680_heater_conf *heatr_conf, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
u8 data_u8[BME680_SENS_HEATR_CONF_LEN];
|
|
|
|
u8 index;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
if (BME680_SPI_INTERFACE == bme680->interface) {
|
|
|
|
/* memory page switch the SPI address*/
|
|
|
|
com_status = bme680_set_memory_page(
|
|
|
|
BME680_PAGE1_INTERFACE_SPI, bme680);
|
|
|
|
} else if (BME680_I2C_INTERFACE == bme680->interface)
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
|
|
|
|
for (index = 0; index < BME680_SENS_HEATR_CONF_LEN; index++)
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
2017-05-09 13:59:35 +02:00
|
|
|
BME680_ADDR_SENS_CONF_START,
|
2016-06-22 14:23:09 +02:00
|
|
|
data_u8,
|
|
|
|
BME680_SENS_HEATR_CONF_LEN);
|
|
|
|
if (BME680_COMM_RES_OK == com_status) {
|
|
|
|
/* 0<= pc <=10 has been modified in order to
|
|
|
|
* avoid warning, "pointless comparison of
|
|
|
|
* unsigned int with zero"
|
|
|
|
*/
|
|
|
|
if ((heatr_conf->profile_cnt > 0 &&
|
|
|
|
heatr_conf->profile_cnt <= BME680_PROFILE_MAX) ||
|
|
|
|
(heatr_conf->profile_cnt == 0)) {
|
|
|
|
for (index = 0; index < BME680_PROFILE_MAX;
|
|
|
|
index++) {
|
|
|
|
heatr_conf->heater_temp[index] =
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index];
|
2016-06-22 14:23:09 +02:00
|
|
|
heatr_conf->heatr_dur[index] =
|
2017-05-09 13:59:35 +02:00
|
|
|
data_u8[index + 10];
|
2016-06-22 14:23:09 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
com_status = BME680_PROFILE_CNT_ERROR;
|
|
|
|
}
|
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
heatr_conf->heatr_dur_shared = data_u8[20];
|
2016-06-22 14:23:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to compensate the TPHG raw
|
|
|
|
* values of the sensor in order to convert to meaningful values
|
|
|
|
*
|
|
|
|
* @param uncomp_data : Pointer to array of structure which
|
|
|
|
* contains the uncompensated TPHG data
|
|
|
|
* @param comp_data : Pointer to array of structure which
|
|
|
|
* stores the compensated TPHG data
|
|
|
|
* @param field_count : total no of field data which needs to be
|
|
|
|
* compensated.
|
|
|
|
*
|
|
|
|
*field_count | Expected values
|
|
|
|
* -------------|-----------------------
|
|
|
|
* 1 | ONLY_ONE FIELD
|
|
|
|
* 2 | ONLY_TWO_FIELD
|
|
|
|
* 3 | THREE_FIELD
|
|
|
|
*
|
|
|
|
* @param sensor_type : Type of sensor
|
|
|
|
*
|
|
|
|
* sensor_type | Expected values
|
|
|
|
* ---------------------|-------------------
|
|
|
|
* BME680_ALL | TPGH data
|
|
|
|
* BME680_PRESSURE | Pressure data
|
|
|
|
* BME680_TEMPERATURE| Temp data
|
|
|
|
* BME680_HUMIDITY | Humidity data
|
|
|
|
* BME680_GAS | Gas data
|
|
|
|
*
|
|
|
|
* @note: if "BME680_SPECIFIC_FIELD_DATA_READ_ENABLED" is not defined in
|
|
|
|
* bme680.h then for any sensor_type function will perform
|
|
|
|
* read operation for BME680_ALL.
|
|
|
|
* @note : pressure and humidity depends on temperature.
|
|
|
|
*
|
|
|
|
* @param bme680 : structure pointer.
|
|
|
|
*
|
|
|
|
* @note Undefined behaviour for values other than mentioned above
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
* @note error code is returned when data readout is attempted
|
|
|
|
* in sleep mode or when field_count is not in the below range
|
|
|
|
* it must be 1<= field_count <= 3
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_compensate_data(
|
|
|
|
struct bme680_uncomp_field_data *uncomp_data,
|
|
|
|
struct bme680_comp_field_data *comp_data,
|
|
|
|
u8 field_count, u8 sensor_type, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
u8 index;
|
|
|
|
u8 max_count = 3;
|
|
|
|
|
|
|
|
if ((field_count < 1 || field_count > 3)
|
|
|
|
|| (BME680_SLEEP_MODE == bme680->last_set_mode)) {
|
|
|
|
com_status = BME680_COMM_RES_ERROR;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (BME680_FORCED_MODE == bme680->last_set_mode)
|
|
|
|
field_count = BME680_PRESENT_DATA_FIELD;
|
|
|
|
|
|
|
|
#ifndef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
sensor_type = BME680_ALL;
|
|
|
|
field_count = BME680_ALL_DATA_FIELD;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (index = 0; ((index < field_count) &&
|
|
|
|
(index < max_count)); index++) {
|
|
|
|
|
|
|
|
#ifdef FIXED_POINT_COMPENSATION
|
|
|
|
switch (sensor_type) {
|
|
|
|
|
|
|
|
case BME680_TEMPERATURE:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_int32(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_PRESSURE:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_int32(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_pressure =
|
|
|
|
bme680_compensate_pressure_int32(
|
|
|
|
(uncomp_data+index)->pres_adcv,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_HUMIDITY:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_int32(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_humidity =
|
|
|
|
bme680_compensate_humidity_int32(
|
|
|
|
(uncomp_data+index)->hum_adcv,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_GAS:
|
|
|
|
(comp_data + index)->comp_gas = bme680_calculate_gas_int32(
|
|
|
|
(uncomp_data+index)->gas_res_adcv,
|
|
|
|
(uncomp_data + index)->gas_range, bme680);
|
|
|
|
break;
|
|
|
|
case BME680_ALL:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_int32(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
(comp_data + index)->comp_pressure =
|
|
|
|
bme680_compensate_pressure_int32(
|
|
|
|
(uncomp_data+index)->pres_adcv,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
(comp_data + index)->comp_humidity =
|
|
|
|
bme680_compensate_humidity_int32(
|
|
|
|
(uncomp_data+index)->hum_adcv,
|
|
|
|
bme680);
|
|
|
|
|
|
|
|
(comp_data + index)->comp_gas = bme680_calculate_gas_int32(
|
|
|
|
(uncomp_data+index)->gas_res_adcv,
|
|
|
|
(uncomp_data + index)->gas_range,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
switch (sensor_type) {
|
|
|
|
|
|
|
|
case BME680_TEMPERATURE:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_double(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_PRESSURE:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_double(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_pressure =
|
|
|
|
bme680_compensate_pressure_double(
|
|
|
|
(uncomp_data+index)->pres_adcv,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_HUMIDITY:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_double(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_humidity =
|
|
|
|
bme680_compensate_humidity_double(
|
|
|
|
(uncomp_data+index)->hum_adcv,
|
|
|
|
(comp_data + index)->comp_temperature1,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_GAS:
|
|
|
|
(comp_data + index)->comp_gas =
|
|
|
|
bme680_compensate_gas_double(
|
|
|
|
(uncomp_data+index)->gas_res_adcv,
|
|
|
|
(uncomp_data + index)->gas_range,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
case BME680_ALL:
|
|
|
|
(comp_data + index)->comp_temperature1 =
|
|
|
|
bme680_compensate_temperature_double(
|
|
|
|
(uncomp_data+index)->temp_adcv,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_pressure =
|
|
|
|
bme680_compensate_pressure_double(
|
|
|
|
(uncomp_data+index)->pres_adcv,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_humidity =
|
|
|
|
bme680_compensate_humidity_double(
|
|
|
|
(uncomp_data+index)->hum_adcv,
|
|
|
|
(comp_data + index)->comp_temperature1,
|
|
|
|
bme680);
|
|
|
|
(comp_data + index)->comp_gas = bme680_compensate_gas_double(
|
|
|
|
(uncomp_data+index)->gas_res_adcv,
|
|
|
|
(uncomp_data + index)->gas_range,
|
|
|
|
bme680);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
com_status = BME680_COMM_RES_OK;
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to write memory page
|
|
|
|
* from the register 0x73 bit 4
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param memory_page_u8:
|
|
|
|
* The value of memory page
|
|
|
|
* value | Description
|
|
|
|
* --------|--------------
|
|
|
|
* 0 | BME680_PAGE0_INTERFACE_SPI
|
|
|
|
* 1 | BME680_PAGE1_INTERFACE_SPI
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval any negative value -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static enum bme680_return_type bme680_set_memory_page(u8 memory_page_u8,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 data_u8 = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
/* check the bme680 is NULL pointer */
|
|
|
|
if (BME680_NULL_PTR == bme680) {
|
|
|
|
com_status = BME680_ERROR_NULL_PTR;
|
|
|
|
} else {
|
|
|
|
/* write memory page*/
|
|
|
|
com_status = (enum bme680_return_type)bme680->bme680_bus_read(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_SPI_MEM_PAGE,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_READ_DATA_LENGTH);
|
|
|
|
data_u8 = BME680_SET_REG(data_u8, memory_page_u8,
|
|
|
|
BME680_MASK_MEM_PAGE,
|
|
|
|
BME680_SHIFT_SPI_MEM_PAGE);
|
|
|
|
if (BME680_COMM_RES_OK == com_status)
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_write(
|
|
|
|
bme680->dev_addr,
|
|
|
|
BME680_ADDR_SPI_MEM_PAGE,
|
|
|
|
&data_u8,
|
|
|
|
BME680_GEN_WRITE_DATA_LENGTH);
|
|
|
|
}
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to Align uncompensated data
|
|
|
|
* from function bme680_get_uncomp_data()
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to buffer
|
|
|
|
* @param field_count : total no of field data which needs
|
|
|
|
* to be compensated
|
|
|
|
* @param sensor_type : Type of sensor
|
|
|
|
*
|
|
|
|
* sensor_type | Expected values
|
|
|
|
* ---------------------|-------------------
|
|
|
|
* BME680_ALL | TPGH data
|
|
|
|
* BME680_PRESSURE | Pressure data
|
|
|
|
* BME680_TEMPERATURE| Temp data
|
|
|
|
* BME680_HUMIDITY | Humidity data
|
|
|
|
* BME680_GAS | Gas data
|
|
|
|
*
|
|
|
|
* @note : pressure and humidity depends on temperature.
|
|
|
|
*
|
|
|
|
* @param uncomp_data : Pointer to array of structure which
|
|
|
|
* contains the uncompensated TPHG data
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
* @return - None
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void bme680_align_uncomp_data(u8 *a_data_u8, u8 field_count, u8 sensor_type,
|
|
|
|
struct bme680_uncomp_field_data *uncomp_data, struct bme680_t *bme680)
|
|
|
|
{
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 offset = 0;
|
|
|
|
s8 index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
if (BME680_FORCED_MODE != bme680->last_set_mode)
|
|
|
|
field_count = BME680_ALL_DATA_FIELD;
|
|
|
|
|
|
|
|
for (index = 0; index < field_count; index++) {
|
|
|
|
|
|
|
|
offset = (index * BME680_FIELD_SIZE);
|
|
|
|
|
|
|
|
/* field_index status */
|
|
|
|
(uncomp_data + index)->status.new_data = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_MEAS_STATUS_0 + offset],
|
|
|
|
BME680_MASK_NEW_DATA,
|
|
|
|
BME680_SHIFT_NEW_DATA);
|
|
|
|
(uncomp_data + index)->status.gas_meas_stat = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_MEAS_STATUS_0 + offset],
|
|
|
|
BME680_MASK_GAS_MEAS_STAT,
|
|
|
|
BME680_SHIFT_GAS_MEAS_STAT);
|
|
|
|
(uncomp_data + index)->status.tphg_meas_stat = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_MEAS_STATUS_0 + offset],
|
|
|
|
BME680_MASK_TPHG_MEAS_STAT,
|
|
|
|
BME680_SHIFT_TPHG_MEAS_STAT);
|
|
|
|
(uncomp_data + index)->status.gas_meas_index = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_MEAS_STATUS_0 + offset],
|
|
|
|
BME680_MASK_GAS_MEAS_INDEX,
|
|
|
|
BME680_SHIFT_GAS_MEAS_INDEX);
|
|
|
|
(uncomp_data + index)->status.meas_index =
|
|
|
|
a_data_u8[FIELD_0_MEAS_STATUS_1 + offset];
|
|
|
|
(uncomp_data + index)->gas_range = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_GAS_RL_LSB + offset],
|
|
|
|
BME680_MASK_GAS_RANGE,
|
|
|
|
BME680_SHIFT_GAS_RANGE);
|
|
|
|
(uncomp_data + index)->status.gas_valid = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_GAS_RL_LSB + offset],
|
|
|
|
BME680_MASK_GAS_VALID,
|
|
|
|
BME680_SHIFT_GAS_VALID);
|
|
|
|
(uncomp_data + index)->status.heatr_stab = BME680_GET_REG(
|
|
|
|
a_data_u8[FIELD_0_GAS_RL_LSB + offset],
|
|
|
|
BME680_MASK_HEATR_STAB,
|
|
|
|
BME680_SHIFT_HEATR_STAB);
|
|
|
|
|
|
|
|
/* uncompensated field zero
|
|
|
|
pressure data*/
|
|
|
|
bme680_align_sensor_type_uncomp_data(a_data_u8, index, offset,
|
|
|
|
sensor_type,
|
|
|
|
uncomp_data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to get the index of latest, recent and old
|
|
|
|
* field data according to the sub_meas_index parameter.
|
|
|
|
*
|
|
|
|
* @param sensor_data : structure pointer of uncompensated array
|
|
|
|
* of 3 structure
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval Any Negative -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void bme680_get_latest_recent_old_field_index(
|
|
|
|
struct bme680_uncomp_field_data *sensor_data,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* Array holding the filed0, field1 and field2
|
|
|
|
temperature, pressure, humidity and gas data*/
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 latest = 0;
|
|
|
|
u8 recent = 0;
|
|
|
|
u8 old = 0;
|
|
|
|
u8 index = 0;
|
|
|
|
u8 large_index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
u8 max_index = 2;
|
|
|
|
u8 meas_index[3];
|
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < 3; index++)
|
|
|
|
meas_index[index] = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
index = 0;
|
|
|
|
for (index = 0; index < 3; index++)
|
|
|
|
meas_index[index] = (sensor_data + index)->status.meas_index;
|
|
|
|
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
latest = DIFF(meas_index[0], meas_index[1]);
|
|
|
|
if ((DIFF(meas_index[0], meas_index[1]) > 2) ||
|
|
|
|
(DIFF(meas_index[1], meas_index[2]) > 2)) {
|
|
|
|
|
|
|
|
while (meas_index[index++] != 255)
|
|
|
|
;
|
|
|
|
old = --index;
|
|
|
|
if (index == 2) {
|
|
|
|
recent = index - 2;
|
|
|
|
latest = index - 1;
|
|
|
|
} else if (index == 1) {
|
|
|
|
recent = index + 1;
|
|
|
|
latest = index - 1;
|
|
|
|
} else {
|
|
|
|
recent = index + 1;
|
|
|
|
latest = index + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
large_index = bme680_find_largest_index(meas_index);
|
|
|
|
latest = large_index;
|
|
|
|
if (large_index == max_index) {
|
|
|
|
recent = max_index - 1;
|
|
|
|
old = max_index - 2;
|
|
|
|
} else if (large_index == (max_index - 1)) {
|
|
|
|
recent = max_index - 2;
|
|
|
|
old = max_index;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
recent = max_index;
|
|
|
|
old = max_index - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
bme680->latest_field_index = latest;
|
|
|
|
bme680->recent_field_index = recent;
|
|
|
|
bme680->old_field_index = old;
|
|
|
|
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to read the status of all 3 fields
|
|
|
|
*
|
|
|
|
* @param uncomp_data : Pointer to array of uncompensated data structure.
|
|
|
|
* @param a_data_u8: pointer to store the read status data.
|
|
|
|
* @param new_data: pointer to store the new_data value of given field
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval Any Negative -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum bme680_return_type bme680_read_status_fields(
|
|
|
|
struct bme680_uncomp_field_data *uncomp_data,
|
|
|
|
u8 *a_data_u8, u8 *new_data,
|
|
|
|
struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
/* used to return the communication result*/
|
|
|
|
enum bme680_return_type com_status = BME680_COMM_RES_ERROR;
|
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
/* local buffer length is 5 and it's the maximum */
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 temp_data_u8[2] = {0, 0};
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*read the 2 byte of status form 0x1D - field_0*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_0_STATUS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_STATUS_DATA_LEN);
|
|
|
|
/* Assign data to the reserved
|
|
|
|
index of the input buffer */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_STATUS_DATA_LEN; count++)
|
|
|
|
a_data_u8[0 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
(uncomp_data + 0)->status.meas_index = a_data_u8[1];
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status)
|
|
|
|
new_data[0] = BME680_GET_REG(a_data_u8[0],
|
|
|
|
BME680_MASK_NEW_DATA,
|
|
|
|
BME680_SHIFT_NEW_DATA);
|
|
|
|
|
|
|
|
|
|
|
|
/*read the 2 byte of status form 0x2E - field_1*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_1_STATUS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_STATUS_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
17 and 18 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_STATUS_DATA_LEN; count++)
|
|
|
|
a_data_u8[17 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
(uncomp_data + 1)->status.meas_index = a_data_u8[18];
|
|
|
|
|
|
|
|
if (BME680_COMM_RES_OK == com_status)
|
|
|
|
new_data[1] = BME680_GET_REG(a_data_u8[17],
|
|
|
|
BME680_MASK_NEW_DATA,
|
|
|
|
BME680_SHIFT_NEW_DATA);
|
|
|
|
|
|
|
|
/*read the 2 byte of status form 0x3F - field_2*/
|
|
|
|
com_status = (enum bme680_return_type)
|
|
|
|
bme680->bme680_bus_read(bme680->dev_addr,
|
|
|
|
BME680_ADDR_FIELD_2_STATUS,
|
|
|
|
temp_data_u8,
|
|
|
|
BME680_STATUS_DATA_LEN);
|
|
|
|
/*Assign data to the reserved index
|
|
|
|
34 and 35 of the input buffer*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (count = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
count < BME680_STATUS_DATA_LEN; count++)
|
|
|
|
a_data_u8[34 + count] = temp_data_u8[count];
|
|
|
|
|
|
|
|
(uncomp_data + 2)->status.meas_index = a_data_u8[35];
|
|
|
|
if (BME680_COMM_RES_OK == com_status)
|
|
|
|
new_data[2] = BME680_GET_REG(a_data_u8[34],
|
|
|
|
BME680_MASK_NEW_DATA,
|
|
|
|
BME680_SHIFT_NEW_DATA);
|
|
|
|
return com_status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to copy the ordered
|
|
|
|
* uncompensated data
|
|
|
|
*
|
|
|
|
* @param sensor_data : structure pointer of uncompensated array
|
|
|
|
* of 3 structure
|
|
|
|
* @param latest : total no of field
|
|
|
|
* @param recent : total no of field
|
|
|
|
* @param old : total no of field
|
|
|
|
*
|
|
|
|
* @param sensor_type : type of the sensor
|
|
|
|
* @param temp_sensor_data: structure pointer.
|
|
|
|
*
|
|
|
|
* @return results of bus communication function
|
|
|
|
* @retval 0 -> Success
|
|
|
|
* @retval Any Negative -> Error
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void bme680_copy_ordered_sensor_field_data(
|
|
|
|
struct bme680_uncomp_field_data *sensor_data,
|
|
|
|
u8 latest, u8 recent, u8 old, u8 sensor_type,
|
|
|
|
struct bme680_uncomp_field_data *temp_sensor_data)
|
|
|
|
{
|
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
#ifndef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
sensor_type = BME680_ALL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED
|
|
|
|
/* copy status of all field */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
sensor_data[index].status =
|
|
|
|
temp_sensor_data[latest].status;
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
sensor_data[index].status =
|
|
|
|
temp_sensor_data[recent].status;
|
|
|
|
else
|
|
|
|
sensor_data[index].status =
|
|
|
|
temp_sensor_data[old].status;
|
|
|
|
}
|
|
|
|
if (BME680_PRESSURE == sensor_type || BME680_TEMPERATURE == sensor_type
|
|
|
|
|| BME680_HUMIDITY == sensor_type) {
|
|
|
|
|
|
|
|
/* copy temperature data
|
|
|
|
by default for Pressure and Humidity
|
|
|
|
*/
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
sensor_data[index].temp_adcv =
|
|
|
|
temp_sensor_data[latest].temp_adcv;
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
sensor_data[index].temp_adcv =
|
|
|
|
temp_sensor_data[recent].temp_adcv;
|
|
|
|
else {
|
|
|
|
sensor_data[index].temp_adcv =
|
|
|
|
temp_sensor_data[old].temp_adcv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (sensor_type) {
|
|
|
|
case BME680_PRESSURE:
|
|
|
|
/* copying only pressure data */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
sensor_data[index].pres_adcv =
|
|
|
|
temp_sensor_data[latest].pres_adcv;
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
sensor_data[index].pres_adcv =
|
|
|
|
temp_sensor_data[recent].pres_adcv;
|
|
|
|
else {
|
|
|
|
sensor_data[index].pres_adcv =
|
|
|
|
temp_sensor_data[old].pres_adcv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BME680_HUMIDITY:
|
|
|
|
/* copying only humidity data */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
sensor_data[index].hum_adcv =
|
|
|
|
temp_sensor_data[latest].hum_adcv;
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
sensor_data[index].hum_adcv =
|
|
|
|
temp_sensor_data[recent].hum_adcv;
|
|
|
|
else {
|
|
|
|
sensor_data[index].hum_adcv =
|
|
|
|
temp_sensor_data[old].hum_adcv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (BME680_GAS == sensor_type) {
|
|
|
|
/* copying only gas data */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
sensor_data[index].gas_res_adcv =
|
|
|
|
temp_sensor_data[latest].gas_res_adcv;
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
sensor_data[index].gas_res_adcv =
|
|
|
|
temp_sensor_data[recent].gas_res_adcv;
|
|
|
|
else {
|
|
|
|
sensor_data[index].gas_res_adcv =
|
|
|
|
temp_sensor_data[old].gas_res_adcv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (BME680_ALL == sensor_type) {
|
|
|
|
/* copying T,P,G,& H data */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
*(sensor_data + index) =
|
|
|
|
*(temp_sensor_data + latest);
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
*(sensor_data + index) =
|
|
|
|
*(temp_sensor_data + recent);
|
|
|
|
else
|
|
|
|
*(sensor_data + index) =
|
|
|
|
*(temp_sensor_data + old);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (BME680_ALL == sensor_type) {
|
|
|
|
/* copying T,P,G,& H data */
|
2017-05-09 13:59:35 +02:00
|
|
|
for (index = 0; index < BME680_MAX_FIELD_INDEX;
|
2016-06-22 14:23:09 +02:00
|
|
|
index++) {
|
|
|
|
if (index == BME680_FIELD_INDEX0)
|
|
|
|
*(sensor_data + index) =
|
|
|
|
*(temp_sensor_data + latest);
|
|
|
|
else if (index == BME680_FIELD_INDEX1)
|
|
|
|
*(sensor_data + index) =
|
|
|
|
*(temp_sensor_data + recent);
|
|
|
|
else
|
|
|
|
*(sensor_data + index) =
|
|
|
|
*(temp_sensor_data + old);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This utility function is to return the largest number
|
|
|
|
* index of the input array passed to the function.
|
|
|
|
*
|
|
|
|
* @param meas_index: pointer to the integer array
|
|
|
|
*
|
|
|
|
* @return index of largest element of the array
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static u8 bme680_find_largest_index(u8 *meas_index)
|
|
|
|
{
|
|
|
|
|
2017-05-09 13:59:35 +02:00
|
|
|
u8 index = 0;
|
|
|
|
u8 temp_index = 0;
|
2016-06-22 14:23:09 +02:00
|
|
|
|
|
|
|
if (*(meas_index + index) > *(meas_index + (index + 2))) {
|
|
|
|
if (*(meas_index + index) > *(meas_index + (index + 1)))
|
|
|
|
temp_index = index;
|
|
|
|
else
|
|
|
|
temp_index = index + 1;
|
|
|
|
} else {
|
|
|
|
temp_index = index + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return temp_index;
|
|
|
|
}
|
|
|
|
/*!
|
|
|
|
* @brief This function is used to uncompensated data
|
|
|
|
* for the specified sensor type and called from the
|
|
|
|
* function bme680_align_uncomp_data()
|
|
|
|
*
|
|
|
|
* @param a_data_u8 : pointer to buffer
|
|
|
|
* @param index : index value
|
|
|
|
* @param offset : offset value
|
|
|
|
* @param uncomp_data : Pointer to array of structure which
|
|
|
|
* contains the uncompensated TPHG data
|
|
|
|
* @param sensor_type : type of sensor which needs
|
|
|
|
* to be compensated.
|
|
|
|
*
|
|
|
|
* sensor_type | Expected values
|
|
|
|
* ---------------------|-------------------
|
|
|
|
* BME680_ALL | TPGH data
|
|
|
|
* BME680_PRESSURE | Pressure data
|
|
|
|
* BME680_TEMPERATURE| Temp data
|
|
|
|
* BME680_HUMIDITY | Humidity data
|
|
|
|
* BME680_GAS | Gas data
|
|
|
|
*
|
|
|
|
* @note : pressure and humidity depends on temperature.
|
|
|
|
*
|
|
|
|
* @param bme680 structure pointer.
|
|
|
|
*
|
|
|
|
* @return - None
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void bme680_align_sensor_type_uncomp_data(u8 *a_data_u8, u8 index,
|
|
|
|
u8 offset, u8 sensor_type,
|
|
|
|
struct bme680_uncomp_field_data *uncomp_data)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (sensor_type) {
|
|
|
|
case BME680_PRESSURE:
|
|
|
|
/* uncompensated field zero
|
|
|
|
temperature data*/
|
|
|
|
(uncomp_data + index)->temp_adcv = (u32)(((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_MSB_DATA + offset]))
|
|
|
|
<< 12) | ((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_LSB_DATA + offset]))
|
|
|
|
<< 4) | ((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_XLSB_DATA + offset]
|
|
|
|
>> 4));
|
|
|
|
/* uncompensated field zero
|
|
|
|
pressure data*/
|
|
|
|
(uncomp_data + index)->pres_adcv = (u32)(((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_PRESSURE_MSB_DATA + offset])) << 12) |
|
|
|
|
((((u32)a_data_u8[BME680_DATA_FRAME_PRESSURE_LSB_DATA
|
|
|
|
+ offset])) << 4) | ((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_PRESSURE_XLSB_DATA + offset] >> 4));
|
|
|
|
break;
|
|
|
|
case BME680_TEMPERATURE:
|
|
|
|
/* uncompensated field zero
|
|
|
|
temperature data*/
|
|
|
|
(uncomp_data + index)->temp_adcv = (u32)(((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_MSB_DATA + offset]))
|
|
|
|
<< 12) | ((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_LSB_DATA + offset]))
|
|
|
|
<< 4) | ((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_XLSB_DATA + offset]
|
|
|
|
>> 4));
|
|
|
|
break;
|
|
|
|
case BME680_HUMIDITY:
|
|
|
|
/* uncompensated field zero
|
|
|
|
temperature data*/
|
|
|
|
(uncomp_data + index)->temp_adcv = (u32)(((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_MSB_DATA + offset]))
|
|
|
|
<< 12) | ((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_LSB_DATA + offset]))
|
|
|
|
<< 4) | ((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_XLSB_DATA + offset]
|
|
|
|
>> 4));
|
|
|
|
/* uncompensated field zero
|
|
|
|
humidity data*/
|
|
|
|
(uncomp_data + index)->hum_adcv = (u16)(((((u16)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_HUMIDITY_MSB_DATA + offset])) << 8)|
|
|
|
|
((a_data_u8[BME680_DATA_FRAME_HUMIDITY_LSB_DATA +
|
|
|
|
offset])));
|
|
|
|
break;
|
|
|
|
case BME680_GAS:
|
|
|
|
/* Gas values are updated
|
|
|
|
only if gas valid is set */
|
|
|
|
/* uncompensated field zero Gas data*/
|
|
|
|
if (BME680_TRUE == (uncomp_data + index)->status.gas_valid) {
|
|
|
|
(uncomp_data + index)->gas_res_adcv =
|
|
|
|
(u16)(((((u16)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_GAS_MSB_DATA + offset])) << 2)
|
|
|
|
| ((((u16)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_GAS_LSB_DATA + offset])
|
|
|
|
& BME680_GAS_BIT_MASK) >> 6));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BME680_ALL:
|
|
|
|
/* uncompensated field zero
|
|
|
|
pressure data*/
|
|
|
|
(uncomp_data + index)->pres_adcv = (u32)
|
|
|
|
(((((u32)a_data_u8[BME680_DATA_FRAME_PRESSURE_MSB_DATA +
|
|
|
|
offset])) << 12) | ((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_PRESSURE_LSB_DATA + offset])) << 4) |
|
|
|
|
((u32)a_data_u8[BME680_DATA_FRAME_PRESSURE_XLSB_DATA +
|
|
|
|
offset] >> 4));
|
|
|
|
/* uncompensated field zero
|
|
|
|
temperature data*/
|
|
|
|
(uncomp_data + index)->temp_adcv = (u32)(((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_MSB_DATA + offset]))
|
|
|
|
<< 12) | ((((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_LSB_DATA + offset]))
|
|
|
|
<< 4) | ((u32)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_TEMPERATURE1_XLSB_DATA + offset]
|
|
|
|
>> 4));
|
|
|
|
/* uncompensated field zero
|
|
|
|
humidity data*/
|
|
|
|
(uncomp_data + index)->hum_adcv = (u16)(((((u16)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_HUMIDITY_MSB_DATA + offset])) << 8)|
|
|
|
|
((a_data_u8[BME680_DATA_FRAME_HUMIDITY_LSB_DATA +
|
|
|
|
offset])));
|
|
|
|
/* Gas values are updated
|
|
|
|
only if gas valid is set */
|
|
|
|
/* uncompensated field zero Gas data*/
|
|
|
|
if (BME680_TRUE == (uncomp_data + index)->status.gas_valid) {
|
|
|
|
(uncomp_data + index)->gas_res_adcv =
|
|
|
|
(u16)(((((u16)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_GAS_MSB_DATA
|
|
|
|
+ offset])) << 2) | ((((u16)a_data_u8[
|
|
|
|
BME680_DATA_FRAME_GAS_LSB_DATA + offset]) &
|
|
|
|
BME680_GAS_BIT_MASK) >> 6));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void bme680_packing_calib_param(u8 *a_data_u8, struct bme680_t *bme680)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* read temperature calibration*/
|
|
|
|
bme680->cal_param.par_T1 = (u16)((((u16)(a_data_u8[DIG_T1_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_T1_LSB_REG]);
|
|
|
|
bme680->cal_param.par_T2 = (s16)(((((u16)a_data_u8[DIG_T2_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_T2_LSB_REG]);
|
|
|
|
bme680->cal_param.par_T3 = (s8)(a_data_u8[DIG_T3_REG]);
|
|
|
|
|
|
|
|
/* read pressure calibration*/
|
|
|
|
bme680->cal_param.par_P1 = (u16)((((u16)(a_data_u8[DIG_P1_MSB_REG])) <<
|
|
|
|
8) | a_data_u8[DIG_P1_LSB_REG]);
|
|
|
|
bme680->cal_param.par_P2 = (s16)(((((u16)a_data_u8[DIG_P2_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_P2_LSB_REG]);
|
|
|
|
bme680->cal_param.par_P3 = (s8)a_data_u8[DIG_P3_REG];
|
|
|
|
bme680->cal_param.par_P4 = (s16)(((((u16)a_data_u8[DIG_P4_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_P4_LSB_REG]);
|
|
|
|
bme680->cal_param.par_P5 = (s16)(((((u16)a_data_u8[DIG_P5_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_P5_LSB_REG]);
|
|
|
|
bme680->cal_param.par_P6 = (s8)(a_data_u8[DIG_P6_REG]);
|
|
|
|
bme680->cal_param.par_P7 = (s8)(a_data_u8[DIG_P7_REG]);
|
|
|
|
bme680->cal_param.par_P8 = (s16)(((((u16)a_data_u8[DIG_P8_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_P8_LSB_REG]);
|
|
|
|
bme680->cal_param.par_P9 = (s16)(((((u16)a_data_u8[DIG_P9_MSB_REG]))
|
|
|
|
<< 8) | a_data_u8[DIG_P9_LSB_REG]);
|
|
|
|
bme680->cal_param.par_P10 = (u8)(a_data_u8[DIG_P10_REG]);
|
|
|
|
|
|
|
|
/* read humidity calibration*/
|
|
|
|
bme680->cal_param.par_H1 = (u16)(((((u16)a_data_u8[DIG_H1_MSB_REG]))
|
|
|
|
<< 4) | (a_data_u8[DIG_H1_LSB_REG] & BME680_BIT_MASK_H1_DATA));
|
|
|
|
bme680->cal_param.par_H2 = (u16)(((((u16)a_data_u8[DIG_H2_MSB_REG]))
|
|
|
|
<< 4) | ((a_data_u8[DIG_H2_LSB_REG]) >> 4));
|
|
|
|
bme680->cal_param.par_H3 = (s8)a_data_u8[DIG_H3_REG];
|
|
|
|
bme680->cal_param.par_H4 = (s8) a_data_u8[DIG_H4_REG];
|
|
|
|
bme680->cal_param.par_H5 = (s8) a_data_u8[DIG_H5_REG];
|
|
|
|
bme680->cal_param.par_H6 = (u8)a_data_u8[DIG_H6_REG];
|
|
|
|
bme680->cal_param.par_H7 = (s8)a_data_u8[DIG_H7_REG];
|
|
|
|
|
|
|
|
/* read gas calibration*/
|
|
|
|
bme680->cal_param.par_GH1 = (s8)a_data_u8[DIG_GH1_REG];
|
|
|
|
bme680->cal_param.par_GH2 = (s16)(((((u16)a_data_u8[DIG_GH2_MSB_REG]))
|
|
|
|
<<8) | a_data_u8[DIG_GH2_LSB_REG]);
|
|
|
|
bme680->cal_param.par_GH3 = (s8)a_data_u8[DIG_GH3_REG];
|
|
|
|
|
|
|
|
}
|
|
|
|
|