Repo for ESP32 Weather Station Development
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1497 lines
48KB

  1. /**
  2. * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
  3. *
  4. * BSD-3-Clause
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * 3. Neither the name of the copyright holder nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  26. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  27. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  29. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. * POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. * @file bme280.c
  34. * @date 21/01/2020
  35. * @version 3.4.2
  36. *
  37. */
  38. /*! @file bme280.c
  39. * @brief Sensor driver for BME280 sensor
  40. */
  41. #include "bme280.h"
  42. /**\name Internal macros */
  43. /* To identify osr settings selected by user */
  44. #define OVERSAMPLING_SETTINGS UINT8_C(0x07)
  45. /* To identify filter and standby settings selected by user */
  46. #define FILTER_STANDBY_SETTINGS UINT8_C(0x18)
  47. /*!
  48. * @brief This internal API puts the device to sleep mode.
  49. *
  50. * @param[in] dev : Structure instance of bme280_dev.
  51. *
  52. * @return Result of API execution status.
  53. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  54. */
  55. static int8_t put_device_to_sleep(const struct bme280_dev *dev);
  56. /*!
  57. * @brief This internal API writes the power mode in the sensor.
  58. *
  59. * @param[in] dev : Structure instance of bme280_dev.
  60. * @param[in] sensor_mode : Variable which contains the power mode to be set.
  61. *
  62. * @return Result of API execution status.
  63. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  64. */
  65. static int8_t write_power_mode(uint8_t sensor_mode, const struct bme280_dev *dev);
  66. /*!
  67. * @brief This internal API is used to validate the device pointer for
  68. * null conditions.
  69. *
  70. * @param[in] dev : Structure instance of bme280_dev.
  71. *
  72. * @return Result of API execution status
  73. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  74. */
  75. static int8_t null_ptr_check(const struct bme280_dev *dev);
  76. /*!
  77. * @brief This internal API interleaves the register address between the
  78. * register data buffer for burst write operation.
  79. *
  80. * @param[in] reg_addr : Contains the register address array.
  81. * @param[out] temp_buff : Contains the temporary buffer to store the
  82. * register data and register address.
  83. * @param[in] reg_data : Contains the register data to be written in the
  84. * temporary buffer.
  85. * @param[in] len : No of bytes of data to be written for burst write.
  86. */
  87. static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len);
  88. /*!
  89. * @brief This internal API reads the calibration data from the sensor, parse
  90. * it and store in the device structure.
  91. *
  92. * @param[in] dev : Structure instance of bme280_dev.
  93. *
  94. * @return Result of API execution status
  95. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  96. */
  97. static int8_t get_calib_data(struct bme280_dev *dev);
  98. /*!
  99. * @brief This internal API is used to parse the temperature and
  100. * pressure calibration data and store it in the device structure.
  101. *
  102. * @param[out] dev : Structure instance of bme280_dev to store the calib data.
  103. * @param[in] reg_data : Contains the calibration data to be parsed.
  104. */
  105. static void parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_dev *dev);
  106. /*!
  107. * @brief This internal API is used to parse the humidity calibration data
  108. * and store it in device structure.
  109. *
  110. * @param[out] dev : Structure instance of bme280_dev to store the calib data.
  111. * @param[in] reg_data : Contains calibration data to be parsed.
  112. */
  113. static void parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev);
  114. #ifdef BME280_FLOAT_ENABLE
  115. /*!
  116. * @brief This internal API is used to compensate the raw pressure data and
  117. * return the compensated pressure data in double data type.
  118. *
  119. * @param[in] uncomp_data : Contains the uncompensated pressure data.
  120. * @param[in] calib_data : Pointer to the calibration data structure.
  121. *
  122. * @return Compensated pressure data.
  123. * @retval Compensated pressure data in double.
  124. */
  125. static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
  126. const struct bme280_calib_data *calib_data);
  127. /*!
  128. * @brief This internal API is used to compensate the raw humidity data and
  129. * return the compensated humidity data in double data type.
  130. *
  131. * @param[in] uncomp_data : Contains the uncompensated humidity data.
  132. * @param[in] calib_data : Pointer to the calibration data structure.
  133. *
  134. * @return Compensated humidity data.
  135. * @retval Compensated humidity data in double.
  136. */
  137. static double compensate_humidity(const struct bme280_uncomp_data *uncomp_data,
  138. const struct bme280_calib_data *calib_data);
  139. /*!
  140. * @brief This internal API is used to compensate the raw temperature data and
  141. * return the compensated temperature data in double data type.
  142. *
  143. * @param[in] uncomp_data : Contains the uncompensated temperature data.
  144. * @param[in] calib_data : Pointer to calibration data structure.
  145. *
  146. * @return Compensated temperature data.
  147. * @retval Compensated temperature data in double.
  148. */
  149. static double compensate_temperature(const struct bme280_uncomp_data *uncomp_data,
  150. struct bme280_calib_data *calib_data);
  151. #else
  152. /*!
  153. * @brief This internal API is used to compensate the raw temperature data and
  154. * return the compensated temperature data in integer data type.
  155. *
  156. * @param[in] uncomp_data : Contains the uncompensated temperature data.
  157. * @param[in] calib_data : Pointer to calibration data structure.
  158. *
  159. * @return Compensated temperature data.
  160. * @retval Compensated temperature data in integer.
  161. */
  162. static int32_t compensate_temperature(const struct bme280_uncomp_data *uncomp_data,
  163. struct bme280_calib_data *calib_data);
  164. /*!
  165. * @brief This internal API is used to compensate the raw pressure data and
  166. * return the compensated pressure data in integer data type.
  167. *
  168. * @param[in] uncomp_data : Contains the uncompensated pressure data.
  169. * @param[in] calib_data : Pointer to the calibration data structure.
  170. *
  171. * @return Compensated pressure data.
  172. * @retval Compensated pressure data in integer.
  173. */
  174. static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
  175. const struct bme280_calib_data *calib_data);
  176. /*!
  177. * @brief This internal API is used to compensate the raw humidity data and
  178. * return the compensated humidity data in integer data type.
  179. *
  180. * @param[in] uncomp_data : Contains the uncompensated humidity data.
  181. * @param[in] calib_data : Pointer to the calibration data structure.
  182. *
  183. * @return Compensated humidity data.
  184. * @retval Compensated humidity data in integer.
  185. */
  186. static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data,
  187. const struct bme280_calib_data *calib_data);
  188. #endif
  189. /*!
  190. * @brief This internal API is used to identify the settings which the user
  191. * wants to modify in the sensor.
  192. *
  193. * @param[in] sub_settings : Contains the settings subset to identify particular
  194. * group of settings which the user is interested to change.
  195. * @param[in] desired_settings : Contains the user specified settings.
  196. *
  197. * @return Indicates whether user is interested to modify the settings which
  198. * are related to sub_settings.
  199. * @retval True -> User wants to modify this group of settings
  200. * @retval False -> User does not want to modify this group of settings
  201. */
  202. static uint8_t are_settings_changed(uint8_t sub_settings, uint8_t desired_settings);
  203. /*!
  204. * @brief This API sets the humidity oversampling settings of the sensor.
  205. *
  206. * @param[in] dev : Structure instance of bme280_dev.
  207. *
  208. * @return Result of API execution status
  209. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  210. */
  211. static int8_t set_osr_humidity_settings(const struct bme280_settings *settings, const struct bme280_dev *dev);
  212. /*!
  213. * @brief This internal API sets the oversampling settings for pressure,
  214. * temperature and humidity in the sensor.
  215. *
  216. * @param[in] desired_settings : Variable used to select the settings which
  217. * are to be set.
  218. * @param[in] dev : Structure instance of bme280_dev.
  219. *
  220. * @return Result of API execution status
  221. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  222. */
  223. static int8_t set_osr_settings(uint8_t desired_settings,
  224. const struct bme280_settings *settings,
  225. const struct bme280_dev *dev);
  226. /*!
  227. * @brief This API sets the pressure and/or temperature oversampling settings
  228. * in the sensor according to the settings selected by the user.
  229. *
  230. * @param[in] dev : Structure instance of bme280_dev.
  231. * @param[in] desired_settings: variable to select the pressure and/or
  232. * temperature oversampling settings.
  233. *
  234. * @return Result of API execution status
  235. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  236. */
  237. static int8_t set_osr_press_temp_settings(uint8_t desired_settings,
  238. const struct bme280_settings *settings,
  239. const struct bme280_dev *dev);
  240. /*!
  241. * @brief This internal API fills the pressure oversampling settings provided by
  242. * the user in the data buffer so as to write in the sensor.
  243. *
  244. * @param[in] dev : Structure instance of bme280_dev.
  245. * @param[out] reg_data : Variable which is filled according to the pressure
  246. * oversampling data provided by the user.
  247. */
  248. static void fill_osr_press_settings(uint8_t *reg_data, const struct bme280_settings *settings);
  249. /*!
  250. * @brief This internal API fills the temperature oversampling settings provided
  251. * by the user in the data buffer so as to write in the sensor.
  252. *
  253. * @param[in] dev : Structure instance of bme280_dev.
  254. * @param[out] reg_data : Variable which is filled according to the temperature
  255. * oversampling data provided by the user.
  256. */
  257. static void fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settings *settings);
  258. /*!
  259. * @brief This internal API sets the filter and/or standby duration settings
  260. * in the sensor according to the settings selected by the user.
  261. *
  262. * @param[in] dev : Structure instance of bme280_dev.
  263. * @param[in] desired_settings : variable to select the filter and/or
  264. * standby duration settings.
  265. *
  266. * @return Result of API execution status
  267. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  268. */
  269. static int8_t set_filter_standby_settings(uint8_t desired_settings,
  270. const struct bme280_settings *settings,
  271. const struct bme280_dev *dev);
  272. /*!
  273. * @brief This internal API fills the filter settings provided by the user
  274. * in the data buffer so as to write in the sensor.
  275. *
  276. * @param[in] dev : Structure instance of bme280_dev.
  277. * @param[out] reg_data : Variable which is filled according to the filter
  278. * settings data provided by the user.
  279. */
  280. static void fill_filter_settings(uint8_t *reg_data, const struct bme280_settings *settings);
  281. /*!
  282. * @brief This internal API fills the standby duration settings provided by the
  283. * user in the data buffer so as to write in the sensor.
  284. *
  285. * @param[in] dev : Structure instance of bme280_dev.
  286. * @param[out] reg_data : Variable which is filled according to the standby
  287. * settings data provided by the user.
  288. */
  289. static void fill_standby_settings(uint8_t *reg_data, const struct bme280_settings *settings);
  290. /*!
  291. * @brief This internal API parse the oversampling(pressure, temperature
  292. * and humidity), filter and standby duration settings and store in the
  293. * device structure.
  294. *
  295. * @param[out] dev : Structure instance of bme280_dev.
  296. * @param[in] reg_data : Register data to be parsed.
  297. */
  298. static void parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings);
  299. /*!
  300. * @brief This internal API reloads the already existing device settings in the
  301. * sensor after soft reset.
  302. *
  303. * @param[in] dev : Structure instance of bme280_dev.
  304. * @param[in] settings : Pointer variable which contains the settings to
  305. * be set in the sensor.
  306. *
  307. * @return Result of API execution status
  308. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  309. */
  310. static int8_t reload_device_settings(const struct bme280_settings *settings, const struct bme280_dev *dev);
  311. /****************** Global Function Definitions *******************************/
  312. /*!
  313. * @brief This API is the entry point.
  314. * It reads the chip-id and calibration data from the sensor.
  315. */
  316. int8_t bme280_init(struct bme280_dev *dev)
  317. {
  318. int8_t rslt;
  319. /* chip id read try count */
  320. uint8_t try_count = 5;
  321. uint8_t chip_id = 0;
  322. /* Check for null pointer in the device structure*/
  323. rslt = null_ptr_check(dev);
  324. /* Proceed if null check is fine */
  325. if (rslt == BME280_OK)
  326. {
  327. while (try_count)
  328. {
  329. /* Read the chip-id of bme280 sensor */
  330. rslt = bme280_get_regs(BME280_CHIP_ID_ADDR, &chip_id, 1, dev);
  331. /* Check for chip id validity */
  332. if ((rslt == BME280_OK) && (chip_id == BME280_CHIP_ID))
  333. {
  334. dev->chip_id = chip_id;
  335. /* Reset the sensor */
  336. rslt = bme280_soft_reset(dev);
  337. if (rslt == BME280_OK)
  338. {
  339. /* Read the calibration data */
  340. rslt = get_calib_data(dev);
  341. }
  342. break;
  343. }
  344. /* Wait for 1 ms */
  345. dev->delay_ms(1);
  346. --try_count;
  347. }
  348. /* Chip id check failed */
  349. if (!try_count)
  350. {
  351. rslt = BME280_E_DEV_NOT_FOUND;
  352. }
  353. }
  354. return rslt;
  355. }
  356. /*!
  357. * @brief This API reads the data from the given register address of the sensor.
  358. */
  359. int8_t bme280_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct bme280_dev *dev)
  360. {
  361. int8_t rslt;
  362. /* Check for null pointer in the device structure*/
  363. rslt = null_ptr_check(dev);
  364. /* Proceed if null check is fine */
  365. if (rslt == BME280_OK)
  366. {
  367. /* If interface selected is SPI */
  368. if (dev->intf != BME280_I2C_INTF)
  369. {
  370. reg_addr = reg_addr | 0x80;
  371. }
  372. /* Read the data */
  373. rslt = dev->read(dev->dev_id, reg_addr, reg_data, len);
  374. /* Check for communication error */
  375. if (rslt != BME280_OK)
  376. {
  377. rslt = BME280_E_COMM_FAIL;
  378. }
  379. }
  380. return rslt;
  381. }
  382. /*!
  383. * @brief This API writes the given data to the register address
  384. * of the sensor.
  385. */
  386. int8_t bme280_set_regs(uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len, const struct bme280_dev *dev)
  387. {
  388. int8_t rslt;
  389. uint8_t temp_buff[20]; /* Typically not to write more than 10 registers */
  390. if (len > 10)
  391. {
  392. len = 10;
  393. }
  394. uint16_t temp_len;
  395. uint8_t reg_addr_cnt;
  396. /* Check for null pointer in the device structure*/
  397. rslt = null_ptr_check(dev);
  398. /* Check for arguments validity */
  399. if ((rslt == BME280_OK) && (reg_addr != NULL) && (reg_data != NULL))
  400. {
  401. if (len != 0)
  402. {
  403. temp_buff[0] = reg_data[0];
  404. /* If interface selected is SPI */
  405. if (dev->intf != BME280_I2C_INTF)
  406. {
  407. for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++)
  408. {
  409. reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & 0x7F;
  410. }
  411. }
  412. /* Burst write mode */
  413. if (len > 1)
  414. {
  415. /* Interleave register address w.r.t data for
  416. * burst write
  417. */
  418. interleave_reg_addr(reg_addr, temp_buff, reg_data, len);
  419. temp_len = ((len * 2) - 1);
  420. }
  421. else
  422. {
  423. temp_len = len;
  424. }
  425. rslt = dev->write(dev->dev_id, reg_addr[0], temp_buff, temp_len);
  426. /* Check for communication error */
  427. if (rslt != BME280_OK)
  428. {
  429. rslt = BME280_E_COMM_FAIL;
  430. }
  431. }
  432. else
  433. {
  434. rslt = BME280_E_INVALID_LEN;
  435. }
  436. }
  437. else
  438. {
  439. rslt = BME280_E_NULL_PTR;
  440. }
  441. return rslt;
  442. }
  443. /*!
  444. * @brief This API sets the oversampling, filter and standby duration
  445. * (normal mode) settings in the sensor.
  446. */
  447. int8_t bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev)
  448. {
  449. int8_t rslt;
  450. uint8_t sensor_mode;
  451. /* Check for null pointer in the device structure*/
  452. rslt = null_ptr_check(dev);
  453. /* Proceed if null check is fine */
  454. if (rslt == BME280_OK)
  455. {
  456. rslt = bme280_get_sensor_mode(&sensor_mode, dev);
  457. if ((rslt == BME280_OK) && (sensor_mode != BME280_SLEEP_MODE))
  458. {
  459. rslt = put_device_to_sleep(dev);
  460. }
  461. if (rslt == BME280_OK)
  462. {
  463. /* Check if user wants to change oversampling
  464. * settings
  465. */
  466. if (are_settings_changed(OVERSAMPLING_SETTINGS, desired_settings))
  467. {
  468. rslt = set_osr_settings(desired_settings, &dev->settings, dev);
  469. }
  470. /* Check if user wants to change filter and/or
  471. * standby settings
  472. */
  473. if ((rslt == BME280_OK) && are_settings_changed(FILTER_STANDBY_SETTINGS, desired_settings))
  474. {
  475. rslt = set_filter_standby_settings(desired_settings, &dev->settings, dev);
  476. }
  477. }
  478. }
  479. return rslt;
  480. }
  481. /*!
  482. * @brief This API gets the oversampling, filter and standby duration
  483. * (normal mode) settings from the sensor.
  484. */
  485. int8_t bme280_get_sensor_settings(struct bme280_dev *dev)
  486. {
  487. int8_t rslt;
  488. uint8_t reg_data[4];
  489. /* Check for null pointer in the device structure*/
  490. rslt = null_ptr_check(dev);
  491. /* Proceed if null check is fine */
  492. if (rslt == BME280_OK)
  493. {
  494. rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev);
  495. if (rslt == BME280_OK)
  496. {
  497. parse_device_settings(reg_data, &dev->settings);
  498. }
  499. }
  500. return rslt;
  501. }
  502. /*!
  503. * @brief This API sets the power mode of the sensor.
  504. */
  505. int8_t bme280_set_sensor_mode(uint8_t sensor_mode, const struct bme280_dev *dev)
  506. {
  507. int8_t rslt;
  508. uint8_t last_set_mode;
  509. /* Check for null pointer in the device structure*/
  510. rslt = null_ptr_check(dev);
  511. if (rslt == BME280_OK)
  512. {
  513. rslt = bme280_get_sensor_mode(&last_set_mode, dev);
  514. /* If the sensor is not in sleep mode put the device to sleep
  515. * mode
  516. */
  517. if ((rslt == BME280_OK) && (last_set_mode != BME280_SLEEP_MODE))
  518. {
  519. rslt = put_device_to_sleep(dev);
  520. }
  521. /* Set the power mode */
  522. if (rslt == BME280_OK)
  523. {
  524. rslt = write_power_mode(sensor_mode, dev);
  525. }
  526. }
  527. return rslt;
  528. }
  529. /*!
  530. * @brief This API gets the power mode of the sensor.
  531. */
  532. int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev)
  533. {
  534. int8_t rslt;
  535. /* Check for null pointer in the device structure*/
  536. rslt = null_ptr_check(dev);
  537. if (rslt == BME280_OK)
  538. {
  539. /* Read the power mode register */
  540. rslt = bme280_get_regs(BME280_PWR_CTRL_ADDR, sensor_mode, 1, dev);
  541. /* Assign the power mode in the device structure */
  542. *sensor_mode = BME280_GET_BITS_POS_0(*sensor_mode, BME280_SENSOR_MODE);
  543. }
  544. return rslt;
  545. }
  546. /*!
  547. * @brief This API performs the soft reset of the sensor.
  548. */
  549. int8_t bme280_soft_reset(const struct bme280_dev *dev)
  550. {
  551. int8_t rslt;
  552. uint8_t reg_addr = BME280_RESET_ADDR;
  553. uint8_t status_reg = 0;
  554. uint8_t try_run = 5;
  555. /* 0xB6 is the soft reset command */
  556. uint8_t soft_rst_cmd = BME280_SOFT_RESET_COMMAND;
  557. /* Check for null pointer in the device structure*/
  558. rslt = null_ptr_check(dev);
  559. /* Proceed if null check is fine */
  560. if (rslt == BME280_OK)
  561. {
  562. /* Write the soft reset command in the sensor */
  563. rslt = bme280_set_regs(&reg_addr, &soft_rst_cmd, 1, dev);
  564. if (rslt == BME280_OK)
  565. {
  566. /* If NVM not copied yet, Wait for NVM to copy */
  567. do
  568. {
  569. /* As per data sheet - Table 1, startup time is 2 ms. */
  570. dev->delay_ms(2);
  571. rslt = bme280_get_regs(BME280_STATUS_REG_ADDR, &status_reg, 1, dev);
  572. } while ((rslt == BME280_OK) && (try_run--) && (status_reg & BME280_STATUS_IM_UPDATE));
  573. if (status_reg & BME280_STATUS_IM_UPDATE)
  574. {
  575. rslt = BME280_E_NVM_COPY_FAILED;
  576. }
  577. }
  578. }
  579. return rslt;
  580. }
  581. /*!
  582. * @brief This API reads the pressure, temperature and humidity data from the
  583. * sensor, compensates the data and store it in the bme280_data structure
  584. * instance passed by the user.
  585. */
  586. int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev)
  587. {
  588. int8_t rslt;
  589. /* Array to store the pressure, temperature and humidity data read from
  590. * the sensor
  591. */
  592. uint8_t reg_data[BME280_P_T_H_DATA_LEN] = { 0 };
  593. struct bme280_uncomp_data uncomp_data = { 0 };
  594. /* Check for null pointer in the device structure*/
  595. rslt = null_ptr_check(dev);
  596. if ((rslt == BME280_OK) && (comp_data != NULL))
  597. {
  598. /* Read the pressure and temperature data from the sensor */
  599. rslt = bme280_get_regs(BME280_DATA_ADDR, reg_data, BME280_P_T_H_DATA_LEN, dev);
  600. if (rslt == BME280_OK)
  601. {
  602. /* Parse the read data from the sensor */
  603. bme280_parse_sensor_data(reg_data, &uncomp_data);
  604. /* Compensate the pressure and/or temperature and/or
  605. * humidity data from the sensor
  606. */
  607. rslt = bme280_compensate_data(sensor_comp, &uncomp_data, comp_data, &dev->calib_data);
  608. }
  609. }
  610. else
  611. {
  612. rslt = BME280_E_NULL_PTR;
  613. }
  614. return rslt;
  615. }
  616. /*!
  617. * @brief This API is used to parse the pressure, temperature and
  618. * humidity data and store it in the bme280_uncomp_data structure instance.
  619. */
  620. void bme280_parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data)
  621. {
  622. /* Variables to store the sensor data */
  623. uint32_t data_xlsb;
  624. uint32_t data_lsb;
  625. uint32_t data_msb;
  626. /* Store the parsed register values for pressure data */
  627. data_msb = (uint32_t)reg_data[0] << 12;
  628. data_lsb = (uint32_t)reg_data[1] << 4;
  629. data_xlsb = (uint32_t)reg_data[2] >> 4;
  630. uncomp_data->pressure = data_msb | data_lsb | data_xlsb;
  631. /* Store the parsed register values for temperature data */
  632. data_msb = (uint32_t)reg_data[3] << 12;
  633. data_lsb = (uint32_t)reg_data[4] << 4;
  634. data_xlsb = (uint32_t)reg_data[5] >> 4;
  635. uncomp_data->temperature = data_msb | data_lsb | data_xlsb;
  636. /* Store the parsed register values for humidity data */
  637. data_msb = (uint32_t)reg_data[6] << 8;
  638. data_lsb = (uint32_t)reg_data[7];
  639. uncomp_data->humidity = data_msb | data_lsb;
  640. }
  641. /*!
  642. * @brief This API is used to compensate the pressure and/or
  643. * temperature and/or humidity data according to the component selected
  644. * by the user.
  645. */
  646. int8_t bme280_compensate_data(uint8_t sensor_comp,
  647. const struct bme280_uncomp_data *uncomp_data,
  648. struct bme280_data *comp_data,
  649. struct bme280_calib_data *calib_data)
  650. {
  651. int8_t rslt = BME280_OK;
  652. if ((uncomp_data != NULL) && (comp_data != NULL) && (calib_data != NULL))
  653. {
  654. /* Initialize to zero */
  655. comp_data->temperature = 0;
  656. comp_data->pressure = 0;
  657. comp_data->humidity = 0;
  658. /* If pressure or temperature component is selected */
  659. if (sensor_comp & (BME280_PRESS | BME280_TEMP | BME280_HUM))
  660. {
  661. /* Compensate the temperature data */
  662. comp_data->temperature = compensate_temperature(uncomp_data, calib_data);
  663. }
  664. if (sensor_comp & BME280_PRESS)
  665. {
  666. /* Compensate the pressure data */
  667. comp_data->pressure = compensate_pressure(uncomp_data, calib_data);
  668. }
  669. if (sensor_comp & BME280_HUM)
  670. {
  671. /* Compensate the humidity data */
  672. comp_data->humidity = compensate_humidity(uncomp_data, calib_data);
  673. }
  674. }
  675. else
  676. {
  677. rslt = BME280_E_NULL_PTR;
  678. }
  679. return rslt;
  680. }
  681. /*!
  682. * @brief This API is used to calculate the maximum delay in milliseconds required for the
  683. * temperature/pressure/humidity(which ever at enabled) measurement to complete.
  684. */
  685. uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings)
  686. {
  687. uint32_t max_delay;
  688. uint8_t temp_osr;
  689. uint8_t pres_osr;
  690. uint8_t hum_osr;
  691. /*Array to map OSR config register value to actual OSR */
  692. uint8_t osr_sett_to_act_osr[] = { 0, 1, 2, 4, 8, 16 };
  693. /* Mapping osr settings to the actual osr values e.g. 0b101 -> osr X16 */
  694. if (settings->osr_t <= 5)
  695. {
  696. temp_osr = osr_sett_to_act_osr[settings->osr_t];
  697. }
  698. else
  699. {
  700. temp_osr = 16;
  701. }
  702. if (settings->osr_p <= 5)
  703. {
  704. pres_osr = osr_sett_to_act_osr[settings->osr_p];
  705. }
  706. else
  707. {
  708. pres_osr = 16;
  709. }
  710. if (settings->osr_h <= 5)
  711. {
  712. hum_osr = osr_sett_to_act_osr[settings->osr_h];
  713. }
  714. else
  715. {
  716. hum_osr = 16;
  717. }
  718. max_delay =
  719. (uint32_t)((BME280_MEAS_OFFSET + (BME280_MEAS_DUR * temp_osr) +
  720. ((BME280_MEAS_DUR * pres_osr) + BME280_PRES_HUM_MEAS_OFFSET) +
  721. ((BME280_MEAS_DUR * hum_osr) + BME280_PRES_HUM_MEAS_OFFSET)) / BME280_MEAS_SCALING_FACTOR);
  722. return max_delay;
  723. }
  724. /*!
  725. * @brief This internal API sets the oversampling settings for pressure,
  726. * temperature and humidity in the sensor.
  727. */
  728. static int8_t set_osr_settings(uint8_t desired_settings,
  729. const struct bme280_settings *settings,
  730. const struct bme280_dev *dev)
  731. {
  732. int8_t rslt = BME280_W_INVALID_OSR_MACRO;
  733. if (desired_settings & BME280_OSR_HUM_SEL)
  734. {
  735. rslt = set_osr_humidity_settings(settings, dev);
  736. }
  737. if (desired_settings & (BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL))
  738. {
  739. rslt = set_osr_press_temp_settings(desired_settings, settings, dev);
  740. }
  741. return rslt;
  742. }
  743. /*!
  744. * @brief This API sets the humidity oversampling settings of the sensor.
  745. */
  746. static int8_t set_osr_humidity_settings(const struct bme280_settings *settings, const struct bme280_dev *dev)
  747. {
  748. int8_t rslt;
  749. uint8_t ctrl_hum;
  750. uint8_t ctrl_meas;
  751. uint8_t reg_addr = BME280_CTRL_HUM_ADDR;
  752. ctrl_hum = settings->osr_h & BME280_CTRL_HUM_MSK;
  753. /* Write the humidity control value in the register */
  754. rslt = bme280_set_regs(&reg_addr, &ctrl_hum, 1, dev);
  755. /* Humidity related changes will be only effective after a
  756. * write operation to ctrl_meas register
  757. */
  758. if (rslt == BME280_OK)
  759. {
  760. reg_addr = BME280_CTRL_MEAS_ADDR;
  761. rslt = bme280_get_regs(reg_addr, &ctrl_meas, 1, dev);
  762. if (rslt == BME280_OK)
  763. {
  764. rslt = bme280_set_regs(&reg_addr, &ctrl_meas, 1, dev);
  765. }
  766. }
  767. return rslt;
  768. }
  769. /*!
  770. * @brief This API sets the pressure and/or temperature oversampling settings
  771. * in the sensor according to the settings selected by the user.
  772. */
  773. static int8_t set_osr_press_temp_settings(uint8_t desired_settings,
  774. const struct bme280_settings *settings,
  775. const struct bme280_dev *dev)
  776. {
  777. int8_t rslt;
  778. uint8_t reg_addr = BME280_CTRL_MEAS_ADDR;
  779. uint8_t reg_data;
  780. rslt = bme280_get_regs(reg_addr, &reg_data, 1, dev);
  781. if (rslt == BME280_OK)
  782. {
  783. if (desired_settings & BME280_OSR_PRESS_SEL)
  784. {
  785. fill_osr_press_settings(&reg_data, settings);
  786. }
  787. if (desired_settings & BME280_OSR_TEMP_SEL)
  788. {
  789. fill_osr_temp_settings(&reg_data, settings);
  790. }
  791. /* Write the oversampling settings in the register */
  792. rslt = bme280_set_regs(&reg_addr, &reg_data, 1, dev);
  793. }
  794. return rslt;
  795. }
  796. /*!
  797. * @brief This internal API sets the filter and/or standby duration settings
  798. * in the sensor according to the settings selected by the user.
  799. */
  800. static int8_t set_filter_standby_settings(uint8_t desired_settings,
  801. const struct bme280_settings *settings,
  802. const struct bme280_dev *dev)
  803. {
  804. int8_t rslt;
  805. uint8_t reg_addr = BME280_CONFIG_ADDR;
  806. uint8_t reg_data;
  807. rslt = bme280_get_regs(reg_addr, &reg_data, 1, dev);
  808. if (rslt == BME280_OK)
  809. {
  810. if (desired_settings & BME280_FILTER_SEL)
  811. {
  812. fill_filter_settings(&reg_data, settings);
  813. }
  814. if (desired_settings & BME280_STANDBY_SEL)
  815. {
  816. fill_standby_settings(&reg_data, settings);
  817. }
  818. /* Write the oversampling settings in the register */
  819. rslt = bme280_set_regs(&reg_addr, &reg_data, 1, dev);
  820. }
  821. return rslt;
  822. }
  823. /*!
  824. * @brief This internal API fills the filter settings provided by the user
  825. * in the data buffer so as to write in the sensor.
  826. */
  827. static void fill_filter_settings(uint8_t *reg_data, const struct bme280_settings *settings)
  828. {
  829. *reg_data = BME280_SET_BITS(*reg_data, BME280_FILTER, settings->filter);
  830. }
  831. /*!
  832. * @brief This internal API fills the standby duration settings provided by
  833. * the user in the data buffer so as to write in the sensor.
  834. */
  835. static void fill_standby_settings(uint8_t *reg_data, const struct bme280_settings *settings)
  836. {
  837. *reg_data = BME280_SET_BITS(*reg_data, BME280_STANDBY, settings->standby_time);
  838. }
  839. /*!
  840. * @brief This internal API fills the pressure oversampling settings provided by
  841. * the user in the data buffer so as to write in the sensor.
  842. */
  843. static void fill_osr_press_settings(uint8_t *reg_data, const struct bme280_settings *settings)
  844. {
  845. *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_PRESS, settings->osr_p);
  846. }
  847. /*!
  848. * @brief This internal API fills the temperature oversampling settings
  849. * provided by the user in the data buffer so as to write in the sensor.
  850. */
  851. static void fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settings *settings)
  852. {
  853. *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_TEMP, settings->osr_t);
  854. }
  855. /*!
  856. * @brief This internal API parse the oversampling(pressure, temperature
  857. * and humidity), filter and standby duration settings and store in the
  858. * device structure.
  859. */
  860. static void parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings)
  861. {
  862. settings->osr_h = BME280_GET_BITS_POS_0(reg_data[0], BME280_CTRL_HUM);
  863. settings->osr_p = BME280_GET_BITS(reg_data[2], BME280_CTRL_PRESS);
  864. settings->osr_t = BME280_GET_BITS(reg_data[2], BME280_CTRL_TEMP);
  865. settings->filter = BME280_GET_BITS(reg_data[3], BME280_FILTER);
  866. settings->standby_time = BME280_GET_BITS(reg_data[3], BME280_STANDBY);
  867. }
  868. /*!
  869. * @brief This internal API writes the power mode in the sensor.
  870. */
  871. static int8_t write_power_mode(uint8_t sensor_mode, const struct bme280_dev *dev)
  872. {
  873. int8_t rslt;
  874. uint8_t reg_addr = BME280_PWR_CTRL_ADDR;
  875. /* Variable to store the value read from power mode register */
  876. uint8_t sensor_mode_reg_val;
  877. /* Read the power mode register */
  878. rslt = bme280_get_regs(reg_addr, &sensor_mode_reg_val, 1, dev);
  879. /* Set the power mode */
  880. if (rslt == BME280_OK)
  881. {
  882. sensor_mode_reg_val = BME280_SET_BITS_POS_0(sensor_mode_reg_val, BME280_SENSOR_MODE, sensor_mode);
  883. /* Write the power mode in the register */
  884. rslt = bme280_set_regs(&reg_addr, &sensor_mode_reg_val, 1, dev);
  885. }
  886. return rslt;
  887. }
  888. /*!
  889. * @brief This internal API puts the device to sleep mode.
  890. */
  891. static int8_t put_device_to_sleep(const struct bme280_dev *dev)
  892. {
  893. int8_t rslt;
  894. uint8_t reg_data[4];
  895. struct bme280_settings settings;
  896. rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev);
  897. if (rslt == BME280_OK)
  898. {
  899. parse_device_settings(reg_data, &settings);
  900. rslt = bme280_soft_reset(dev);
  901. if (rslt == BME280_OK)
  902. {
  903. rslt = reload_device_settings(&settings, dev);
  904. }
  905. }
  906. return rslt;
  907. }
  908. /*!
  909. * @brief This internal API reloads the already existing device settings in
  910. * the sensor after soft reset.
  911. */
  912. static int8_t reload_device_settings(const struct bme280_settings *settings, const struct bme280_dev *dev)
  913. {
  914. int8_t rslt;
  915. rslt = set_osr_settings(BME280_ALL_SETTINGS_SEL, settings, dev);
  916. if (rslt == BME280_OK)
  917. {
  918. rslt = set_filter_standby_settings(BME280_ALL_SETTINGS_SEL, settings, dev);
  919. }
  920. return rslt;
  921. }
  922. #ifdef BME280_FLOAT_ENABLE
  923. /*!
  924. * @brief This internal API is used to compensate the raw temperature data and
  925. * return the compensated temperature data in double data type.
  926. */
  927. static double compensate_temperature(const struct bme280_uncomp_data *uncomp_data, struct bme280_calib_data *calib_data)
  928. {
  929. double var1;
  930. double var2;
  931. double temperature;
  932. double temperature_min = -40;
  933. double temperature_max = 85;
  934. var1 = ((double)uncomp_data->temperature) / 16384.0 - ((double)calib_data->dig_t1) / 1024.0;
  935. var1 = var1 * ((double)calib_data->dig_t2);
  936. var2 = (((double)uncomp_data->temperature) / 131072.0 - ((double)calib_data->dig_t1) / 8192.0);
  937. var2 = (var2 * var2) * ((double)calib_data->dig_t3);
  938. calib_data->t_fine = (int32_t)(var1 + var2);
  939. temperature = (var1 + var2) / 5120.0;
  940. if (temperature < temperature_min)
  941. {
  942. temperature = temperature_min;
  943. }
  944. else if (temperature > temperature_max)
  945. {
  946. temperature = temperature_max;
  947. }
  948. return temperature;
  949. }
  950. /*!
  951. * @brief This internal API is used to compensate the raw pressure data and
  952. * return the compensated pressure data in double data type.
  953. */
  954. static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
  955. const struct bme280_calib_data *calib_data)
  956. {
  957. double var1;
  958. double var2;
  959. double var3;
  960. double pressure;
  961. double pressure_min = 30000.0;
  962. double pressure_max = 110000.0;
  963. var1 = ((double)calib_data->t_fine / 2.0) - 64000.0;
  964. var2 = var1 * var1 * ((double)calib_data->dig_p6) / 32768.0;
  965. var2 = var2 + var1 * ((double)calib_data->dig_p5) * 2.0;
  966. var2 = (var2 / 4.0) + (((double)calib_data->dig_p4) * 65536.0);
  967. var3 = ((double)calib_data->dig_p3) * var1 * var1 / 524288.0;
  968. var1 = (var3 + ((double)calib_data->dig_p2) * var1) / 524288.0;
  969. var1 = (1.0 + var1 / 32768.0) * ((double)calib_data->dig_p1);
  970. /* avoid exception caused by division by zero */
  971. if (var1 > (0.0))
  972. {
  973. pressure = 1048576.0 - (double) uncomp_data->pressure;
  974. pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;
  975. var1 = ((double)calib_data->dig_p9) * pressure * pressure / 2147483648.0;
  976. var2 = pressure * ((double)calib_data->dig_p8) / 32768.0;
  977. pressure = pressure + (var1 + var2 + ((double)calib_data->dig_p7)) / 16.0;
  978. if (pressure < pressure_min)
  979. {
  980. pressure = pressure_min;
  981. }
  982. else if (pressure > pressure_max)
  983. {
  984. pressure = pressure_max;
  985. }
  986. }
  987. else /* Invalid case */
  988. {
  989. pressure = pressure_min;
  990. }
  991. return pressure;
  992. }
  993. /*!
  994. * @brief This internal API is used to compensate the raw humidity data and
  995. * return the compensated humidity data in double data type.
  996. */
  997. static double compensate_humidity(const struct bme280_uncomp_data *uncomp_data,
  998. const struct bme280_calib_data *calib_data)
  999. {
  1000. double humidity;
  1001. double humidity_min = 0.0;
  1002. double humidity_max = 100.0;
  1003. double var1;
  1004. double var2;
  1005. double var3;
  1006. double var4;
  1007. double var5;
  1008. double var6;
  1009. var1 = ((double)calib_data->t_fine) - 76800.0;
  1010. var2 = (((double)calib_data->dig_h4) * 64.0 + (((double)calib_data->dig_h5) / 16384.0) * var1);
  1011. var3 = uncomp_data->humidity - var2;
  1012. var4 = ((double)calib_data->dig_h2) / 65536.0;
  1013. var5 = (1.0 + (((double)calib_data->dig_h3) / 67108864.0) * var1);
  1014. var6 = 1.0 + (((double)calib_data->dig_h6) / 67108864.0) * var1 * var5;
  1015. var6 = var3 * var4 * (var5 * var6);
  1016. humidity = var6 * (1.0 - ((double)calib_data->dig_h1) * var6 / 524288.0);
  1017. if (humidity > humidity_max)
  1018. {
  1019. humidity = humidity_max;
  1020. }
  1021. else if (humidity < humidity_min)
  1022. {
  1023. humidity = humidity_min;
  1024. }
  1025. return humidity;
  1026. }
  1027. #else
  1028. /*!
  1029. * @brief This internal API is used to compensate the raw temperature data and
  1030. * return the compensated temperature data in integer data type.
  1031. */
  1032. static int32_t compensate_temperature(const struct bme280_uncomp_data *uncomp_data,
  1033. struct bme280_calib_data *calib_data)
  1034. {
  1035. int32_t var1;
  1036. int32_t var2;
  1037. int32_t temperature;
  1038. int32_t temperature_min = -4000;
  1039. int32_t temperature_max = 8500;
  1040. var1 = (int32_t)((uncomp_data->temperature / 8) - ((int32_t)calib_data->dig_t1 * 2));
  1041. var1 = (var1 * ((int32_t)calib_data->dig_t2)) / 2048;
  1042. var2 = (int32_t)((uncomp_data->temperature / 16) - ((int32_t)calib_data->dig_t1));
  1043. var2 = (((var2 * var2) / 4096) * ((int32_t)calib_data->dig_t3)) / 16384;
  1044. calib_data->t_fine = var1 + var2;
  1045. temperature = (calib_data->t_fine * 5 + 128) / 256;
  1046. if (temperature < temperature_min)
  1047. {
  1048. temperature = temperature_min;
  1049. }
  1050. else if (temperature > temperature_max)
  1051. {
  1052. temperature = temperature_max;
  1053. }
  1054. return temperature;
  1055. }
  1056. #ifdef BME280_64BIT_ENABLE
  1057. /*!
  1058. * @brief This internal API is used to compensate the raw pressure data and
  1059. * return the compensated pressure data in integer data type with higher
  1060. * accuracy.
  1061. */
  1062. static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
  1063. const struct bme280_calib_data *calib_data)
  1064. {
  1065. int64_t var1;
  1066. int64_t var2;
  1067. int64_t var3;
  1068. int64_t var4;
  1069. uint32_t pressure;
  1070. uint32_t pressure_min = 3000000;
  1071. uint32_t pressure_max = 11000000;
  1072. var1 = ((int64_t)calib_data->t_fine) - 128000;
  1073. var2 = var1 * var1 * (int64_t)calib_data->dig_p6;
  1074. var2 = var2 + ((var1 * (int64_t)calib_data->dig_p5) * 131072);
  1075. var2 = var2 + (((int64_t)calib_data->dig_p4) * 34359738368);
  1076. var1 = ((var1 * var1 * (int64_t)calib_data->dig_p3) / 256) + ((var1 * ((int64_t)calib_data->dig_p2) * 4096));
  1077. var3 = ((int64_t)1) * 140737488355328;
  1078. var1 = (var3 + var1) * ((int64_t)calib_data->dig_p1) / 8589934592;
  1079. /* To avoid divide by zero exception */
  1080. if (var1 != 0)
  1081. {
  1082. var4 = 1048576 - uncomp_data->pressure;
  1083. var4 = (((var4 * INT64_C(2147483648)) - var2) * 3125) / var1;
  1084. var1 = (((int64_t)calib_data->dig_p9) * (var4 / 8192) * (var4 / 8192)) / 33554432;
  1085. var2 = (((int64_t)calib_data->dig_p8) * var4) / 524288;
  1086. var4 = ((var4 + var1 + var2) / 256) + (((int64_t)calib_data->dig_p7) * 16);
  1087. pressure = (uint32_t)(((var4 / 2) * 100) / 128);
  1088. if (pressure < pressure_min)
  1089. {
  1090. pressure = pressure_min;
  1091. }
  1092. else if (pressure > pressure_max)
  1093. {
  1094. pressure = pressure_max;
  1095. }
  1096. }
  1097. else
  1098. {
  1099. pressure = pressure_min;
  1100. }
  1101. return pressure;
  1102. }
  1103. #else
  1104. /*!
  1105. * @brief This internal API is used to compensate the raw pressure data and
  1106. * return the compensated pressure data in integer data type.
  1107. */
  1108. static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
  1109. const struct bme280_calib_data *calib_data)
  1110. {
  1111. int32_t var1;
  1112. int32_t var2;
  1113. int32_t var3;
  1114. int32_t var4;
  1115. uint32_t var5;
  1116. uint32_t pressure;
  1117. uint32_t pressure_min = 30000;
  1118. uint32_t pressure_max = 110000;
  1119. var1 = (((int32_t)calib_data->t_fine) / 2) - (int32_t)64000;
  1120. var2 = (((var1 / 4) * (var1 / 4)) / 2048) * ((int32_t)calib_data->dig_p6);
  1121. var2 = var2 + ((var1 * ((int32_t)calib_data->dig_p5)) * 2);
  1122. var2 = (var2 / 4) + (((int32_t)calib_data->dig_p4) * 65536);
  1123. var3 = (calib_data->dig_p3 * (((var1 / 4) * (var1 / 4)) / 8192)) / 8;
  1124. var4 = (((int32_t)calib_data->dig_p2) * var1) / 2;
  1125. var1 = (var3 + var4) / 262144;
  1126. var1 = (((32768 + var1)) * ((int32_t)calib_data->dig_p1)) / 32768;
  1127. /* avoid exception caused by division by zero */
  1128. if (var1)
  1129. {
  1130. var5 = (uint32_t)((uint32_t)1048576) - uncomp_data->pressure;
  1131. pressure = ((uint32_t)(var5 - (uint32_t)(var2 / 4096))) * 3125;
  1132. if (pressure < 0x80000000)
  1133. {
  1134. pressure = (pressure << 1) / ((uint32_t)var1);
  1135. }
  1136. else
  1137. {
  1138. pressure = (pressure / (uint32_t)var1) * 2;
  1139. }
  1140. var1 = (((int32_t)calib_data->dig_p9) * ((int32_t)(((pressure / 8) * (pressure / 8)) / 8192))) / 4096;
  1141. var2 = (((int32_t)(pressure / 4)) * ((int32_t)calib_data->dig_p8)) / 8192;
  1142. pressure = (uint32_t)((int32_t)pressure + ((var1 + var2 + calib_data->dig_p7) / 16));
  1143. if (pressure < pressure_min)
  1144. {
  1145. pressure = pressure_min;
  1146. }
  1147. else if (pressure > pressure_max)
  1148. {
  1149. pressure = pressure_max;
  1150. }
  1151. }
  1152. else
  1153. {
  1154. pressure = pressure_min;
  1155. }
  1156. return pressure;
  1157. }
  1158. #endif
  1159. /*!
  1160. * @brief This internal API is used to compensate the raw humidity data and
  1161. * return the compensated humidity data in integer data type.
  1162. */
  1163. static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data,
  1164. const struct bme280_calib_data *calib_data)
  1165. {
  1166. int32_t var1;
  1167. int32_t var2;
  1168. int32_t var3;
  1169. int32_t var4;
  1170. int32_t var5;
  1171. uint32_t humidity;
  1172. uint32_t humidity_max = 102400;
  1173. var1 = calib_data->t_fine - ((int32_t)76800);
  1174. var2 = (int32_t)(uncomp_data->humidity * 16384);
  1175. var3 = (int32_t)(((int32_t)calib_data->dig_h4) * 1048576);
  1176. var4 = ((int32_t)calib_data->dig_h5) * var1;
  1177. var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768;
  1178. var2 = (var1 * ((int32_t)calib_data->dig_h6)) / 1024;
  1179. var3 = (var1 * ((int32_t)calib_data->dig_h3)) / 2048;
  1180. var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152;
  1181. var2 = ((var4 * ((int32_t)calib_data->dig_h2)) + 8192) / 16384;
  1182. var3 = var5 * var2;
  1183. var4 = ((var3 / 32768) * (var3 / 32768)) / 128;
  1184. var5 = var3 - ((var4 * ((int32_t)calib_data->dig_h1)) / 16);
  1185. var5 = (var5 < 0 ? 0 : var5);
  1186. var5 = (var5 > 419430400 ? 419430400 : var5);
  1187. humidity = (uint32_t)(var5 / 4096);
  1188. if (humidity > humidity_max)
  1189. {
  1190. humidity = humidity_max;
  1191. }
  1192. return humidity;
  1193. }
  1194. #endif
  1195. /*!
  1196. * @brief This internal API reads the calibration data from the sensor, parse
  1197. * it and store in the device structure.
  1198. */
  1199. static int8_t get_calib_data(struct bme280_dev *dev)
  1200. {
  1201. int8_t rslt;
  1202. uint8_t reg_addr = BME280_TEMP_PRESS_CALIB_DATA_ADDR;
  1203. /* Array to store calibration data */
  1204. uint8_t calib_data[BME280_TEMP_PRESS_CALIB_DATA_LEN] = { 0 };
  1205. /* Read the calibration data from the sensor */
  1206. rslt = bme280_get_regs(reg_addr, calib_data, BME280_TEMP_PRESS_CALIB_DATA_LEN, dev);
  1207. if (rslt == BME280_OK)
  1208. {
  1209. /* Parse temperature and pressure calibration data and store
  1210. * it in device structure
  1211. */
  1212. parse_temp_press_calib_data(calib_data, dev);
  1213. reg_addr = BME280_HUMIDITY_CALIB_DATA_ADDR;
  1214. /* Read the humidity calibration data from the sensor */
  1215. rslt = bme280_get_regs(reg_addr, calib_data, BME280_HUMIDITY_CALIB_DATA_LEN, dev);
  1216. if (rslt == BME280_OK)
  1217. {
  1218. /* Parse humidity calibration data and store it in
  1219. * device structure
  1220. */
  1221. parse_humidity_calib_data(calib_data, dev);
  1222. }
  1223. }
  1224. return rslt;
  1225. }
  1226. /*!
  1227. * @brief This internal API interleaves the register address between the
  1228. * register data buffer for burst write operation.
  1229. */
  1230. static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len)
  1231. {
  1232. uint8_t index;
  1233. for (index = 1; index < len; index++)
  1234. {
  1235. temp_buff[(index * 2) - 1] = reg_addr[index];
  1236. temp_buff[index * 2] = reg_data[index];
  1237. }
  1238. }
  1239. /*!
  1240. * @brief This internal API is used to parse the temperature and
  1241. * pressure calibration data and store it in device structure.
  1242. */
  1243. static void parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_dev *dev)
  1244. {
  1245. struct bme280_calib_data *calib_data = &dev->calib_data;
  1246. calib_data->dig_t1 = BME280_CONCAT_BYTES(reg_data[1], reg_data[0]);
  1247. calib_data->dig_t2 = (int16_t)BME280_CONCAT_BYTES(reg_data[3], reg_data[2]);
  1248. calib_data->dig_t3 = (int16_t)BME280_CONCAT_BYTES(reg_data[5], reg_data[4]);
  1249. calib_data->dig_p1 = BME280_CONCAT_BYTES(reg_data[7], reg_data[6]);
  1250. calib_data->dig_p2 = (int16_t)BME280_CONCAT_BYTES(reg_data[9], reg_data[8]);
  1251. calib_data->dig_p3 = (int16_t)BME280_CONCAT_BYTES(reg_data[11], reg_data[10]);
  1252. calib_data->dig_p4 = (int16_t)BME280_CONCAT_BYTES(reg_data[13], reg_data[12]);
  1253. calib_data->dig_p5 = (int16_t)BME280_CONCAT_BYTES(reg_data[15], reg_data[14]);
  1254. calib_data->dig_p6 = (int16_t)BME280_CONCAT_BYTES(reg_data[17], reg_data[16]);
  1255. calib_data->dig_p7 = (int16_t)BME280_CONCAT_BYTES(reg_data[19], reg_data[18]);
  1256. calib_data->dig_p8 = (int16_t)BME280_CONCAT_BYTES(reg_data[21], reg_data[20]);
  1257. calib_data->dig_p9 = (int16_t)BME280_CONCAT_BYTES(reg_data[23], reg_data[22]);
  1258. calib_data->dig_h1 = reg_data[25];
  1259. }
  1260. /*!
  1261. * @brief This internal API is used to parse the humidity calibration data
  1262. * and store it in device structure.
  1263. */
  1264. static void parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev)
  1265. {
  1266. struct bme280_calib_data *calib_data = &dev->calib_data;
  1267. int16_t dig_h4_lsb;
  1268. int16_t dig_h4_msb;
  1269. int16_t dig_h5_lsb;
  1270. int16_t dig_h5_msb;
  1271. calib_data->dig_h2 = (int16_t)BME280_CONCAT_BYTES(reg_data[1], reg_data[0]);
  1272. calib_data->dig_h3 = reg_data[2];
  1273. dig_h4_msb = (int16_t)(int8_t)reg_data[3] * 16;
  1274. dig_h4_lsb = (int16_t)(reg_data[4] & 0x0F);
  1275. calib_data->dig_h4 = dig_h4_msb | dig_h4_lsb;
  1276. dig_h5_msb = (int16_t)(int8_t)reg_data[5] * 16;
  1277. dig_h5_lsb = (int16_t)(reg_data[4] >> 4);
  1278. calib_data->dig_h5 = dig_h5_msb | dig_h5_lsb;
  1279. calib_data->dig_h6 = (int8_t)reg_data[6];
  1280. }
  1281. /*!
  1282. * @brief This internal API is used to identify the settings which the user
  1283. * wants to modify in the sensor.
  1284. */
  1285. static uint8_t are_settings_changed(uint8_t sub_settings, uint8_t desired_settings)
  1286. {
  1287. uint8_t settings_changed = FALSE;
  1288. if (sub_settings & desired_settings)
  1289. {
  1290. /* User wants to modify this particular settings */
  1291. settings_changed = TRUE;
  1292. }
  1293. else
  1294. {
  1295. /* User don't want to modify this particular settings */
  1296. settings_changed = FALSE;
  1297. }
  1298. return settings_changed;
  1299. }
  1300. /*!
  1301. * @brief This internal API is used to validate the device structure pointer for
  1302. * null conditions.
  1303. */
  1304. static int8_t null_ptr_check(const struct bme280_dev *dev)
  1305. {
  1306. int8_t rslt;
  1307. if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL))
  1308. {
  1309. /* Device structure pointer is not valid */
  1310. rslt = BME280_E_NULL_PTR;
  1311. }
  1312. else
  1313. {
  1314. /* Device structure is fine */
  1315. rslt = BME280_OK;
  1316. }
  1317. return rslt;
  1318. }