diff --git a/BME680_SensorAPI_Example_Guide.pdf b/BME680_SensorAPI_Example_Guide.pdf deleted file mode 100644 index 87eeca2..0000000 Binary files a/BME680_SensorAPI_Example_Guide.pdf and /dev/null differ diff --git a/README.md b/README.md index eb19a0e..5cf73d2 100644 --- a/README.md +++ b/README.md @@ -1,148 +1,239 @@ -## Table of Contents -- [Introduction](#intro) -- [Version](#ver) -- [Integration details](#integration) -- [Driver files information](#fileinfo) -- [Supported sensor interface](#interface) -- [Simple Integration Example](#sample) +# BME680 sensor API +## Introduction +This package contains the Bosch Sensortec's BME680 gas sensor API -### Introduction -- This package contains the Bosch Sensortec MEMS BME680 sensor driver (sensor API) -- The sensor driver package includes below files - * bme680.c - * bme680.h - * bme680_calculations.c - * bme680_calculations.h - * bme680_internal.h - * sensor_api_common_types.h +The sensor driver package includes bme680.h, bme680.c and bme680_defs.h files -### Version +## Version File | Version | Date -----|---------|----- -bme680.c | 2.2.0 | 5 May 2017 -bme680.h | 2.2.0 | 5 May 2017 -bme680_calculations.c | 2.2.0 | 5 May 2017 -bme680_calculations.h | 2.2.0 | 5 May 2017 -bme680_internal.h | 2.2.0 | 5 May 2017 -sensor_api_common_types.h | 2.2.0 | 5 May 2017 +bme680.c | 3.5.1 | 5 Jul 2017 +bme680.h | 3.5.1 | 5 Jul 2017 +bme680_defs.h | 3.5.1 | 5 Jul 2017 -### Integration details -- Integrate files bme680.c, bme680.h, bme680_calculations.c, bme680_calculations.h, bme680_internal.h and sensor_api_common_types.h into your project. -- Include the bme680.h file in your code like below. +## Integration details +* Integrate bme680.h, bme680_defs.h and bme680.c file in to your project. +* Include the bme680.h file in your code like below. ``` c #include "bme680.h" -``` -- The BME680_SensorAPI_Example_Guide.pdf contains examples for API use cases. - -### Driver files information -- bme680.h - * This header file has the constant definitions, user data types and supported sensor driver calls declarations which is required by the user. -- bme680.c - * This file contains the implementation for the sensor driver APIs. -- bme680_calculations.h - * This header file has the internal function declaration for the sensor calculation. -- bme680_calculations.c - * This file contains the implementation of the sensor calculations for sensor driver APIs. -- bme680_internal.h - * This header file has the register address definition, internal constant definitions. -- sensor_api_common_types.h - * This header file has the data type definition for different compiler platform. - -### Supported sensor interface -- This BME680 sensor driver supports SPI and I2C interfaces - -### Simple Integration Example -- A simple example for BME680 is given below. -- Example meant for Single BME680 sensor in Force Mode with Temperature, Pressure, Humidity and Gas Enabled -- Please refer bme680.h to refer the API calls for the integration. -``` c -/* include bme680 main header */ -#include "bme680.h" -/*! -* BME680_MAX_NO_OF_SENSOR = 2; defined in bme680.h file -* In order to interface only one sensor over SPI, user must change the value of -* BME680_MAX_NO_OF_SENSOR = 1 -* Test setup: It has been assumed that �BME680 sensor_0� interfaced over SPI with -* Native chip select line -*/ -/* BME680 sensor structure instance */ -struct bme680_t bme680_sensor_no[BME680_MAX_NO_OF_SENSOR]; -/* BME680 sensor's compensated data structure instance */ -struct bme680_comp_field_data compensate_data_sensor[BME680_MAX_NO_OF_SENSOR][3]; -/* BME680 sensor's uncompensated data structure instance */ -struct bme680_uncomp_field_data uncompensated_data_of_sensor[BME680_MAX_NO_OF_SENSOR][3]; -/* BME680 sensor's configuration structure instance */ -struct bme680_sens_conf set_conf_sensor[BME680_MAX_NO_OF_SENSOR]; -/* BME680 sensor's heater configuration structure instance */ -struct bme680_heater_conf set_heatr_conf_sensor[BME680_MAX_NO_OF_SENSOR]; - -void main(void) -{ - unsigned int i = 0; - enum bme680_return_type com_rslt = BME680_COMM_RES_ERROR; - - /* Do BME680 sensor structure instance initialization*/ - /* Sensor_0 interface over SPI with native chip select line */ - /* USER defined SPI bus read function */ - bme680_sensor_no[0].bme680_bus_read = BME680_SPI_bus_read_user; - /* USER defined SPI bus write function */ - bme680_sensor_no[0].bme680_bus_write = BME680_SPI_bus_write_user; - /* USER defined SPI burst read function */ - bme680_sensor_no[0].bme680_burst_read = BME680_SPI_bus_read_user; - /* USER defined delay function */ - bme680_sensor_no[0].delay_msec = BME680_delay_msec_user; - /* Mention communication interface */ - bme680_sensor_no[0].interface = BME680_SPI_INTERFACE; - - /* get chip id and calibration parameter */ - com_rslt = bme680_init(&bme680_sensor_no[0]); - - /* Do Sensor initialization */ - for (i=0;i 0 Warning + */ +static int8_t analyze_sensor_data(struct bme680_field_data *data, uint8_t n_meas); + +/*! + * @brief Self-test API for the BME680 + */ +int8_t bme680_self_test(struct bme680_dev *dev) +{ + int8_t rslt = BME680_OK; + struct bme680_field_data data[N_MEAS]; + + struct bme680_dev t_dev; + + /* Copy required parameters from reference bme680_dev struct */ + t_dev.dev_id = dev->dev_id; + t_dev.amb_temp = 25; + t_dev.read = dev->read; + t_dev.write = dev->write; + t_dev.intf = dev->intf; + t_dev.delay_ms = dev->delay_ms; + + rslt = bme680_init(&t_dev); + + if (rslt == BME680_OK) { + /* Select the power mode */ + /* Must be set before writing the sensor configuration */ + t_dev.power_mode = BME680_FORCED_MODE; + + uint16_t settings_sel; + + /* Set the temperature, pressure and humidity & filter settings */ + t_dev.tph_sett.os_hum = BME680_OS_1X; + t_dev.tph_sett.os_pres = BME680_OS_16X; + t_dev.tph_sett.os_temp = BME680_OS_2X; + + /* Set the remaining gas sensor settings and link the heating profile */ + t_dev.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; + t_dev.gas_sett.heatr_dur = HEATR_DUR; + + settings_sel = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL; + + uint16_t profile_dur = 0; + bme680_get_profile_dur(&profile_dur, &t_dev); + + uint8_t i = 0; + while ((rslt == BME680_OK) && (i < N_MEAS)) { + if (rslt == BME680_OK) { + + if (i % 2 == 0) + t_dev.gas_sett.heatr_temp = LOW_TEMP; /* Lower temperature */ + else + t_dev.gas_sett.heatr_temp = HIGH_TEMP; /* Higher temperature */ + + rslt = bme680_set_sensor_settings(settings_sel, &t_dev); + + if (rslt == BME680_OK) { + + rslt = bme680_set_sensor_mode(&t_dev); /* Trigger a measurement */ + + t_dev.delay_ms(profile_dur); /* Wait for the measurement to complete */ + + rslt = bme680_get_sensor_data(&data[i], &t_dev); + } + } + + i++; + } + + if (rslt == BME680_OK) + rslt = analyze_sensor_data(data, N_MEAS); + } + + return rslt; +} + +/*! + * @brief Function to analyze the sensor data + */ +static int8_t analyze_sensor_data(struct bme680_field_data *data, uint8_t n_meas) +{ + int8_t rslt = BME680_OK; + uint8_t self_test_failed = 0, i; + uint32_t cent_res = 0; + + if ((data[0].temperature < MIN_TEMPERATURE) || (data[0].temperature > MAX_TEMPERATURE)) + self_test_failed++; + + if ((data[0].pressure < MIN_PRESSURE) || (data[0].pressure > MAX_PRESSURE)) + self_test_failed++; + + if ((data[0].humidity < MIN_HUMIDITY) || (data[0].humidity > MAX_HUMIDITY)) + self_test_failed++; + + for (i = 0; i < n_meas; i++) /* Every gas measurement should be valid */ + if (!(data[i].status & (BME680_GASM_VALID_MSK | BME680_HEAT_STAB_MSK))) + self_test_failed++; + + for (i = 2; i < n_meas; i += 2) { + /* Invert formula to get integer values for centroid resistance, i.e. > 1 */ + cent_res = (data[i - 2].gas_resistance + data[i].gas_resistance) / (2 * data[i - 1].gas_resistance); + } + + if ((cent_res < 3) || (cent_res > 20)) /* 0.05 > cent_res^-1 < 0.03 */ + self_test_failed++; + + if (self_test_failed) + rslt = BME680_W_SELF_TEST_FAILED; + + return rslt; +} + +/** @}*/ diff --git a/Self test/bme680_selftest.h b/Self test/bme680_selftest.h new file mode 100644 index 0000000..1b1be60 --- /dev/null +++ b/Self test/bme680_selftest.h @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bme680_selftest.h + * @date 5 Jul 2017 + * @version 3.5.1 + * @brief + * + */ + +/*! + * @addtogroup bme680_selftest + * @brief + * @{*/ + + +#ifndef BME680_SELFTEST_H_ +#define BME680_SELFTEST_H_ + +#include "bme680.h" + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" +{ +#endif + +#define BME680_W_SELF_TEST_FAILED 3 + +/*! + * @brief Self-test API for the BME680 + * + * @param[in] Device structure containing relevant information on how + * to communicate with the sensor + * + * @return Error code + * @retval 0 Success + * @retval < 0 Error + * @retval > 0 Warning + */ +int8_t bme680_self_test(struct bme680_dev *dev); + +/*! CPP guard */ +#ifdef __cplusplus +} +#endif + +#endif /* BME680_SELFTEST_H_ */ + +/** @}*/ diff --git a/bme680.c b/bme680.c index d4efcc2..1b53aa5 100644 --- a/bme680.c +++ b/bme680.c @@ -1,2558 +1,1105 @@ /**\mainpage -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bme680.c -* -* Date: 5 May 2017 -* -* Revision : 2.2.0 $ -* -* Usage: Sensor Driver for BME680 sensor -* -**************************************************************************** -* -* \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. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bme680.c - \brief BME680 Sensor Driver Support source File */ + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * File bme680.c + * @date 5 Jul 2017 + * @version 3.5.1 + * + */ -/*************************************************************************** - Header files -****************************************************************************/ +/*! @file bme680.c + @brief Sensor driver for BME680 sensor */ #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 -****************************************************************************/ +/**static variables */ +/**Look up table for the possible gas range values */ +uint32_t lookupTable1[16] = { UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), + UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2130303777), UINT32_C(2147483647), + UINT32_C(2147483647), UINT32_C(2143188679), UINT32_C(2136746228), UINT32_C(2147483647), UINT32_C(2126008810), + UINT32_C(2147483647), UINT32_C(2147483647) }; +/**Look up table for the possible gas range values */ +uint32_t lookupTable2[16] = { UINT32_C(4096000000), UINT32_C(2048000000), UINT32_C(1024000000), UINT32_C(512000000), + UINT32_C(255744255), UINT32_C(127110228), UINT32_C(64000000), UINT32_C(32258064), UINT32_C(16016016), UINT32_C( + 8000000), UINT32_C(4000000), UINT32_C(2000000), UINT32_C(1000000), UINT32_C(500000), UINT32_C(250000), + UINT32_C(125000) }; /*! - * @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 + * @brief This internal API is used to read the calibrated data from the sensor. * - * @param bme680 structure pointer. + * This function is used to retrieve the calibration + * data from the image registers of the sensor. * - * @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; - u8 data_u8 = 0; - /* 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 + * @note Registers 89h to A1h for calibration data 1 to 24 * from bit 0 to 7 - * @note Registers E1h to F0h for calibration data 25 to 40 + * @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*/ - u8 v_data_u8 = 0; - u8 a_data_u8[BME680_CALIB_PARAM_SIZE]; - u8 index = 0; - - - for (; index < BME680_CALIB_PARAM_SIZE; index++) - a_data_u8[index] = 0; - - /* 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 - * + * @param[in] dev :Structure instance of bme680_dev. * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve 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; -} +static int8_t get_calib_data(struct bme680_dev *dev); + /*! - * @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 + * @brief This internal API is used to set the gas configuration of the sensor. * + * @param[in] dev :Structure instance of bme680_dev. * + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve 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; -} +static int8_t set_gas_config(struct bme680_dev *dev); /*! - * @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 + * @brief This internal API is used to get the gas configuration of the sensor. * + * @param[in] dev :Structure instance of bme680_dev. * - * @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; -} + * @return Result of API execution status. + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t get_gas_config(struct bme680_dev *dev); /*! - * @brief This function is used to read the uncompensated - * sensor data from Field-0, Field-1, Field-2 and page-1 + * @brief This internal API is used to calculate the Heat duration value. * - * @param uncomp_data: - * Pointer to store the value of uncompensated sensor - * data of pressure, temperature, humidity and gas + * @param[in] dur :Value of the duration to be shared. * - * @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; - u8 index = 0; - 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*/ - u8 new_data[BME680_THREE] = {0, 0, - 0}; - #endif - /*clear the the latest, recent and old field index*/ - bme680->latest_field_index = 0; - bme680->recent_field_index = 0; - bme680->old_field_index = 0; - - 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) { - - for (index = 0; index < - 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; -} - + * @return uint8_t threshold duration after calculation. + */ +static uint8_t calc_heater_dur(uint16_t dur); /*! - * @brief This function is used to read the uncompensated - * Temperature for specific Field type. - * Field-0, Field-1 and Field-2 + * @brief This internal API is used to calculate the temperature value. * - * @param field_index : index of the field which needs - * to be read from the sensor + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] temp_adc :Contains the temperature ADC value . * - * @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]; - u8 count = 0; - - for (count = 0; count < BME680_THREE; count++) - temp_data_u8[count] = 0; - - /*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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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]; - u8 count = 0; - - for (count = 0; count < BME680_THREE; count++) - temp_data_u8[count] = 0; - - /*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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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]; - u8 count = 0; - - for (count = 0; count < BME680_TWO; count++) - temp_data_u8[count] = 0; - /*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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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]; - u8 count = 0; - - for (count = 0; count < BME680_TWO; count++) - temp_data_u8[count] = 0; - - /*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*/ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - count < BME680_GAS_DATA_LEN; count++) - a_data_u8[47 + count] = temp_data_u8[count]; - - } - return com_status; -} - -#endif - - - + * @return uint32_t calculated temperature. + */ +static int16_t calc_temperature(uint32_t temp_adc, struct bme680_dev *dev); /*! - * @brief This function is used to get the - * Operational Mode from the sensor in the - * register 0x74 bit 0 and 1 + * @brief This internal API is used to calculate the pressure value. * - * @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[in] dev :Structure instance of bme680_dev. + * @param[in] pres_adc :Contains the pressure ADC value . * - * @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) -{ - u8 data_u8 = 0; - /* 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) -{ - u8 data_u8 = 0; - /* 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++) - data_u8[index] = 0; - 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++) - data_u8[index] = 0; - - 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; -} - + * @return uint32_t calculated pressure. + */ +static uint32_t calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev); /*! - * @brief This function is used for setting gas heater configuration - * of the sensor from register 5A to 6E address + * @brief This internal API is used to calculate the humidity value. * - * @param heatr_conf : structure pointer of Heater configuration - * structure + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] hum_adc :Contains the humidity ADC value. * - * @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++) { - - #ifdef FIXED_POINT_COMPENSATION - data_u8[index] = - bme680_convert_temperature_to_resistance_int32( - heatr_conf->heater_temp[index], - 25, bme680); - #else - data_u8[index] = - 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]); - data_u8[index + 10] = heatr_conf->heatr_dur[index]; - - } - 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); - data_u8[20] = heatr_conf->heatr_dur_shared; - - } -#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; -} + * @return uint32_t calculated humidity. + */ +static uint32_t calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev); /*! - * @brief This function is used to convert the gas duration - * according to multiplication factor of the sensor + * @brief This internal API is used to calculate the Gas Resistance value. * - * @note - * gas_wait_X(5:0) define 64 timer values - * gas_wait_X(7:6) define a multiplication factor + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] gas_res_adc :Contains the Gas Resistance ADC value. + * @param[in] gas_range :Contains the range of gas values. * - * 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); - -} + * @return uint32_t calculated gas resistance. + */ +static uint32_t calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev); /*! - * @brief This function is used to rearrange the buffer - * according to burst write configuration of BME680 sensor + * @brief This internal API is used to calculate the Heat Resistance value. * - * @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 + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] temp :Contains the temporary value. * - * @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 - * configuration from register 5A to 6E address - * - * @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++) - data_u8[index] = 0; - - com_status = (enum bme680_return_type) - bme680->bme680_bus_read(bme680->dev_addr, - BME680_ADDR_SENS_CONF_START, - 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] = - data_u8[index]; - heatr_conf->heatr_dur[index] = - data_u8[index + 10]; - } - } else { - com_status = BME680_PROFILE_CNT_ERROR; - } - - heatr_conf->heatr_dur_shared = data_u8[20]; - } - } - } - return com_status; - - -} + * @return uint8_t calculated heater resistance. + */ +static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev); /*! - * @brief This function is used to compensate the TPHG raw - * values of the sensor in order to convert to meaningful values + * @brief This internal API is used to calculate the field data of sensor. * - * @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. + * @param[out] data :Structure instance to hold the data + * @param[in] dev :Structure instance of bme680_dev. * - *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) -{ + * @return int8_t result of the field data from sensor. + */ +static int8_t read_field_data(struct bme680_field_data *data, struct bme680_dev *dev); - /* 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 + * @brief This internal API is used to set the memory page + * based on register address. * - * - * @param memory_page_u8: - * The value of memory page - * value | Description + * The value of memory page + * value | Description * --------|-------------- - * 0 | BME680_PAGE0_INTERFACE_SPI - * 1 | BME680_PAGE1_INTERFACE_SPI + * 0 | BME680_PAGE0_SPI + * 1 | BME680_PAGE1_SPI * + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] reg_addr :Contains the register address array. * - * @param bme680 structure pointer. + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t set_mem_page(uint8_t reg_addr, struct bme680_dev *dev); + +/*! + * @brief This internal API is used to get the memory page based + * on register address. * - * @return results of bus communication function - * @retval 0 -> Success - * @retval any negative value -> Error + * The value of memory page + * value | Description + * --------|-------------- + * 0 | BME680_PAGE0_SPI + * 1 | BME680_PAGE1_SPI * + * @param[in] dev :Structure instance of bme680_dev. * -*/ -static enum bme680_return_type bme680_set_memory_page(u8 memory_page_u8, - struct bme680_t *bme680) + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t get_mem_page(struct bme680_dev *dev); + +/*! + * @brief This internal API is used to validate the device pointer for + * null conditions. + * + * @param[in] dev :Structure instance of bme680_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t null_ptr_check(const struct bme680_dev *dev); + +/*! + * @brief This internal API is used to check the boundary + * conditions. + * + * @param[in] value :pointer to the value. + * @param[in] min :minimum value. + * @param[in] max :maximum value. + * @param[in] dev :Structure instance of bme680_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +static int8_t boundary_check(uint8_t *value, uint8_t min, uint8_t max, struct bme680_dev *dev); + +/****************** Global Function Definitions *******************************/ +/*! + *@brief This API is the entry point. + *It reads the chip-id and calibration data from the sensor. + */ +int8_t bme680_init(struct bme680_dev *dev) { - u8 data_u8 = 0; - /* 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; + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) + { + /* Soft reset to restore it to default values*/ + rslt = bme680_soft_reset(dev); + + if (rslt == BME680_OK) { + rslt = bme680_get_regs(BME680_CHIP_ID_ADDR, &dev->chip_id, 1, dev); + if (rslt == BME680_OK) { + if (dev->chip_id == BME680_CHIP_ID) { + rslt = get_calib_data(dev); + } else { + rslt = BME680_E_DEV_NOT_FOUND; + } + } + } + } + + return rslt; +} + +/*! + * @brief This API reads the data from the given register address of the sensor. + */ +int8_t bme680_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme680_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + if (dev->intf == BME680_SPI_INTF) { + /* Set the memory page */ + rslt = set_mem_page(reg_addr, dev); + if (rslt == BME680_OK) + reg_addr = reg_addr | BME680_SPI_RD_MSK; + } + dev->com_rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); + if (dev->com_rslt != 0) + rslt = BME680_E_COM_FAIL; + } + + return rslt; +} + +/*! + * @brief This API writes the given data to the register address + * of the sensor. + */ +int8_t bme680_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme680_dev *dev) +{ + int8_t rslt; + /* Length of the temporary buffer is 2*(length of register)*/ + uint8_t tmp_buff[BME680_TMP_BUFFER_LENGTH] = { 0 }; + uint16_t index; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + if ((len > 0) && (len < BME680_TMP_BUFFER_LENGTH / 2)) { + /* Interleave the 2 arrays */ + for (index = 0; index < len; index++) { + if (dev->intf == BME680_SPI_INTF) { + /* Set the memory page */ + rslt = set_mem_page(reg_addr[index], dev); + tmp_buff[(2 * index)] = reg_addr[index] & BME680_SPI_WR_MSK; + } else { + tmp_buff[(2 * index)] = reg_addr[index]; + } + tmp_buff[(2 * index) + 1] = reg_data[index]; + } + /* Write the interleaved array */ + if (rslt == BME680_OK) { + dev->com_rslt = dev->write(dev->dev_id, tmp_buff[0], &tmp_buff[1], (2 * len) - 1); + if (dev->com_rslt != 0) + rslt = BME680_E_COM_FAIL; + } } 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); + rslt = BME680_E_INVALID_LENGTH; + } } - return com_status; + + return rslt; } /*! - * @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) + * @brief This API performs the soft reset of the sensor. + */ +int8_t bme680_soft_reset(struct bme680_dev *dev) { - u8 offset = 0; - s8 index = 0; + int8_t rslt; + uint8_t reg_addr = BME680_SOFT_RESET_ADDR; + /* 0xb6 is the soft reset command */ + uint8_t soft_rst_cmd = BME680_SOFT_RESET_CMD; - if (BME680_FORCED_MODE != bme680->last_set_mode) - field_count = BME680_ALL_DATA_FIELD; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + if (dev->intf == BME680_SPI_INTF) + rslt = get_mem_page(dev); - 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); + /* Reset the device */ + if (rslt == BME680_OK) { + rslt = bme680_set_regs(®_addr, &soft_rst_cmd, 1, dev); + /* Wait for 5ms */ + dev->delay_ms(BME680_RESET_PERIOD); + if (rslt == BME680_OK) { + /* After reset get the memory page */ + if (dev->intf == BME680_SPI_INTF) + rslt = get_mem_page(dev); + } + } } + return rslt; } /*! - * @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) + * @brief This API is used to set the oversampling, filter and T,P,H, gas selection + * settings in the sensor. + */ +int8_t bme680_set_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev) { - /* Array holding the filed0, field1 and field2 - temperature, pressure, humidity and gas data*/ - u8 latest = 0; - u8 recent = 0; - u8 old = 0; - u8 index = 0; - u8 large_index = 0; - u8 max_index = 2; - u8 meas_index[3]; + int8_t rslt; + uint8_t reg_addr; + uint8_t data = 0; + uint8_t count = 0; + uint8_t reg_array[BME680_REG_BUFFER_LENGTH] = { 0 }; + uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 }; + uint8_t intended_power_mode = dev->power_mode; /* Save intended power mode */ - for (index = 0; index < 3; index++) - meas_index[index] = 0; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + if (desired_settings & BME680_GAS_MEAS_SEL) + rslt = set_gas_config(dev); - index = 0; - for (index = 0; index < 3; index++) - meas_index[index] = (sensor_data + index)->status.meas_index; + dev->power_mode = BME680_SLEEP_MODE; + if (rslt == BME680_OK) + rslt = bme680_set_sensor_mode(dev); + /* Selecting the filter */ + if (desired_settings & BME680_FILTER_SEL) { + rslt = boundary_check(&dev->tph_sett.filter, BME680_FILTER_SIZE_0, BME680_FILTER_SIZE_127, dev); + reg_addr = BME680_CONF_ODR_FILT_ADDR; - 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)) { + if (rslt == BME680_OK) + rslt = bme680_get_regs(reg_addr, &data, 1, dev); - 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; + if (desired_settings & BME680_FILTER_SEL) + data = BME680_SET_BITS(data, BME680_FILTER, dev->tph_sett.filter); + + reg_array[count] = reg_addr; /* Append configuration */ + data_array[count] = data; + count++; + } + + /* Selecting heater control for the sensor */ + if (desired_settings & BME680_HCNTRL_SEL) { + rslt = boundary_check(&dev->gas_sett.heatr_ctrl, BME680_ENABLE_HEATER, BME680_DISABLE_HEATER, dev); + reg_addr = BME680_CONF_HEAT_CTRL_ADDR; + + if (rslt == BME680_OK) + rslt = bme680_get_regs(reg_addr, &data, 1, dev); + data = BME680_SET_BITS_POS_0(data, BME680_HCTRL, dev->gas_sett.heatr_ctrl); + + reg_array[count] = reg_addr; /* Append configuration */ + data_array[count] = data; + count++; + } + + /* Selecting heater T,P oversampling for the sensor */ + if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) { + rslt = boundary_check(&dev->tph_sett.os_temp, BME680_OS_NONE, BME680_OS_16X, dev); + reg_addr = BME680_CONF_T_P_MODE_ADDR; + + if (rslt == BME680_OK) + rslt = bme680_get_regs(reg_addr, &data, 1, dev); + + if (desired_settings & BME680_OST_SEL) + data = BME680_SET_BITS(data, BME680_OST, dev->tph_sett.os_temp); + + if (desired_settings & BME680_OSP_SEL) + data = BME680_SET_BITS(data, BME680_OSP, dev->tph_sett.os_pres); + + reg_array[count] = reg_addr; + data_array[count] = data; + count++; + } + + /* Selecting humidity oversampling for the sensor */ + if (desired_settings & BME680_OSH_SEL) { + rslt = boundary_check(&dev->tph_sett.os_hum, BME680_OS_NONE, BME680_OS_16X, dev); + reg_addr = BME680_CONF_OS_H_ADDR; + + if (rslt == BME680_OK) + rslt = bme680_get_regs(reg_addr, &data, 1, dev); + data = BME680_SET_BITS_POS_0(data, BME680_OSH, dev->tph_sett.os_hum); + + reg_array[count] = reg_addr; /* Append configuration */ + data_array[count] = data; + count++; + } + + /* Selecting the runGas and NB conversion settings for the sensor */ + if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) { + rslt = boundary_check(&dev->gas_sett.run_gas, BME680_RUN_GAS_DISABLE, BME680_RUN_GAS_ENABLE, dev); + if (rslt == BME680_OK) + rslt = boundary_check(&dev->gas_sett.nb_conv, BME680_NBCONV_MIN, BME680_NBCONV_MAX, dev); + reg_addr = BME680_CONF_ODR_RUN_GAS_NBC_ADDR; + + if (rslt == BME680_OK) + rslt = bme680_get_regs(reg_addr, &data, 1, dev); + + if (desired_settings & BME680_RUN_GAS_SEL) + data = BME680_SET_BITS(data, BME680_RUN_GAS, dev->gas_sett.run_gas); + + if (desired_settings & BME680_NBCONV_SEL) + data = BME680_SET_BITS_POS_0(data, BME680_NBCONV, dev->gas_sett.nb_conv); + + reg_array[count] = reg_addr; /* Append configuration */ + data_array[count] = data; + count++; + } + + if (rslt == BME680_OK) + rslt = bme680_set_regs(reg_array, data_array, count, dev); + + /* Restore previous intended power mode */ + dev->power_mode = intended_power_mode; + } + + return rslt; +} + +/*! + * @brief This API is used to get the oversampling, filter and T,P,H, gas selection + * settings in the sensor. + */ +int8_t bme680_get_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev) +{ + int8_t rslt; + /* starting address of the register array for burst read*/ + uint8_t reg_addr = BME680_CONF_HEAT_CTRL_ADDR; + uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 }; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + rslt = bme680_get_regs(reg_addr, data_array, BME680_REG_BUFFER_LENGTH, dev); + + if (rslt == BME680_OK) { + if (desired_settings & BME680_GAS_MEAS_SEL) + rslt = get_gas_config(dev); + + /* get the T,P,H ,Filter,ODR settings here */ + if (desired_settings & BME680_FILTER_SEL) + dev->tph_sett.filter = BME680_GET_BITS(data_array[BME680_REG_FILTER_INDEX], BME680_FILTER); + + if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) { + dev->tph_sett.os_temp = BME680_GET_BITS(data_array[BME680_REG_TEMP_INDEX], BME680_OST); + dev->tph_sett.os_pres = BME680_GET_BITS(data_array[BME680_REG_PRES_INDEX], BME680_OSP); } + if (desired_settings & BME680_OSH_SEL) + dev->tph_sett.os_hum = BME680_GET_BITS_POS_0(data_array[BME680_REG_HUM_INDEX], BME680_OSH); + + /* get the gas related settings */ + if (desired_settings & BME680_HCNTRL_SEL) + dev->gas_sett.heatr_ctrl = BME680_GET_BITS_POS_0(data_array[BME680_REG_HCTRL_INDEX], BME680_HCTRL); + + if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) { + dev->gas_sett.nb_conv = BME680_GET_BITS_POS_0(data_array[BME680_REG_NBCONV_INDEX], BME680_NBCONV); + dev->gas_sett.run_gas = BME680_GET_BITS(data_array[BME680_REG_RUN_GAS_INDEX], BME680_RUN_GAS); + } + } } 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; - } - + rslt = BME680_E_NULL_PTR; } - 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; - - u8 count = 0; - /* local buffer length is 5 and it's the maximum */ - u8 temp_data_u8[2] = {0, 0}; - - - /*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 */ - for (count = 0; - 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*/ - for (count = 0; - 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*/ - for (count = 0; - 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; + return rslt; } /*! - * @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) + * @brief This API is used to set the power mode of the sensor. + */ +int8_t bme680_set_sensor_mode(struct bme680_dev *dev) { + int8_t rslt; + uint8_t tmp_pow_mode; + uint8_t pow_mode = 0; + uint8_t reg_addr = BME680_CONF_T_P_MODE_ADDR; - u8 index = 0; -#ifndef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED - sensor_type = BME680_ALL; -#endif + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + /* Call recursively until in sleep */ + do { + rslt = bme680_get_regs(BME680_CONF_T_P_MODE_ADDR, &tmp_pow_mode, 1, dev); + if (rslt == BME680_OK) { + /* Put to sleep before changing mode */ + pow_mode = (tmp_pow_mode & BME680_MODE_MSK); -#ifdef BME680_SPECIFIC_FIELD_DATA_READ_ENABLED - /* copy status of all field */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 (pow_mode != BME680_SLEEP_MODE) { + tmp_pow_mode = tmp_pow_mode & (~BME680_MODE_MSK); /* Set to sleep */ + rslt = bme680_set_regs(®_addr, &tmp_pow_mode, 1, dev); + dev->delay_ms(BME680_POLL_PERIOD_MS); + } + } + } while (pow_mode != BME680_SLEEP_MODE); + + /* Already in sleep */ + if (dev->power_mode != BME680_SLEEP_MODE) { + tmp_pow_mode = (tmp_pow_mode & ~BME680_MODE_MSK) | (dev->power_mode & BME680_MODE_MSK); + if (rslt == BME680_OK) + rslt = bme680_set_regs(®_addr, &tmp_pow_mode, 1, dev); + } } - if (BME680_PRESSURE == sensor_type || BME680_TEMPERATURE == sensor_type - || BME680_HUMIDITY == sensor_type) { - /* copy temperature data - by default for Pressure and Humidity - */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 */ - for (index = 0; index < BME680_MAX_FIELD_INDEX; - 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 + return rslt; } + /*! - * @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) + * @brief This API is used to get the power mode of the sensor. + */ +int8_t bme680_get_sensor_mode(struct bme680_dev *dev) { + int8_t rslt; + uint8_t mode; - u8 index = 0; - u8 temp_index = 0; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + rslt = bme680_get_regs(BME680_CONF_T_P_MODE_ADDR, &mode, 1, dev); + /* Masking the other register bit info*/ + dev->power_mode = mode & BME680_MODE_MSK; + } - if (*(meas_index + index) > *(meas_index + (index + 2))) { - if (*(meas_index + index) > *(meas_index + (index + 1))) - temp_index = index; - else - temp_index = index + 1; + return rslt; +} + +/*! + * @brief This API is used to set the profile duration of the sensor. + */ +void bme680_set_profile_dur(uint16_t duration, struct bme680_dev *dev) +{ + uint32_t tph_dur; /* Calculate in us */ + + /* TPH measurement duration */ + tph_dur = ((uint32_t) (dev->tph_sett.os_temp + dev->tph_sett.os_pres + dev->tph_sett.os_hum) * UINT32_C(1963)); + tph_dur += UINT32_C(477 * 4); /* TPH switching duration */ + tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */ + tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/ + tph_dur /= UINT32_C(1000); /* Convert to ms */ + + tph_dur += UINT32_C(1); /* Wake up duration of 1ms */ + /* The remaining time should be used for heating */ + dev->gas_sett.heatr_dur = duration - (uint16_t) tph_dur; +} + +/*! + * @brief This API is used to get the profile duration of the sensor. + */ +void bme680_get_profile_dur(uint16_t *duration, struct bme680_dev *dev) +{ + uint32_t tph_dur; /* Calculate in us */ + + /* TPH measurement duration */ + tph_dur = ((uint32_t) (dev->tph_sett.os_temp + dev->tph_sett.os_pres + dev->tph_sett.os_hum) * UINT32_C(1963)); + tph_dur += UINT32_C(477 * 4); /* TPH switching duration */ + tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */ + tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/ + tph_dur /= UINT32_C(1000); /* Convert to ms */ + + tph_dur += UINT32_C(1); /* Wake up duration of 1ms */ + /* The remaining time should be used for heating */ + *duration = dev->gas_sett.heatr_dur + (uint16_t) tph_dur; +} + +/*! + * @brief This API reads the pressure, temperature and humidity and gas data + * from the sensor, compensates the data and store it in the bme680_data + * structure instance passed by the user. + */ +int8_t bme680_get_sensor_data(struct bme680_field_data *data, struct bme680_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + /* Reading the sensor data in forced mode only */ + rslt = read_field_data(data, dev); + if (rslt == BME680_OK) { + if (data->status & BME680_NEW_DATA_MSK) + dev->new_fields = 1; + else + dev->new_fields = 0; + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to read the calibrated data from the sensor. + */ +static int8_t get_calib_data(struct bme680_dev *dev) +{ + int8_t rslt; + uint8_t coeff_array[BME680_COEFF_SIZE] = { 0 }; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + rslt = bme680_get_regs(BME680_COEFF_ADDR1, coeff_array, BME680_COEFF_ADDR1_LEN, dev); + /* Append the second half in the same array */ + if (rslt == BME680_OK) + rslt = bme680_get_regs(BME680_COEFF_ADDR2, &coeff_array[BME680_COEFF_ADDR1_LEN], BME680_COEFF_ADDR2_LEN, + dev); + + /* Temperature related coefficients */ + dev->calib.par_t1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T1_MSB_REG], + coeff_array[BME680_T1_LSB_REG])); + dev->calib.par_t2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T2_MSB_REG], + coeff_array[BME680_T2_LSB_REG])); + dev->calib.par_t3 = (int8_t) (coeff_array[BME680_T3_REG]); + + /* Pressure related coefficients */ + dev->calib.par_p1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P1_MSB_REG], + coeff_array[BME680_P1_LSB_REG])); + dev->calib.par_p2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P2_MSB_REG], + coeff_array[BME680_P2_LSB_REG])); + dev->calib.par_p3 = (int8_t) coeff_array[BME680_P3_REG]; + dev->calib.par_p4 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P4_MSB_REG], + coeff_array[BME680_P4_LSB_REG])); + dev->calib.par_p5 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P5_MSB_REG], + coeff_array[BME680_P5_LSB_REG])); + dev->calib.par_p6 = (int8_t) (coeff_array[BME680_P6_REG]); + dev->calib.par_p7 = (int8_t) (coeff_array[BME680_P7_REG]); + dev->calib.par_p8 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P8_MSB_REG], + coeff_array[BME680_P8_LSB_REG])); + dev->calib.par_p9 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P9_MSB_REG], + coeff_array[BME680_P9_LSB_REG])); + dev->calib.par_p10 = (uint8_t) (coeff_array[BME680_P10_REG]); + + /* Humidity related coefficients */ + dev->calib.par_h1 = (uint16_t) (((uint16_t) coeff_array[BME680_H1_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) + | (coeff_array[BME680_H1_LSB_REG] & BME680_BIT_H1_DATA_MSK)); + dev->calib.par_h2 = (uint16_t) (((uint16_t) coeff_array[BME680_H2_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) + | ((coeff_array[BME680_H2_LSB_REG]) >> BME680_HUM_REG_SHIFT_VAL)); + dev->calib.par_h3 = (int8_t) coeff_array[BME680_H3_REG]; + dev->calib.par_h4 = (int8_t) coeff_array[BME680_H4_REG]; + dev->calib.par_h5 = (int8_t) coeff_array[BME680_H5_REG]; + dev->calib.par_h6 = (uint8_t) coeff_array[BME680_H6_REG]; + dev->calib.par_h7 = (int8_t) coeff_array[BME680_H7_REG]; + + /* Gas heater related coefficients */ + dev->calib.par_gh1 = (int8_t) coeff_array[BME680_GH1_REG]; + dev->calib.par_gh2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_GH2_MSB_REG], + coeff_array[BME680_GH2_LSB_REG])); + dev->calib.par_gh3 = (int8_t) coeff_array[BME680_GH3_REG]; + + /* Other coefficients */ + uint8_t temp_var = 0; /* Temporary variable */ + + if (rslt == BME680_OK) { + rslt = bme680_get_regs(BME680_ADDR_RES_HEAT_RANGE_ADDR, &temp_var, 1, dev); + + dev->calib.res_heat_range = ((temp_var & BME680_RHRANGE_MSK) / 16); + if (rslt == BME680_OK) { + rslt = bme680_get_regs(BME680_ADDR_RES_HEAT_VAL_ADDR, &temp_var, 1, dev); + + dev->calib.res_heat_val = (int8_t) temp_var; + if (rslt == BME680_OK) + rslt = bme680_get_regs(BME680_ADDR_RANGE_SW_ERR_ADDR, &temp_var, 1, dev); + } + } + dev->calib.range_sw_err = ((int8_t) temp_var & (int8_t) BME680_RSERROR_MSK) / 16; + } + + return rslt; +} + +/*! + * @brief This internal API is used to set the gas configuration of the sensor. + */ +static int8_t set_gas_config(struct bme680_dev *dev) +{ + int8_t rslt; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + + uint8_t reg_addr[2], reg_data[2]; + + if (dev->power_mode == BME680_FORCED_MODE) { + reg_addr[0] = BME680_RES_HEAT0_ADDR; + reg_data[0] = calc_heater_res(dev->gas_sett.heatr_temp, dev); + reg_addr[1] = BME680_GAS_WAIT0_ADDR; + reg_data[1] = calc_heater_dur(dev->gas_sett.heatr_dur); + dev->gas_sett.nb_conv = 0; + } else { + rslt = BME680_W_DEFINE_PWR_MODE; + } + if (rslt == BME680_OK) + rslt = bme680_set_regs(reg_addr, reg_data, 2, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to get the gas configuration of the sensor. + */ +static int8_t get_gas_config(struct bme680_dev *dev) +{ + int8_t rslt; + /* starting address of the register array for burst read*/ + uint8_t reg_addr1 = BME680_ADDR_SENS_CONF_START; + uint8_t reg_addr2 = BME680_ADDR_GAS_CONF_START; + uint8_t data_array[BME680_GAS_HEATER_PROF_LEN_MAX] = { 0 }; + uint8_t index; + + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + if (BME680_SPI_INTF == dev->intf) { + /* Memory page switch the SPI address*/ + rslt = set_mem_page(reg_addr1, dev); + } + + if (rslt == BME680_OK) { + rslt = bme680_get_regs(reg_addr1, data_array, BME680_GAS_HEATER_PROF_LEN_MAX, dev); + if (rslt == BME680_OK) { + for (index = 0; index < BME680_GAS_HEATER_PROF_LEN_MAX; index++) + dev->gas_sett.heatr_temp = data_array[index]; + } + + rslt = bme680_get_regs(reg_addr2, data_array, BME680_GAS_HEATER_PROF_LEN_MAX, dev); + if (rslt == BME680_OK) { + for (index = 0; index < BME680_GAS_HEATER_PROF_LEN_MAX; index++) + dev->gas_sett.heatr_dur = data_array[index]; + } + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to calculate the temperature value. + */ +static int16_t calc_temperature(uint32_t temp_adc, struct bme680_dev *dev) +{ + int64_t var1; + int64_t var2; + int64_t var3; + int16_t calc_temp; + + var1 = ((int32_t) temp_adc / 8) - ((int32_t) dev->calib.par_t1 * 2); + var2 = (var1 * (int32_t) dev->calib.par_t2) / 2048; + var3 = ((var1 / 2) * (var1 / 2)) / 4096; + var3 = ((var3) * ((int32_t) dev->calib.par_t3 * 16)) / 16384; + dev->calib.t_fine = (int32_t) (var2 + var3); + calc_temp = (int16_t) (((dev->calib.t_fine * 5) + 128) / 256); + + return calc_temp; +} + +/*! + * @brief This internal API is used to calculate the pressure value. + */ +static uint32_t calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) +{ + int32_t var1; + int32_t var2; + int32_t var3; + int32_t calc_pres; + + var1 = (((int32_t) dev->calib.t_fine) / 2) - 64000; + var2 = ((var1 / 4) * (var1 / 4)) / 2048; + var2 = ((var2) * (int32_t) dev->calib.par_p6) / 4; + var2 = var2 + ((var1 * (int32_t) dev->calib.par_p5) * 2); + var2 = (var2 / 4) + ((int32_t) dev->calib.par_p4 * 65536); + var1 = ((var1 / 4) * (var1 / 4)) / 8192; + var1 = (((var1) * ((int32_t) dev->calib.par_p3 * 32)) / 8) + (((int32_t) dev->calib.par_p2 * var1) / 2); + var1 = var1 / 262144; + var1 = ((32768 + var1) * (int32_t) dev->calib.par_p1) / 32768; + calc_pres = (int32_t) (1048576 - pres_adc); + calc_pres = (int32_t) ((calc_pres - (var2 / 4096)) * (3125)); + calc_pres = ((calc_pres / var1) * 2); + var1 = ((int32_t) dev->calib.par_p9 * (int32_t) (((calc_pres / 8) * (calc_pres / 8)) / 8192)) / 4096; + var2 = ((int32_t) (calc_pres / 4) * (int32_t) dev->calib.par_p8) / 8192; + var3 = ((int32_t) (calc_pres / 256) * (int32_t) (calc_pres / 256) * (int32_t) (calc_pres / 256) + * (int32_t) dev->calib.par_p10) / 131072; + calc_pres = (int32_t) (calc_pres) + ((var1 + var2 + var3 + ((int32_t) dev->calib.par_p7 * 128)) / 16); + + return (uint32_t) calc_pres; +} + +/*! + * @brief This internal API is used to calculate the humidity value. + */ +static uint32_t calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev) +{ + int32_t var1; + int32_t var2; + int32_t var3; + int32_t var4; + int32_t var5; + int32_t var6; + int32_t temp_scaled; + int32_t calc_hum; + + temp_scaled = (((int32_t) dev->calib.t_fine * 5) + 128) / 256; + var1 = (int32_t) (hum_adc - ((int32_t) ((int32_t) dev->calib.par_h1 * 16))) + - (((temp_scaled * (int32_t) dev->calib.par_h3) / ((int32_t) 100)) / 2); + var2 = ((int32_t) dev->calib.par_h2 + * (((temp_scaled * (int32_t) dev->calib.par_h4) / ((int32_t) 100)) + + (((temp_scaled * ((temp_scaled * (int32_t) dev->calib.par_h5) / ((int32_t) 100))) / 64) + / ((int32_t) 100)) + (int32_t) (1 * 16384))) / 1024; + var3 = var1 * var2; + var4 = (int32_t) dev->calib.par_h6 * 128; + var4 = ((var4) + ((temp_scaled * (int32_t) dev->calib.par_h7) / ((int32_t) 100))) / 16; + var5 = ((var3 / 16384) * (var3 / 16384)) / 1024; + var6 = (var4 * var5) / 2; + calc_hum = (((var3 + var6) / 1024) * ((int32_t) 1000)) / 4096; + + if (calc_hum > 100000) /* Cap at 100%rH */ + calc_hum = 100000; + else if (calc_hum < 0) + calc_hum = 0; + + return (uint32_t) calc_hum; +} + +/*! + * @brief This internal API is used to calculate the Gas Resistance value. + */ +static uint32_t calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev) +{ + int64_t var1; + uint64_t var2; + int64_t var3; + uint32_t calc_gas_res; + + var1 = (int64_t) ((1340 + (5 * (int64_t) dev->calib.range_sw_err)) * ((int64_t) lookupTable1[gas_range])) / 65536; + var2 = (((int64_t) ((int64_t) gas_res_adc * 32768) - (int64_t) (16777216)) + var1); + var3 = (((int64_t) lookupTable2[gas_range] * (int64_t) var1) / 512); + calc_gas_res = (uint32_t) ((var3 + ((int64_t) var2 / 2)) / (int64_t) var2); + + return calc_gas_res; +} + +/*! + * @brief This internal API is used to calculate the Heat Resistance value. + */ +static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev) +{ + uint8_t heatr_res; + int32_t var1; + int32_t var2; + int32_t var3; + int32_t var4; + int32_t var5; + int32_t heatr_res_x100; + + if (temp < 200) /* Cap temperature */ + temp = 200; + else if (temp > 400) + temp = 400; + + var1 = (((int32_t) dev->amb_temp * dev->calib.par_gh3) / 1000) * 256; + var2 = (dev->calib.par_gh1 + 784) * (((((dev->calib.par_gh2 + 154009) * temp * 5) / 100) + 3276800) / 10); + var3 = var1 + (var2 / 2); + var4 = (var3 / (dev->calib.res_heat_range + 4)); + var5 = (131 * dev->calib.res_heat_val) + 65536; + heatr_res_x100 = (int32_t) (((var4 / var5) - 250) * 34); + heatr_res = (uint8_t) ((heatr_res_x100 + 50) / 100); + + return heatr_res; +} + +/*! + * @brief This internal API is used to calculate the Heat duration value. + */ +static uint8_t calc_heater_dur(uint16_t dur) +{ + uint8_t factor = 0; + uint8_t durval; + + if (dur >= 0xfc0) { + durval = 0xff; /* Max duration*/ } else { - temp_index = index + 2; + while (dur > 0x3F) { + dur = dur / 4; + factor += 1; + } + durval = (uint8_t) (dur + (factor * 64)); } - return temp_index; + return durval; } + /*! - * @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) + * @brief This internal API is used to calculate the field data of sensor. + */ +static int8_t read_field_data(struct bme680_field_data *data, struct bme680_dev *dev) { + int8_t rslt; + uint8_t buff[BME680_FIELD_LENGTH] = { 0 }; + uint8_t gas_range; + uint32_t adc_temp; + uint32_t adc_pres; + uint16_t adc_hum; + uint16_t adc_gas_res; + uint8_t tries = 10; - 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)); + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + do { + if (rslt == BME680_OK) { + rslt = bme680_get_regs(((uint8_t) (BME680_FIELD0_ADDR)), buff, (uint16_t) BME680_FIELD_LENGTH, dev); + + data->status = buff[0] & BME680_NEW_DATA_MSK; + data->gas_index = buff[0] & BME680_GAS_INDEX_MSK; + data->meas_index = buff[1]; + + /* read the raw data from the sensor */ + adc_pres = (uint32_t) (((uint32_t) buff[2] * 4096) | ((uint32_t) buff[3] * 16) | ((uint32_t) buff[4] / 16)); + adc_temp = (uint32_t) (((uint32_t) buff[5] * 4096) | ((uint32_t) buff[6] * 16) | ((uint32_t) buff[7] / 16)); + adc_hum = (uint16_t) (((uint32_t) buff[8] * 256) | (uint32_t) buff[9]); + adc_gas_res = (uint16_t) ((uint32_t) buff[13] * 4 | (((uint32_t) buff[14]) / 64)); + gas_range = buff[14] & BME680_GAS_RANGE_MSK; + + data->status |= buff[14] & BME680_GASM_VALID_MSK; + data->status |= buff[14] & BME680_HEAT_STAB_MSK; + + if (data->status & BME680_NEW_DATA_MSK) { + data->temperature = calc_temperature(adc_temp, dev); + data->pressure = calc_pressure(adc_pres, dev); + data->humidity = calc_humidity(adc_hum, dev); + data->gas_resistance = calc_gas_resistance(adc_gas_res, gas_range, dev); + break; + } else { + dev->delay_ms(BME680_POLL_PERIOD_MS); + } } - 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)); + tries--; + } while (tries); + + if (!tries) + rslt = BME680_W_NO_NEW_DATA; + + return rslt; +} + +/*! + * @brief This internal API is used to set the memory page based on register address. + */ +static int8_t set_mem_page(uint8_t reg_addr, struct bme680_dev *dev) +{ + int8_t rslt; + uint8_t reg; + uint8_t mem_page; + + /* Check for null pointers in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + if (reg_addr > 0x7f) + mem_page = BME680_MEM_PAGE1; + else + mem_page = BME680_MEM_PAGE0; + + if (mem_page != dev->mem_page) { + dev->mem_page = mem_page; + + dev->com_rslt = dev->read(dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, ®, 1); + if (dev->com_rslt != 0) + rslt = BME680_E_COM_FAIL; + + if (rslt == BME680_OK) { + reg = reg & (~BME680_MEM_PAGE_MSK); + reg = reg | (dev->mem_page & BME680_MEM_PAGE_MSK); + + dev->com_rslt = dev->write(dev->dev_id, BME680_MEM_PAGE_ADDR & BME680_SPI_WR_MSK, ®, 1); + if (dev->com_rslt != 0) + rslt = BME680_E_COM_FAIL; + } } - break; } + return rslt; } - -static void bme680_packing_calib_param(u8 *a_data_u8, struct bme680_t *bme680) +/*! + * @brief This internal API is used to get the memory page based on register address. + */ +static int8_t get_mem_page(struct bme680_dev *dev) { + int8_t rslt; + uint8_t reg; - /* 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]; + /* Check for null pointer in the device structure*/ + rslt = null_ptr_check(dev); + if (rslt == BME680_OK) { + dev->com_rslt = dev->read(dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, ®, 1); + if (dev->com_rslt != 0) + rslt = BME680_E_COM_FAIL; + else + dev->mem_page = reg & BME680_MEM_PAGE_MSK; + } + return rslt; } +/*! + * @brief This internal API is used to validate the boundary + * conditions. + */ +static int8_t boundary_check(uint8_t *value, uint8_t min, uint8_t max, struct bme680_dev *dev) +{ + int8_t rslt = BME680_OK; + + if (value != NULL) { + /* Check if value is below minimum value */ + if (*value < min) { + /* Auto correct the invalid value to minimum value */ + *value = min; + dev->info_msg |= BME680_I_MIN_CORRECTION; + } + /* Check if value is above maximum value */ + if (*value > max) { + /* Auto correct the invalid value to maximum value */ + *value = max; + dev->info_msg |= BME680_I_MAX_CORRECTION; + } + } else { + rslt = BME680_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This internal API is used to validate the device structure pointer for + * null conditions. + */ +static int8_t null_ptr_check(const struct bme680_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { + /* Device structure pointer is not valid */ + rslt = BME680_E_NULL_PTR; + } else { + /* Device structure is fine */ + rslt = BME680_OK; + } + + return rslt; +} diff --git a/bme680.h b/bme680.h index a309c18..38b8628 100644 --- a/bme680.h +++ b/bme680.h @@ -1,667 +1,225 @@ /** -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bme680.h -* -* Date: 5 May 2017 -* -* Revision : 2.2.0 $ -* -* Usage: Sensor Driver for BME680 sensor -* -**************************************************************************** -* -* \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. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bme680.h - \brief BME680 Sensor Driver Support Header File */ - -#ifndef __BME680_H__ -#define __BME680_H__ + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bme680.h + * @date 5 Jul 2017 + * @version 3.5.1 + * @brief + * + */ +/*! @file bme680.h + @brief Sensor driver for BME680 sensor */ +/*! + * @defgroup BME680 SENSOR API + * @{*/ +#ifndef BME680_H_ +#define BME680_H_ +/*! CPP guard */ #ifdef __cplusplus extern "C" { #endif -/* BME680 Release version 2.0.0 -BME680 Release Version format major_version.minor_version.point_version -Example: 2.0.0 */ -#define BME680_API_REL_MAJOR_VERSION (2) -#define BME680_API_REL_MINOR_VERSION (0) -#define BME680_API_REL_POINT_VERSION (1) - -/*************************************************************************** - Header files -****************************************************************************/ -#include "sensor_api_common_types.h" - - -/* sensor_api_common_types.h */ - -/************************************************************************ - Macros, Enums, Constants -*************************************************************************/ -#define BME680_PRESSURE (0U) -#define BME680_TEMPERATURE (1U) -#define BME680_HUMIDITY (2U) -#define BME680_GAS (3U) -#define BME680_ALL (4U) - -#define BME680_STATUS_DATA_LEN (2U) -#define BME680_TEMPERATURE_DATA_LEN (3U) -#define BME680_PRESSURE_DATA_LEN (3U) -#define BME680_GAS_DATA_LEN (2U) -#define BME680_HUMIDITY_DATA_LEN (2U) - -#define BME680_PRESENT_DATA_FIELD (1U) -#define BME680_PRESENT_AND_PREVIOUS_DATA_FIELD (2U) -#define BME680_ALL_DATA_FIELD (3U) - -#define BME680_MAX_FIELD_INDEX (3U) -#define BME680_FIELD_INDEX0 (0U) -#define BME680_FIELD_INDEX1 (1U) -#define BME680_FIELD_INDEX2 (2U) - -/***************************************************************/ -/**\name BUS READ AND WRITE FUNCTION POINTERS */ -/***************************************************************/ - - -/**< function pointer to the SPI or I2C burst read function */ -typedef s8 (*sensor_burst_read)(u8 slave_addr, u8 reg_addr, u8 *data_u8, - u32 length_u32); - -typedef s8 (*sensor_write)(u8 dev_addr, u8 reg_addr, u8 *reg_data_ptr, - u8 data_len); -/**< function pointer for Write operation in either I2C or SPI*/ -typedef s8 (*sensor_read)(u8 dev_addr, u8 reg_addr, u8 *reg_data_ptr, - u8 data_len); -/**< function pointer for Read operation in either I2C or SPI*/ - -#define BME680_MAX_NO_OF_SENSOR (2) -/**< This macro used for maximum number of sensor*/ - -#define BME680_MDELAY_DATA_TYPE u32 -/**< This macro used for delay*/ - -#define BME680_CHIP_ID (0x61) -/**< BME680 chip identifier */ - -#define BME680_SPECIFIC_FIELD_DATA_READ_ENABLED -/**< This macro is used to prevent the compilation -of single function calls when not used */ - -/* - * Use below macro for fixed Point Calculation - * else Floating Point calculation will be used -*/ - -/* #define FIXED_POINT_COMPENSATION */ - -/* temperature to Resistance formulae #defines */ - -/* - * Use any of the below constants according to - * the heater version of the sensor used -*/ - -#define HEATER_C1_ENABLE - -/* Sensor Specific constants */ -#define BME680_SLEEP_MODE (0x00) -#define BME680_FORCED_MODE (0x01) -#define BME680_PARALLEL_MODE (0x02) -#define BME680_SEQUENTIAL_MODE (0x03) -#define BME680_GAS_PROFILE_TEMPERATURE_MIN (200) -#define BME680_GAS_PROFILE_TEMPERATURE_MAX (400) -#define BME680_GAS_RANGE_RL_LENGTH (16) -#define BME680_SIGN_BIT_MASK (0x08) - -#ifdef FIXED_POINT_COMPENSATION -/**< Multiply by 1000, In order to convert -float value into fixed point */ -#define BME680_MAX_HUMIDITY_VALUE (102400) -#define BME680_MIN_HUMIDITY_VALUE (0) -#else -#define BME680_MAX_HUMIDITY_VALUE (double)(100.0) -#define BME680_MIN_HUMIDITY_VALUE (double)(0.0) -#endif - -/* BME680 I2C addresses */ -#define BME680_I2C_ADDR_PRIMARY (0x76) -#define BME680_I2C_ADDR_SECONDARY (0x77) - -/* Maximum no of gas profiles to be used */ -#define BME680_MAX_PROFILES (10) - - -/**************************************************************/ -/**\name Interface selection macro */ -/*************************************************************/ - -#define BME680_SPI_INTERFACE (1) -#define BME680_I2C_INTERFACE (2) - - - -/* bme680_internal.h */ - -/***************************************************************/ -/**\name COMMON USED CONSTANTS */ -/***************************************************************/ -/* Constants */ -#define BME680_NULL_PTR ((void *)0) -#define BME680_RETURN_FUNCTION_TYPE s8 - -/* Section 3.5: Function macros */ -#define BME680_SET_REG(reg, data, mask, shift)\ - ((reg & mask) | ((data << shift) & ~mask)) -#define BME680_GET_REG(reg, mask, shift)\ - ((reg & ~mask) >> shift) -#define DIFF(a, b) ((a > b)?(a - b):(b - a)) - - -/************************************************************* - Module globals, typedefs -**************************************************************/ +/* Header includes */ +#include "bme680_defs.h" +/* function prototype declarations */ /*! - * @brief This structure holds all - * calibration parameters - */ -struct bme680_calibration_param_t { - - s8 par_T3;/** Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bme680_init(struct bme680_dev *dev); /*! - * @brief This function is used to Align uncompensated data - * from function bme680_get_uncomp_data() -*/ -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); + * @brief This API writes the given data to the register address + * of the sensor. + * + * @param[in] reg_addr : Register address from where the data to be written. + * @param[in] reg_data : Pointer to data buffer which is to be written + * in the sensor. + * @param[in] len : No of bytes of data to write.. + * @param[in] dev : Structure instance of bme680_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bme680_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme680_dev *dev); /*! - * @brief This function is used to read the status according to filed index. -*/ -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); -/* bme680_calculations.h */ + * @brief This API reads the data from the given register address of the sensor. + * + * @param[in] reg_addr : Register address from where the data to be read + * @param[out] reg_data : Pointer to data buffer to store the read data. + * @param[in] len : No of bytes of data to be read. + * @param[in] dev : Structure instance of bme680_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bme680_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme680_dev *dev); +/*! + * @brief This API performs the soft reset of the sensor. + * + * @param[in] dev : Structure instance of bme680_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bme680_soft_reset(struct bme680_dev *dev); + +/*! + * @brief This API is used to set the power mode of the sensor. + * + * @param[in] dev : Structure instance of bme680_dev + * @note : Pass the value to bme680_dev.power_mode structure variable. + * + * value | mode + * -------------|------------------ + * 0x00 | BME680_SLEEP_MODE + * 0x01 | BME680_FORCED_MODE + * + * * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bme680_set_sensor_mode(struct bme680_dev *dev); + +/*! + * @brief This API is used to get the power mode of the sensor. + * + * @param[in] dev : Structure instance of bme680_dev + * @note : bme680_dev.power_mode structure variable hold the power mode. + * + * value | mode + * ---------|------------------ + * 0x00 | BME680_SLEEP_MODE + * 0x01 | BME680_FORCED_MODE + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bme680_get_sensor_mode(struct bme680_dev *dev); + +/*! + * @brief This API is used to set the profile duration of the sensor. + * + * @param[in] dev : Structure instance of bme680_dev. + * @param[in] duration : Duration of the measurement in ms. + * + * @return Nothing + */ +void bme680_set_profile_dur(uint16_t duration, struct bme680_dev *dev); + +/*! + * @brief This API is used to get the profile duration of the sensor. + * + * @param[in] dev : Structure instance of bme680_dev. + * @param[in] duration : Duration of the measurement in ms. + * + * @return Nothing + */ +void bme680_get_profile_dur(uint16_t *duration, struct bme680_dev *dev); + +/*! + * @brief This API reads the pressure, temperature and humidity and gas data + * from the sensor, compensates the data and store it in the bme680_data + * structure instance passed by the user. + * + * @param[out] data: Structure instance to hold the data. + * @param[in] dev : Structure instance of bme680_dev. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error + */ +int8_t bme680_get_sensor_data(struct bme680_field_data *data, struct bme680_dev *dev); + +/*! + * @brief This API is used to set the oversampling, filter and T,P,H, gas selection + * settings in the sensor. + * + * @param[in] dev : Structure instance of bme680_dev. + * @param[in] desired_settings : Variable used to select the settings which + * are to be set in the sensor. + * + * Macros | Functionality + *-------------------------|---------------------------------------------- + * BME680_OST_SEL | To set temperature oversampling. + * BME680_OSP_SEL | To set pressure oversampling. + * BME680_OSH_SEL | To set humidity oversampling. + * BME680_GAS_MEAS_SEL | To set gas measurement setting. + * BME680_FILTER_SEL | To set filter setting. + * BME680_HCNTRL_SEL | To set humidity control setting. + * BME680_RUN_GAS_SEL | To set run gas setting. + * BME680_NBCONV_SEL | To set NB conversion setting. + * BME680_GAS_SENSOR_SEL | To set all gas sensor related settings + * + * @note : Below are the macros to be used by the user for selecting the + * desired settings. User can do OR operation of these macros for configuring + * multiple settings. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bme680_set_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev); + +/*! + * @brief This API is used to get the oversampling, filter and T,P,H, gas selection + * settings in the sensor. + * + * @param[in] dev : Structure instance of bme680_dev. + * @param[in] desired_settings : Variable used to select the settings which + * are to be get from the sensor. + * + * @return Result of API execution status + * @retval zero -> Success / +ve value -> Warning / -ve value -> Error. + */ +int8_t bme680_get_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev); #ifdef __cplusplus } -#endif - -#endif +#endif /* End of CPP guard */ +#endif /* BME680_H_ */ +/** @}*/ diff --git a/bme680_calculations.c b/bme680_calculations.c deleted file mode 100644 index 130b028..0000000 --- a/bme680_calculations.c +++ /dev/null @@ -1,684 +0,0 @@ -/** -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bme680_calculations.c -* -* Date: 5 May 2017 -* -* Revision : 2.2.0 $ -* -* Usage: Sensor Driver for BME680 sensor -* -**************************************************************************** -* -* \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. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bme680_calculations.c - \brief BME680 Sensor Driver calculation source File */ - -/*************************************************************************** - Header files -****************************************************************************/ -#include "bme680_calculations.h" - - -/*************************************************************************** - Macros, Enums, Constants -****************************************************************************/ - - -/*************************************************************************** - File globals, typedefs -****************************************************************************/ - - -/*************************************************************************** - Function definitions -****************************************************************************/ -/* bme680.c */ -#ifdef FIXED_POINT_COMPENSATION -/*! - * @brief This function is used to convert uncompensated gas data to - * compensated gas data using compensation formula(integer version) - * - * @param gas_adc_u16: The value of gas resistance calculated - * using temperature - * @param gas_range_u8: The value of gas range form register value - * @param bme680: structure pointer. - * - * @return calculated compensated gas from compensation formula - * @retval compensated gas data - * - * -*/ -s32 bme680_calculate_gas_int32(u16 gas_adc_u16, u8 gas_range_u8, - struct bme680_t *bme680) -{ - s8 range_switching_error_val = 0; - s64 var1 = 0; - s64 var2 = 0; - s32 gas_res = 0; - - - - const u64 lookup_k1_range[BME680_GAS_RANGE_RL_LENGTH] = { - 2147483647UL, 2147483647UL, 2147483647UL, 2147483647UL, 2147483647UL, - 2126008810UL, 2147483647UL, 2130303777UL, 2147483647UL, 2147483647UL, - 2143188679UL, 2136746228UL, 2147483647UL, 2126008810UL, 2147483647UL, - 2147483647UL}; - - const u64 lookup_k2_range[BME680_GAS_RANGE_RL_LENGTH] = { - 4096000000UL, 2048000000UL, 1024000000UL, 512000000UL, - 255744255UL, 127110228UL, 64000000UL, 32258064UL, 16016016UL, - 8000000UL, 4000000UL, 2000000UL, 1000000UL, 500000UL, 250000UL, - 125000UL}; - - - - range_switching_error_val = - bme680->cal_param.range_switching_error; - - - var1 = (s64)((1340 + (5 * (s64)range_switching_error_val)) * - ((s64)lookup_k1_range[gas_range_u8])) >> 16; - var2 = (s64)((s64)gas_adc_u16 << 15) - (s64)(1 << 24) + var1; - #ifndef __KERNEL__ - gas_res = (s32)(((((s64)lookup_k2_range[gas_range_u8] * - (s64)var1) >> 9) + (var2 >> 1)) / var2); - #else - gas_res = (s32)(div64_s64(((((s64)lookup_k2_range[gas_range_u8] * - (s64)var1) >> 9) + (var2 >> 1)), var2)); - #endif - return gas_res; -} -/*! - * @brief This function is used to convert the uncompensated - * temperature data to compensated temperature data using - * compensation formula(integer version) - * @note Returns the value in 0.01 degree Centigrade - * Output value of "5123" equals 51.23 DegC. - * - * - * - * @param v_uncomp_temperature_u32 : value of uncompensated temperature - * @param bme680: structure pointer. - * - * @return Returns the compensated temperature data - * -*/ -s32 bme680_compensate_temperature_int32(u32 v_uncomp_temperature_u32, - struct bme680_t *bme680) -{ - s32 var1 = 0; - s32 var2 = 0; - s32 var3 = 0; - s32 temp_comp = 0; - - var1 = ((s32)v_uncomp_temperature_u32 >> 3) - - ((s32)bme680->cal_param.par_T1 << 1); - var2 = (var1 * (s32)bme680->cal_param.par_T2) >> 11; - var3 = ((((var1 >> 1) * (var1 >> 1)) >> 12) * - ((s32)bme680->cal_param.par_T3 << 4)) >> 14; - bme680->cal_param.t_fine = var2 + var3; - temp_comp = ((bme680->cal_param.t_fine * 5) + 128) >> 8; - - return temp_comp; - -} - -/*! - * @brief This function is used to convert the uncompensated - * humidity data to compensated humidity data using - * compensation formula(integer version) - * - * @note Returns the value in %rH as unsigned 32bit integer - * in Q22.10 format(22 integer 10 fractional bits). - * @note An output value of 42313 - * represents 42313 / 1024 = 41.321 %rH - * - * - * - * @param v_uncomp_humidity_u32: value of uncompensated humidity - * @param bme680: structure pointer. - * - * @return Return the compensated humidity data - * -*/ -s32 bme680_compensate_humidity_int32(u32 v_uncomp_humidity_u32, - struct bme680_t *bme680) -{ - s32 temp_scaled = 0; - s32 var1 = 0; - s32 var2 = 0; - s32 var3 = 0; - s32 var4 = 0; - s32 var5 = 0; - s32 var6 = 0; - s32 humidity_comp = 0; - - temp_scaled = (((s32)bme680->cal_param.t_fine * 5) + 128) >> 8; - var1 = (s32)v_uncomp_humidity_u32 - - ((s32)((s32)bme680->cal_param.par_H1 << 4)) - - (((temp_scaled * (s32)bme680->cal_param.par_H3) / - ((s32)100)) >> 1); - - var2 = ((s32)bme680->cal_param.par_H2 * - (((temp_scaled * (s32)bme680->cal_param.par_H4) / - ((s32)100)) + (((temp_scaled * - ((temp_scaled * (s32)bme680->cal_param.par_H5) / - ((s32)100))) >> 6) / ((s32)100)) + (s32)(1 << 14))) >> 10; - - var3 = var1 * var2; - - var4 = ((((s32)bme680->cal_param.par_H6) << 7) + - ((temp_scaled * (s32)bme680->cal_param.par_H7) / - ((s32)100))) >> 4; - - var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; - var6 = (var4 * var5) >> 1; - - humidity_comp = (var3 + var6) >> 12; - if (humidity_comp > BME680_MAX_HUMIDITY_VALUE) - humidity_comp = BME680_MAX_HUMIDITY_VALUE; - else if (humidity_comp < BME680_MIN_HUMIDITY_VALUE) - humidity_comp = BME680_MIN_HUMIDITY_VALUE; - - return humidity_comp; -} - - -/*! - * @brief This function is used to convert the uncompensated - * pressure data to compensated pressure data data using - * compensation formula(integer version) - * - * @note Returns the value in Pascal(Pa) - * Output value of "96386" equals 96386 Pa = - * 963.86 hPa = 963.86 millibar - * - * - * - * @param v_uncomp_pressure_u32 : value of uncompensated pressure - * @param bme680: structure pointer. - * - * @return Return the compensated pressure data - * -*/ -s32 bme680_compensate_pressure_int32(u32 v_uncomp_pressure_u32, - struct bme680_t *bme680) -{ - s32 var1 = 0; - s32 var2 = 0; - s32 var3 = 0; - s32 var4 = 0; - s32 pressure_comp = 0; - - var1 = (((s32)bme680->cal_param.t_fine) >> 1) - 64000; - var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * - (s32)bme680->cal_param.par_P6) >> 2; - var2 = var2 + ((var1 * (s32)bme680->cal_param.par_P5) << 1); - var2 = (var2 >> 2) + ((s32)bme680->cal_param.par_P4 << 16); - var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * - ((s32)bme680->cal_param.par_P3 << 5)) >> 3) + - (((s32)bme680->cal_param.par_P2 * var1) >> 1); - var1 = var1 >> 18; - var1 = ((32768 + var1) * (s32)bme680->cal_param.par_P1) >> 15; - pressure_comp = 1048576 - v_uncomp_pressure_u32; - pressure_comp = (s32)((pressure_comp - (var2 >> 12)) * ((u32)3125)); - var4 = (1 << 31); - if (pressure_comp >= var4) - pressure_comp = ((pressure_comp / (u32)var1) << 1); - else - pressure_comp = ((pressure_comp << 1) / (u32)var1); - var1 = ((s32)bme680->cal_param.par_P9 * (s32)(((pressure_comp >> 3) * - (pressure_comp >> 3)) >> 13)) >> 12; - var2 = ((s32)(pressure_comp >> 2) * - (s32)bme680->cal_param.par_P8) >> 13; - var3 = ((s32)(pressure_comp >> 8) * (s32)(pressure_comp >> 8) * - (s32)(pressure_comp >> 8) * - (s32)bme680->cal_param.par_P10) >> 17; - - pressure_comp = (s32)(pressure_comp) + ((var1 + var2 + var3 + - ((s32)bme680->cal_param.par_P7 << 7)) >> 4); - - return pressure_comp; -} -/*! - * @brief This function is used to convert temperature to resistance - * using the integer compensation formula - * - * @param heater_temp_u16: The value of heater temperature - * @param ambient_temp_s16: The value of ambient temperature - * @param bme680: structure pointer. - * - * @return calculated resistance from temperature - * - * - * -*/ -u8 bme680_convert_temperature_to_resistance_int32(u16 heater_temp_u16, - s16 ambient_temp_s16, struct bme680_t *bme680) -{ - s32 var1 = 0; - s32 var2 = 0; - s32 var3 = 0; - s32 var4 = 0; - s32 var5 = 0; - s32 res_heat_x100 = 0; - u8 res_heat = 0; - - - if ((heater_temp_u16 >= BME680_GAS_PROFILE_TEMPERATURE_MIN) - && (heater_temp_u16 <= BME680_GAS_PROFILE_TEMPERATURE_MAX)) { - - var1 = (((s32)ambient_temp_s16 * - bme680->cal_param.par_GH3) / 10) << 8; - var2 = (bme680->cal_param.par_GH1 + 784) * - (((((bme680->cal_param.par_GH2 + 154009) * - heater_temp_u16 * 5) / 100) + 3276800) / 10); - var3 = var1 + (var2 >> 1); - var4 = (var3 / (bme680->cal_param.res_heat_range + 4)); - - var5 = (131 * bme680->cal_param.res_heat_val) + 65536; - - res_heat_x100 = (s32)(((var4 / var5) - 250) * 34); - res_heat = (u8) ((res_heat_x100 + 50) / 100); - - } - return res_heat; -} -/*! - * @brief Reads actual humidity from uncompensated humidity - * @note Returns the value in %rH as unsigned 16bit integer - * @note An output value of 42313 - * represents 42313/512 = 82.643 %rH - * - * - * - * @param v_uncomp_humidity_u32: value of uncompensated humidity - * @param bme680: structure pointer. - * - * @return Return the actual relative humidity output as u16 - * -*/ -u16 bme680_compensate_H_int32_sixteen_bit_output(u32 v_uncomp_humidity_u32, - struct bme680_t *bme680) -{ - u32 v_x1_u32 = 0; - u16 v_x2_u32 = 0; - - v_x1_u32 = (u32) bme680_compensate_humidity_int32( - v_uncomp_humidity_u32, bme680); - v_x2_u32 = (u16)(v_x1_u32 >> 1); - return v_x2_u32; -} - -/*! - * @brief Reads actual temperature from uncompensated temperature - * @note Returns the value with 500LSB/DegC centred around 24 DegC - * output value of "5123" equals(5123/500)+24 = 34.246DegC - * - * - * @param v_uncomp_temperature_u32: value of uncompensated temperature - * @param bme680: structure pointer. - * - * - * @return Return the actual temperature as s16 output - * -*/ -s16 bme680_compensate_T_int32_sixteen_bit_output(u32 v_uncomp_temperature_u32, - struct bme680_t *bme680) -{ - s16 temperature = 0; - - bme680_compensate_temperature_int32(v_uncomp_temperature_u32, bme680); - temperature = (s16)(((( - bme680->cal_param.t_fine - 122880) * 25) + 128) >> 8); - - return temperature; -} - -/*! - * @brief Reads actual pressure from uncompensated pressure - * @note Returns the value in Pa. - * @note Output value of "12337434" - * @note represents 12337434 / 128 = 96386.2 Pa = 963.862 hPa - * - * - * - * @param v_uncomp_pressure_u32 : value of uncompensated pressure - * @param bme680: structure pointer. - * - * @return the actual pressure in u32 - * -*/ -u32 bme680_compensate_P_int32_twentyfour_bit_output(u32 v_uncomp_pressure_u32, - struct bme680_t *bme680) -{ - u32 pressure = 0; - - pressure = (u32)bme680_compensate_pressure_int32( - v_uncomp_pressure_u32, bme680); - pressure = (u32)(pressure >> 1); - return pressure; -} -#else -/*! - * @brief This function is used to convert uncompensated gas data to - * compensated gas data using compensation formula - * - * @param gas_adc_u16: The value of gas resistance calculated - * using temperature - * @param gas_range_u8: The value of gas range form register value - * @param bme680: structure pointer. - * - * @return calculated compensated gas from compensation formula - * @retval compensated gas - * - * -*/ - -double bme680_compensate_gas_double(u16 gas_adc_u16, u8 gas_range_u8, - struct bme680_t *bme680) -{ - double gas_res_d = 0; - - -#ifdef HEATER_C1_ENABLE - - const double lookup_k1_range[BME680_GAS_RANGE_RL_LENGTH] = { - 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, - 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0}; - const double lookup_k2_range[BME680_GAS_RANGE_RL_LENGTH] = { - 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, - -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - s8 range_switching_error_val = 0; - double var1 = 0; - double var2 = 0; - double var3 = 0; - - - - range_switching_error_val = - bme680->cal_param.range_switching_error; - - - var1 = (1340.0 + (5.0 * range_switching_error_val)); - var2 = (var1) * (1.0 + lookup_k1_range[gas_range_u8]/100.0); - var3 = 1.0 + (lookup_k2_range[gas_range_u8]/100.0); - - gas_res_d = 1.0 / (double)(var3 * (0.000000125) * - (double)(1 << gas_range_u8) - * (((((double)gas_adc_u16) - 512.00)/var2) + 1.0)); - -#else - gas_res_d = 1.0 / ((0.000000125) * (double)(1 << gas_range_u8) * - ((((double)(gas_adc_u16) - 512.00) / 1365.3333) + 1.0)); -#endif - return gas_res_d; -} - - -/*! - * @brief This function is used to convert the uncompensated - * humidity data to compensated humidity data data using - * compensation formula - * @note returns the value in relative humidity (%rH) - * @note Output value of "42.12" equals 42.12 %rH - * - * @param uncom_humidity_u16 : value of uncompensated humidity - * @param comp_temperature : value of compensated temperature - * @param bme680: structure pointer. - * - * - * @return Return the compensated humidity data in floating point - * -*/ -double bme680_compensate_humidity_double(u16 uncom_humidity_u16, - double comp_temperature, struct bme680_t *bme680) -{ - double humidity_comp = 0; - double var1 = 0; - double var2 = 0; - double var3 = 0; - double var4 = 0; - - var1 = (double)((double)uncom_humidity_u16) - (((double) - bme680->cal_param.par_H1 * 16.0) + - (((double)bme680->cal_param.par_H3 / 2.0) - * comp_temperature)); - - var2 = var1 * ((double)( - ((double) bme680->cal_param.par_H2 / 262144.0) - *(1.0 + (((double)bme680->cal_param.par_H4 / 16384.0) - * comp_temperature) + (((double)bme680->cal_param.par_H5 - / 1048576.0) * comp_temperature - * comp_temperature)))); - var3 = (double) bme680->cal_param.par_H6 / 16384.0; - var4 = (double) bme680->cal_param.par_H7 / 2097152.0; - - humidity_comp = var2 + - ((var3 + (var4 * comp_temperature)) * var2 * var2); - if (humidity_comp > BME680_MAX_HUMIDITY_VALUE) - humidity_comp = BME680_MAX_HUMIDITY_VALUE; - else if (humidity_comp < BME680_MIN_HUMIDITY_VALUE) - humidity_comp = BME680_MIN_HUMIDITY_VALUE; - return humidity_comp; -} - -/*! - * @brief This function is used to convert the uncompensated - * pressure data to compensated data using compensation formula - * @note Returns pressure in Pa as double. - * @note Output value of "96386.2" - * equals 96386.2 Pa = 963.862 hPa. - * - * - * @param uncom_pressure_u32 : value of uncompensated pressure - * @param bme680: structure pointer. - * - * @return Return the compensated pressure data in floating point - * -*/ -double bme680_compensate_pressure_double(u32 uncom_pressure_u32, - struct bme680_t *bme680) -{ - double data1_d = 0; - double data2_d = 0; - double data3_d = 0; - double pressure_comp = 0; - - data1_d = (((double)bme680->cal_param.t_fine / 2.0) - 64000.0); - data2_d = data1_d * data1_d * (((double)bme680->cal_param.par_P6) / - (131072.0)); - data2_d = data2_d + (data1_d * ((double)bme680->cal_param.par_P5) * - 2.0); - data2_d = (data2_d / 4.0) + (((double)bme680->cal_param.par_P4) * - 65536.0); - data1_d = (((((double)bme680->cal_param.par_P3 * data1_d - * data1_d) / 16384.0) + ((double)bme680->cal_param.par_P2 - * data1_d)) / 524288.0); - data1_d = ((1.0 + (data1_d / 32768.0)) * - ((double)bme680->cal_param.par_P1)); - pressure_comp = (1048576.0 - ((double)uncom_pressure_u32)); - /* Avoid exception caused by division by zero */ - if ((int)data1_d != 0) { - pressure_comp = (((pressure_comp - (data2_d - / 4096.0)) * 6250.0) / data1_d); - data1_d = (((double)bme680->cal_param.par_P9) * - pressure_comp * pressure_comp) / 2147483648.0; - data2_d = pressure_comp * (((double)bme680->cal_param.par_P8) - / 32768.0); - data3_d = ((pressure_comp / 256.0) * (pressure_comp / 256.0) * - (pressure_comp / 256.0) * - (bme680->cal_param.par_P10 / 131072.0)); - pressure_comp = (pressure_comp + (data1_d + data2_d + data3_d + - ((double)bme680->cal_param.par_P7 * 128.0)) / 16.0); - return pressure_comp; - - } else { - return 0; - } - - -} - -/*! - * @brief This function used to convert temperature data - * to uncompensated temperature data using compensation formula - * @note returns the value in Degree centigrade - * @note Output value of "51.23" equals 51.23 DegC. - * - * @param uncom_temperature_u32 : value of uncompensated temperature - * @param bme680: structure pointer. - * - * @return Return the actual temperature in floating point - * -*/ -double bme680_compensate_temperature_double(u32 uncom_temperature_u32, - struct bme680_t *bme680) -{ - double data1_d = 0; - double data2_d = 0; - double temperature = 0; - /* calculate x1 data */ - data1_d = ((((double)uncom_temperature_u32 / 16384.0) - - ((double)bme680->cal_param.par_T1 / 1024.0)) - * ((double)bme680->cal_param.par_T2)); - /* calculate x2 data */ - data2_d = (((((double)uncom_temperature_u32 / 131072.0) - - ((double)bme680->cal_param.par_T1 / 8192.0)) * - (((double)uncom_temperature_u32 / 131072.0) - - ((double)bme680->cal_param.par_T1 / 8192.0))) * - ((double)bme680->cal_param.par_T3 * 16.0)); - /* t fine value*/ - bme680->cal_param.t_fine = (s32)(data1_d + data2_d); - /* compensated temperature data*/ - temperature = ((data1_d + data2_d) / - 5120.0); - - - return temperature; -} - - -/*! - * @brief This function is used to convert temperature to resistance - * using the compensation formula - * - * @param heater_temp_u16: The value of heater temperature - * @param ambient_temp_s16: The value of ambient temperature - * @param bme680: structure pointer. - * - * @return calculated resistance from temperature - * - * - * -*/ -double bme680_convert_temperature_to_resistance_double(u16 heater_temp_u16, - s16 ambient_temp_s16, struct bme680_t *bme680) -{ - double var1 = 0; - double var2 = 0; - double var3 = 0; - double var4 = 0; - double var5 = 0; - double res_heat = 0; - - if ((heater_temp_u16 >= BME680_GAS_PROFILE_TEMPERATURE_MIN) - && (heater_temp_u16 <= BME680_GAS_PROFILE_TEMPERATURE_MAX)) { -#ifdef HEATER_C1_ENABLE - var1 = (((double)bme680->cal_param.par_GH1 / (16.0)) + 49.0); - var2 = ((((double)bme680->cal_param.par_GH2 - /(32768.0)) * (0.0005)) + 0.00235); -#endif - var3 = ((double)bme680->cal_param.par_GH3 / (1024.0)); - var4 = (var1 * (1.0 + (var2 * (double)heater_temp_u16))); - var5 = (var4 + (var3 * (double)ambient_temp_s16)); - -#ifdef HEATER_C1_ENABLE - res_heat = (u8)(3.4 * ((var5 * - (4 / (4 + (double)bme680->cal_param.res_heat_range)) * - (1/(1 + ((double)bme680->cal_param.res_heat_val - * 0.002)))) - 25)); -#else - res_heat = (((var5 * (4.0 / - (4.0 + (double)bme680->cal_param.res_heat_range))) - - 25.0) * 3.4); -#endif - - } - return (u8)res_heat; -} - -#endif -/* bme680.c */ diff --git a/bme680_calculations.h b/bme680_calculations.h deleted file mode 100644 index 797c042..0000000 --- a/bme680_calculations.h +++ /dev/null @@ -1,277 +0,0 @@ -/** -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bme680_calculations.h -* -* Date: 5 May 2017 -* -* Revision : 2.2.0 $ -* -* Usage: Sensor Driver for BME680 sensor -* -**************************************************************************** -* -* \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. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bme680_calculations.h - \brief BME680 Sensor Driver calculation Header File */ - -/*************************************************************************/ -#ifndef __BME680_CALCULATIONS_H__ -#define __BME680_CALCULATIONS_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/*************************************************************************** - Header files - ****************************************************************************/ -#include "bme680.h" - -/*************************************************************************** - Macros, Enums, Constants - ****************************************************************************/ - -/*************************************************************************** - Module globals, typedefs - ****************************************************************************/ - -/*************************************************************************** - Function definitions - ****************************************************************************/ -/* bme680_calculations.h */ -#ifdef FIXED_POINT_COMPENSATION -/**************************************************************/ -/**\name FUNCTION FOR INTEGER OUTPUT GAS*/ -/**************************************************************/ -/*! - * @brief This function is used to convert uncompensated gas data to - * compensated gas data using compensation formula(integer version) - */ -s32 bme680_calculate_gas_int32(u16 gas_adc_u16, u8 gas_range_u8, - struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION FOR INTEGER OUTPUT TEMPERATURE*/ -/**************************************************************/ -/*! - * @brief This function is used to convert the uncompensated - * temperature data to compensated temperature data using - * compensation formula(integer version) - * - * @note Returns the value in 0.01 degree Centigrade - * Output value of "5123" equals 51.23 DegC. - */ -s32 bme680_compensate_temperature_int32(u32 v_uncomp_temperature_u32, - struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION FOR INTEGER OUTPUT HUMIDITY*/ -/**************************************************************/ -/*! - * @brief This function is used to convert the uncompensated - * humidity data to compensated humidity data using - * compensation formula(integer version) - * - * @note Returns the value in %rH as unsigned 32bit integer - * in Q22.10 format(22 integer 10 fractional bits). - * @note An output value of 42313 represents 42313 / 1024 = 41.321 %rH - */ -s32 bme680_compensate_humidity_int32(u32 v_uncomp_humidity_u32, - struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION FOR INTEGER OUTPUT PRESSURE*/ -/**************************************************************/ -/*! - * @brief This function is used to convert the uncompensated - * pressure data to compensated pressure data data using - * compensation formula(integer version) - * - * @note Returns the value in Pascal(Pa) - * Output value of "96386" equals 96386 Pa = 963.86 hPa = 963.86 millibar - */ -s32 bme680_compensate_pressure_int32(u32 v_uncomp_pressure_u32, - struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION FOR INTEGER TEMPERATURE-RESISTANCE*/ -/**************************************************************/ -/*! - * @brief This function is used to convert temperature to resistance - * using the integer compensation formula - */ -u8 bme680_convert_temperature_to_resistance_int32(u16 heater_temp_u16, - s16 ambient_temp_s16, struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION TO CONVERT INT32_H to U16_H BIT OPUTPUT*/ -/**************************************************************/ -/*! - * @brief Reads actual humidity from uncompensated humidity - * - * @note Returns the value in %rH as unsigned 16bit integer - * @note An output value of 42313 represents 42313/512 = 82.643 %rH - */ -u16 bme680_compensate_H_int32_sixteen_bit_output(u32 v_uncomp_humidity_u32, - struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION TO CONVERT INT32_T to S16_T BIT OPUTPUT*/ -/**************************************************************/ -/*! - * @brief Reads actual temperature from uncompensated temperature - * - * @note Returns the value with 500LSB/DegC centred around 24 DegC - * output value of "5123" equals(5123/500)+24 = 34.246DegC - */ -s16 bme680_compensate_T_int32_sixteen_bit_output(u32 v_uncomp_temperature_u32, - struct bme680_t *bme680); -/**************************************************************/ -/**\name FUNCTION TO CONVERT INT32_P to U24_P BIT OPUTPUT*/ -/**************************************************************/ -/*! - * @brief Reads actual pressure from uncompensated pressure in Pa. - * - * @note Output value of "12337434" represents - * 12337434 / 128 = 96386.2 Pa = 963.862 hPa - */ -u32 bme680_compensate_P_int32_twentyfour_bit_output(u32 v_uncomp_pressure_u32, - struct bme680_t *bme680); - -#else -/**************************************************************/ -/**\name FUNCTION FOR FLOAT OUTPUT GAS */ -/**************************************************************/ -/*! - * @brief This function is used to convert uncompensated gas data to - * compensated gas data using compensation formula - */ -double bme680_compensate_gas_double(u16 gas_adc_u16, u8 gas_range_u8, - struct bme680_t *bme680); - -/**************************************************************/ -/**\name FUNCTION FOR FLOAT OUTPUT HUMIDITY */ -/**************************************************************/ - -/*! - * @brief This function is used to convert the uncompensated - * humidity data to compensated humidity data data using - * compensation formula - * - * @note returns the value in relative humidity (%rH) - * @note Output value of "42.12" equals 42.12 %rH - */ -double bme680_compensate_humidity_double(u16 uncom_humidity_u16, - double comp_temperature, struct bme680_t *bme680); - -/**************************************************************/ -/**\name FUNCTION FOR FLOAT OUTPUT PRESSURE*/ -/**************************************************************/ -/*! - * @brief This function is used to convert the uncompensated - * pressure data to compensated data using compensation formula - * - * @note Returns pressure in Pa as double. - * @note Output value of "96386.2" equals 96386.2 Pa = 963.862 hPa. - */ -double bme680_compensate_pressure_double(u32 uncom_pressure_u32, - struct bme680_t *bme680); - -/**************************************************************/ -/**\name FUNCTION FOR FLOAT OUTPUT TEMPERATURE*/ -/**************************************************************/ - -/*! - * @brief This function used to convert temperature data - * to uncompensated temperature data using compensation formula - * - * @note returns the value in Degree centigrade - * @note Output value of "51.23" equals 51.23 DegC. - */ -double bme680_compensate_temperature_double(u32 uncom_temperature_u32, - struct bme680_t *bme680); - -/**************************************************************/ -/**\name FUNCTION FOR TEMPERATURE TO RESISTANCE */ -/**************************************************************/ - -/*! - * @brief This function is used to convert temperature to resistance - * using the compensation formula - */ -double bme680_convert_temperature_to_resistance_double(u16 heater_temp_u16, - s16 ambient_temp_s16, struct bme680_t *bme680); -#endif -/* bme680_calculations.h */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/bme680_defs.h b/bme680_defs.h new file mode 100644 index 0000000..4ef701f --- /dev/null +++ b/bme680_defs.h @@ -0,0 +1,529 @@ +/** + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bme680_defs.h + * @date 5 Jul 2017 + * @version 3.5.1 + * @brief + * + */ + +/*! @file bme680_defs.h + @brief Sensor driver for BME680 sensor */ +/*! + * @defgroup BME680 SENSOR API + * @brief + * @{*/ +#ifndef BME680_DEFS_H_ +#define BME680_DEFS_H_ + +/********************************************************/ +/* header includes */ +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#ifdef __KERNEL__ +#if (LONG_MAX) > 0x7fffffff +#define __have_long64 1 +#elif (LONG_MAX) == 0x7fffffff +#define __have_long32 1 +#endif + +#if !defined(UINT8_C) +#define INT8_C(x) x +#if (INT_MAX) > 0x7f +#define UINT8_C(x) x +#else +#define UINT8_C(x) x##U +#endif +#endif + +#if !defined(UINT16_C) +#define INT16_C(x) x +#if (INT_MAX) > 0x7fff +#define UINT16_C(x) x +#else +#define UINT16_C(x) x##U +#endif +#endif + +#if !defined(INT32_C) && !defined(UINT32_C) +#if __have_long32 +#define INT32_C(x) x##L +#define UINT32_C(x) x##UL +#else +#define INT32_C(x) x +#define UINT32_C(x) x##U +#endif +#endif + +#if !defined(INT64_C) && !defined(UINT64_C) +#if __have_long64 +#define INT64_C(x) x##L +#define UINT64_C(x) x##UL +#else +#define INT64_C(x) x##LL +#define UINT64_C(x) x##ULL +#endif +#endif +#endif +/**@}*/ + +/**\name C standard macros */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/** BME680 General config */ +#define BME680_POLL_PERIOD_MS UINT8_C(10) + +/** BME680 I2C addresses */ +#define BME680_I2C_ADDR_PRIMARY UINT8_C(0x76) +#define BME680_I2C_ADDR_SECONDARY UINT8_C(0x77) + +/** BME680 unique chip identifier */ +#define BME680_CHIP_ID UINT8_C(0x61) + +/** BME680 coefficients related defines */ +#define BME680_COEFF_SIZE UINT8_C(0x41) +#define BME680_COEFF_ADDR1_LEN UINT8_C(25) +#define BME680_COEFF_ADDR2_LEN UINT8_C(16) + +/** BME680 field_x related defines */ +#define BME680_FIELD_LENGTH UINT8_C(15) +#define BME680_FIELD_ADDR_OFFSET UINT8_C(17) + +/** Soft reset command */ +#define BME680_SOFT_RESET_CMD UINT8_C(0xb6) + +/** Error code definitions */ +#define BME680_OK INT8_C(0) +/* Errors */ +#define BME680_E_NULL_PTR INT8_C(-1) +#define BME680_E_COM_FAIL INT8_C(-2) +#define BME680_E_DEV_NOT_FOUND INT8_C(-3) +#define BME680_E_INVALID_LENGTH INT8_C(-4) + +/* Warnings */ +#define BME680_W_DEFINE_PWR_MODE INT8_C(1) +#define BME680_W_NO_NEW_DATA INT8_C(2) + +/* Info's */ +#define BME680_I_MIN_CORRECTION UINT8_C(1) +#define BME680_I_MAX_CORRECTION UINT8_C(2) + +/** Register map */ +/** Other coefficient's address */ +#define BME680_ADDR_RES_HEAT_VAL_ADDR UINT8_C(0x00) +#define BME680_ADDR_RES_HEAT_RANGE_ADDR UINT8_C(0x02) +#define BME680_ADDR_RANGE_SW_ERR_ADDR UINT8_C(0x04) +#define BME680_ADDR_SENS_CONF_START UINT8_C(0x5A) +#define BME680_ADDR_GAS_CONF_START UINT8_C(0x64) + +/** Field settings */ +#define BME680_FIELD0_ADDR UINT8_C(0x1d) + +/** Heater settings */ +#define BME680_RES_HEAT0_ADDR UINT8_C(0x5a) +#define BME680_GAS_WAIT0_ADDR UINT8_C(0x64) + +/** Sensor configuration registers */ +#define BME680_CONF_HEAT_CTRL_ADDR UINT8_C(0x70) +#define BME680_CONF_ODR_RUN_GAS_NBC_ADDR UINT8_C(0x71) +#define BME680_CONF_OS_H_ADDR UINT8_C(0x72) +#define BME680_MEM_PAGE_ADDR UINT8_C(0xf3) +#define BME680_CONF_T_P_MODE_ADDR UINT8_C(0x74) +#define BME680_CONF_ODR_FILT_ADDR UINT8_C(0x75) + +/** Coefficient's address */ +#define BME680_COEFF_ADDR1 UINT8_C(0x89) +#define BME680_COEFF_ADDR2 UINT8_C(0xe1) + +/** Chip identifier */ +#define BME680_CHIP_ID_ADDR UINT8_C(0xd0) + +/** Soft reset register */ +#define BME680_SOFT_RESET_ADDR UINT8_C(0xe0) + +/** Heater control settings */ +#define BME680_ENABLE_HEATER UINT8_C(0x00) +#define BME680_DISABLE_HEATER UINT8_C(0x08) + +/** Gas measurement settings */ +#define BME680_DISABLE_GAS_MEAS UINT8_C(0x00) +#define BME680_ENABLE_GAS_MEAS UINT8_C(0x01) + +/** Over-sampling settings */ +#define BME680_OS_NONE UINT8_C(0) +#define BME680_OS_1X UINT8_C(1) +#define BME680_OS_2X UINT8_C(2) +#define BME680_OS_4X UINT8_C(3) +#define BME680_OS_8X UINT8_C(4) +#define BME680_OS_16X UINT8_C(5) + +/** IIR filter settings */ +#define BME680_FILTER_SIZE_0 UINT8_C(0) +#define BME680_FILTER_SIZE_1 UINT8_C(1) +#define BME680_FILTER_SIZE_3 UINT8_C(2) +#define BME680_FILTER_SIZE_7 UINT8_C(3) +#define BME680_FILTER_SIZE_15 UINT8_C(4) +#define BME680_FILTER_SIZE_31 UINT8_C(5) +#define BME680_FILTER_SIZE_63 UINT8_C(6) +#define BME680_FILTER_SIZE_127 UINT8_C(7) + +/** Power mode settings */ +#define BME680_SLEEP_MODE UINT8_C(0) +#define BME680_FORCED_MODE UINT8_C(1) + +/** Delay related macro declaration */ +#define BME680_RESET_PERIOD UINT32_C(10) + +/** SPI memory page settings */ +#define BME680_MEM_PAGE0 UINT8_C(0x10) +#define BME680_MEM_PAGE1 UINT8_C(0x00) + +/** Ambient humidity shift value for compensation */ +#define BME680_HUM_REG_SHIFT_VAL UINT8_C(4) + +/** Run gas enable and disable settings */ +#define BME680_RUN_GAS_DISABLE UINT8_C(0) +#define BME680_RUN_GAS_ENABLE UINT8_C(1) + +/** Buffer length macro declaration */ +#define BME680_TMP_BUFFER_LENGTH UINT8_C(40) +#define BME680_REG_BUFFER_LENGTH UINT8_C(6) +#define BME680_FIELD_DATA_LENGTH UINT8_C(3) +#define BME680_GAS_REG_BUF_LENGTH UINT8_C(20) +#define BME680_GAS_HEATER_PROF_LEN_MAX UINT8_C(10) + +/** Settings selector */ +#define BME680_OST_SEL UINT16_C(1) +#define BME680_OSP_SEL UINT16_C(2) +#define BME680_OSH_SEL UINT16_C(4) +#define BME680_GAS_MEAS_SEL UINT16_C(8) +#define BME680_FILTER_SEL UINT16_C(16) +#define BME680_HCNTRL_SEL UINT16_C(32) +#define BME680_RUN_GAS_SEL UINT16_C(64) +#define BME680_NBCONV_SEL UINT16_C(128) +#define BME680_GAS_SENSOR_SEL UINT16_C(BME680_GAS_MEAS_SEL | BME680_RUN_GAS_SEL | BME680_NBCONV_SEL) + +/** Number of conversion settings*/ +#define BME680_NBCONV_MIN UINT8_C(0) +#define BME680_NBCONV_MAX UINT8_C(10) + +/** Mask definitions */ +#define BME680_GAS_MEAS_MSK UINT8_C(0x30) +#define BME680_NBCONV_MSK UINT8_C(0X0F) +#define BME680_FILTER_MSK UINT8_C(0X1C) +#define BME680_OST_MSK UINT8_C(0XE0) +#define BME680_OSP_MSK UINT8_C(0X1C) +#define BME680_OSH_MSK UINT8_C(0X07) +#define BME680_HCTRL_MSK UINT8_C(0x08) +#define BME680_RUN_GAS_MSK UINT8_C(0x10) +#define BME680_MODE_MSK UINT8_C(0x03) +#define BME680_RHRANGE_MSK UINT8_C(0x30) +#define BME680_RSERROR_MSK UINT8_C(0xf0) +#define BME680_NEW_DATA_MSK UINT8_C(0x80) +#define BME680_GAS_INDEX_MSK UINT8_C(0x0f) +#define BME680_GAS_RANGE_MSK UINT8_C(0x0f) +#define BME680_GASM_VALID_MSK UINT8_C(0x20) +#define BME680_HEAT_STAB_MSK UINT8_C(0x10) +#define BME680_MEM_PAGE_MSK UINT8_C(0x10) +#define BME680_SPI_RD_MSK UINT8_C(0x80) +#define BME680_SPI_WR_MSK UINT8_C(0x7f) +#define BME680_BIT_H1_DATA_MSK UINT8_C(0x0F) + +/** Bit position definitions for sensor settings */ +#define BME680_GAS_MEAS_POS UINT8_C(4) +#define BME680_FILTER_POS UINT8_C(2) +#define BME680_OST_POS UINT8_C(5) +#define BME680_OSP_POS UINT8_C(2) +#define BME680_RUN_GAS_POS UINT8_C(4) + +/** Array Index to Field data mapping for Calibration Data*/ +#define BME680_T2_LSB_REG (1) +#define BME680_T2_MSB_REG (2) +#define BME680_T3_REG (3) +#define BME680_P1_LSB_REG (5) +#define BME680_P1_MSB_REG (6) +#define BME680_P2_LSB_REG (7) +#define BME680_P2_MSB_REG (8) +#define BME680_P3_REG (9) +#define BME680_P4_LSB_REG (11) +#define BME680_P4_MSB_REG (12) +#define BME680_P5_LSB_REG (13) +#define BME680_P5_MSB_REG (14) +#define BME680_P7_REG (15) +#define BME680_P6_REG (16) +#define BME680_P8_LSB_REG (19) +#define BME680_P8_MSB_REG (20) +#define BME680_P9_LSB_REG (21) +#define BME680_P9_MSB_REG (22) +#define BME680_P10_REG (23) +#define BME680_H2_MSB_REG (25) +#define BME680_H2_LSB_REG (26) +#define BME680_H1_LSB_REG (26) +#define BME680_H1_MSB_REG (27) +#define BME680_H3_REG (28) +#define BME680_H4_REG (29) +#define BME680_H5_REG (30) +#define BME680_H6_REG (31) +#define BME680_H7_REG (32) +#define BME680_T1_LSB_REG (33) +#define BME680_T1_MSB_REG (34) +#define BME680_GH2_LSB_REG (35) +#define BME680_GH2_MSB_REG (36) +#define BME680_GH1_REG (37) +#define BME680_GH3_REG (38) + +/** BME680 register buffer index settings*/ +#define BME680_REG_FILTER_INDEX UINT8_C(5) +#define BME680_REG_TEMP_INDEX UINT8_C(4) +#define BME680_REG_PRES_INDEX UINT8_C(4) +#define BME680_REG_HUM_INDEX UINT8_C(2) +#define BME680_REG_NBCONV_INDEX UINT8_C(1) +#define BME680_REG_RUN_GAS_INDEX UINT8_C(1) +#define BME680_REG_HCTRL_INDEX UINT8_C(0) + +/** Macro to combine two 8 bit data's to form a 16 bit data */ +#define BME680_CONCAT_BYTES(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb) + +/** Macro to SET and GET BITS of a register */ +#define BME680_SET_BITS(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + ((data << bitname##_POS) & bitname##_MSK)) +#define BME680_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \ + (bitname##_POS)) + +/** Macro variant to handle the bitname position if it is zero */ +#define BME680_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) +#define BME680_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +/** Type definitions */ +/* + * Generic communication function pointer + * @param[in] dev_id: Place holder to store the id of the device structure + * Can be used to store the index of the Chip select or + * I2C address of the device. + * @param[in] reg_addr: Used to select the register the where data needs to + * be read from or written to. + * @param[in/out] reg_data: Data array to read/write + * @param[in] len: Length of the data array + */ +typedef int8_t (*bme680_com_fptr_t)(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len); + +/* + * Delay function pointer + * @param[in] period: Time period in milliseconds + */ +typedef void (*bme680_delay_fptr_t)(uint32_t period); + +/*! + * @brief Interface selection Enumerations + */ +enum bme680_intf { + /*! SPI interface */ + BME680_SPI_INTF, + /*! I2C interface */ + BME680_I2C_INTF +}; + +/* structure definitions */ +/*! + * @brief Sensor field data structure + */ +struct bme680_field_data { + /*! Contains new_data, gasm_valid & heat_stab */ + uint8_t status; + /*! The index of the heater profile used */ + uint8_t gas_index; + /*! Measurement index to track order */ + uint8_t meas_index; + /*! Temperature in degree celsius x100 */ + int16_t temperature; + /*! Pressure in Pascal */ + uint32_t pressure; + /*! Humidity in % relative humidity x1000 */ + uint32_t humidity; + /*! Gas resistance in Ohms */ + uint32_t gas_resistance; +}; + +/*! + * @brief Structure to hold the Calibration data + */ +struct bme680_calib_data { + /*! Variable to store calibrated humidity data */ + uint16_t par_h1; + /*! Variable to store calibrated humidity data */ + uint16_t par_h2; + /*! Variable to store calibrated humidity data */ + int8_t par_h3; + /*! Variable to store calibrated humidity data */ + int8_t par_h4; + /*! Variable to store calibrated humidity data */ + int8_t par_h5; + /*! Variable to store calibrated humidity data */ + uint8_t par_h6; + /*! Variable to store calibrated humidity data */ + int8_t par_h7; + /*! Variable to store calibrated gas data */ + int8_t par_gh1; + /*! Variable to store calibrated gas data */ + int16_t par_gh2; + /*! Variable to store calibrated gas data */ + int8_t par_gh3; + /*! Variable to store calibrated temperature data */ + uint16_t par_t1; + /*! Variable to store calibrated temperature data */ + int16_t par_t2; + /*! Variable to store calibrated temperature data */ + int8_t par_t3; + /*! Variable to store calibrated pressure data */ + uint16_t par_p1; + /*! Variable to store calibrated pressure data */ + int16_t par_p2; + /*! Variable to store calibrated pressure data */ + int8_t par_p3; + /*! Variable to store calibrated pressure data */ + int16_t par_p4; + /*! Variable to store calibrated pressure data */ + int16_t par_p5; + /*! Variable to store calibrated pressure data */ + int8_t par_p6; + /*! Variable to store calibrated pressure data */ + int8_t par_p7; + /*! Variable to store calibrated pressure data */ + int16_t par_p8; + /*! Variable to store calibrated pressure data */ + int16_t par_p9; + /*! Variable to store calibrated pressure data */ + uint8_t par_p10; + /*! Variable to store t_fine size */ + int32_t t_fine; + /*! Variable to store heater resistance range */ + uint8_t res_heat_range; + /*! Variable to store heater resistance value */ + int8_t res_heat_val; + /*! Variable to store error range */ + int8_t range_sw_err; +}; + +/*! + * @brief BME680 sensor settings structure which comprises of ODR, + * over-sampling and filter settings. + */ +struct bme680_tph_sett { + /*! Humidity oversampling */ + uint8_t os_hum; + /*! Temperature oversampling */ + uint8_t os_temp; + /*! Pressure oversampling */ + uint8_t os_pres; + /*! Filter coefficient */ + uint8_t filter; +}; + +/*! + * @brief BME680 gas sensor which comprises of gas settings + * and status parameters + */ +struct bme680_gas_sett { + /*! Variable to store nb conversion */ + uint8_t nb_conv; + /*! Variable to store heater control */ + uint8_t heatr_ctrl; + /*! Run gas enable value */ + uint8_t run_gas; + /*! Pointer to store heater temperature */ + uint16_t heatr_temp; + /*! Pointer to store duration profile */ + uint16_t heatr_dur; +}; + +/*! + * @brief BME680 device structure + */ +struct bme680_dev { + /*! Chip Id */ + uint8_t chip_id; + /*! Device Id */ + uint8_t dev_id; + /*! SPI/I2C interface */ + enum bme680_intf intf; + /*! Memory page used */ + uint8_t mem_page; + /*! Ambient temperature in Degree C*/ + int8_t amb_temp; + /*! Sensor calibration data */ + struct bme680_calib_data calib; + /*! Sensor settings */ + struct bme680_tph_sett tph_sett; + /*! Gas Sensor settings */ + struct bme680_gas_sett gas_sett; + /*! Sensor power modes */ + uint8_t power_mode; + /*! New sensor fields */ + uint8_t new_fields; + /*! Store the info messages */ + uint8_t info_msg; + /*! Burst read structure */ + bme680_com_fptr_t read; + /*! Burst write structure */ + bme680_com_fptr_t write; + /*! Delay in ms */ + bme680_delay_fptr_t delay_ms; + /*! Communication function result */ + int8_t com_rslt; +}; + +#endif /* BME680_DEFS_H_ */ +/** @}*/ +/** @}*/ diff --git a/bme680_internal.h b/bme680_internal.h deleted file mode 100644 index 3d79c4e..0000000 --- a/bme680_internal.h +++ /dev/null @@ -1,313 +0,0 @@ -/** -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : bme680_internal.h -* -* Date: 5 May 2017 -* -* Revision : 2.2.0 $ -* -* Usage: Sensor Driver for BME680 sensor -* -**************************************************************************** -* -* \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. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file bme680_internal.h - \brief BME680 Sensor Driver internal support Header File */ - -#ifndef _BME680_INTERNAL_H -#define _BME680_INTERNAL_H - -/*************************************************************************** - Header files -****************************************************************************/ - - - - -/*************************************************************************** - Macros Enums, Constants only sensor Specific constants -****************************************************************************/ -/* bme680_internal.h */ -/* Pre-processor switch for separating between I2C and SPI addresses */ - -#define BME680_CALIB_SPI_ADDR_1 (0x09) -#define BME680_CALIB_SPI_ADDR_2 (0x61) -#define BME680_PAGE0_SPI_ID_REG (0x50) - -#define BME680_CALIB_I2C_ADDR_1 (0x89) -#define BME680_CALIB_I2C_ADDR_2 (0xE1) -#define BME680_PAGE0_I2C_ID_REG (0xD0) - -#define BME680_OVERSAMP_TEMP_SHIFT (0x03) -#define BME680_GAS_WAIT_STEP_SIZE (477) - -#define BME680_SENS_CONF_LEN (0x06) -#define BME680_SENS_HEATR_CONF_LEN (0x15) - -#define BME680_TRUE (1) -#define BME680_FALSE (0) - -#define BME680_CALIB_PARAM_SIZE ((u8)41) -#define BME680_PAGE0_INTERFACE_SPI ((u8)0) -#define BME680_PAGE1_INTERFACE_SPI ((u8)1) -#define BME680_CALIB_DATA_LENGTH_GAS (25) -#define BME680_CALIB_DATA_LENGTH (16) -#define BME680_BIT_MASK_H1_DATA (0x0F) -#define BME680_FIELD_ZERO (0) -#define BME680_FIELD_ONE (1) -#define BME680_FIELD_TWO (2) -#define BME680_FIELD_ONE_OFFSET (17) -#define BME680_FIELD_TWO_OFFSET (34) -#define BME680_FIELD_SIZE (17) - -/* Sensor Specific constants */ -#define BME680_GAS_BIT_MASK (0x00C0) -#define BME680_GAS_WAIT_MAX_TIMER_VALUE (0x3F) -#define BME680_GAS_WAIT_MIN_TIMER_VALUE (0x00) - -#define BME680_PROFILE_MAX (10) - - -#define BME680_ADDR_SPI_MEM_PAGE (0x73) -#define BME680_ADDR_OP_MODE (0x74) -#define BME680_ADDR_SENS_CONF_START (0x5A) -#define BME680_ADDR_FIELD_0 (0x1D) -#define BME680_ADDR_SENSOR_CONFIG (0x70) -#define BME680_ADDR_RES_HEAT_VAL (0x00) -#define BME680_ADDR_RES_HEAT_RANGE (0x02) -#define BME680_ADDR_RANGE_SWITCHING_ERR (0x04) - -/* Section 3.2: Sub-register addresses, masks and bit shifts */ - -#define BME680_MASK_OP_MODE (0xFC) -#define BME680_MASK_HEATR_CTRL (0xF7) -#define BME680_MASK_ODR_3 (0x7F) -#define BME680_MASK_ODR_2_0 (0x1F) -#define BME680_MASK_RUN_GAS (0xEF) -#define BME680_MASK_PROF_INDEX (0xF0) -#define BME680_MASK_OSRS_HUM (0xF8) -#define BME680_MASK_OSRS_PRES (0xE3) -#define BME680_MASK_OSRS_TEMP (0x1F) -#define BME680_MASK_FILTER (0xE3) -#define BME680_MASK_NEW_DATA (0x7F) -#define BME680_MASK_GAS_MEAS_STAT (0xBF) -#define BME680_MASK_TPHG_MEAS_STAT (0xDF) -#define BME680_MASK_GAS_MEAS_INDEX (0xF0) -#define BME680_MASK_GAS_RANGE (0xF0) -#define BME680_MASK_GAS_VALID (0xDF) -#define BME680_MASK_HEATR_STAB (0xEF) -#define BME680_MASK_SPI_3W_INT (0xBF) -#define BME680_MASK_SPI_3W_EN (0xFE) -#define BME680_MASK_MEM_PAGE (0xEF) -#define BME680_MASK_RES_HEAT_RANGE (0xCF) -#define BME680_MASK_RANGE_ERR (0x0F) - -/* Section : Register settings/values */ -/* Lengths to support burst reads/writes */ - -#define BME680_SINGLE_FIELD_LENGTH (15) -#define BME680_LEN_ALL_FIELD_SIZE (49) - - -#define BME680_ADDR_FIELD_0_STATUS (0x1D) -#define BME680_ADDR_FIELD_1_STATUS (0x2E) -#define BME680_ADDR_FIELD_2_STATUS (0x3F) -#define BME680_ADDR_FIELD_0_TEMP1 (0x22) -#define BME680_ADDR_FIELD_0_TEMP2 (0x27) -#define BME680_ADDR_FIELD_1_TEMP1 (0x33) -#define BME680_ADDR_FIELD_1_TEMP2 (0x38) -#define BME680_ADDR_FIELD_2_TEMP1 (0x44) -#define BME680_ADDR_FIELD_2_TEMP2 (0x49) -#define BME680_ADDR_FIELD_0_PRESS (0x1F) -#define BME680_ADDR_FIELD_1_PRESS (0x30) -#define BME680_ADDR_FIELD_2_PRESS (0x41) -#define BME680_ADDR_FIELD_0_HUM (0x25) -#define BME680_ADDR_FIELD_1_HUM (0x36) -#define BME680_ADDR_FIELD_2_HUM (0x47) -#define BME680_ADDR_FIELD_0_GAS (0x2A) -#define BME680_ADDR_FIELD_1_GAS (0x3B) -#define BME680_ADDR_FIELD_2_GAS (0x4C) - - -/*******************************************************/ -/* Array Index to Field data mapping*/ -/********************************************************/ -/* For Calibration Data*/ - -#define DIG_T2_LSB_REG (1) -#define DIG_T2_MSB_REG (2) -#define DIG_T3_REG (3) -#define DIG_P1_LSB_REG (5) -#define DIG_P1_MSB_REG (6) -#define DIG_P2_LSB_REG (7) -#define DIG_P2_MSB_REG (8) -#define DIG_P3_REG (9) -#define DIG_P4_LSB_REG (11) -#define DIG_P4_MSB_REG (12) -#define DIG_P5_LSB_REG (13) -#define DIG_P5_MSB_REG (14) -#define DIG_P7_REG (15) -#define DIG_P6_REG (16) -#define DIG_P8_LSB_REG (19) -#define DIG_P8_MSB_REG (20) -#define DIG_P9_LSB_REG (21) -#define DIG_P9_MSB_REG (22) -#define DIG_P10_REG (23) -#define DIG_H2_MSB_REG (25) -#define DIG_H2_LSB_REG (26) -#define DIG_H1_LSB_REG (26) -#define DIG_H1_MSB_REG (27) -#define DIG_H3_REG (28) -#define DIG_H4_REG (29) -#define DIG_H5_REG (30) -#define DIG_H6_REG (31) -#define DIG_H7_REG (32) -#define DIG_T1_LSB_REG (33) -#define DIG_T1_MSB_REG (34) -#define DIG_GH2_LSB_REG (35) -#define DIG_GH2_MSB_REG (36) -#define DIG_GH1_REG (37) -#define DIG_GH3_REG (38) - -/* For TPHG data */ - -#define FIELD_0_MEAS_STATUS_0 (0) -#define FIELD_0_MEAS_STATUS_1 (1) -#define FIELD_0_GAS_RL_LSB (14) - -/*! -@brief data frame includes temperature, pressure, humidity -and gas data*/ -#define BME680_DATA_FRAME_PRESSURE_MSB_DATA ((u8)2) -#define BME680_DATA_FRAME_PRESSURE_LSB_DATA ((u8)3) -#define BME680_DATA_FRAME_PRESSURE_XLSB_DATA ((u8)4) -#define BME680_DATA_FRAME_TEMPERATURE1_MSB_DATA ((u8)5) -#define BME680_DATA_FRAME_TEMPERATURE1_LSB_DATA ((u8)6) -#define BME680_DATA_FRAME_TEMPERATURE1_XLSB_DATA ((u8)7) -#define BME680_DATA_FRAME_HUMIDITY_MSB_DATA ((u8)8) -#define BME680_DATA_FRAME_HUMIDITY_LSB_DATA ((u8)9) -#define BME680_DATA_FRAME_GAS_MSB_DATA ((u8)13) -#define BME680_DATA_FRAME_GAS_LSB_DATA ((u8)14) - - -/* Positions to support indexing in an array */ -#define BME680_INDEX_CTRL_GAS_0 (0) -#define BME680_INDEX_CTRL_GAS_1 (1) -#define BME680_INDEX_CTRL_HUM (2) -#define BME680_INDEX_CTRL_MEAS (4) -#define BME680_INDEX_CONFIG (5) - -/* Constants to store the bit shift parameters */ -#define BME680_SHIFT_OP_MODE (0) -#define BME680_SHIFT_HEATR_CTRL (3) -#define BME680_SHIFT_ODR_3 (4) -#define BME680_SHIFT_ODR_2_0 (5) -#define BME680_SHIFT_RUN_GAS (4) -#define BME680_SHIFT_PROF_INDEX (0) -#define BME680_SHIFT_OSRS_HUM (0) -#define BME680_SHIFT_OSRS_TEMP (5) -#define BME680_SHIFT_OSRS_PRES (2) -#define BME680_SHIFT_FILTER (2) -#define BME680_SHIFT_NEW_DATA (7) -#define BME680_SHIFT_GAS_MEAS_STAT (6) -#define BME680_SHIFT_TPHG_MEAS_STAT (5) -#define BME680_SHIFT_GAS_MEAS_INDEX (0) -#define BME680_SHIFT_GAS_RANGE (0) -#define BME680_SHIFT_GAS_VALID (5) -#define BME680_SHIFT_HEATR_STAB (4) -#define BME680_SHIFT_SPI_3W_INT (6) -#define BME680_SHIFT_SPI_3W_EN (0) -#define BME680_SHIFT_SPI_MEM_PAGE (4) -#define BME680_SHIFT_RES_HEAT_RANGE (4) -#define BME680_SHIFT_RANGE_ERR (4) - -#define BME680_ONE (1) -#define BME680_TWO (2) -#define BME680_THREE (3) - -#define BME680_GEN_READ_DATA_LENGTH ((u8)1) -#define BME680_GEN_WRITE_DATA_LENGTH ((u8)1) - -/* bme680_internal.h */ -/*************************************************************************** - Module globals, typedefs -****************************************************************************/ - - -/*************************************************************************** - Function definitions -****************************************************************************/ - - -#endif diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..36bc4ab --- /dev/null +++ b/changelog.md @@ -0,0 +1,42 @@ +# Change Log +All notable changes to the BME680 Sensor API will be documented in this file. + +## v3.5.1, 5 Jul 2017 +### Changed + - Fixed bug with overwriting of the result with communication results + - Added member in the dev structure to store communication results + - Updated set profile duration API to not return a result. + - Added new API to get the duration for the existing profile + - Fixed bug with setting gas configuration. Reduced to writing only relevant bytes + - Updated readme + - Updated documentation for the type definitions + - Removed mode check for get sensor data and setting and getting profile dur + + +## v3.5.0, 28 Jun 2017 +### Changed +- Fixed bug with getting and setting mem pages +- Changed initialization sequence to be more robust +- Added additional tries while reading data in case of inadequate delay + + +## v3.4.0, 8 Jun 2017 +### Changed +- Modified the bme680_get_sensor_data API. User has to now pass the struct that stores the data rather than retrieving from the bme680_dev structure. +- Fixed possible bugs + +## v3.3.0, 24 May 2017 +### Changed +- Name changes in the BME680 device structure. +- Removed sequential and parallel modes. +- Removed ODR related sensor settings +- Modified get sensor settings API with user selection. +- Removed sort sensor data and swap fields API which are not required. + +### Added +- BME680 set profile duration API. + +## v3.2.1, 17 May 2017 +### Added +- Took the reference as base version 3.2.1 of BME680 sensor and added. + diff --git a/sensor_api_common_types.h b/sensor_api_common_types.h deleted file mode 100644 index 9177171..0000000 --- a/sensor_api_common_types.h +++ /dev/null @@ -1,340 +0,0 @@ -/** -* -**************************************************************************** -* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH -* -* File : sensor_api_common_types.h -* -* Date: 5 May 2017 -* -* Revision : 2.2.0 $ -* -* Usage: Sensor Driver for BME680 sensor -* -**************************************************************************** -* -* \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. -* -* The purchaser must monitor the market for the purchased products, -* particularly with regard to product safety and inform Bosch Sensortec -* without delay of all security relevant incidents. -* -* Engineering Samples are marked with an asterisk (*) or (e). -* Samples may vary from the valid technical specifications of the product -* series. They are therefore not intended or fit for resale to third -* parties or for use in end products. Their sole purpose is internal -* client testing. The testing of an engineering sample may in no way -* replace the testing of a product series. Bosch Sensortec assumes -* no liability for the use of engineering samples. -* By accepting the engineering samples, the Purchaser agrees to indemnify -* Bosch Sensortec from all claims arising from the use of engineering -* samples. -* -* Special: -* This software module (hereinafter called "Software") and any information -* on application-sheets (hereinafter called "Information") is provided -* free of charge for the sole purpose to support your application work. -* The Software and Information is subject to the following -* terms and conditions: -* -* The Software is specifically designed for the exclusive use for -* Bosch Sensortec products by personnel who have special experience -* and training. Do not use this Software if you do not have the -* proper experience or training. -* -* This Software package is provided `` as is `` and without any expressed -* or implied warranties,including without limitation, the implied warranties -* of merchantability and fitness for a particular purpose. -* -* Bosch Sensortec and their representatives and agents deny any liability -* for the functional impairment -* of this Software in terms of fitness, performance and safety. -* Bosch Sensortec and their representatives and agents shall not be liable -* for any direct or indirect damages or injury, except as -* otherwise stipulated in mandatory applicable law. -* -* The Information provided is believed to be accurate and reliable. -* Bosch Sensortec assumes no responsibility for the consequences of use -* of such Information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of Bosch. Specifications mentioned in the Information are -* subject to change without notice. -**************************************************************************/ -/*! \file sensor_api_common_types.h - \brief sensor API common data types Header File */ - -#ifndef __SENSOR_API_COMMON_TYPES_H__ -#define __SENSOR_API_COMMON_TYPES_H__ - - -/***************************************************************************/ - - -/*************************************************************************** - Macros, Enum, Constant -****************************************************************************/ -/* sensor_api_common_types.h */ -/*! -* @brief The following definition is used for defining the data types -* -* @note While porting the API please consider the following -* @note Please check the version of C standard -* @note Are you using Linux platform -*/ - -/*! -* @brief For the Linux platform support -* Please use the types.h for your data types definitions -*/ -#ifdef __KERNEL__ - -#include -#include - /* singed integer type*/ - typedef int8_t s8;/**< used for signed 8bit */ - typedef int16_t s16;/**< used for signed 16bit */ - typedef int32_t s32;/**< used for signed 32bit */ - typedef int64_t s64;/**< used for signed 64bit */ - - typedef u_int8_t u8;/**< used for unsigned 8bit */ - typedef u_int16_t u16;/**< used for unsigned 16bit */ - typedef u_int32_t u32;/**< used for unsigned 32bit */ - /*typedef u_int64_t u64;*//**< used for unsigned 64bit */ - typedef signed long long int s64; -#else /* ! __KERNEL__ */ - /********************************************************** - * These definitions are used to define the C - * standard version data types - ***********************************************************/ -# if defined(__STDC_VERSION__) - /************************************************ - * compiler is C11 C standard - ************************************************/ -#if (__STDC_VERSION__ == 201112L) - /************************************************/ -#include - - /************************************************/ - /*unsigned integer types*/ - typedef uint8_t u8;/**< used for unsigned 8bit */ - typedef uint16_t u16;/**< used for unsigned 16bit */ - typedef uint32_t u32;/**< used for unsigned 32bit */ - typedef uint64_t u64;/**< used for unsigned 64bit */ - - /*signed integer types*/ - typedef int8_t s8;/**< used for signed 8bit */ - typedef int16_t s16;/**< used for signed 16bit */ - typedef int32_t s32;/**< used for signed 32bit */ - typedef int64_t s64;/**< used for signed 64bit */ - /*typedef signed long long int s64;*/ - /************************************************ - * compiler is C99 C standard - ************************************************/ -#elif (__STDC_VERSION__ == 199901L) - - /* stdint.h is a C99 supported c library. - which is used to fixed the integer size*/ - /************************************************/ -#include - /************************************************/ - - /*unsigned integer types*/ - typedef uint8_t u8;/**< used for unsigned 8bit */ - typedef uint16_t u16;/**< used for unsigned 16bit */ - typedef uint32_t u32;/**< used for unsigned 32bit */ - typedef uint64_t u64;/**< used for unsigned 64bit */ - - /*signed integer types*/ - typedef int8_t s8;/**< used for signed 8bit */ - typedef int16_t s16;/**< used for signed 16bit */ - typedef int32_t s32;/**< used for signed 32bit */ - /*typedef int64_t s64;*//**< used for signed 64bit */ - - typedef signed long long int s64; - /************************************************ - * compiler is C89 or other C standard - ************************************************/ -#else /* !defined(__STDC_VERSION__) */ - /*! - * @brief By default it is defined as 32 bit machine configuration - * define your data types based on your - * machine/compiler/controller configuration - */ -#define MACHINE_32_BIT - - /*! @brief - * If your machine support 16 bit - * define the MACHINE_16_BIT - */ -#ifdef MACHINE_16_BIT -#include - /*signed integer types*/ - typedef signed char s8;/**< used for signed 8bit */ - typedef signed short int s16;/**< used for signed 16bit */ - typedef signed long int s32;/**< used for signed 32bit */ - -#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL - typedef long int s64;/**< used for signed 64bit */ - typedef unsigned long int u64;/**< used for unsigned 64bit */ -#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL) - typedef long long int s64;/**< used for signed 64bit */ - typedef unsigned long long int u64;/**< used for unsigned 64bit */ -#else -#warning Either the correct data type for signed 64 bit integer \ - could not be found, or 64 bit integers are not - supported in your environment. -#warning If 64 bit integers are supported on your platform, \ - please set s64 manually. -#endif - - /*unsigned integer types*/ - typedef unsigned char u8;/**< used for unsigned 8bit */ - typedef unsigned short int u16;/**< used for unsigned 16bit */ - typedef unsigned int u32;/**< used for unsigned 32bit */ - - /* If your machine support 32 bit - define the MACHINE_32_BIT*/ -#elif defined MACHINE_32_BIT - /*signed integer types*/ - typedef signed char s8;/**< used for signed 8bit */ - typedef signed short int s16;/**< used for signed 16bit */ - typedef signed int s32;/**< used for signed 32bit */ - typedef signed long long int s64;/**< used for signed 64bit */ - - /*unsigned integer types*/ - typedef unsigned char u8;/**< used for unsigned 8bit */ - typedef unsigned short int u16;/**< used for unsigned 16bit */ - typedef unsigned int u32;/**< used for unsigned 32bit */ - typedef unsigned long long int u64;/**< used for unsigned 64bit */ - - /* If your machine support 64 bit - define the MACHINE_64_BIT*/ -#elif defined MACHINE_64_BIT - /*signed integer types*/ - typedef signed char s8;/**< used for signed 8bit */ - typedef signed short int s16;/**< used for signed 16bit */ - typedef signed int s32;/**< used for signed 32bit */ - typedef signed long int s64;/**< used for signed 64bit */ - - /*unsigned integer types*/ - typedef unsigned char u8;/**< used for unsigned 8bit */ - typedef unsigned short int u16;/**< used for unsigned 16bit */ - typedef unsigned int u32;/**< used for unsigned 32bit */ - typedef unsigned long int u64;/**< used for unsigned 64bit */ - -#else -#warning The data types defined above which not supported \ - define the data types manually -#endif -#endif - - /*** This else will execute for the compilers - * which are not supported the C standards - * Like C89/C99/C11***/ -#else - /*! - * @brief By default it is defined as 32 bit machine configuration - * define your data types based on your - * machine/compiler/controller configuration - */ -#define MACHINE_32_BIT - /* If your machine support 16 bit - define the MACHINE_16_BIT*/ -#ifdef MACHINE_16_BIT -#include - /*signed integer types*/ - typedef signed char s8;/**< used for signed 8bit */ - typedef signed short int s16;/**< used for signed 16bit */ - typedef signed long int s32;/**< used for signed 32bit */ - -#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL - typedef long int s64;/**< used for signed 64bit */ - typedef unsigned long int u64;/**< used for unsigned 64bit */ -#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL) - typedef long long int s64;/**< used for signed 64bit */ - typedef unsigned long long int u64;/**< used for unsigned 64bit */ -#else -#warning Either the correct data type for signed 64 bit integer \ - could not be found, or 64 bit integers are not - supported in your environment. -#warning If 64 bit integers are supported on your platform, \ - please set s64 manually. -#endif - - /*unsigned integer types*/ - typedef unsigned char u8;/**< used for unsigned 8bit */ - typedef unsigned short int u16;/**< used for unsigned 16bit */ - typedef unsigned int u32;/**< used for unsigned 32bit */ - /*! @brief If your machine support 32 bit - define the MACHINE_32_BIT*/ -#elif defined MACHINE_32_BIT - /*signed integer types*/ - typedef signed char s8;/**< used for signed 8bit */ - typedef signed short int s16;/**< used for signed 16bit */ - typedef signed int s32;/**< used for signed 32bit */ - typedef signed long long int s64;/**< used for signed 64bit */ - - /*unsigned integer types*/ - typedef unsigned char u8;/**< used for unsigned 8bit */ - typedef unsigned short int u16;/**< used for unsigned 16bit */ - typedef unsigned int u32;/**< used for unsigned 32bit - - int and long int is same for u32*/ - typedef unsigned long long int u64;/**< used for unsigned 64bit */ - - /* If your machine support 64 bit - define the MACHINE_64_BIT*/ -#elif defined MACHINE_64_BIT - /*signed integer types*/ - typedef signed char s8;/**< used for signed 8bit */ - typedef signed short int s16;/**< used for signed 16bit */ - typedef signed int s32;/**< used for signed 32bit */ - typedef signed long int s64;/**< used for signed 64bit */ - - /*unsigned integer types*/ - typedef unsigned char u8;/**< used for unsigned 8bit */ - typedef unsigned short int u16;/**< used for unsigned 16bit */ - typedef unsigned int u32;/**< used for unsigned 32bit */ - typedef unsigned long int u64;/**< used for unsigned 64bit */ - -#else -#warning The data types defined above which not supported \ - define the data types manually -#endif -#endif -#endif - -/* sensor_api_common_types.h */ - -/*************************************************************************** - Module globals, typedefs -****************************************************************************/ - -/*************************************************************************** - Function definition -****************************************************************************/ - -#endif - -