Low power gas, pressure, temperature and humidity sensor
Dependents: MERGE Sensor_iAQ_sgp30_bme_si7051 POCBreath_V2_smd_commercial
BME680.cpp@3:8aefe9304f85, 2018-07-23 (annotated)
- Committer:
- mcm
- Date:
- Mon Jul 23 11:41:39 2018 +0000
- Revision:
- 3:8aefe9304f85
- Parent:
- 1:4d60db802cfb
An example that shows how to use this driver was added into the header file.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mcm | 1:4d60db802cfb | 1 | /** |
mcm | 1:4d60db802cfb | 2 | * @brief BME680.cpp |
mcm | 1:4d60db802cfb | 3 | * @details Low power gas, pressure, temperature & humidity sensor. |
mcm | 1:4d60db802cfb | 4 | * Function file. |
mcm | 1:4d60db802cfb | 5 | * |
mcm | 1:4d60db802cfb | 6 | * |
mcm | 1:4d60db802cfb | 7 | * @return N/A |
mcm | 1:4d60db802cfb | 8 | * |
mcm | 1:4d60db802cfb | 9 | * @author Manuel Caballero |
mcm | 1:4d60db802cfb | 10 | * @date 21/July/2018 |
mcm | 1:4d60db802cfb | 11 | * @version 21/July/2018 The ORIGIN |
mcm | 1:4d60db802cfb | 12 | * @pre This is just a port from Bosh driver to mBed ( c++ ) |
mcm | 1:4d60db802cfb | 13 | * @warning N/A |
mcm | 1:4d60db802cfb | 14 | * @pre This code belongs to Nimbus Centre ( http://www.nimbus.cit.ie ). |
mcm | 1:4d60db802cfb | 15 | */ |
mcm | 1:4d60db802cfb | 16 | /**\mainpage |
mcm | 1:4d60db802cfb | 17 | * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH |
mcm | 1:4d60db802cfb | 18 | * |
mcm | 1:4d60db802cfb | 19 | * Redistribution and use in source and binary forms, with or without |
mcm | 1:4d60db802cfb | 20 | * modification, are permitted provided that the following conditions are met: |
mcm | 1:4d60db802cfb | 21 | * |
mcm | 1:4d60db802cfb | 22 | * Redistributions of source code must retain the above copyright |
mcm | 1:4d60db802cfb | 23 | * notice, this list of conditions and the following disclaimer. |
mcm | 1:4d60db802cfb | 24 | * |
mcm | 1:4d60db802cfb | 25 | * Redistributions in binary form must reproduce the above copyright |
mcm | 1:4d60db802cfb | 26 | * notice, this list of conditions and the following disclaimer in the |
mcm | 1:4d60db802cfb | 27 | * documentation and/or other materials provided with the distribution. |
mcm | 1:4d60db802cfb | 28 | * |
mcm | 1:4d60db802cfb | 29 | * Neither the name of the copyright holder nor the names of the |
mcm | 1:4d60db802cfb | 30 | * contributors may be used to endorse or promote products derived from |
mcm | 1:4d60db802cfb | 31 | * this software without specific prior written permission. |
mcm | 1:4d60db802cfb | 32 | * |
mcm | 1:4d60db802cfb | 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
mcm | 1:4d60db802cfb | 34 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR |
mcm | 1:4d60db802cfb | 35 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
mcm | 1:4d60db802cfb | 36 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
mcm | 1:4d60db802cfb | 37 | * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER |
mcm | 1:4d60db802cfb | 38 | * OR CONTRIBUTORS BE LIABLE FOR ANY |
mcm | 1:4d60db802cfb | 39 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
mcm | 1:4d60db802cfb | 40 | * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, |
mcm | 1:4d60db802cfb | 41 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
mcm | 1:4d60db802cfb | 42 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
mcm | 1:4d60db802cfb | 43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
mcm | 1:4d60db802cfb | 44 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
mcm | 1:4d60db802cfb | 45 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
mcm | 1:4d60db802cfb | 46 | * ANY WAY OUT OF THE USE OF THIS |
mcm | 1:4d60db802cfb | 47 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE |
mcm | 1:4d60db802cfb | 48 | * |
mcm | 1:4d60db802cfb | 49 | * The information provided is believed to be accurate and reliable. |
mcm | 1:4d60db802cfb | 50 | * The copyright holder assumes no responsibility |
mcm | 1:4d60db802cfb | 51 | * for the consequences of use |
mcm | 1:4d60db802cfb | 52 | * of such information nor for any infringement of patents or |
mcm | 1:4d60db802cfb | 53 | * other rights of third parties which may result from its use. |
mcm | 1:4d60db802cfb | 54 | * No license is granted by implication or otherwise under any patent or |
mcm | 1:4d60db802cfb | 55 | * patent rights of the copyright holder. |
mcm | 1:4d60db802cfb | 56 | * |
mcm | 1:4d60db802cfb | 57 | * File bme680.c |
mcm | 1:4d60db802cfb | 58 | * @date 19 Jun 2018 |
mcm | 1:4d60db802cfb | 59 | * @version 3.5.9 |
mcm | 1:4d60db802cfb | 60 | * |
mcm | 1:4d60db802cfb | 61 | */ |
mcm | 1:4d60db802cfb | 62 | |
mcm | 1:4d60db802cfb | 63 | /*! @file bme680.c |
mcm | 1:4d60db802cfb | 64 | @brief Sensor driver for BME680 sensor */ |
mcm | 1:4d60db802cfb | 65 | #include "BME680.h" |
mcm | 1:4d60db802cfb | 66 | |
mcm | 1:4d60db802cfb | 67 | BME680::BME680 ( PinName sda, PinName scl, uint32_t freq ) |
mcm | 1:4d60db802cfb | 68 | : _i2c ( sda, scl ) |
mcm | 1:4d60db802cfb | 69 | { |
mcm | 1:4d60db802cfb | 70 | _i2c.frequency ( freq ); |
mcm | 1:4d60db802cfb | 71 | } |
mcm | 1:4d60db802cfb | 72 | |
mcm | 1:4d60db802cfb | 73 | |
mcm | 1:4d60db802cfb | 74 | BME680::~BME680() |
mcm | 1:4d60db802cfb | 75 | { |
mcm | 1:4d60db802cfb | 76 | } |
mcm | 1:4d60db802cfb | 77 | |
mcm | 1:4d60db802cfb | 78 | |
mcm | 1:4d60db802cfb | 79 | /****************** Global Function Definitions *******************************/ |
mcm | 1:4d60db802cfb | 80 | /*! |
mcm | 1:4d60db802cfb | 81 | *@brief This API is the entry point. |
mcm | 1:4d60db802cfb | 82 | *It reads the chip-id and calibration data from the sensor. |
mcm | 1:4d60db802cfb | 83 | */ |
mcm | 1:4d60db802cfb | 84 | int8_t BME680::bme680_init(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 85 | { |
mcm | 1:4d60db802cfb | 86 | int8_t rslt; |
mcm | 1:4d60db802cfb | 87 | |
mcm | 1:4d60db802cfb | 88 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 89 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 90 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 91 | /* Soft reset to restore it to default values*/ |
mcm | 1:4d60db802cfb | 92 | rslt = bme680_soft_reset(dev); |
mcm | 1:4d60db802cfb | 93 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 94 | rslt = bme680_get_regs(BME680_CHIP_ID_ADDR, &dev->chip_id, 1, dev); |
mcm | 1:4d60db802cfb | 95 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 96 | if (dev->chip_id == BME680_CHIP_ID) { |
mcm | 1:4d60db802cfb | 97 | /* Get the Calibration data */ |
mcm | 1:4d60db802cfb | 98 | rslt = get_calib_data(dev); |
mcm | 1:4d60db802cfb | 99 | } else { |
mcm | 1:4d60db802cfb | 100 | rslt = BME680_E_DEV_NOT_FOUND; |
mcm | 1:4d60db802cfb | 101 | } |
mcm | 1:4d60db802cfb | 102 | } |
mcm | 1:4d60db802cfb | 103 | } |
mcm | 1:4d60db802cfb | 104 | } |
mcm | 1:4d60db802cfb | 105 | |
mcm | 1:4d60db802cfb | 106 | return rslt; |
mcm | 1:4d60db802cfb | 107 | } |
mcm | 1:4d60db802cfb | 108 | |
mcm | 1:4d60db802cfb | 109 | /*! |
mcm | 1:4d60db802cfb | 110 | * @brief This API reads the data from the given register address of the sensor. |
mcm | 1:4d60db802cfb | 111 | */ |
mcm | 1:4d60db802cfb | 112 | int8_t BME680::bme680_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 113 | { |
mcm | 1:4d60db802cfb | 114 | int8_t rslt; |
mcm | 1:4d60db802cfb | 115 | |
mcm | 1:4d60db802cfb | 116 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 117 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 118 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 119 | if (dev->intf == BME680_SPI_INTF) { |
mcm | 1:4d60db802cfb | 120 | /* Set the memory page */ |
mcm | 1:4d60db802cfb | 121 | rslt = set_mem_page(reg_addr, dev); |
mcm | 1:4d60db802cfb | 122 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 123 | reg_addr = reg_addr | BME680_SPI_RD_MSK; |
mcm | 1:4d60db802cfb | 124 | } |
mcm | 1:4d60db802cfb | 125 | dev->com_rslt = dev->read(dev->dev_id, reg_addr, reg_data, len); |
mcm | 1:4d60db802cfb | 126 | if (dev->com_rslt != 0) |
mcm | 1:4d60db802cfb | 127 | rslt = BME680_E_COM_FAIL; |
mcm | 1:4d60db802cfb | 128 | } |
mcm | 1:4d60db802cfb | 129 | |
mcm | 1:4d60db802cfb | 130 | return rslt; |
mcm | 1:4d60db802cfb | 131 | } |
mcm | 1:4d60db802cfb | 132 | |
mcm | 1:4d60db802cfb | 133 | /*! |
mcm | 1:4d60db802cfb | 134 | * @brief This API writes the given data to the register address |
mcm | 1:4d60db802cfb | 135 | * of the sensor. |
mcm | 1:4d60db802cfb | 136 | */ |
mcm | 1:4d60db802cfb | 137 | int8_t BME680::bme680_set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 138 | { |
mcm | 1:4d60db802cfb | 139 | int8_t rslt; |
mcm | 1:4d60db802cfb | 140 | /* Length of the temporary buffer is 2*(length of register)*/ |
mcm | 1:4d60db802cfb | 141 | uint8_t tmp_buff[BME680_TMP_BUFFER_LENGTH] = { 0 }; |
mcm | 1:4d60db802cfb | 142 | uint16_t index; |
mcm | 1:4d60db802cfb | 143 | |
mcm | 1:4d60db802cfb | 144 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 145 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 146 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 147 | if ((len > 0) && (len < BME680_TMP_BUFFER_LENGTH / 2)) { |
mcm | 1:4d60db802cfb | 148 | /* Interleave the 2 arrays */ |
mcm | 1:4d60db802cfb | 149 | for (index = 0; index < len; index++) { |
mcm | 1:4d60db802cfb | 150 | if (dev->intf == BME680_SPI_INTF) { |
mcm | 1:4d60db802cfb | 151 | /* Set the memory page */ |
mcm | 1:4d60db802cfb | 152 | rslt = set_mem_page(reg_addr[index], dev); |
mcm | 1:4d60db802cfb | 153 | tmp_buff[(2 * index)] = reg_addr[index] & BME680_SPI_WR_MSK; |
mcm | 1:4d60db802cfb | 154 | } else { |
mcm | 1:4d60db802cfb | 155 | tmp_buff[(2 * index)] = reg_addr[index]; |
mcm | 1:4d60db802cfb | 156 | } |
mcm | 1:4d60db802cfb | 157 | tmp_buff[(2 * index) + 1] = reg_data[index]; |
mcm | 1:4d60db802cfb | 158 | } |
mcm | 1:4d60db802cfb | 159 | /* Write the interleaved array */ |
mcm | 1:4d60db802cfb | 160 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 161 | dev->com_rslt = dev->write(dev->dev_id, tmp_buff[0], &tmp_buff[1], (2 * len) - 1); |
mcm | 1:4d60db802cfb | 162 | if (dev->com_rslt != 0) |
mcm | 1:4d60db802cfb | 163 | rslt = BME680_E_COM_FAIL; |
mcm | 1:4d60db802cfb | 164 | } |
mcm | 1:4d60db802cfb | 165 | } else { |
mcm | 1:4d60db802cfb | 166 | rslt = BME680_E_INVALID_LENGTH; |
mcm | 1:4d60db802cfb | 167 | } |
mcm | 1:4d60db802cfb | 168 | } |
mcm | 1:4d60db802cfb | 169 | |
mcm | 1:4d60db802cfb | 170 | return rslt; |
mcm | 1:4d60db802cfb | 171 | } |
mcm | 1:4d60db802cfb | 172 | |
mcm | 1:4d60db802cfb | 173 | /*! |
mcm | 1:4d60db802cfb | 174 | * @brief This API performs the soft reset of the sensor. |
mcm | 1:4d60db802cfb | 175 | */ |
mcm | 1:4d60db802cfb | 176 | int8_t BME680::bme680_soft_reset(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 177 | { |
mcm | 1:4d60db802cfb | 178 | int8_t rslt; |
mcm | 1:4d60db802cfb | 179 | uint8_t reg_addr = BME680_SOFT_RESET_ADDR; |
mcm | 1:4d60db802cfb | 180 | /* 0xb6 is the soft reset command */ |
mcm | 1:4d60db802cfb | 181 | uint8_t soft_rst_cmd = BME680_SOFT_RESET_CMD; |
mcm | 1:4d60db802cfb | 182 | |
mcm | 1:4d60db802cfb | 183 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 184 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 185 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 186 | if (dev->intf == BME680_SPI_INTF) |
mcm | 1:4d60db802cfb | 187 | rslt = get_mem_page(dev); |
mcm | 1:4d60db802cfb | 188 | |
mcm | 1:4d60db802cfb | 189 | /* Reset the device */ |
mcm | 1:4d60db802cfb | 190 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 191 | rslt = bme680_set_regs(®_addr, &soft_rst_cmd, 1, dev); |
mcm | 1:4d60db802cfb | 192 | /* Wait for 5ms */ |
mcm | 1:4d60db802cfb | 193 | dev->delay_ms(BME680_RESET_PERIOD); |
mcm | 1:4d60db802cfb | 194 | |
mcm | 1:4d60db802cfb | 195 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 196 | /* After reset get the memory page */ |
mcm | 1:4d60db802cfb | 197 | if (dev->intf == BME680_SPI_INTF) |
mcm | 1:4d60db802cfb | 198 | rslt = get_mem_page(dev); |
mcm | 1:4d60db802cfb | 199 | } |
mcm | 1:4d60db802cfb | 200 | } |
mcm | 1:4d60db802cfb | 201 | } |
mcm | 1:4d60db802cfb | 202 | |
mcm | 1:4d60db802cfb | 203 | return rslt; |
mcm | 1:4d60db802cfb | 204 | } |
mcm | 1:4d60db802cfb | 205 | |
mcm | 1:4d60db802cfb | 206 | /*! |
mcm | 1:4d60db802cfb | 207 | * @brief This API is used to set the oversampling, filter and T,P,H, gas selection |
mcm | 1:4d60db802cfb | 208 | * settings in the sensor. |
mcm | 1:4d60db802cfb | 209 | */ |
mcm | 1:4d60db802cfb | 210 | int8_t BME680::bme680_set_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 211 | { |
mcm | 1:4d60db802cfb | 212 | int8_t rslt; |
mcm | 1:4d60db802cfb | 213 | uint8_t reg_addr; |
mcm | 1:4d60db802cfb | 214 | uint8_t data = 0; |
mcm | 1:4d60db802cfb | 215 | uint8_t count = 0; |
mcm | 1:4d60db802cfb | 216 | uint8_t reg_array[BME680_REG_BUFFER_LENGTH] = { 0 }; |
mcm | 1:4d60db802cfb | 217 | uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 }; |
mcm | 1:4d60db802cfb | 218 | uint8_t intended_power_mode = dev->power_mode; /* Save intended power mode */ |
mcm | 1:4d60db802cfb | 219 | |
mcm | 1:4d60db802cfb | 220 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 221 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 222 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 223 | if (desired_settings & BME680_GAS_MEAS_SEL) |
mcm | 1:4d60db802cfb | 224 | rslt = set_gas_config(dev); |
mcm | 1:4d60db802cfb | 225 | |
mcm | 1:4d60db802cfb | 226 | dev->power_mode = BME680_SLEEP_MODE; |
mcm | 1:4d60db802cfb | 227 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 228 | rslt = bme680_set_sensor_mode(dev); |
mcm | 1:4d60db802cfb | 229 | |
mcm | 1:4d60db802cfb | 230 | /* Selecting the filter */ |
mcm | 1:4d60db802cfb | 231 | if (desired_settings & BME680_FILTER_SEL) { |
mcm | 1:4d60db802cfb | 232 | rslt = boundary_check(&dev->tph_sett.filter, BME680_FILTER_SIZE_0, BME680_FILTER_SIZE_127, dev); |
mcm | 1:4d60db802cfb | 233 | reg_addr = BME680_CONF_ODR_FILT_ADDR; |
mcm | 1:4d60db802cfb | 234 | |
mcm | 1:4d60db802cfb | 235 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 236 | rslt = bme680_get_regs(reg_addr, &data, 1, dev); |
mcm | 1:4d60db802cfb | 237 | |
mcm | 1:4d60db802cfb | 238 | if (desired_settings & BME680_FILTER_SEL) |
mcm | 1:4d60db802cfb | 239 | data = BME680_SET_BITS(data, BME680_FILTER, dev->tph_sett.filter); |
mcm | 1:4d60db802cfb | 240 | |
mcm | 1:4d60db802cfb | 241 | reg_array[count] = reg_addr; /* Append configuration */ |
mcm | 1:4d60db802cfb | 242 | data_array[count] = data; |
mcm | 1:4d60db802cfb | 243 | count++; |
mcm | 1:4d60db802cfb | 244 | } |
mcm | 1:4d60db802cfb | 245 | |
mcm | 1:4d60db802cfb | 246 | /* Selecting heater control for the sensor */ |
mcm | 1:4d60db802cfb | 247 | if (desired_settings & BME680_HCNTRL_SEL) { |
mcm | 1:4d60db802cfb | 248 | rslt = boundary_check(&dev->gas_sett.heatr_ctrl, BME680_ENABLE_HEATER, |
mcm | 1:4d60db802cfb | 249 | BME680_DISABLE_HEATER, dev); |
mcm | 1:4d60db802cfb | 250 | reg_addr = BME680_CONF_HEAT_CTRL_ADDR; |
mcm | 1:4d60db802cfb | 251 | |
mcm | 1:4d60db802cfb | 252 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 253 | rslt = bme680_get_regs(reg_addr, &data, 1, dev); |
mcm | 1:4d60db802cfb | 254 | data = BME680_SET_BITS_POS_0(data, BME680_HCTRL, dev->gas_sett.heatr_ctrl); |
mcm | 1:4d60db802cfb | 255 | |
mcm | 1:4d60db802cfb | 256 | reg_array[count] = reg_addr; /* Append configuration */ |
mcm | 1:4d60db802cfb | 257 | data_array[count] = data; |
mcm | 1:4d60db802cfb | 258 | count++; |
mcm | 1:4d60db802cfb | 259 | } |
mcm | 1:4d60db802cfb | 260 | |
mcm | 1:4d60db802cfb | 261 | /* Selecting heater T,P oversampling for the sensor */ |
mcm | 1:4d60db802cfb | 262 | if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) { |
mcm | 1:4d60db802cfb | 263 | rslt = boundary_check(&dev->tph_sett.os_temp, BME680_OS_NONE, BME680_OS_16X, dev); |
mcm | 1:4d60db802cfb | 264 | reg_addr = BME680_CONF_T_P_MODE_ADDR; |
mcm | 1:4d60db802cfb | 265 | |
mcm | 1:4d60db802cfb | 266 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 267 | rslt = bme680_get_regs(reg_addr, &data, 1, dev); |
mcm | 1:4d60db802cfb | 268 | |
mcm | 1:4d60db802cfb | 269 | if (desired_settings & BME680_OST_SEL) |
mcm | 1:4d60db802cfb | 270 | data = BME680_SET_BITS(data, BME680_OST, dev->tph_sett.os_temp); |
mcm | 1:4d60db802cfb | 271 | |
mcm | 1:4d60db802cfb | 272 | if (desired_settings & BME680_OSP_SEL) |
mcm | 1:4d60db802cfb | 273 | data = BME680_SET_BITS(data, BME680_OSP, dev->tph_sett.os_pres); |
mcm | 1:4d60db802cfb | 274 | |
mcm | 1:4d60db802cfb | 275 | reg_array[count] = reg_addr; |
mcm | 1:4d60db802cfb | 276 | data_array[count] = data; |
mcm | 1:4d60db802cfb | 277 | count++; |
mcm | 1:4d60db802cfb | 278 | } |
mcm | 1:4d60db802cfb | 279 | |
mcm | 1:4d60db802cfb | 280 | /* Selecting humidity oversampling for the sensor */ |
mcm | 1:4d60db802cfb | 281 | if (desired_settings & BME680_OSH_SEL) { |
mcm | 1:4d60db802cfb | 282 | rslt = boundary_check(&dev->tph_sett.os_hum, BME680_OS_NONE, BME680_OS_16X, dev); |
mcm | 1:4d60db802cfb | 283 | reg_addr = BME680_CONF_OS_H_ADDR; |
mcm | 1:4d60db802cfb | 284 | |
mcm | 1:4d60db802cfb | 285 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 286 | rslt = bme680_get_regs(reg_addr, &data, 1, dev); |
mcm | 1:4d60db802cfb | 287 | data = BME680_SET_BITS_POS_0(data, BME680_OSH, dev->tph_sett.os_hum); |
mcm | 1:4d60db802cfb | 288 | |
mcm | 1:4d60db802cfb | 289 | reg_array[count] = reg_addr; /* Append configuration */ |
mcm | 1:4d60db802cfb | 290 | data_array[count] = data; |
mcm | 1:4d60db802cfb | 291 | count++; |
mcm | 1:4d60db802cfb | 292 | } |
mcm | 1:4d60db802cfb | 293 | |
mcm | 1:4d60db802cfb | 294 | /* Selecting the runGas and NB conversion settings for the sensor */ |
mcm | 1:4d60db802cfb | 295 | if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) { |
mcm | 1:4d60db802cfb | 296 | rslt = boundary_check(&dev->gas_sett.run_gas, BME680_RUN_GAS_DISABLE, |
mcm | 1:4d60db802cfb | 297 | BME680_RUN_GAS_ENABLE, dev); |
mcm | 1:4d60db802cfb | 298 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 299 | /* Validate boundary conditions */ |
mcm | 1:4d60db802cfb | 300 | rslt = boundary_check(&dev->gas_sett.nb_conv, BME680_NBCONV_MIN, |
mcm | 1:4d60db802cfb | 301 | BME680_NBCONV_MAX, dev); |
mcm | 1:4d60db802cfb | 302 | } |
mcm | 1:4d60db802cfb | 303 | |
mcm | 1:4d60db802cfb | 304 | reg_addr = BME680_CONF_ODR_RUN_GAS_NBC_ADDR; |
mcm | 1:4d60db802cfb | 305 | |
mcm | 1:4d60db802cfb | 306 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 307 | rslt = bme680_get_regs(reg_addr, &data, 1, dev); |
mcm | 1:4d60db802cfb | 308 | |
mcm | 1:4d60db802cfb | 309 | if (desired_settings & BME680_RUN_GAS_SEL) |
mcm | 1:4d60db802cfb | 310 | data = BME680_SET_BITS(data, BME680_RUN_GAS, dev->gas_sett.run_gas); |
mcm | 1:4d60db802cfb | 311 | |
mcm | 1:4d60db802cfb | 312 | if (desired_settings & BME680_NBCONV_SEL) |
mcm | 1:4d60db802cfb | 313 | data = BME680_SET_BITS_POS_0(data, BME680_NBCONV, dev->gas_sett.nb_conv); |
mcm | 1:4d60db802cfb | 314 | |
mcm | 1:4d60db802cfb | 315 | reg_array[count] = reg_addr; /* Append configuration */ |
mcm | 1:4d60db802cfb | 316 | data_array[count] = data; |
mcm | 1:4d60db802cfb | 317 | count++; |
mcm | 1:4d60db802cfb | 318 | } |
mcm | 1:4d60db802cfb | 319 | |
mcm | 1:4d60db802cfb | 320 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 321 | rslt = bme680_set_regs(reg_array, data_array, count, dev); |
mcm | 1:4d60db802cfb | 322 | |
mcm | 1:4d60db802cfb | 323 | /* Restore previous intended power mode */ |
mcm | 1:4d60db802cfb | 324 | dev->power_mode = intended_power_mode; |
mcm | 1:4d60db802cfb | 325 | } |
mcm | 1:4d60db802cfb | 326 | |
mcm | 1:4d60db802cfb | 327 | return rslt; |
mcm | 1:4d60db802cfb | 328 | } |
mcm | 1:4d60db802cfb | 329 | |
mcm | 1:4d60db802cfb | 330 | /*! |
mcm | 1:4d60db802cfb | 331 | * @brief This API is used to get the oversampling, filter and T,P,H, gas selection |
mcm | 1:4d60db802cfb | 332 | * settings in the sensor. |
mcm | 1:4d60db802cfb | 333 | */ |
mcm | 1:4d60db802cfb | 334 | int8_t BME680::bme680_get_sensor_settings(uint16_t desired_settings, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 335 | { |
mcm | 1:4d60db802cfb | 336 | int8_t rslt; |
mcm | 1:4d60db802cfb | 337 | /* starting address of the register array for burst read*/ |
mcm | 1:4d60db802cfb | 338 | uint8_t reg_addr = BME680_CONF_HEAT_CTRL_ADDR; |
mcm | 1:4d60db802cfb | 339 | uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 }; |
mcm | 1:4d60db802cfb | 340 | |
mcm | 1:4d60db802cfb | 341 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 342 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 343 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 344 | rslt = bme680_get_regs(reg_addr, data_array, BME680_REG_BUFFER_LENGTH, dev); |
mcm | 1:4d60db802cfb | 345 | |
mcm | 1:4d60db802cfb | 346 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 347 | if (desired_settings & BME680_GAS_MEAS_SEL) |
mcm | 1:4d60db802cfb | 348 | rslt = get_gas_config(dev); |
mcm | 1:4d60db802cfb | 349 | |
mcm | 1:4d60db802cfb | 350 | /* get the T,P,H ,Filter,ODR settings here */ |
mcm | 1:4d60db802cfb | 351 | if (desired_settings & BME680_FILTER_SEL) |
mcm | 1:4d60db802cfb | 352 | dev->tph_sett.filter = BME680_GET_BITS(data_array[BME680_REG_FILTER_INDEX], |
mcm | 1:4d60db802cfb | 353 | BME680_FILTER); |
mcm | 1:4d60db802cfb | 354 | |
mcm | 1:4d60db802cfb | 355 | if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) { |
mcm | 1:4d60db802cfb | 356 | dev->tph_sett.os_temp = BME680_GET_BITS(data_array[BME680_REG_TEMP_INDEX], BME680_OST); |
mcm | 1:4d60db802cfb | 357 | dev->tph_sett.os_pres = BME680_GET_BITS(data_array[BME680_REG_PRES_INDEX], BME680_OSP); |
mcm | 1:4d60db802cfb | 358 | } |
mcm | 1:4d60db802cfb | 359 | |
mcm | 1:4d60db802cfb | 360 | if (desired_settings & BME680_OSH_SEL) |
mcm | 1:4d60db802cfb | 361 | dev->tph_sett.os_hum = BME680_GET_BITS_POS_0(data_array[BME680_REG_HUM_INDEX], |
mcm | 1:4d60db802cfb | 362 | BME680_OSH); |
mcm | 1:4d60db802cfb | 363 | |
mcm | 1:4d60db802cfb | 364 | /* get the gas related settings */ |
mcm | 1:4d60db802cfb | 365 | if (desired_settings & BME680_HCNTRL_SEL) |
mcm | 1:4d60db802cfb | 366 | dev->gas_sett.heatr_ctrl = BME680_GET_BITS_POS_0(data_array[BME680_REG_HCTRL_INDEX], |
mcm | 1:4d60db802cfb | 367 | BME680_HCTRL); |
mcm | 1:4d60db802cfb | 368 | |
mcm | 1:4d60db802cfb | 369 | if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) { |
mcm | 1:4d60db802cfb | 370 | dev->gas_sett.nb_conv = BME680_GET_BITS_POS_0(data_array[BME680_REG_NBCONV_INDEX], |
mcm | 1:4d60db802cfb | 371 | BME680_NBCONV); |
mcm | 1:4d60db802cfb | 372 | dev->gas_sett.run_gas = BME680_GET_BITS(data_array[BME680_REG_RUN_GAS_INDEX], |
mcm | 1:4d60db802cfb | 373 | BME680_RUN_GAS); |
mcm | 1:4d60db802cfb | 374 | } |
mcm | 1:4d60db802cfb | 375 | } |
mcm | 1:4d60db802cfb | 376 | } else { |
mcm | 1:4d60db802cfb | 377 | rslt = BME680_E_NULL_PTR; |
mcm | 1:4d60db802cfb | 378 | } |
mcm | 1:4d60db802cfb | 379 | |
mcm | 1:4d60db802cfb | 380 | return rslt; |
mcm | 1:4d60db802cfb | 381 | } |
mcm | 1:4d60db802cfb | 382 | |
mcm | 1:4d60db802cfb | 383 | /*! |
mcm | 1:4d60db802cfb | 384 | * @brief This API is used to set the power mode of the sensor. |
mcm | 1:4d60db802cfb | 385 | */ |
mcm | 1:4d60db802cfb | 386 | int8_t BME680::bme680_set_sensor_mode(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 387 | { |
mcm | 1:4d60db802cfb | 388 | int8_t rslt; |
mcm | 1:4d60db802cfb | 389 | uint8_t tmp_pow_mode; |
mcm | 1:4d60db802cfb | 390 | uint8_t pow_mode = 0; |
mcm | 1:4d60db802cfb | 391 | uint8_t reg_addr = BME680_CONF_T_P_MODE_ADDR; |
mcm | 1:4d60db802cfb | 392 | |
mcm | 1:4d60db802cfb | 393 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 394 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 395 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 396 | /* Call repeatedly until in sleep */ |
mcm | 1:4d60db802cfb | 397 | do { |
mcm | 1:4d60db802cfb | 398 | rslt = bme680_get_regs(BME680_CONF_T_P_MODE_ADDR, &tmp_pow_mode, 1, dev); |
mcm | 1:4d60db802cfb | 399 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 400 | /* Put to sleep before changing mode */ |
mcm | 1:4d60db802cfb | 401 | pow_mode = (tmp_pow_mode & BME680_MODE_MSK); |
mcm | 1:4d60db802cfb | 402 | |
mcm | 1:4d60db802cfb | 403 | if (pow_mode != BME680_SLEEP_MODE) { |
mcm | 1:4d60db802cfb | 404 | tmp_pow_mode = tmp_pow_mode & (~BME680_MODE_MSK); /* Set to sleep */ |
mcm | 1:4d60db802cfb | 405 | rslt = bme680_set_regs(®_addr, &tmp_pow_mode, 1, dev); |
mcm | 1:4d60db802cfb | 406 | dev->delay_ms(BME680_POLL_PERIOD_MS); |
mcm | 1:4d60db802cfb | 407 | } |
mcm | 1:4d60db802cfb | 408 | } |
mcm | 1:4d60db802cfb | 409 | } while (pow_mode != BME680_SLEEP_MODE); |
mcm | 1:4d60db802cfb | 410 | |
mcm | 1:4d60db802cfb | 411 | /* Already in sleep */ |
mcm | 1:4d60db802cfb | 412 | if (dev->power_mode != BME680_SLEEP_MODE) { |
mcm | 1:4d60db802cfb | 413 | tmp_pow_mode = (tmp_pow_mode & ~BME680_MODE_MSK) | (dev->power_mode & BME680_MODE_MSK); |
mcm | 1:4d60db802cfb | 414 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 415 | rslt = bme680_set_regs(®_addr, &tmp_pow_mode, 1, dev); |
mcm | 1:4d60db802cfb | 416 | } |
mcm | 1:4d60db802cfb | 417 | } |
mcm | 1:4d60db802cfb | 418 | |
mcm | 1:4d60db802cfb | 419 | return rslt; |
mcm | 1:4d60db802cfb | 420 | } |
mcm | 1:4d60db802cfb | 421 | |
mcm | 1:4d60db802cfb | 422 | /*! |
mcm | 1:4d60db802cfb | 423 | * @brief This API is used to get the power mode of the sensor. |
mcm | 1:4d60db802cfb | 424 | */ |
mcm | 1:4d60db802cfb | 425 | int8_t BME680::bme680_get_sensor_mode(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 426 | { |
mcm | 1:4d60db802cfb | 427 | int8_t rslt; |
mcm | 1:4d60db802cfb | 428 | uint8_t mode; |
mcm | 1:4d60db802cfb | 429 | |
mcm | 1:4d60db802cfb | 430 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 431 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 432 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 433 | rslt = bme680_get_regs(BME680_CONF_T_P_MODE_ADDR, &mode, 1, dev); |
mcm | 1:4d60db802cfb | 434 | /* Masking the other register bit info*/ |
mcm | 1:4d60db802cfb | 435 | dev->power_mode = mode & BME680_MODE_MSK; |
mcm | 1:4d60db802cfb | 436 | } |
mcm | 1:4d60db802cfb | 437 | |
mcm | 1:4d60db802cfb | 438 | return rslt; |
mcm | 1:4d60db802cfb | 439 | } |
mcm | 1:4d60db802cfb | 440 | |
mcm | 1:4d60db802cfb | 441 | /*! |
mcm | 1:4d60db802cfb | 442 | * @brief This API is used to set the profile duration of the sensor. |
mcm | 1:4d60db802cfb | 443 | */ |
mcm | 1:4d60db802cfb | 444 | void BME680::bme680_set_profile_dur(uint16_t duration, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 445 | { |
mcm | 1:4d60db802cfb | 446 | uint32_t tph_dur; /* Calculate in us */ |
mcm | 1:4d60db802cfb | 447 | uint32_t meas_cycles; |
mcm | 1:4d60db802cfb | 448 | uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16}; |
mcm | 1:4d60db802cfb | 449 | |
mcm | 1:4d60db802cfb | 450 | meas_cycles = os_to_meas_cycles[dev->tph_sett.os_temp]; |
mcm | 1:4d60db802cfb | 451 | meas_cycles += os_to_meas_cycles[dev->tph_sett.os_pres]; |
mcm | 1:4d60db802cfb | 452 | meas_cycles += os_to_meas_cycles[dev->tph_sett.os_hum]; |
mcm | 1:4d60db802cfb | 453 | |
mcm | 1:4d60db802cfb | 454 | /* TPH measurement duration */ |
mcm | 1:4d60db802cfb | 455 | tph_dur = meas_cycles * UINT32_C(1963); |
mcm | 1:4d60db802cfb | 456 | tph_dur += UINT32_C(477 * 4); /* TPH switching duration */ |
mcm | 1:4d60db802cfb | 457 | tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */ |
mcm | 1:4d60db802cfb | 458 | tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/ |
mcm | 1:4d60db802cfb | 459 | tph_dur /= UINT32_C(1000); /* Convert to ms */ |
mcm | 1:4d60db802cfb | 460 | |
mcm | 1:4d60db802cfb | 461 | tph_dur += UINT32_C(1); /* Wake up duration of 1ms */ |
mcm | 1:4d60db802cfb | 462 | /* The remaining time should be used for heating */ |
mcm | 1:4d60db802cfb | 463 | dev->gas_sett.heatr_dur = duration - (uint16_t) tph_dur; |
mcm | 1:4d60db802cfb | 464 | } |
mcm | 1:4d60db802cfb | 465 | |
mcm | 1:4d60db802cfb | 466 | /*! |
mcm | 1:4d60db802cfb | 467 | * @brief This API is used to get the profile duration of the sensor. |
mcm | 1:4d60db802cfb | 468 | */ |
mcm | 1:4d60db802cfb | 469 | void BME680::bme680_get_profile_dur(uint16_t *duration, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 470 | { |
mcm | 1:4d60db802cfb | 471 | uint32_t tph_dur; /* Calculate in us */ |
mcm | 1:4d60db802cfb | 472 | uint32_t meas_cycles; |
mcm | 1:4d60db802cfb | 473 | uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16}; |
mcm | 1:4d60db802cfb | 474 | |
mcm | 1:4d60db802cfb | 475 | meas_cycles = os_to_meas_cycles[dev->tph_sett.os_temp]; |
mcm | 1:4d60db802cfb | 476 | meas_cycles += os_to_meas_cycles[dev->tph_sett.os_pres]; |
mcm | 1:4d60db802cfb | 477 | meas_cycles += os_to_meas_cycles[dev->tph_sett.os_hum]; |
mcm | 1:4d60db802cfb | 478 | |
mcm | 1:4d60db802cfb | 479 | /* TPH measurement duration */ |
mcm | 1:4d60db802cfb | 480 | tph_dur = meas_cycles * UINT32_C(1963); |
mcm | 1:4d60db802cfb | 481 | tph_dur += UINT32_C(477 * 4); /* TPH switching duration */ |
mcm | 1:4d60db802cfb | 482 | tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */ |
mcm | 1:4d60db802cfb | 483 | tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/ |
mcm | 1:4d60db802cfb | 484 | tph_dur /= UINT32_C(1000); /* Convert to ms */ |
mcm | 1:4d60db802cfb | 485 | |
mcm | 1:4d60db802cfb | 486 | tph_dur += UINT32_C(1); /* Wake up duration of 1ms */ |
mcm | 1:4d60db802cfb | 487 | |
mcm | 1:4d60db802cfb | 488 | *duration = (uint16_t) tph_dur; |
mcm | 1:4d60db802cfb | 489 | |
mcm | 1:4d60db802cfb | 490 | /* Get the gas duration only when the run gas is enabled */ |
mcm | 1:4d60db802cfb | 491 | if (dev->gas_sett.run_gas) { |
mcm | 1:4d60db802cfb | 492 | /* The remaining time should be used for heating */ |
mcm | 1:4d60db802cfb | 493 | *duration += dev->gas_sett.heatr_dur; |
mcm | 1:4d60db802cfb | 494 | } |
mcm | 1:4d60db802cfb | 495 | } |
mcm | 1:4d60db802cfb | 496 | |
mcm | 1:4d60db802cfb | 497 | /*! |
mcm | 1:4d60db802cfb | 498 | * @brief This API reads the pressure, temperature and humidity and gas data |
mcm | 1:4d60db802cfb | 499 | * from the sensor, compensates the data and store it in the bme680_data |
mcm | 1:4d60db802cfb | 500 | * structure instance passed by the user. |
mcm | 1:4d60db802cfb | 501 | */ |
mcm | 1:4d60db802cfb | 502 | int8_t BME680::bme680_get_sensor_data(struct bme680_field_data *data, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 503 | { |
mcm | 1:4d60db802cfb | 504 | int8_t rslt; |
mcm | 1:4d60db802cfb | 505 | |
mcm | 1:4d60db802cfb | 506 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 507 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 508 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 509 | /* Reading the sensor data in forced mode only */ |
mcm | 1:4d60db802cfb | 510 | rslt = read_field_data(data, dev); |
mcm | 1:4d60db802cfb | 511 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 512 | if (data->status & BME680_NEW_DATA_MSK) |
mcm | 1:4d60db802cfb | 513 | dev->new_fields = 1; |
mcm | 1:4d60db802cfb | 514 | else |
mcm | 1:4d60db802cfb | 515 | dev->new_fields = 0; |
mcm | 1:4d60db802cfb | 516 | } |
mcm | 1:4d60db802cfb | 517 | } |
mcm | 1:4d60db802cfb | 518 | |
mcm | 1:4d60db802cfb | 519 | return rslt; |
mcm | 1:4d60db802cfb | 520 | } |
mcm | 1:4d60db802cfb | 521 | |
mcm | 1:4d60db802cfb | 522 | /*! |
mcm | 1:4d60db802cfb | 523 | * @brief This internal API is used to read the calibrated data from the sensor. |
mcm | 1:4d60db802cfb | 524 | */ |
mcm | 1:4d60db802cfb | 525 | int8_t BME680::get_calib_data(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 526 | { |
mcm | 1:4d60db802cfb | 527 | int8_t rslt; |
mcm | 1:4d60db802cfb | 528 | uint8_t coeff_array[BME680_COEFF_SIZE] = { 0 }; |
mcm | 1:4d60db802cfb | 529 | uint8_t temp_var = 0; /* Temporary variable */ |
mcm | 1:4d60db802cfb | 530 | |
mcm | 1:4d60db802cfb | 531 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 532 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 533 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 534 | rslt = bme680_get_regs(BME680_COEFF_ADDR1, coeff_array, BME680_COEFF_ADDR1_LEN, dev); |
mcm | 1:4d60db802cfb | 535 | /* Append the second half in the same array */ |
mcm | 1:4d60db802cfb | 536 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 537 | rslt = bme680_get_regs(BME680_COEFF_ADDR2, &coeff_array[BME680_COEFF_ADDR1_LEN] |
mcm | 1:4d60db802cfb | 538 | , BME680_COEFF_ADDR2_LEN, dev); |
mcm | 1:4d60db802cfb | 539 | |
mcm | 1:4d60db802cfb | 540 | /* Temperature related coefficients */ |
mcm | 1:4d60db802cfb | 541 | dev->calib.par_t1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T1_MSB_REG], |
mcm | 1:4d60db802cfb | 542 | coeff_array[BME680_T1_LSB_REG])); |
mcm | 1:4d60db802cfb | 543 | dev->calib.par_t2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T2_MSB_REG], |
mcm | 1:4d60db802cfb | 544 | coeff_array[BME680_T2_LSB_REG])); |
mcm | 1:4d60db802cfb | 545 | dev->calib.par_t3 = (int8_t) (coeff_array[BME680_T3_REG]); |
mcm | 1:4d60db802cfb | 546 | |
mcm | 1:4d60db802cfb | 547 | /* Pressure related coefficients */ |
mcm | 1:4d60db802cfb | 548 | dev->calib.par_p1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P1_MSB_REG], |
mcm | 1:4d60db802cfb | 549 | coeff_array[BME680_P1_LSB_REG])); |
mcm | 1:4d60db802cfb | 550 | dev->calib.par_p2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P2_MSB_REG], |
mcm | 1:4d60db802cfb | 551 | coeff_array[BME680_P2_LSB_REG])); |
mcm | 1:4d60db802cfb | 552 | dev->calib.par_p3 = (int8_t) coeff_array[BME680_P3_REG]; |
mcm | 1:4d60db802cfb | 553 | dev->calib.par_p4 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P4_MSB_REG], |
mcm | 1:4d60db802cfb | 554 | coeff_array[BME680_P4_LSB_REG])); |
mcm | 1:4d60db802cfb | 555 | dev->calib.par_p5 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P5_MSB_REG], |
mcm | 1:4d60db802cfb | 556 | coeff_array[BME680_P5_LSB_REG])); |
mcm | 1:4d60db802cfb | 557 | dev->calib.par_p6 = (int8_t) (coeff_array[BME680_P6_REG]); |
mcm | 1:4d60db802cfb | 558 | dev->calib.par_p7 = (int8_t) (coeff_array[BME680_P7_REG]); |
mcm | 1:4d60db802cfb | 559 | dev->calib.par_p8 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P8_MSB_REG], |
mcm | 1:4d60db802cfb | 560 | coeff_array[BME680_P8_LSB_REG])); |
mcm | 1:4d60db802cfb | 561 | dev->calib.par_p9 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P9_MSB_REG], |
mcm | 1:4d60db802cfb | 562 | coeff_array[BME680_P9_LSB_REG])); |
mcm | 1:4d60db802cfb | 563 | dev->calib.par_p10 = (uint8_t) (coeff_array[BME680_P10_REG]); |
mcm | 1:4d60db802cfb | 564 | |
mcm | 1:4d60db802cfb | 565 | /* Humidity related coefficients */ |
mcm | 1:4d60db802cfb | 566 | dev->calib.par_h1 = (uint16_t) (((uint16_t) coeff_array[BME680_H1_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) |
mcm | 1:4d60db802cfb | 567 | | (coeff_array[BME680_H1_LSB_REG] & BME680_BIT_H1_DATA_MSK)); |
mcm | 1:4d60db802cfb | 568 | dev->calib.par_h2 = (uint16_t) (((uint16_t) coeff_array[BME680_H2_MSB_REG] << BME680_HUM_REG_SHIFT_VAL) |
mcm | 1:4d60db802cfb | 569 | | ((coeff_array[BME680_H2_LSB_REG]) >> BME680_HUM_REG_SHIFT_VAL)); |
mcm | 1:4d60db802cfb | 570 | dev->calib.par_h3 = (int8_t) coeff_array[BME680_H3_REG]; |
mcm | 1:4d60db802cfb | 571 | dev->calib.par_h4 = (int8_t) coeff_array[BME680_H4_REG]; |
mcm | 1:4d60db802cfb | 572 | dev->calib.par_h5 = (int8_t) coeff_array[BME680_H5_REG]; |
mcm | 1:4d60db802cfb | 573 | dev->calib.par_h6 = (uint8_t) coeff_array[BME680_H6_REG]; |
mcm | 1:4d60db802cfb | 574 | dev->calib.par_h7 = (int8_t) coeff_array[BME680_H7_REG]; |
mcm | 1:4d60db802cfb | 575 | |
mcm | 1:4d60db802cfb | 576 | /* Gas heater related coefficients */ |
mcm | 1:4d60db802cfb | 577 | dev->calib.par_gh1 = (int8_t) coeff_array[BME680_GH1_REG]; |
mcm | 1:4d60db802cfb | 578 | dev->calib.par_gh2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_GH2_MSB_REG], |
mcm | 1:4d60db802cfb | 579 | coeff_array[BME680_GH2_LSB_REG])); |
mcm | 1:4d60db802cfb | 580 | dev->calib.par_gh3 = (int8_t) coeff_array[BME680_GH3_REG]; |
mcm | 1:4d60db802cfb | 581 | |
mcm | 1:4d60db802cfb | 582 | /* Other coefficients */ |
mcm | 1:4d60db802cfb | 583 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 584 | rslt = bme680_get_regs(BME680_ADDR_RES_HEAT_RANGE_ADDR, &temp_var, 1, dev); |
mcm | 1:4d60db802cfb | 585 | |
mcm | 1:4d60db802cfb | 586 | dev->calib.res_heat_range = ((temp_var & BME680_RHRANGE_MSK) / 16); |
mcm | 1:4d60db802cfb | 587 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 588 | rslt = bme680_get_regs(BME680_ADDR_RES_HEAT_VAL_ADDR, &temp_var, 1, dev); |
mcm | 1:4d60db802cfb | 589 | |
mcm | 1:4d60db802cfb | 590 | dev->calib.res_heat_val = (int8_t) temp_var; |
mcm | 1:4d60db802cfb | 591 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 592 | rslt = bme680_get_regs(BME680_ADDR_RANGE_SW_ERR_ADDR, &temp_var, 1, dev); |
mcm | 1:4d60db802cfb | 593 | } |
mcm | 1:4d60db802cfb | 594 | } |
mcm | 1:4d60db802cfb | 595 | dev->calib.range_sw_err = ((int8_t) temp_var & (int8_t) BME680_RSERROR_MSK) / 16; |
mcm | 1:4d60db802cfb | 596 | } |
mcm | 1:4d60db802cfb | 597 | |
mcm | 1:4d60db802cfb | 598 | return rslt; |
mcm | 1:4d60db802cfb | 599 | } |
mcm | 1:4d60db802cfb | 600 | |
mcm | 1:4d60db802cfb | 601 | /*! |
mcm | 1:4d60db802cfb | 602 | * @brief This internal API is used to set the gas configuration of the sensor. |
mcm | 1:4d60db802cfb | 603 | */ |
mcm | 1:4d60db802cfb | 604 | int8_t BME680::set_gas_config(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 605 | { |
mcm | 1:4d60db802cfb | 606 | int8_t rslt; |
mcm | 1:4d60db802cfb | 607 | |
mcm | 1:4d60db802cfb | 608 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 609 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 610 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 611 | |
mcm | 1:4d60db802cfb | 612 | uint8_t reg_addr[2] = {0}; |
mcm | 1:4d60db802cfb | 613 | uint8_t reg_data[2] = {0}; |
mcm | 1:4d60db802cfb | 614 | |
mcm | 1:4d60db802cfb | 615 | if (dev->power_mode == BME680_FORCED_MODE) { |
mcm | 1:4d60db802cfb | 616 | reg_addr[0] = BME680_RES_HEAT0_ADDR; |
mcm | 1:4d60db802cfb | 617 | reg_data[0] = calc_heater_res(dev->gas_sett.heatr_temp, dev); |
mcm | 1:4d60db802cfb | 618 | reg_addr[1] = BME680_GAS_WAIT0_ADDR; |
mcm | 1:4d60db802cfb | 619 | reg_data[1] = calc_heater_dur(dev->gas_sett.heatr_dur); |
mcm | 1:4d60db802cfb | 620 | dev->gas_sett.nb_conv = 0; |
mcm | 1:4d60db802cfb | 621 | } else { |
mcm | 1:4d60db802cfb | 622 | rslt = BME680_W_DEFINE_PWR_MODE; |
mcm | 1:4d60db802cfb | 623 | } |
mcm | 1:4d60db802cfb | 624 | if (rslt == BME680_OK) |
mcm | 1:4d60db802cfb | 625 | rslt = bme680_set_regs(reg_addr, reg_data, 2, dev); |
mcm | 1:4d60db802cfb | 626 | } |
mcm | 1:4d60db802cfb | 627 | |
mcm | 1:4d60db802cfb | 628 | return rslt; |
mcm | 1:4d60db802cfb | 629 | } |
mcm | 1:4d60db802cfb | 630 | |
mcm | 1:4d60db802cfb | 631 | /*! |
mcm | 1:4d60db802cfb | 632 | * @brief This internal API is used to get the gas configuration of the sensor. |
mcm | 1:4d60db802cfb | 633 | * @note heatr_temp and heatr_dur values are currently register data |
mcm | 1:4d60db802cfb | 634 | * and not the actual values set |
mcm | 1:4d60db802cfb | 635 | */ |
mcm | 1:4d60db802cfb | 636 | int8_t BME680::get_gas_config(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 637 | { |
mcm | 1:4d60db802cfb | 638 | int8_t rslt; |
mcm | 1:4d60db802cfb | 639 | /* starting address of the register array for burst read*/ |
mcm | 1:4d60db802cfb | 640 | uint8_t reg_addr1 = BME680_ADDR_SENS_CONF_START; |
mcm | 1:4d60db802cfb | 641 | uint8_t reg_addr2 = BME680_ADDR_GAS_CONF_START; |
mcm | 1:4d60db802cfb | 642 | uint8_t reg_data = 0; |
mcm | 1:4d60db802cfb | 643 | |
mcm | 1:4d60db802cfb | 644 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 645 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 646 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 647 | if (BME680_SPI_INTF == dev->intf) { |
mcm | 1:4d60db802cfb | 648 | /* Memory page switch the SPI address*/ |
mcm | 1:4d60db802cfb | 649 | rslt = set_mem_page(reg_addr1, dev); |
mcm | 1:4d60db802cfb | 650 | } |
mcm | 1:4d60db802cfb | 651 | |
mcm | 1:4d60db802cfb | 652 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 653 | rslt = bme680_get_regs(reg_addr1, ®_data, 1, dev); |
mcm | 1:4d60db802cfb | 654 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 655 | dev->gas_sett.heatr_temp = reg_data; |
mcm | 1:4d60db802cfb | 656 | rslt = bme680_get_regs(reg_addr2, ®_data, 1, dev); |
mcm | 1:4d60db802cfb | 657 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 658 | /* Heating duration register value */ |
mcm | 1:4d60db802cfb | 659 | dev->gas_sett.heatr_dur = reg_data; |
mcm | 1:4d60db802cfb | 660 | } |
mcm | 1:4d60db802cfb | 661 | } |
mcm | 1:4d60db802cfb | 662 | } |
mcm | 1:4d60db802cfb | 663 | } |
mcm | 1:4d60db802cfb | 664 | |
mcm | 1:4d60db802cfb | 665 | return rslt; |
mcm | 1:4d60db802cfb | 666 | } |
mcm | 1:4d60db802cfb | 667 | |
mcm | 1:4d60db802cfb | 668 | #ifndef BME680_FLOAT_POINT_COMPENSATION |
mcm | 1:4d60db802cfb | 669 | |
mcm | 1:4d60db802cfb | 670 | /*! |
mcm | 1:4d60db802cfb | 671 | * @brief This internal API is used to calculate the temperature value. |
mcm | 1:4d60db802cfb | 672 | */ |
mcm | 1:4d60db802cfb | 673 | int16_t BME680::calc_temperature(uint32_t temp_adc, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 674 | { |
mcm | 1:4d60db802cfb | 675 | int64_t var1; |
mcm | 1:4d60db802cfb | 676 | int64_t var2; |
mcm | 1:4d60db802cfb | 677 | int64_t var3; |
mcm | 1:4d60db802cfb | 678 | int16_t calc_temp; |
mcm | 1:4d60db802cfb | 679 | |
mcm | 1:4d60db802cfb | 680 | var1 = ((int32_t) temp_adc >> 3) - ((int32_t) dev->calib.par_t1 << 1); |
mcm | 1:4d60db802cfb | 681 | var2 = (var1 * (int32_t) dev->calib.par_t2) >> 11; |
mcm | 1:4d60db802cfb | 682 | var3 = ((var1 >> 1) * (var1 >> 1)) >> 12; |
mcm | 1:4d60db802cfb | 683 | var3 = ((var3) * ((int32_t) dev->calib.par_t3 << 4)) >> 14; |
mcm | 1:4d60db802cfb | 684 | dev->calib.t_fine = (int32_t) (var2 + var3); |
mcm | 1:4d60db802cfb | 685 | calc_temp = (int16_t) (((dev->calib.t_fine * 5) + 128) >> 8); |
mcm | 1:4d60db802cfb | 686 | |
mcm | 1:4d60db802cfb | 687 | return calc_temp; |
mcm | 1:4d60db802cfb | 688 | } |
mcm | 1:4d60db802cfb | 689 | |
mcm | 1:4d60db802cfb | 690 | /*! |
mcm | 1:4d60db802cfb | 691 | * @brief This internal API is used to calculate the pressure value. |
mcm | 1:4d60db802cfb | 692 | */ |
mcm | 1:4d60db802cfb | 693 | uint32_t BME680::calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 694 | { |
mcm | 1:4d60db802cfb | 695 | int32_t var1; |
mcm | 1:4d60db802cfb | 696 | int32_t var2; |
mcm | 1:4d60db802cfb | 697 | int32_t var3; |
mcm | 1:4d60db802cfb | 698 | int32_t pressure_comp; |
mcm | 1:4d60db802cfb | 699 | |
mcm | 1:4d60db802cfb | 700 | var1 = (((int32_t)dev->calib.t_fine) >> 1) - 64000; |
mcm | 1:4d60db802cfb | 701 | var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * |
mcm | 1:4d60db802cfb | 702 | (int32_t)dev->calib.par_p6) >> 2; |
mcm | 1:4d60db802cfb | 703 | var2 = var2 + ((var1 * (int32_t)dev->calib.par_p5) << 1); |
mcm | 1:4d60db802cfb | 704 | var2 = (var2 >> 2) + ((int32_t)dev->calib.par_p4 << 16); |
mcm | 1:4d60db802cfb | 705 | var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * |
mcm | 1:4d60db802cfb | 706 | ((int32_t)dev->calib.par_p3 << 5)) >> 3) + |
mcm | 1:4d60db802cfb | 707 | (((int32_t)dev->calib.par_p2 * var1) >> 1); |
mcm | 1:4d60db802cfb | 708 | var1 = var1 >> 18; |
mcm | 1:4d60db802cfb | 709 | var1 = ((32768 + var1) * (int32_t)dev->calib.par_p1) >> 15; |
mcm | 1:4d60db802cfb | 710 | pressure_comp = 1048576 - pres_adc; |
mcm | 1:4d60db802cfb | 711 | pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125)); |
mcm | 1:4d60db802cfb | 712 | if (pressure_comp >= BME680_MAX_OVERFLOW_VAL) |
mcm | 1:4d60db802cfb | 713 | pressure_comp = ((pressure_comp / var1) << 1); |
mcm | 1:4d60db802cfb | 714 | else |
mcm | 1:4d60db802cfb | 715 | pressure_comp = ((pressure_comp << 1) / var1); |
mcm | 1:4d60db802cfb | 716 | var1 = ((int32_t)dev->calib.par_p9 * (int32_t)(((pressure_comp >> 3) * |
mcm | 1:4d60db802cfb | 717 | (pressure_comp >> 3)) >> 13)) >> 12; |
mcm | 1:4d60db802cfb | 718 | var2 = ((int32_t)(pressure_comp >> 2) * |
mcm | 1:4d60db802cfb | 719 | (int32_t)dev->calib.par_p8) >> 13; |
mcm | 1:4d60db802cfb | 720 | var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) * |
mcm | 1:4d60db802cfb | 721 | (int32_t)(pressure_comp >> 8) * |
mcm | 1:4d60db802cfb | 722 | (int32_t)dev->calib.par_p10) >> 17; |
mcm | 1:4d60db802cfb | 723 | |
mcm | 1:4d60db802cfb | 724 | pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 + |
mcm | 1:4d60db802cfb | 725 | ((int32_t)dev->calib.par_p7 << 7)) >> 4); |
mcm | 1:4d60db802cfb | 726 | |
mcm | 1:4d60db802cfb | 727 | return (uint32_t)pressure_comp; |
mcm | 1:4d60db802cfb | 728 | |
mcm | 1:4d60db802cfb | 729 | } |
mcm | 1:4d60db802cfb | 730 | |
mcm | 1:4d60db802cfb | 731 | /*! |
mcm | 1:4d60db802cfb | 732 | * @brief This internal API is used to calculate the humidity value. |
mcm | 1:4d60db802cfb | 733 | */ |
mcm | 1:4d60db802cfb | 734 | uint32_t BME680::calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 735 | { |
mcm | 1:4d60db802cfb | 736 | int32_t var1; |
mcm | 1:4d60db802cfb | 737 | int32_t var2; |
mcm | 1:4d60db802cfb | 738 | int32_t var3; |
mcm | 1:4d60db802cfb | 739 | int32_t var4; |
mcm | 1:4d60db802cfb | 740 | int32_t var5; |
mcm | 1:4d60db802cfb | 741 | int32_t var6; |
mcm | 1:4d60db802cfb | 742 | int32_t temp_scaled; |
mcm | 1:4d60db802cfb | 743 | int32_t calc_hum; |
mcm | 1:4d60db802cfb | 744 | |
mcm | 1:4d60db802cfb | 745 | temp_scaled = (((int32_t) dev->calib.t_fine * 5) + 128) >> 8; |
mcm | 1:4d60db802cfb | 746 | var1 = (int32_t) (hum_adc - ((int32_t) ((int32_t) dev->calib.par_h1 * 16))) |
mcm | 1:4d60db802cfb | 747 | - (((temp_scaled * (int32_t) dev->calib.par_h3) / ((int32_t) 100)) >> 1); |
mcm | 1:4d60db802cfb | 748 | var2 = ((int32_t) dev->calib.par_h2 |
mcm | 1:4d60db802cfb | 749 | * (((temp_scaled * (int32_t) dev->calib.par_h4) / ((int32_t) 100)) |
mcm | 1:4d60db802cfb | 750 | + (((temp_scaled * ((temp_scaled * (int32_t) dev->calib.par_h5) / ((int32_t) 100))) >> 6) |
mcm | 1:4d60db802cfb | 751 | / ((int32_t) 100)) + (int32_t) (1 << 14))) >> 10; |
mcm | 1:4d60db802cfb | 752 | var3 = var1 * var2; |
mcm | 1:4d60db802cfb | 753 | var4 = (int32_t) dev->calib.par_h6 << 7; |
mcm | 1:4d60db802cfb | 754 | var4 = ((var4) + ((temp_scaled * (int32_t) dev->calib.par_h7) / ((int32_t) 100))) >> 4; |
mcm | 1:4d60db802cfb | 755 | var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; |
mcm | 1:4d60db802cfb | 756 | var6 = (var4 * var5) >> 1; |
mcm | 1:4d60db802cfb | 757 | calc_hum = (((var3 + var6) >> 10) * ((int32_t) 1000)) >> 12; |
mcm | 1:4d60db802cfb | 758 | |
mcm | 1:4d60db802cfb | 759 | if (calc_hum > 100000) /* Cap at 100%rH */ |
mcm | 1:4d60db802cfb | 760 | calc_hum = 100000; |
mcm | 1:4d60db802cfb | 761 | else if (calc_hum < 0) |
mcm | 1:4d60db802cfb | 762 | calc_hum = 0; |
mcm | 1:4d60db802cfb | 763 | |
mcm | 1:4d60db802cfb | 764 | return (uint32_t) calc_hum; |
mcm | 1:4d60db802cfb | 765 | } |
mcm | 1:4d60db802cfb | 766 | |
mcm | 1:4d60db802cfb | 767 | /*! |
mcm | 1:4d60db802cfb | 768 | * @brief This internal API is used to calculate the Gas Resistance value. |
mcm | 1:4d60db802cfb | 769 | */ |
mcm | 1:4d60db802cfb | 770 | uint32_t BME680::calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 771 | { |
mcm | 1:4d60db802cfb | 772 | int64_t var1; |
mcm | 1:4d60db802cfb | 773 | uint64_t var2; |
mcm | 1:4d60db802cfb | 774 | int64_t var3; |
mcm | 1:4d60db802cfb | 775 | uint32_t calc_gas_res; |
mcm | 1:4d60db802cfb | 776 | /**Look up table 1 for the possible gas range values */ |
mcm | 1:4d60db802cfb | 777 | uint32_t lookupTable1[16] = { UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), |
mcm | 1:4d60db802cfb | 778 | UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2130303777), |
mcm | 1:4d60db802cfb | 779 | UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2143188679), UINT32_C(2136746228), |
mcm | 1:4d60db802cfb | 780 | UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2147483647) |
mcm | 1:4d60db802cfb | 781 | }; |
mcm | 1:4d60db802cfb | 782 | /**Look up table 2 for the possible gas range values */ |
mcm | 1:4d60db802cfb | 783 | uint32_t lookupTable2[16] = { UINT32_C(4096000000), UINT32_C(2048000000), UINT32_C(1024000000), UINT32_C(512000000), |
mcm | 1:4d60db802cfb | 784 | UINT32_C(255744255), UINT32_C(127110228), UINT32_C(64000000), UINT32_C(32258064), UINT32_C(16016016), |
mcm | 1:4d60db802cfb | 785 | UINT32_C(8000000), UINT32_C(4000000), UINT32_C(2000000), UINT32_C(1000000), UINT32_C(500000), |
mcm | 1:4d60db802cfb | 786 | UINT32_C(250000), UINT32_C(125000) |
mcm | 1:4d60db802cfb | 787 | }; |
mcm | 1:4d60db802cfb | 788 | |
mcm | 1:4d60db802cfb | 789 | var1 = (int64_t) ((1340 + (5 * (int64_t) dev->calib.range_sw_err)) * |
mcm | 1:4d60db802cfb | 790 | ((int64_t) lookupTable1[gas_range])) >> 16; |
mcm | 1:4d60db802cfb | 791 | var2 = (((int64_t) ((int64_t) gas_res_adc << 15) - (int64_t) (16777216)) + var1); |
mcm | 1:4d60db802cfb | 792 | var3 = (((int64_t) lookupTable2[gas_range] * (int64_t) var1) >> 9); |
mcm | 1:4d60db802cfb | 793 | calc_gas_res = (uint32_t) ((var3 + ((int64_t) var2 >> 1)) / (int64_t) var2); |
mcm | 1:4d60db802cfb | 794 | |
mcm | 1:4d60db802cfb | 795 | return calc_gas_res; |
mcm | 1:4d60db802cfb | 796 | } |
mcm | 1:4d60db802cfb | 797 | |
mcm | 1:4d60db802cfb | 798 | /*! |
mcm | 1:4d60db802cfb | 799 | * @brief This internal API is used to calculate the Heat Resistance value. |
mcm | 1:4d60db802cfb | 800 | */ |
mcm | 1:4d60db802cfb | 801 | uint8_t BME680::calc_heater_res(uint16_t temp, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 802 | { |
mcm | 1:4d60db802cfb | 803 | uint8_t heatr_res; |
mcm | 1:4d60db802cfb | 804 | int32_t var1; |
mcm | 1:4d60db802cfb | 805 | int32_t var2; |
mcm | 1:4d60db802cfb | 806 | int32_t var3; |
mcm | 1:4d60db802cfb | 807 | int32_t var4; |
mcm | 1:4d60db802cfb | 808 | int32_t var5; |
mcm | 1:4d60db802cfb | 809 | int32_t heatr_res_x100; |
mcm | 1:4d60db802cfb | 810 | |
mcm | 1:4d60db802cfb | 811 | if (temp > 400) /* Cap temperature */ |
mcm | 1:4d60db802cfb | 812 | temp = 400; |
mcm | 1:4d60db802cfb | 813 | |
mcm | 1:4d60db802cfb | 814 | var1 = (((int32_t) dev->amb_temp * dev->calib.par_gh3) / 1000) * 256; |
mcm | 1:4d60db802cfb | 815 | var2 = (dev->calib.par_gh1 + 784) * (((((dev->calib.par_gh2 + 154009) * temp * 5) / 100) + 3276800) / 10); |
mcm | 1:4d60db802cfb | 816 | var3 = var1 + (var2 / 2); |
mcm | 1:4d60db802cfb | 817 | var4 = (var3 / (dev->calib.res_heat_range + 4)); |
mcm | 1:4d60db802cfb | 818 | var5 = (131 * dev->calib.res_heat_val) + 65536; |
mcm | 1:4d60db802cfb | 819 | heatr_res_x100 = (int32_t) (((var4 / var5) - 250) * 34); |
mcm | 1:4d60db802cfb | 820 | heatr_res = (uint8_t) ((heatr_res_x100 + 50) / 100); |
mcm | 1:4d60db802cfb | 821 | |
mcm | 1:4d60db802cfb | 822 | return heatr_res; |
mcm | 1:4d60db802cfb | 823 | } |
mcm | 1:4d60db802cfb | 824 | |
mcm | 1:4d60db802cfb | 825 | #else |
mcm | 1:4d60db802cfb | 826 | |
mcm | 1:4d60db802cfb | 827 | |
mcm | 1:4d60db802cfb | 828 | /*! |
mcm | 1:4d60db802cfb | 829 | * @brief This internal API is used to calculate the |
mcm | 1:4d60db802cfb | 830 | * temperature value in float format |
mcm | 1:4d60db802cfb | 831 | */ |
mcm | 1:4d60db802cfb | 832 | float BME680::calc_temperature(uint32_t temp_adc, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 833 | { |
mcm | 1:4d60db802cfb | 834 | float var1 = 0; |
mcm | 1:4d60db802cfb | 835 | float var2 = 0; |
mcm | 1:4d60db802cfb | 836 | float calc_temp = 0; |
mcm | 1:4d60db802cfb | 837 | |
mcm | 1:4d60db802cfb | 838 | /* calculate var1 data */ |
mcm | 1:4d60db802cfb | 839 | var1 = ((((float)temp_adc / 16384.0f) - ((float)dev->calib.par_t1 / 1024.0f)) |
mcm | 1:4d60db802cfb | 840 | * ((float)dev->calib.par_t2)); |
mcm | 1:4d60db802cfb | 841 | |
mcm | 1:4d60db802cfb | 842 | /* calculate var2 data */ |
mcm | 1:4d60db802cfb | 843 | var2 = (((((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f)) * |
mcm | 1:4d60db802cfb | 844 | (((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f))) * |
mcm | 1:4d60db802cfb | 845 | ((float)dev->calib.par_t3 * 16.0f)); |
mcm | 1:4d60db802cfb | 846 | |
mcm | 1:4d60db802cfb | 847 | /* t_fine value*/ |
mcm | 1:4d60db802cfb | 848 | dev->calib.t_fine = (var1 + var2); |
mcm | 1:4d60db802cfb | 849 | |
mcm | 1:4d60db802cfb | 850 | /* compensated temperature data*/ |
mcm | 1:4d60db802cfb | 851 | calc_temp = ((dev->calib.t_fine) / 5120.0f); |
mcm | 1:4d60db802cfb | 852 | |
mcm | 1:4d60db802cfb | 853 | return calc_temp; |
mcm | 1:4d60db802cfb | 854 | } |
mcm | 1:4d60db802cfb | 855 | |
mcm | 1:4d60db802cfb | 856 | /*! |
mcm | 1:4d60db802cfb | 857 | * @brief This internal API is used to calculate the |
mcm | 1:4d60db802cfb | 858 | * pressure value in float format |
mcm | 1:4d60db802cfb | 859 | */ |
mcm | 1:4d60db802cfb | 860 | float BME680::calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 861 | { |
mcm | 1:4d60db802cfb | 862 | float var1 = 0; |
mcm | 1:4d60db802cfb | 863 | float var2 = 0; |
mcm | 1:4d60db802cfb | 864 | float var3 = 0; |
mcm | 1:4d60db802cfb | 865 | float calc_pres = 0; |
mcm | 1:4d60db802cfb | 866 | |
mcm | 1:4d60db802cfb | 867 | var1 = (((float)dev->calib.t_fine / 2.0f) - 64000.0f); |
mcm | 1:4d60db802cfb | 868 | var2 = var1 * var1 * (((float)dev->calib.par_p6) / (131072.0f)); |
mcm | 1:4d60db802cfb | 869 | var2 = var2 + (var1 * ((float)dev->calib.par_p5) * 2.0f); |
mcm | 1:4d60db802cfb | 870 | var2 = (var2 / 4.0f) + (((float)dev->calib.par_p4) * 65536.0f); |
mcm | 1:4d60db802cfb | 871 | var1 = (((((float)dev->calib.par_p3 * var1 * var1) / 16384.0f) |
mcm | 1:4d60db802cfb | 872 | + ((float)dev->calib.par_p2 * var1)) / 524288.0f); |
mcm | 1:4d60db802cfb | 873 | var1 = ((1.0f + (var1 / 32768.0f)) * ((float)dev->calib.par_p1)); |
mcm | 1:4d60db802cfb | 874 | calc_pres = (1048576.0f - ((float)pres_adc)); |
mcm | 1:4d60db802cfb | 875 | |
mcm | 1:4d60db802cfb | 876 | /* Avoid exception caused by division by zero */ |
mcm | 1:4d60db802cfb | 877 | if ((int)var1 != 0) { |
mcm | 1:4d60db802cfb | 878 | calc_pres = (((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1); |
mcm | 1:4d60db802cfb | 879 | var1 = (((float)dev->calib.par_p9) * calc_pres * calc_pres) / 2147483648.0f; |
mcm | 1:4d60db802cfb | 880 | var2 = calc_pres * (((float)dev->calib.par_p8) / 32768.0f); |
mcm | 1:4d60db802cfb | 881 | var3 = ((calc_pres / 256.0f) * (calc_pres / 256.0f) * (calc_pres / 256.0f) |
mcm | 1:4d60db802cfb | 882 | * (dev->calib.par_p10 / 131072.0f)); |
mcm | 1:4d60db802cfb | 883 | calc_pres = (calc_pres + (var1 + var2 + var3 + ((float)dev->calib.par_p7 * 128.0f)) / 16.0f); |
mcm | 1:4d60db802cfb | 884 | } else { |
mcm | 1:4d60db802cfb | 885 | calc_pres = 0; |
mcm | 1:4d60db802cfb | 886 | } |
mcm | 1:4d60db802cfb | 887 | |
mcm | 1:4d60db802cfb | 888 | return calc_pres; |
mcm | 1:4d60db802cfb | 889 | } |
mcm | 1:4d60db802cfb | 890 | |
mcm | 1:4d60db802cfb | 891 | /*! |
mcm | 1:4d60db802cfb | 892 | * @brief This internal API is used to calculate the |
mcm | 1:4d60db802cfb | 893 | * humidity value in float format |
mcm | 1:4d60db802cfb | 894 | */ |
mcm | 1:4d60db802cfb | 895 | float BME680::calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 896 | { |
mcm | 1:4d60db802cfb | 897 | float calc_hum = 0; |
mcm | 1:4d60db802cfb | 898 | float var1 = 0; |
mcm | 1:4d60db802cfb | 899 | float var2 = 0; |
mcm | 1:4d60db802cfb | 900 | float var3 = 0; |
mcm | 1:4d60db802cfb | 901 | float var4 = 0; |
mcm | 1:4d60db802cfb | 902 | float temp_comp; |
mcm | 1:4d60db802cfb | 903 | |
mcm | 1:4d60db802cfb | 904 | /* compensated temperature data*/ |
mcm | 1:4d60db802cfb | 905 | temp_comp = ((dev->calib.t_fine) / 5120.0f); |
mcm | 1:4d60db802cfb | 906 | |
mcm | 1:4d60db802cfb | 907 | var1 = (float)((float)hum_adc) - (((float)dev->calib.par_h1 * 16.0f) + (((float)dev->calib.par_h3 / 2.0f) |
mcm | 1:4d60db802cfb | 908 | * temp_comp)); |
mcm | 1:4d60db802cfb | 909 | |
mcm | 1:4d60db802cfb | 910 | var2 = var1 * ((float)(((float) dev->calib.par_h2 / 262144.0f) * (1.0f + (((float)dev->calib.par_h4 / 16384.0f) |
mcm | 1:4d60db802cfb | 911 | * temp_comp) + (((float)dev->calib.par_h5 / 1048576.0f) * temp_comp * temp_comp)))); |
mcm | 1:4d60db802cfb | 912 | |
mcm | 1:4d60db802cfb | 913 | var3 = (float) dev->calib.par_h6 / 16384.0f; |
mcm | 1:4d60db802cfb | 914 | |
mcm | 1:4d60db802cfb | 915 | var4 = (float) dev->calib.par_h7 / 2097152.0f; |
mcm | 1:4d60db802cfb | 916 | |
mcm | 1:4d60db802cfb | 917 | calc_hum = var2 + ((var3 + (var4 * temp_comp)) * var2 * var2); |
mcm | 1:4d60db802cfb | 918 | |
mcm | 1:4d60db802cfb | 919 | if (calc_hum > 100.0f) |
mcm | 1:4d60db802cfb | 920 | calc_hum = 100.0f; |
mcm | 1:4d60db802cfb | 921 | else if (calc_hum < 0.0f) |
mcm | 1:4d60db802cfb | 922 | calc_hum = 0.0f; |
mcm | 1:4d60db802cfb | 923 | |
mcm | 1:4d60db802cfb | 924 | return calc_hum; |
mcm | 1:4d60db802cfb | 925 | } |
mcm | 1:4d60db802cfb | 926 | |
mcm | 1:4d60db802cfb | 927 | /*! |
mcm | 1:4d60db802cfb | 928 | * @brief This internal API is used to calculate the |
mcm | 1:4d60db802cfb | 929 | * gas resistance value in float format |
mcm | 1:4d60db802cfb | 930 | */ |
mcm | 1:4d60db802cfb | 931 | float BME680::calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 932 | { |
mcm | 1:4d60db802cfb | 933 | float calc_gas_res; |
mcm | 1:4d60db802cfb | 934 | float var1 = 0; |
mcm | 1:4d60db802cfb | 935 | float var2 = 0; |
mcm | 1:4d60db802cfb | 936 | float var3 = 0; |
mcm | 1:4d60db802cfb | 937 | |
mcm | 1:4d60db802cfb | 938 | const float lookup_k1_range[16] = { |
mcm | 1:4d60db802cfb | 939 | 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, |
mcm | 1:4d60db802cfb | 940 | 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0 |
mcm | 1:4d60db802cfb | 941 | }; |
mcm | 1:4d60db802cfb | 942 | const float lookup_k2_range[16] = { |
mcm | 1:4d60db802cfb | 943 | 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, |
mcm | 1:4d60db802cfb | 944 | -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 |
mcm | 1:4d60db802cfb | 945 | }; |
mcm | 1:4d60db802cfb | 946 | |
mcm | 1:4d60db802cfb | 947 | var1 = (1340.0f + (5.0f * dev->calib.range_sw_err)); |
mcm | 1:4d60db802cfb | 948 | var2 = (var1) * (1.0f + lookup_k1_range[gas_range]/100.0f); |
mcm | 1:4d60db802cfb | 949 | var3 = 1.0f + (lookup_k2_range[gas_range]/100.0f); |
mcm | 1:4d60db802cfb | 950 | |
mcm | 1:4d60db802cfb | 951 | calc_gas_res = 1.0f / (float)(var3 * (0.000000125f) * (float)(1 << gas_range) * (((((float)gas_res_adc) |
mcm | 1:4d60db802cfb | 952 | - 512.0f)/var2) + 1.0f)); |
mcm | 1:4d60db802cfb | 953 | |
mcm | 1:4d60db802cfb | 954 | return calc_gas_res; |
mcm | 1:4d60db802cfb | 955 | } |
mcm | 1:4d60db802cfb | 956 | |
mcm | 1:4d60db802cfb | 957 | /*! |
mcm | 1:4d60db802cfb | 958 | * @brief This internal API is used to calculate the |
mcm | 1:4d60db802cfb | 959 | * heater resistance value in float format |
mcm | 1:4d60db802cfb | 960 | */ |
mcm | 1:4d60db802cfb | 961 | float BME680::calc_heater_res(uint16_t temp, const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 962 | { |
mcm | 1:4d60db802cfb | 963 | float var1 = 0; |
mcm | 1:4d60db802cfb | 964 | float var2 = 0; |
mcm | 1:4d60db802cfb | 965 | float var3 = 0; |
mcm | 1:4d60db802cfb | 966 | float var4 = 0; |
mcm | 1:4d60db802cfb | 967 | float var5 = 0; |
mcm | 1:4d60db802cfb | 968 | float res_heat = 0; |
mcm | 1:4d60db802cfb | 969 | |
mcm | 1:4d60db802cfb | 970 | if (temp > 400) /* Cap temperature */ |
mcm | 1:4d60db802cfb | 971 | temp = 400; |
mcm | 1:4d60db802cfb | 972 | |
mcm | 1:4d60db802cfb | 973 | var1 = (((float)dev->calib.par_gh1 / (16.0f)) + 49.0f); |
mcm | 1:4d60db802cfb | 974 | var2 = ((((float)dev->calib.par_gh2 / (32768.0f)) * (0.0005f)) + 0.00235f); |
mcm | 1:4d60db802cfb | 975 | var3 = ((float)dev->calib.par_gh3 / (1024.0f)); |
mcm | 1:4d60db802cfb | 976 | var4 = (var1 * (1.0f + (var2 * (float)temp))); |
mcm | 1:4d60db802cfb | 977 | var5 = (var4 + (var3 * (float)dev->amb_temp)); |
mcm | 1:4d60db802cfb | 978 | res_heat = (uint8_t)(3.4f * ((var5 * (4 / (4 + (float)dev->calib.res_heat_range)) * |
mcm | 1:4d60db802cfb | 979 | (1/(1 + ((float) dev->calib.res_heat_val * 0.002f)))) - 25)); |
mcm | 1:4d60db802cfb | 980 | |
mcm | 1:4d60db802cfb | 981 | return res_heat; |
mcm | 1:4d60db802cfb | 982 | } |
mcm | 1:4d60db802cfb | 983 | |
mcm | 1:4d60db802cfb | 984 | #endif |
mcm | 1:4d60db802cfb | 985 | |
mcm | 1:4d60db802cfb | 986 | /*! |
mcm | 1:4d60db802cfb | 987 | * @brief This internal API is used to calculate the Heat duration value. |
mcm | 1:4d60db802cfb | 988 | */ |
mcm | 1:4d60db802cfb | 989 | uint8_t BME680::calc_heater_dur(uint16_t dur) |
mcm | 1:4d60db802cfb | 990 | { |
mcm | 1:4d60db802cfb | 991 | uint8_t factor = 0; |
mcm | 1:4d60db802cfb | 992 | uint8_t durval; |
mcm | 1:4d60db802cfb | 993 | |
mcm | 1:4d60db802cfb | 994 | if (dur >= 0xfc0) { |
mcm | 1:4d60db802cfb | 995 | durval = 0xff; /* Max duration*/ |
mcm | 1:4d60db802cfb | 996 | } else { |
mcm | 1:4d60db802cfb | 997 | while (dur > 0x3F) { |
mcm | 1:4d60db802cfb | 998 | dur = dur / 4; |
mcm | 1:4d60db802cfb | 999 | factor += 1; |
mcm | 1:4d60db802cfb | 1000 | } |
mcm | 1:4d60db802cfb | 1001 | durval = (uint8_t) (dur + (factor * 64)); |
mcm | 1:4d60db802cfb | 1002 | } |
mcm | 1:4d60db802cfb | 1003 | |
mcm | 1:4d60db802cfb | 1004 | return durval; |
mcm | 1:4d60db802cfb | 1005 | } |
mcm | 1:4d60db802cfb | 1006 | |
mcm | 1:4d60db802cfb | 1007 | /*! |
mcm | 1:4d60db802cfb | 1008 | * @brief This internal API is used to calculate the field data of sensor. |
mcm | 1:4d60db802cfb | 1009 | */ |
mcm | 1:4d60db802cfb | 1010 | int8_t BME680::read_field_data(struct bme680_field_data *data, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 1011 | { |
mcm | 1:4d60db802cfb | 1012 | int8_t rslt; |
mcm | 1:4d60db802cfb | 1013 | uint8_t buff[BME680_FIELD_LENGTH] = { 0 }; |
mcm | 1:4d60db802cfb | 1014 | uint8_t gas_range; |
mcm | 1:4d60db802cfb | 1015 | uint32_t adc_temp; |
mcm | 1:4d60db802cfb | 1016 | uint32_t adc_pres; |
mcm | 1:4d60db802cfb | 1017 | uint16_t adc_hum; |
mcm | 1:4d60db802cfb | 1018 | uint16_t adc_gas_res; |
mcm | 1:4d60db802cfb | 1019 | uint8_t tries = 10; |
mcm | 1:4d60db802cfb | 1020 | |
mcm | 1:4d60db802cfb | 1021 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 1022 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 1023 | do { |
mcm | 1:4d60db802cfb | 1024 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 1025 | rslt = bme680_get_regs(((uint8_t) (BME680_FIELD0_ADDR)), buff, (uint16_t) BME680_FIELD_LENGTH, |
mcm | 1:4d60db802cfb | 1026 | dev); |
mcm | 1:4d60db802cfb | 1027 | |
mcm | 1:4d60db802cfb | 1028 | data->status = buff[0] & BME680_NEW_DATA_MSK; |
mcm | 1:4d60db802cfb | 1029 | data->gas_index = buff[0] & BME680_GAS_INDEX_MSK; |
mcm | 1:4d60db802cfb | 1030 | data->meas_index = buff[1]; |
mcm | 1:4d60db802cfb | 1031 | |
mcm | 1:4d60db802cfb | 1032 | /* read the raw data from the sensor */ |
mcm | 1:4d60db802cfb | 1033 | adc_pres = (uint32_t) (((uint32_t) buff[2] * 4096) | ((uint32_t) buff[3] * 16) |
mcm | 1:4d60db802cfb | 1034 | | ((uint32_t) buff[4] / 16)); |
mcm | 1:4d60db802cfb | 1035 | adc_temp = (uint32_t) (((uint32_t) buff[5] * 4096) | ((uint32_t) buff[6] * 16) |
mcm | 1:4d60db802cfb | 1036 | | ((uint32_t) buff[7] / 16)); |
mcm | 1:4d60db802cfb | 1037 | adc_hum = (uint16_t) (((uint32_t) buff[8] * 256) | (uint32_t) buff[9]); |
mcm | 1:4d60db802cfb | 1038 | adc_gas_res = (uint16_t) ((uint32_t) buff[13] * 4 | (((uint32_t) buff[14]) / 64)); |
mcm | 1:4d60db802cfb | 1039 | gas_range = buff[14] & BME680_GAS_RANGE_MSK; |
mcm | 1:4d60db802cfb | 1040 | |
mcm | 1:4d60db802cfb | 1041 | data->status |= buff[14] & BME680_GASM_VALID_MSK; |
mcm | 1:4d60db802cfb | 1042 | data->status |= buff[14] & BME680_HEAT_STAB_MSK; |
mcm | 1:4d60db802cfb | 1043 | |
mcm | 1:4d60db802cfb | 1044 | if (data->status & BME680_NEW_DATA_MSK) { |
mcm | 1:4d60db802cfb | 1045 | data->temperature = calc_temperature(adc_temp, dev); |
mcm | 1:4d60db802cfb | 1046 | data->pressure = calc_pressure(adc_pres, dev); |
mcm | 1:4d60db802cfb | 1047 | data->humidity = calc_humidity(adc_hum, dev); |
mcm | 1:4d60db802cfb | 1048 | data->gas_resistance = calc_gas_resistance(adc_gas_res, gas_range, dev); |
mcm | 1:4d60db802cfb | 1049 | break; |
mcm | 1:4d60db802cfb | 1050 | } |
mcm | 1:4d60db802cfb | 1051 | /* Delay to poll the data */ |
mcm | 1:4d60db802cfb | 1052 | dev->delay_ms(BME680_POLL_PERIOD_MS); |
mcm | 1:4d60db802cfb | 1053 | } |
mcm | 1:4d60db802cfb | 1054 | tries--; |
mcm | 1:4d60db802cfb | 1055 | } while (tries); |
mcm | 1:4d60db802cfb | 1056 | |
mcm | 1:4d60db802cfb | 1057 | if (!tries) |
mcm | 1:4d60db802cfb | 1058 | rslt = BME680_W_NO_NEW_DATA; |
mcm | 1:4d60db802cfb | 1059 | |
mcm | 1:4d60db802cfb | 1060 | return rslt; |
mcm | 1:4d60db802cfb | 1061 | } |
mcm | 1:4d60db802cfb | 1062 | |
mcm | 1:4d60db802cfb | 1063 | /*! |
mcm | 1:4d60db802cfb | 1064 | * @brief This internal API is used to set the memory page based on register address. |
mcm | 1:4d60db802cfb | 1065 | */ |
mcm | 1:4d60db802cfb | 1066 | int8_t BME680::set_mem_page(uint8_t reg_addr, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 1067 | { |
mcm | 1:4d60db802cfb | 1068 | int8_t rslt; |
mcm | 1:4d60db802cfb | 1069 | uint8_t reg; |
mcm | 1:4d60db802cfb | 1070 | uint8_t mem_page; |
mcm | 1:4d60db802cfb | 1071 | |
mcm | 1:4d60db802cfb | 1072 | /* Check for null pointers in the device structure*/ |
mcm | 1:4d60db802cfb | 1073 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 1074 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 1075 | if (reg_addr > 0x7f) |
mcm | 1:4d60db802cfb | 1076 | mem_page = BME680_MEM_PAGE1; |
mcm | 1:4d60db802cfb | 1077 | else |
mcm | 1:4d60db802cfb | 1078 | mem_page = BME680_MEM_PAGE0; |
mcm | 1:4d60db802cfb | 1079 | |
mcm | 1:4d60db802cfb | 1080 | if (mem_page != dev->mem_page) { |
mcm | 1:4d60db802cfb | 1081 | dev->mem_page = mem_page; |
mcm | 1:4d60db802cfb | 1082 | |
mcm | 1:4d60db802cfb | 1083 | dev->com_rslt = dev->read(dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, ®, 1); |
mcm | 1:4d60db802cfb | 1084 | if (dev->com_rslt != 0) |
mcm | 1:4d60db802cfb | 1085 | rslt = BME680_E_COM_FAIL; |
mcm | 1:4d60db802cfb | 1086 | |
mcm | 1:4d60db802cfb | 1087 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 1088 | reg = reg & (~BME680_MEM_PAGE_MSK); |
mcm | 1:4d60db802cfb | 1089 | reg = reg | (dev->mem_page & BME680_MEM_PAGE_MSK); |
mcm | 1:4d60db802cfb | 1090 | |
mcm | 1:4d60db802cfb | 1091 | dev->com_rslt = dev->write(dev->dev_id, BME680_MEM_PAGE_ADDR & BME680_SPI_WR_MSK, |
mcm | 1:4d60db802cfb | 1092 | ®, 1); |
mcm | 1:4d60db802cfb | 1093 | if (dev->com_rslt != 0) |
mcm | 1:4d60db802cfb | 1094 | rslt = BME680_E_COM_FAIL; |
mcm | 1:4d60db802cfb | 1095 | } |
mcm | 1:4d60db802cfb | 1096 | } |
mcm | 1:4d60db802cfb | 1097 | } |
mcm | 1:4d60db802cfb | 1098 | |
mcm | 1:4d60db802cfb | 1099 | return rslt; |
mcm | 1:4d60db802cfb | 1100 | } |
mcm | 1:4d60db802cfb | 1101 | |
mcm | 1:4d60db802cfb | 1102 | /*! |
mcm | 1:4d60db802cfb | 1103 | * @brief This internal API is used to get the memory page based on register address. |
mcm | 1:4d60db802cfb | 1104 | */ |
mcm | 1:4d60db802cfb | 1105 | int8_t BME680::get_mem_page(struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 1106 | { |
mcm | 1:4d60db802cfb | 1107 | int8_t rslt; |
mcm | 1:4d60db802cfb | 1108 | uint8_t reg; |
mcm | 1:4d60db802cfb | 1109 | |
mcm | 1:4d60db802cfb | 1110 | /* Check for null pointer in the device structure*/ |
mcm | 1:4d60db802cfb | 1111 | rslt = null_ptr_check(dev); |
mcm | 1:4d60db802cfb | 1112 | if (rslt == BME680_OK) { |
mcm | 1:4d60db802cfb | 1113 | dev->com_rslt = dev->read(dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, ®, 1); |
mcm | 1:4d60db802cfb | 1114 | if (dev->com_rslt != 0) |
mcm | 1:4d60db802cfb | 1115 | rslt = BME680_E_COM_FAIL; |
mcm | 1:4d60db802cfb | 1116 | else |
mcm | 1:4d60db802cfb | 1117 | dev->mem_page = reg & BME680_MEM_PAGE_MSK; |
mcm | 1:4d60db802cfb | 1118 | } |
mcm | 1:4d60db802cfb | 1119 | |
mcm | 1:4d60db802cfb | 1120 | return rslt; |
mcm | 1:4d60db802cfb | 1121 | } |
mcm | 1:4d60db802cfb | 1122 | |
mcm | 1:4d60db802cfb | 1123 | /*! |
mcm | 1:4d60db802cfb | 1124 | * @brief This internal API is used to validate the boundary |
mcm | 1:4d60db802cfb | 1125 | * conditions. |
mcm | 1:4d60db802cfb | 1126 | */ |
mcm | 1:4d60db802cfb | 1127 | int8_t BME680::boundary_check(uint8_t *value, uint8_t min, uint8_t max, struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 1128 | { |
mcm | 1:4d60db802cfb | 1129 | int8_t rslt = BME680_OK; |
mcm | 1:4d60db802cfb | 1130 | |
mcm | 1:4d60db802cfb | 1131 | if (value != NULL) { |
mcm | 1:4d60db802cfb | 1132 | /* Check if value is below minimum value */ |
mcm | 1:4d60db802cfb | 1133 | if (*value < min) { |
mcm | 1:4d60db802cfb | 1134 | /* Auto correct the invalid value to minimum value */ |
mcm | 1:4d60db802cfb | 1135 | *value = min; |
mcm | 1:4d60db802cfb | 1136 | dev->info_msg |= BME680_I_MIN_CORRECTION; |
mcm | 1:4d60db802cfb | 1137 | } |
mcm | 1:4d60db802cfb | 1138 | /* Check if value is above maximum value */ |
mcm | 1:4d60db802cfb | 1139 | if (*value > max) { |
mcm | 1:4d60db802cfb | 1140 | /* Auto correct the invalid value to maximum value */ |
mcm | 1:4d60db802cfb | 1141 | *value = max; |
mcm | 1:4d60db802cfb | 1142 | dev->info_msg |= BME680_I_MAX_CORRECTION; |
mcm | 1:4d60db802cfb | 1143 | } |
mcm | 1:4d60db802cfb | 1144 | } else { |
mcm | 1:4d60db802cfb | 1145 | rslt = BME680_E_NULL_PTR; |
mcm | 1:4d60db802cfb | 1146 | } |
mcm | 1:4d60db802cfb | 1147 | |
mcm | 1:4d60db802cfb | 1148 | return rslt; |
mcm | 1:4d60db802cfb | 1149 | } |
mcm | 1:4d60db802cfb | 1150 | |
mcm | 1:4d60db802cfb | 1151 | /*! |
mcm | 1:4d60db802cfb | 1152 | * @brief This internal API is used to validate the device structure pointer for |
mcm | 1:4d60db802cfb | 1153 | * null conditions. |
mcm | 1:4d60db802cfb | 1154 | */ |
mcm | 1:4d60db802cfb | 1155 | int8_t BME680::null_ptr_check(const struct bme680_dev *dev) |
mcm | 1:4d60db802cfb | 1156 | { |
mcm | 1:4d60db802cfb | 1157 | int8_t rslt; |
mcm | 1:4d60db802cfb | 1158 | |
mcm | 1:4d60db802cfb | 1159 | if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { |
mcm | 1:4d60db802cfb | 1160 | /* Device structure pointer is not valid */ |
mcm | 1:4d60db802cfb | 1161 | rslt = BME680_E_NULL_PTR; |
mcm | 1:4d60db802cfb | 1162 | } else { |
mcm | 1:4d60db802cfb | 1163 | /* Device structure is fine */ |
mcm | 1:4d60db802cfb | 1164 | rslt = BME680_OK; |
mcm | 1:4d60db802cfb | 1165 | } |
mcm | 1:4d60db802cfb | 1166 | |
mcm | 1:4d60db802cfb | 1167 | return rslt; |
mcm | 1:4d60db802cfb | 1168 | } |