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