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