]> git.itanic.dy.fi Git - BME280_driver/blob - bme280.c
Updated to v3.2.0
[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         21 Mar 2017
44  * Version      3.2.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 FLOATING_POINT_REPRESENTATION
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->interface != BME280_I2C_INTF)
430                         reg_addr = reg_addr | 0x80;
431                 /* Read the data  */
432                 rslt = dev->read(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[len * 2];
449         uint16_t temp_len;
450         uint8_t reg_addr_cnt;
451
452         /* Check for null pointer in the device structure*/
453         rslt = null_ptr_check(dev);
454         /* Check for arguments validity */
455         if ((rslt ==  BME280_OK) && (reg_addr != NULL) && (reg_data != NULL)) {
456                 if (len != 0) {
457                         temp_buff[0] = reg_data[0];
458                         /* If interface selected is SPI */
459                         if (dev->interface != BME280_I2C_INTF) {
460                                 for (reg_addr_cnt = 0; reg_addr_cnt < len; reg_addr_cnt++)
461                                         reg_addr[reg_addr_cnt] = reg_addr[reg_addr_cnt] & 0x7F;
462                         }
463                         /* Burst write mode */
464                         if (len > 1) {
465                                 /* Interleave register address w.r.t data for
466                                 burst write*/
467                                 interleave_reg_addr(reg_addr, temp_buff, reg_data, len);
468                                 temp_len = len * 2;
469                         } else {
470                                 temp_len = len;
471                         }
472                         rslt = dev->write(dev->id, reg_addr[0], temp_buff, temp_len);
473                         /* Check for communication error */
474                         if (rslt != BME280_OK)
475                                 rslt = BME280_E_COMM_FAIL;
476                 } else {
477                         rslt = BME280_E_INVALID_LEN;
478                 }
479         } else {
480                 rslt = BME280_E_NULL_PTR;
481         }
482
483
484         return rslt;
485 }
486
487 /*!
488  * @brief This API sets the oversampling, filter and standby duration
489  * (normal mode) settings in the sensor.
490  */
491 int8_t bme280_set_sensor_settings(uint8_t desired_settings, const struct bme280_dev *dev)
492 {
493         int8_t rslt;
494         uint8_t sensor_mode;
495
496         /* Check for null pointer in the device structure*/
497         rslt = null_ptr_check(dev);
498         /* Proceed if null check is fine */
499         if (rslt == BME280_OK) {
500                 rslt = bme280_get_sensor_mode(&sensor_mode, dev);
501                 if ((rslt == BME280_OK) && (sensor_mode != BME280_SLEEP_MODE))
502                         rslt = put_device_to_sleep(dev);
503                 if (rslt == BME280_OK) {
504                         /* Check if user wants to change oversampling
505                            settings */
506                         if (are_settings_changed(OVERSAMPLING_SETTINGS, desired_settings))
507                                 rslt = set_osr_settings(desired_settings, &dev->settings, dev);
508                         /* Check if user wants to change filter and/or
509                            standby settings */
510                         if ((rslt == BME280_OK) && are_settings_changed(FILTER_STANDBY_SETTINGS, desired_settings))
511                                 rslt = set_filter_standby_settings(desired_settings, &dev->settings, dev);
512                 }
513         }
514
515         return rslt;
516 }
517
518 /*!
519  * @brief This API gets the oversampling, filter and standby duration
520  * (normal mode) settings from the sensor.
521  */
522 int8_t bme280_get_sensor_settings(struct bme280_dev *dev)
523 {
524         int8_t rslt;
525         uint8_t reg_data[4];
526
527         /* Check for null pointer in the device structure*/
528         rslt = null_ptr_check(dev);
529         /* Proceed if null check is fine */
530         if (rslt == BME280_OK) {
531                 rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev);
532                 if (rslt == BME280_OK)
533                         parse_device_settings(reg_data, &dev->settings);
534         }
535
536         return rslt;
537 }
538
539 /*!
540  * @brief This API sets the power mode of the sensor.
541  */
542 int8_t bme280_set_sensor_mode(uint8_t sensor_mode, const struct bme280_dev *dev)
543 {
544         int8_t rslt;
545         uint8_t last_set_mode;
546
547         /* Check for null pointer in the device structure*/
548         rslt = null_ptr_check(dev);
549
550         if (rslt == BME280_OK) {
551                 rslt = bme280_get_sensor_mode(&last_set_mode, dev);
552                 /* If the sensor is not in sleep mode put the device to sleep
553                    mode */
554                 if ((rslt == BME280_OK) && (last_set_mode != BME280_SLEEP_MODE))
555                         rslt = put_device_to_sleep(dev);
556                 /* Set the power mode */
557                 if (rslt == BME280_OK)
558                         rslt = write_power_mode(sensor_mode, dev);
559         }
560
561         return rslt;
562 }
563
564 /*!
565  * @brief This API gets the power mode of the sensor.
566  */
567 int8_t bme280_get_sensor_mode(uint8_t *sensor_mode, const struct bme280_dev *dev)
568 {
569         int8_t rslt;
570
571         /* Check for null pointer in the device structure*/
572         rslt = null_ptr_check(dev);
573
574         if (rslt == BME280_OK) {
575                 /* Read the power mode register */
576                 rslt = bme280_get_regs(BME280_PWR_CTRL_ADDR, sensor_mode, 1, dev);
577                 /* Assign the power mode in the device structure */
578                 *sensor_mode = BME280_GET_BITS_POS_0(*sensor_mode, BME280_SENSOR_MODE);
579         }
580
581         return rslt;
582 }
583
584 /*!
585  * @brief This API performs the soft reset of the sensor.
586  */
587 int8_t bme280_soft_reset(const struct bme280_dev *dev)
588 {
589         int8_t rslt;
590         uint8_t reg_addr = BME280_RESET_ADDR;
591         /* 0xB6 is the soft reset command */
592         uint8_t soft_rst_cmd = 0xB6;
593
594         /* Check for null pointer in the device structure*/
595         rslt = null_ptr_check(dev);
596         /* Proceed if null check is fine */
597         if (rslt == BME280_OK) {
598                 /* Write the soft reset command in the sensor */
599                 rslt = bme280_set_regs(&reg_addr, &soft_rst_cmd, 1, dev);
600                 /* As per data sheet, startup time is 2 ms. */
601                 dev->delay_ms(2);
602         }
603
604         return rslt;
605 }
606
607 /*!
608  * @brief This API reads the pressure, temperature and humidity data from the
609  * sensor, compensates the data and store it in the bme280_data structure
610  * instance passed by the user.
611  */
612 int8_t bme280_get_sensor_data(uint8_t sensor_comp, struct bme280_data *comp_data, struct bme280_dev *dev)
613 {
614         int8_t rslt;
615         /* Array to store the pressure, temperature and humidity data read from
616         the sensor */
617         uint8_t reg_data[BME280_P_T_H_DATA_LEN] = {0};
618         struct bme280_uncomp_data uncomp_data = {0};
619
620         /* Check for null pointer in the device structure*/
621         rslt = null_ptr_check(dev);
622
623         if ((rslt == BME280_OK) && (comp_data != NULL)) {
624                 /* Read the pressure and temperature data from the sensor */
625                 rslt = bme280_get_regs(BME280_DATA_ADDR, reg_data, BME280_P_T_H_DATA_LEN, dev);
626
627                 if (rslt == BME280_OK) {
628                         /* Parse the read data from the sensor */
629                         parse_sensor_data(reg_data, &uncomp_data);
630                         /* Compensate the pressure and/or temperature and/or
631                            humidity data from the sensor */
632                         rslt = compensate_data(sensor_comp, &uncomp_data, comp_data, &dev->calib_data);
633                 }
634         } else {
635                 rslt = BME280_E_NULL_PTR;
636         }
637
638         return rslt;
639 }
640
641 /*!
642  * @brief This internal API sets the oversampling settings for pressure,
643  * temperature and humidity in the sensor.
644  */
645 static int8_t set_osr_settings(uint8_t desired_settings, const struct bme280_settings *settings,
646                                 const struct bme280_dev *dev)
647 {
648         int8_t rslt = BME280_W_INVALID_OSR_MACRO;
649
650         if (desired_settings & BME280_OSR_HUM_SEL)
651                 rslt = set_osr_humidity_settings(settings, dev);
652         if (desired_settings & (BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL))
653                 rslt = set_osr_press_temp_settings(desired_settings, settings, dev);
654
655         return rslt;
656 }
657
658 /*!
659  * @brief This API sets the humidity oversampling settings of the sensor.
660  */
661 static int8_t set_osr_humidity_settings(const struct bme280_settings *settings, const struct bme280_dev *dev)
662 {
663         int8_t rslt;
664         uint8_t ctrl_hum;
665         uint8_t ctrl_meas;
666         uint8_t reg_addr = BME280_CTRL_HUM_ADDR;
667
668         ctrl_hum = settings->osr_h & BME280_CTRL_HUM_MSK;
669         /* Write the humidity control value in the register */
670         rslt = bme280_set_regs(&reg_addr, &ctrl_hum, 1, dev);
671         /* Humidity related changes will be only effective after a
672            write operation to ctrl_meas register */
673         if (rslt == BME280_OK) {
674                 reg_addr = BME280_CTRL_MEAS_ADDR;
675                 rslt = bme280_get_regs(reg_addr, &ctrl_meas, 1, dev);
676                 if (rslt == BME280_OK)
677                         rslt = bme280_set_regs(&reg_addr, &ctrl_meas, 1, dev);
678         }
679
680         return rslt;
681 }
682
683 /*!
684  * @brief This API sets the pressure and/or temperature oversampling settings
685  * in the sensor according to the settings selected by the user.
686  */
687 static int8_t set_osr_press_temp_settings(uint8_t desired_settings, const struct bme280_settings *settings,
688                                                 const struct bme280_dev *dev)
689 {
690         int8_t rslt;
691         uint8_t reg_addr = BME280_CTRL_MEAS_ADDR;
692         uint8_t reg_data;
693
694         rslt = bme280_get_regs(reg_addr, &reg_data, 1, dev);
695
696         if (rslt == BME280_OK) {
697                 if (desired_settings & BME280_OSR_PRESS_SEL)
698                         fill_osr_press_settings(&reg_data, settings);
699                 if (desired_settings & BME280_OSR_TEMP_SEL)
700                         fill_osr_temp_settings(&reg_data, settings);
701                 /* Write the oversampling settings in the register */
702                 rslt = bme280_set_regs(&reg_addr, &reg_data, 1, dev);
703         }
704
705         return rslt;
706 }
707
708 /*!
709  * @brief This internal API sets the filter and/or standby duration settings
710  * in the sensor according to the settings selected by the user.
711  */
712 static int8_t set_filter_standby_settings(uint8_t desired_settings, const struct bme280_settings *settings,
713                                                 const struct bme280_dev *dev)
714 {
715         int8_t rslt;
716         uint8_t reg_addr = BME280_CONFIG_ADDR;
717         uint8_t reg_data;
718
719         rslt = bme280_get_regs(reg_addr, &reg_data, 1, dev);
720
721         if (rslt == BME280_OK) {
722                 if (desired_settings & BME280_FILTER_SEL)
723                         fill_filter_settings(&reg_data, settings);
724                 if (desired_settings & BME280_STANDBY_SEL)
725                         fill_standby_settings(&reg_data, settings);
726                 /* Write the oversampling settings in the register */
727                 rslt = bme280_set_regs(&reg_addr, &reg_data, 1, dev);
728         }
729
730         return rslt;
731 }
732
733 /*!
734  * @brief This internal API fills the filter settings provided by the user
735  * in the data buffer so as to write in the sensor.
736  */
737 static void fill_filter_settings(uint8_t *reg_data, const struct bme280_settings *settings)
738 {
739         *reg_data = BME280_SET_BITS(*reg_data, BME280_FILTER, settings->filter);
740 }
741
742 /*!
743  * @brief This internal API fills the standby duration settings provided by
744  * the user in the data buffer so as to write in the sensor.
745  */
746 static void fill_standby_settings(uint8_t *reg_data, const struct bme280_settings *settings)
747 {
748         *reg_data = BME280_SET_BITS(*reg_data, BME280_STANDBY, settings->standby_time);
749 }
750
751 /*!
752  * @brief This internal API fills the pressure oversampling settings provided by
753  * the user in the data buffer so as to write in the sensor.
754  */
755 static void fill_osr_press_settings(uint8_t *reg_data, const struct bme280_settings *settings)
756 {
757         *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_PRESS, settings->osr_p);
758 }
759
760 /*!
761  * @brief This internal API fills the temperature oversampling settings
762  * provided by the user in the data buffer so as to write in the sensor.
763  */
764 static void fill_osr_temp_settings(uint8_t *reg_data, const struct bme280_settings *settings)
765 {
766         *reg_data = BME280_SET_BITS(*reg_data, BME280_CTRL_TEMP, settings->osr_t);
767 }
768
769 /*!
770  * @brief This internal API parse the oversampling(pressure, temperature
771  * and humidity), filter and standby duration settings and store in the
772  * device structure.
773  */
774 static void parse_device_settings(const uint8_t *reg_data, struct bme280_settings *settings)
775 {
776         settings->osr_h = BME280_GET_BITS_POS_0(reg_data[0], BME280_CTRL_HUM);
777         settings->osr_p = BME280_GET_BITS(reg_data[2], BME280_CTRL_PRESS);
778         settings->osr_t = BME280_GET_BITS(reg_data[2], BME280_CTRL_TEMP);
779         settings->filter = BME280_GET_BITS(reg_data[3], BME280_FILTER);
780         settings->standby_time = BME280_GET_BITS(reg_data[3], BME280_STANDBY);
781 }
782 /*!
783  * @brief This internal API writes the power mode in the sensor.
784  */
785 static int8_t write_power_mode(uint8_t sensor_mode, const struct bme280_dev *dev)
786 {
787         int8_t rslt;
788         uint8_t reg_addr = BME280_PWR_CTRL_ADDR;
789         /* Variable to store the value read from power mode register */
790         uint8_t sensor_mode_reg_val;
791
792         /* Read the power mode register */
793         rslt = bme280_get_regs(reg_addr, &sensor_mode_reg_val, 1, dev);
794         /* Set the power mode */
795         if (rslt == BME280_OK) {
796                 sensor_mode_reg_val = BME280_SET_BITS_POS_0(sensor_mode_reg_val, BME280_SENSOR_MODE, sensor_mode);
797                 /* Write the power mode in the register */
798                 rslt = bme280_set_regs(&reg_addr, &sensor_mode_reg_val, 1, dev);
799         }
800
801         return rslt;
802 }
803
804 /*!
805  * @brief This internal API puts the device to sleep mode.
806  */
807 static int8_t put_device_to_sleep(const struct bme280_dev *dev)
808 {
809         int8_t rslt;
810         uint8_t reg_data[4];
811         struct bme280_settings settings;
812
813         rslt = bme280_get_regs(BME280_CTRL_HUM_ADDR, reg_data, 4, dev);
814         if (rslt == BME280_OK) {
815                 parse_device_settings(reg_data, &settings);
816                 rslt = bme280_soft_reset(dev);
817                 if (rslt == BME280_OK)
818                         rslt = reload_device_settings(&settings, dev);
819         }
820
821         return rslt;
822 }
823
824 /*!
825  * @brief This internal API reloads the already existing device settings in
826  * the sensor after soft reset.
827  */
828 static int8_t reload_device_settings(const struct bme280_settings *settings, const struct bme280_dev *dev)
829 {
830         int8_t rslt;
831
832         rslt = set_osr_settings(BME280_ALL_SETTINGS_SEL, settings, dev);
833         if (rslt == BME280_OK)
834                 rslt = set_filter_standby_settings(BME280_ALL_SETTINGS_SEL, settings, dev);
835
836         return rslt;
837 }
838
839 /*!
840  *  @brief This internal API is used to parse the pressure, temperature and
841  *  humidity data and store it in the bme280_uncomp_data structure instance.
842  */
843 static void parse_sensor_data(const uint8_t *reg_data, struct bme280_uncomp_data *uncomp_data)
844 {
845         /* Variables to store the sensor data */
846         uint32_t data_xlsb;
847         uint32_t data_lsb;
848         uint32_t data_msb;
849
850         /* Store the parsed register values for pressure data */
851         data_xlsb = (uint32_t)reg_data[0] << 12;
852         data_lsb = (uint32_t)reg_data[1] << 4;
853         data_msb = (uint32_t)reg_data[2] << 4;
854         uncomp_data->pressure = data_msb | data_lsb | data_xlsb;
855
856         /* Store the parsed register values for temperature data */
857         data_xlsb = (uint32_t)reg_data[3] << 12;
858         data_lsb = (uint32_t)reg_data[4] << 4;
859         data_msb = (uint32_t)reg_data[5] << 4;
860         uncomp_data->temperature = data_msb | data_lsb | data_xlsb;
861
862         /* Store the parsed register values for temperature data */
863         data_lsb = (uint32_t)reg_data[6] << 8;
864         data_msb = (uint32_t)reg_data[7];
865         uncomp_data->humidity = data_msb | data_lsb;
866 }
867
868 /*!
869  * @brief This internal API is used to compensate the pressure and/or
870  * temperature and/or humidity data according to the component selected
871  * by the user.
872  */
873 static int8_t compensate_data(uint8_t sensor_comp, const struct bme280_uncomp_data *uncomp_data,
874                                      struct bme280_data *comp_data, struct bme280_calib_data *calib_data)
875 {
876         int8_t rslt = BME280_OK;
877
878         if ((uncomp_data != NULL) && (comp_data != NULL) && (calib_data != NULL)) {
879                 /* Initialize to zero */
880                 comp_data->temperature = 0;
881                 comp_data->pressure = 0;
882                 comp_data->humidity = 0;
883                 /* If pressure or temperature component is selected */
884                 if (sensor_comp & (BME280_PRESS | BME280_TEMP | BME280_HUM)) {
885                         /* Compensate the temperature data */
886                         comp_data->temperature = compensate_temperature(uncomp_data, calib_data);
887                 }
888                 if (sensor_comp & BME280_PRESS) {
889                         /* Compensate the pressure data */
890                         comp_data->pressure = compensate_pressure(uncomp_data, calib_data);
891                 }
892                 if (sensor_comp & BME280_HUM) {
893                         /* Compensate the humidity data */
894                         comp_data->humidity = compensate_humidity(uncomp_data, calib_data);
895                 }
896         } else {
897                 rslt = BME280_E_NULL_PTR;
898         }
899
900         return rslt;
901 }
902
903 #ifdef FLOATING_POINT_REPRESENTATION
904 /*!
905  * @brief This internal API is used to compensate the raw temperature data and
906  * return the compensated temperature data in double data type.
907  */
908 static double compensate_temperature(const struct bme280_uncomp_data *uncomp_data,
909                                                 struct bme280_calib_data *calib_data)
910 {
911         double var1;
912         double var2;
913         double temperature;
914         double temperature_min = -40;
915         double temperature_max = 85;
916
917         var1 = ((double)uncomp_data->temperature) / 16384.0 - ((double)calib_data->dig_T1) / 1024.0;
918         var1 = var1 * ((double)calib_data->dig_T2);
919         var2 = (((double)uncomp_data->temperature) / 131072.0 - ((double)calib_data->dig_T1) / 8192.0);
920         var2 = (var2 * var2) * ((double)calib_data->dig_T3);
921         calib_data->t_fine = (int32_t)(var1 + var2);
922         temperature = (var1 + var2) / 5120.0;
923
924         if (temperature < temperature_min)
925                 temperature = temperature_min;
926         else if (temperature > temperature_max)
927                 temperature = temperature_max;
928
929         return temperature;
930 }
931
932 /*!
933  * @brief This internal API is used to compensate the raw pressure data and
934  * return the compensated pressure data in double data type.
935  */
936 static double compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
937                                                 const struct bme280_calib_data *calib_data)
938 {
939         double var1;
940         double var2;
941         double var3;
942         double pressure;
943         double pressure_min = 30000.0;
944         double pressure_max = 110000.0;
945
946         var1 = ((double)calib_data->t_fine / 2.0) - 64000.0;
947         var2 = var1 * var1 * ((double)calib_data->dig_P6) / 32768.0;
948         var2 = var2 + var1 * ((double)calib_data->dig_P5) * 2.0;
949         var2 = (var2 / 4.0) + (((double)calib_data->dig_P4) * 65536.0);
950         var3 = ((double)calib_data->dig_P3) * var1 * var1 / 524288.0;
951         var1 = (var3 + ((double)calib_data->dig_P2) * var1) / 524288.0;
952         var1 = (1.0 + var1 / 32768.0) * ((double)calib_data->dig_P1);
953         /* avoid exception caused by division by zero */
954         if (var1) {
955                 pressure = 1048576.0 - (double) uncomp_data->pressure;
956                 pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;
957                 var1 = ((double)calib_data->dig_P9) * pressure * pressure / 2147483648.0;
958                 var2 = pressure * ((double)calib_data->dig_P8) / 32768.0;
959                 pressure = pressure + (var1 + var2 + ((double)calib_data->dig_P7)) / 16.0;
960
961                 if (pressure < pressure_min)
962                         pressure = pressure_min;
963                 else if (pressure > pressure_max)
964                         pressure = pressure_max;
965         } else { /* Invalid case */
966                 pressure = pressure_min;
967         }
968
969         return pressure;
970 }
971
972 /*!
973  * @brief This internal API is used to compensate the raw humidity data and
974  * return the compensated humidity data in double data type.
975  */
976 static double compensate_humidity(const struct bme280_uncomp_data *uncomp_data,
977                                                 const struct bme280_calib_data *calib_data)
978 {
979         double humidity;
980         double humidity_min = 0.0;
981         double humidity_max = 100.0;
982         double var1;
983         double var2;
984         double var3;
985         double var4;
986         double var5;
987         double var6;
988
989         var1 = ((double)calib_data->t_fine) - 76800.0;
990         var2 = (((double)calib_data->dig_H4) * 64.0 + (((double)calib_data->dig_H5) / 16384.0) * var1);
991         var3 = uncomp_data->humidity - var2;
992         var4 = ((double)calib_data->dig_H2) / 65536.0;
993         var5 = (1.0 + (((double)calib_data->dig_H3) / 67108864.0) * var1);
994         var6 = 1.0 + (((double)calib_data->dig_H6) / 67108864.0) * var1 * var5;
995         var6 = var3 * var4 * (var5 * var6);
996         humidity = var6 * (1.0 - ((double)calib_data->dig_H1) * var6 / 524288.0);
997
998         if (humidity > humidity_max)
999                 humidity = humidity_max;
1000         else if (humidity < humidity_min)
1001                 humidity = humidity_min;
1002
1003         return humidity;
1004 }
1005
1006 #else
1007 /*!
1008  * @brief This internal API is used to compensate the raw temperature data and
1009  * return the compensated temperature data in integer data type.
1010  */
1011 static int32_t compensate_temperature(const struct bme280_uncomp_data *uncomp_data,
1012                                                 struct bme280_calib_data *calib_data)
1013 {
1014         int32_t var1;
1015         int32_t var2;
1016         int32_t temperature;
1017         int32_t temperature_min = -4000;
1018         int32_t temperature_max = 8500;
1019
1020         var1 = (int32_t)((uncomp_data->temperature / 8) - ((int32_t)calib_data->dig_T1 * 2));
1021         var1 = (var1 * ((int32_t)calib_data->dig_T2)) / 2048;
1022         var2 = (int32_t)((uncomp_data->temperature / 16) - ((int32_t)calib_data->dig_T1));
1023         var2 = (((var2 * var2) / 4096) * ((int32_t)calib_data->dig_T3)) / 16384;
1024         calib_data->t_fine = var1 + var2;
1025         temperature = (calib_data->t_fine * 5 + 128) / 256;
1026
1027         if (temperature < temperature_min)
1028                 temperature = temperature_min;
1029         else if (temperature > temperature_max)
1030                 temperature = temperature_max;
1031
1032         return temperature;
1033 }
1034 #ifdef MACHINE_64_BIT
1035 /*!
1036  * @brief This internal API is used to compensate the raw pressure data and
1037  * return the compensated pressure data in integer data type with higher
1038  * accuracy.
1039  */
1040 static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
1041                                                 const struct bme280_calib_data *calib_data)
1042 {
1043         int64_t var1;
1044         int64_t var2;
1045         int64_t var3;
1046         int64_t var4;
1047         uint32_t pressure;
1048         uint32_t pressure_min = 3000000;
1049         uint32_t pressure_max = 11000000;
1050
1051         var1 = ((int64_t)calib_data->t_fine) - 128000;
1052         var2 = var1 * var1 * (int64_t)calib_data->dig_P6;
1053         var2 = var2 + ((var1 * (int64_t)calib_data->dig_P5) * 131072);
1054         var2 = var2 + (((int64_t)calib_data->dig_P4) * 34359738368);
1055         var1 = ((var1 * var1 * (int64_t)calib_data->dig_P3) / 256) + ((var1 * (int64_t)calib_data->dig_P2) * 4096);
1056         var3 = ((int64_t)1) * 140737488355328;
1057         var1 = (var3 + var1) * ((int64_t)calib_data->dig_P1) / 8589934592;
1058
1059         /* To avoid divide by zero exception */
1060         if (var1 != 0) {
1061                 var4 = 1048576 - uncomp_data->pressure;
1062                 var4 = (((var4 * (2147483648UL)) - var2) * 3125) / var1;
1063                 var1 = (((int64_t)calib_data->dig_P9) * (var4 / 8192) * (var4 / 8192)) / 33554432;
1064                 var2 = (((int64_t)calib_data->dig_P8) * var4) / 524288;
1065                 var4 = ((var4 + var1 + var2) / 256) + (((int64_t)calib_data->dig_P7) * 16);
1066                 pressure = (uint32_t)(((var4 / 2) * 100) / 128);
1067
1068                 if (pressure < pressure_min)
1069                         pressure = pressure_min;
1070                 else if (pressure > pressure_max)
1071                         pressure = pressure_max;
1072         } else {
1073                 pressure = pressure_min;
1074         }
1075
1076         return pressure;
1077 }
1078 #else
1079 /*!
1080  * @brief This internal API is used to compensate the raw pressure data and
1081  * return the compensated pressure data in integer data type.
1082  */
1083 static uint32_t compensate_pressure(const struct bme280_uncomp_data *uncomp_data,
1084                                                 const struct bme280_calib_data *calib_data)
1085 {
1086         int32_t var1;
1087         int32_t var2;
1088         int32_t var3;
1089         int32_t var4;
1090         uint32_t var5;
1091         uint32_t pressure;
1092         uint32_t pressure_min = 30000;
1093         uint32_t pressure_max = 110000;
1094
1095         var1 = (((int32_t)calib_data->t_fine) / 2) - (int32_t)64000;
1096         var2 = (((var1 / 4) * (var1 / 4)) / 2048) * ((int32_t)calib_data->dig_P6);
1097         var2 = var2 + ((var1 * ((int32_t)calib_data->dig_P5)) * 2);
1098         var2 = (var2 / 4) + (((int32_t)calib_data->dig_P4) * 65536);
1099         var3 = (calib_data->dig_P3 * (((var1 / 4) * (var1 / 4)) / 8192)) / 8;
1100         var4 = (((int32_t)calib_data->dig_P2) * var1) / 2;
1101         var1 = (var3 + var4) / 262144;
1102         var1 = (((32768 + var1)) * ((int32_t)calib_data->dig_P1)) / 32768;
1103          /* avoid exception caused by division by zero */
1104         if (var1) {
1105                 var5 = (uint32_t)((uint32_t)1048576) - uncomp_data->pressure;
1106                 pressure = ((uint32_t)(var5 - (uint32_t)(var2 / 4096))) * 3125;
1107                 if (pressure < 0x80000000)
1108                         pressure = (pressure << 1) / ((uint32_t)var1);
1109                 else
1110                         pressure = (pressure / (uint32_t)var1) * 2;
1111
1112                 var1 = (((int32_t)calib_data->dig_P9) * ((int32_t)(((pressure / 8) * (pressure / 8)) / 8192))) / 4096;
1113                 var2 = (((int32_t)(pressure / 4)) * ((int32_t)calib_data->dig_P8)) / 8192;
1114                 pressure = (uint32_t)((int32_t)pressure + ((var1 + var2 + calib_data->dig_P7) / 16));
1115
1116                 if (pressure < pressure_min)
1117                         pressure = pressure_min;
1118                 else if (pressure > pressure_max)
1119                         pressure = pressure_max;
1120         } else {
1121                 pressure = pressure_min;
1122         }
1123
1124         return pressure;
1125 }
1126 #endif
1127
1128 /*!
1129  * @brief This internal API is used to compensate the raw humidity data and
1130  * return the compensated humidity data in integer data type.
1131  */
1132 static uint32_t compensate_humidity(const struct bme280_uncomp_data *uncomp_data,
1133                                                 const struct bme280_calib_data *calib_data)
1134 {
1135         int32_t var1;
1136         int32_t var2;
1137         int32_t var3;
1138         int32_t var4;
1139         int32_t var5;
1140         uint32_t humidity;
1141         uint32_t humidity_max = 100000;
1142
1143         var1 = calib_data->t_fine - ((int32_t)76800);
1144         var2 = (int32_t)(uncomp_data->humidity * 16384);
1145         var3 = (int32_t)(((int32_t)calib_data->dig_H4) * 1048576);
1146         var4 = ((int32_t)calib_data->dig_H5) * var1;
1147         var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768;
1148         var2 = (var1 * ((int32_t)calib_data->dig_H6)) / 1024;
1149         var3 = (var1 * ((int32_t)calib_data->dig_H3)) / 2048;
1150         var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152;
1151         var2 = ((var4 * ((int32_t)calib_data->dig_H2)) + 8192) / 16384;
1152         var3 = var5 * var2;
1153         var4 = ((var3 / 32768) * (var3 / 32768)) / 128;
1154         var5 = var3 - ((var4 * ((int32_t)calib_data->dig_H1)) / 16);
1155         var5 = (var5 < 0 ? 0 : var5);
1156         var5 = (var5 > 419430400 ? 419430400 : var5);
1157         humidity = (uint32_t)(var5 / 4096);
1158
1159         if (humidity > humidity_max)
1160                 humidity = humidity_max;
1161
1162         return humidity;
1163 }
1164 #endif
1165
1166 /*!
1167  * @brief This internal API reads the calibration data from the sensor, parse
1168  * it and store in the device structure.
1169  */
1170 static int8_t get_calib_data(struct bme280_dev *dev)
1171 {
1172         int8_t rslt;
1173         uint8_t reg_addr = BME280_TEMP_PRESS_CALIB_DATA_ADDR;
1174         /* Array to store calibration data */
1175         uint8_t calib_data[BME280_TEMP_PRESS_CALIB_DATA_LEN] = {0};
1176
1177         /* Read the calibration data from the sensor */
1178         rslt = bme280_get_regs(reg_addr, calib_data, BME280_TEMP_PRESS_CALIB_DATA_LEN, dev);
1179
1180         if (rslt == BME280_OK) {
1181                 /* Parse temperature and pressure calibration data and store
1182                    it in device structure */
1183                 parse_temp_press_calib_data(calib_data, dev);
1184
1185                 reg_addr = BME280_HUMIDITY_CALIB_DATA_ADDR;
1186                 /* Read the humidity calibration data from the sensor */
1187                 rslt = bme280_get_regs(reg_addr, calib_data, BME280_HUMIDITY_CALIB_DATA_LEN, dev);
1188                 if (rslt == BME280_OK) {
1189                         /* Parse humidity calibration data and store it in
1190                            device structure */
1191                         parse_humidity_calib_data(calib_data, dev);
1192                 }
1193         }
1194
1195         return rslt;
1196 }
1197
1198 /*!
1199  * @brief This internal API interleaves the register address between the
1200  * register data buffer for burst write operation.
1201  */
1202 static void interleave_reg_addr(const uint8_t *reg_addr, uint8_t *temp_buff, const uint8_t *reg_data, uint8_t len)
1203 {
1204         uint8_t index;
1205
1206         for (index = 1; index < len; index++) {
1207                 temp_buff[(index * 2) - 1] = reg_addr[index];
1208                 temp_buff[index * 2] = reg_data[index];
1209         }
1210 }
1211
1212 /*!
1213  *  @brief This internal API is used to parse the temperature and
1214  *  pressure calibration data and store it in device structure.
1215  */
1216 static void parse_temp_press_calib_data(const uint8_t *reg_data, struct bme280_dev *dev)
1217 {
1218         struct bme280_calib_data *calib_data = &dev->calib_data;
1219
1220         calib_data->dig_T1 = BME280_CONCAT_BYTES(reg_data[1], reg_data[0]);
1221         calib_data->dig_T2 = (int16_t)BME280_CONCAT_BYTES(reg_data[3], reg_data[2]);
1222         calib_data->dig_T3 = (int16_t)BME280_CONCAT_BYTES(reg_data[5], reg_data[4]);
1223         calib_data->dig_P1 = BME280_CONCAT_BYTES(reg_data[7], reg_data[6]);
1224         calib_data->dig_P2 = (int16_t)BME280_CONCAT_BYTES(reg_data[9], reg_data[8]);
1225         calib_data->dig_P3 = (int16_t)BME280_CONCAT_BYTES(reg_data[11], reg_data[10]);
1226         calib_data->dig_P4 = (int16_t)BME280_CONCAT_BYTES(reg_data[13], reg_data[12]);
1227         calib_data->dig_P5 = (int16_t)BME280_CONCAT_BYTES(reg_data[15], reg_data[14]);
1228         calib_data->dig_P6 = (int16_t)BME280_CONCAT_BYTES(reg_data[17], reg_data[16]);
1229         calib_data->dig_P7 = (int16_t)BME280_CONCAT_BYTES(reg_data[19], reg_data[18]);
1230         calib_data->dig_P8 = (int16_t)BME280_CONCAT_BYTES(reg_data[21], reg_data[20]);
1231         calib_data->dig_P9 = (int16_t)BME280_CONCAT_BYTES(reg_data[23], reg_data[22]);
1232         calib_data->dig_H1 = reg_data[25];
1233
1234 }
1235
1236 /*!
1237  *  @brief This internal API is used to parse the humidity calibration data
1238  *  and store it in device structure.
1239  */
1240 static void parse_humidity_calib_data(const uint8_t *reg_data, struct bme280_dev *dev)
1241 {
1242         struct bme280_calib_data *calib_data = &dev->calib_data;
1243         int16_t dig_H4_lsb;
1244         int16_t dig_H4_msb;
1245         int16_t dig_H5_lsb;
1246         int16_t dig_H5_msb;
1247
1248         calib_data->dig_H2 = (int16_t)BME280_CONCAT_BYTES(reg_data[1], reg_data[0]);
1249         calib_data->dig_H3 = reg_data[2];
1250
1251         dig_H4_msb = (int16_t)(int8_t)reg_data[3] * 16;
1252         dig_H4_lsb = (int16_t)(reg_data[4] & 0x0F);
1253         calib_data->dig_H4 = dig_H4_msb | dig_H4_lsb;
1254
1255         dig_H5_msb = (int16_t)(int8_t)reg_data[5] * 16;
1256         dig_H5_lsb = (int16_t)(reg_data[4] >> 4);
1257         calib_data->dig_H5 = dig_H5_msb | dig_H5_lsb;
1258         calib_data->dig_H6 = (int8_t)reg_data[6];
1259 }
1260
1261 /*!
1262  * @brief This internal API is used to identify the settings which the user
1263  * wants to modify in the sensor.
1264  */
1265 static uint8_t are_settings_changed(uint8_t sub_settings, uint8_t desired_settings)
1266 {
1267         uint8_t settings_changed = FALSE;
1268
1269         if (sub_settings & desired_settings) {
1270                 /* User wants to modify this particular settings */
1271                 settings_changed = TRUE;
1272         } else {
1273                 /* User don't want to modify this particular settings */
1274                 settings_changed = FALSE;
1275         }
1276
1277         return settings_changed;
1278 }
1279
1280 /*!
1281  * @brief This internal API is used to validate the device structure pointer for
1282  * null conditions.
1283  */
1284 static int8_t null_ptr_check(const struct bme280_dev *dev)
1285 {
1286         int8_t rslt;
1287
1288         if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) {
1289                 /* Device structure pointer is not valid */
1290                 rslt = BME280_E_NULL_PTR;
1291         } else {
1292                 /* Device structure is fine */
1293                 rslt = BME280_OK;
1294         }
1295
1296         return rslt;
1297 }