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