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