Repo for ESP32 Weather Station Development
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1497 lignes
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. }