]> git.itanic.dy.fi Git - BME280_driver/blob - bme280_support.c
Merge pull request #14 from simoc/master
[BME280_driver] / bme280_support.c
1 /*
2 ****************************************************************************
3 * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
4 *
5 * bme280_support.c
6 * Date: 2016/07/04
7 * Revision: 1.0.6 $
8 *
9 * Usage: Sensor Driver support file for BME280 sensor
10 *
11 ****************************************************************************
12 * License:
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
16 *
17 *   Redistributions of source code must retain the above copyright
18 *   notice, this list of conditions and the following disclaimer.
19 *
20 *   Redistributions in binary form must reproduce the above copyright
21 *   notice, this list of conditions and the following disclaimer in the
22 *   documentation and/or other materials provided with the distribution.
23 *
24 *   Neither the name of the copyright holder nor the names of the
25 *   contributors may be used to endorse or promote products derived from
26 *   this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
33 * OR CONTRIBUTORS BE LIABLE FOR ANY
34 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
35 * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
36 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
41 * ANY WAY OUT OF THE USE OF THIS
42 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
43 *
44 * The information provided is believed to be accurate and reliable.
45 * The copyright holder assumes no responsibility
46 * for the consequences of use
47 * of such information nor for any infringement of patents or
48 * other rights of third parties which may result from its use.
49 * No license is granted by implication or otherwise under any patent or
50 * patent rights of the copyright holder.
51 **************************************************************************/
52 /*---------------------------------------------------------------------------*/
53 /* Includes*/
54 /*---------------------------------------------------------------------------*/
55 #include "bme280.h"
56
57 #define BME280_API
58 /*Enable the macro BME280_API to use this support file */
59 /*----------------------------------------------------------------------------*
60 *  The following functions are used for reading and writing of
61 *       sensor data using I2C or SPI communication
62 *----------------------------------------------------------------------------*/
63 #ifdef BME280_API
64 /*      \Brief: The function is used as I2C bus read
65  *      \Return : Status of the I2C read
66  *      \param dev_addr : The device address of the sensor
67  *      \param reg_addr : Address of the first register, will data is going to be read
68  *      \param reg_data : This data read from the sensor, which is hold in an array
69  *      \param cnt : The no of byte of data to be read
70  */
71 s8 BME280_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
72  /*     \Brief: The function is used as I2C bus write
73  *      \Return : Status of the I2C write
74  *      \param dev_addr : The device address of the sensor
75  *      \param reg_addr : Address of the first register, will data is going to be written
76  *      \param reg_data : It is a value hold in the array,
77  *              will be used for write the value into the register
78  *      \param cnt : The no of byte of data to be write
79  */
80 s8 BME280_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
81 /*      \Brief: The function is used as SPI bus write
82  *      \Return : Status of the SPI write
83  *      \param dev_addr : The device address of the sensor
84  *      \param reg_addr : Address of the first register, will data is going to be written
85  *      \param reg_data : It is a value hold in the array,
86  *              will be used for write the value into the register
87  *      \param cnt : The no of byte of data to be write
88  */
89 s8 BME280_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
90 /*      \Brief: The function is used as SPI bus read
91  *      \Return : Status of the SPI read
92  *      \param dev_addr : The device address of the sensor
93  *      \param reg_addr : Address of the first register, will data is going to be read
94  *      \param reg_data : This data read from the sensor, which is hold in an array
95  *      \param cnt : The no of byte of data to be read */
96 s8 BME280_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
97 /*
98  * \Brief: SPI/I2C init routine
99 */
100 s8 I2C_routine(void);
101 s8 SPI_routine(void);
102 #endif
103 /********************End of I2C/SPI function declarations***********************/
104 /*      Brief : The delay routine
105  *      \param : delay in ms
106 */
107 void BME280_delay_msek(u32 msek);
108 /* This function is an example for reading sensor data
109  *      \param: None
110  *      \return: communication result
111  */
112 s32 bme280_data_readout_template(void);
113 /*----------------------------------------------------------------------------*
114  *  struct bme280_t parameters can be accessed by using bme280
115  *      bme280_t having the following parameters
116  *      Bus write function pointer: BME280_WR_FUNC_PTR
117  *      Bus read function pointer: BME280_RD_FUNC_PTR
118  *      Delay function pointer: delay_msec
119  *      I2C address: dev_addr
120  *      Chip id of the sensor: chip_id
121  *---------------------------------------------------------------------------*/
122 struct bme280_t bme280;
123 /* This function is an example for reading sensor data
124  *      \param: None
125  *      \return: communication result
126  */
127 s32 bme280_data_readout_template(void)
128 {
129         /* The variable used to assign the standby time*/
130         u8 v_stand_by_time_u8 = BME280_INIT_VALUE;
131         /* The variable used to read uncompensated temperature*/
132         s32 v_data_uncomp_temp_s32 = BME280_INIT_VALUE;
133         /* The variable used to read uncompensated pressure*/
134         s32 v_data_uncomp_pres_s32 = BME280_INIT_VALUE;
135         /* The variable used to read uncompensated pressure*/
136         s32 v_data_uncomp_hum_s32 = BME280_INIT_VALUE;
137         /* The variable used to read compensated temperature*/
138         s32 v_comp_temp_s32[2] = {BME280_INIT_VALUE, BME280_INIT_VALUE};
139         /* The variable used to read compensated pressure*/
140         u32 v_comp_press_u32[2] = {BME280_INIT_VALUE, BME280_INIT_VALUE};
141         /* The variable used to read compensated humidity*/
142         u32 v_comp_humidity_u32[2] = {BME280_INIT_VALUE, BME280_INIT_VALUE};
143
144         /* result of communication results*/
145         s32 com_rslt = ERROR;
146
147
148
149  /*********************** START INITIALIZATION ************************/
150   /*    Based on the user need configure I2C or SPI interface.
151   *     It is example code to explain how to use the bme280 API*/
152         #ifdef BME280_API
153         I2C_routine();
154         /*SPI_routine();*/
155         #endif
156 /*--------------------------------------------------------------------------*
157  *  This function used to assign the value/reference of
158  *      the following parameters
159  *      I2C address
160  *      Bus Write
161  *      Bus read
162  *      Chip id
163 *-------------------------------------------------------------------------*/
164         com_rslt = bme280_init(&bme280);
165
166         /*      For initialization it is required to set the mode of
167          *      the sensor as "NORMAL"
168          *      data acquisition/read/write is possible in this mode
169          *      by using the below API able to set the power mode as NORMAL*/
170         /* Set the power mode as NORMAL*/
171         com_rslt += bme280_set_power_mode(BME280_NORMAL_MODE);
172         /*      For reading the pressure, humidity and temperature data it is required to
173          *      set the OSS setting of humidity, pressure and temperature
174          * The "BME280_CTRLHUM_REG_OSRSH" register sets the humidity
175          * data acquisition options of the device.
176          * changes to this registers only become effective after a write operation to
177          * "BME280_CTRLMEAS_REG" register.
178          * In the code automated reading and writing of "BME280_CTRLHUM_REG_OSRSH"
179          * register first set the "BME280_CTRLHUM_REG_OSRSH" and then read and write
180          * the "BME280_CTRLMEAS_REG" register in the function*/
181         com_rslt += bme280_set_oversamp_humidity(BME280_OVERSAMP_1X);
182
183         /* set the pressure oversampling*/
184         com_rslt += bme280_set_oversamp_pressure(BME280_OVERSAMP_2X);
185         /* set the temperature oversampling*/
186         com_rslt += bme280_set_oversamp_temperature(BME280_OVERSAMP_4X);
187 /*--------------------------------------------------------------------------*/
188 /*------------------------------------------------------------------------*
189 ************************* START GET and SET FUNCTIONS DATA ****************
190 *---------------------------------------------------------------------------*/
191         /* This API used to Write the standby time of the sensor input
192          *      value have to be given
193          *      Normal mode comprises an automated perpetual cycling between an (active)
194          *      Measurement period and an (inactive) standby period.
195          *      The standby time is determined by the contents of the register t_sb.
196          *      Standby time can be set using BME280_STANDBYTIME_125_MS.
197          *      Usage Hint : bme280_set_standbydur(BME280_STANDBYTIME_125_MS)*/
198
199         com_rslt += bme280_set_standby_durn(BME280_STANDBY_TIME_1_MS);
200
201         /* This API used to read back the written value of standby time*/
202         com_rslt += bme280_get_standby_durn(&v_stand_by_time_u8);
203 /*-----------------------------------------------------------------*
204 ************************* END GET and SET FUNCTIONS ****************
205 *------------------------------------------------------------------*/
206
207 /************************* END INITIALIZATION *************************/
208
209 /*------------------------------------------------------------------*
210 ************ START READ UNCOMPENSATED PRESSURE, TEMPERATURE
211 AND HUMIDITY DATA ********
212 *---------------------------------------------------------------------*/
213         /* API is used to read the uncompensated temperature*/
214         com_rslt += bme280_read_uncomp_temperature(&v_data_uncomp_temp_s32);
215
216         /* API is used to read the uncompensated pressure*/
217         com_rslt += bme280_read_uncomp_pressure(&v_data_uncomp_pres_s32);
218
219         /* API is used to read the uncompensated humidity*/
220         com_rslt += bme280_read_uncomp_humidity(&v_data_uncomp_hum_s32);
221
222         /* API is used to read the uncompensated temperature,pressure
223         and humidity data */
224         com_rslt += bme280_read_uncomp_pressure_temperature_humidity(
225         &v_data_uncomp_temp_s32, &v_data_uncomp_pres_s32, &v_data_uncomp_hum_s32);
226 /*--------------------------------------------------------------------*
227 ************ END READ UNCOMPENSATED PRESSURE AND TEMPERATURE********
228 *-------------------------------------------------------------------------*/
229
230 /*------------------------------------------------------------------*
231 ************ START READ COMPENSATED PRESSURE, TEMPERATURE
232 AND HUMIDITY DATA ********
233 *---------------------------------------------------------------------*/
234         /* API is used to compute the compensated temperature*/
235         v_comp_temp_s32[0] = bme280_compensate_temperature_int32(
236                         v_data_uncomp_temp_s32);
237
238         /* API is used to compute the compensated pressure*/
239         v_comp_press_u32[0] = bme280_compensate_pressure_int32(
240                         v_data_uncomp_pres_s32);
241
242         /* API is used to compute the compensated humidity*/
243         v_comp_humidity_u32[0] = bme280_compensate_humidity_int32(
244                         v_data_uncomp_hum_s32);
245
246         /* API is used to read the compensated temperature, humidity and pressure*/
247         com_rslt += bme280_read_pressure_temperature_humidity(
248         &v_comp_press_u32[1], &v_comp_temp_s32[1],  &v_comp_humidity_u32[1]);
249 /*--------------------------------------------------------------------*
250 ************ END READ COMPENSATED PRESSURE, TEMPERATURE AND HUMIDITY ********
251 *-------------------------------------------------------------------------*/
252
253 /*-----------------------------------------------------------------------*
254 ************************* START DE-INITIALIZATION ***********************
255 *-------------------------------------------------------------------------*/
256         /*      For de-initialization it is required to set the mode of
257          *      the sensor as "SLEEP"
258          *      the device reaches the lowest power consumption only
259          *      In SLEEP mode no measurements are performed
260          *      All registers are accessible
261          *      by using the below API able to set the power mode as SLEEP*/
262          /* Set the power mode as SLEEP*/
263         com_rslt += bme280_set_power_mode(BME280_SLEEP_MODE);
264 /*---------------------------------------------------------------------*
265 ************************* END DE-INITIALIZATION **********************
266 *---------------------------------------------------------------------*/
267 return com_rslt;
268 }
269
270 #ifdef BME280_API
271 #define SPI_READ        0x80
272 #define SPI_WRITE       0x7F
273 #define BME280_DATA_INDEX       1
274 #define BME280_ADDRESS_INDEX    2
275 /*--------------------------------------------------------------------------*
276 *       The following function is used to map the I2C bus read, write, delay and
277 *       device address with global structure bme280
278 *-------------------------------------------------------------------------*/
279 s8 I2C_routine(void) {
280 /*--------------------------------------------------------------------------*
281  *  By using bme280 the following structure parameter can be accessed
282  *      Bus write function pointer: BME280_WR_FUNC_PTR
283  *      Bus read function pointer: BME280_RD_FUNC_PTR
284  *      Delay function pointer: delay_msec
285  *      I2C address: dev_addr
286  *--------------------------------------------------------------------------*/
287         bme280.bus_write = BME280_I2C_bus_write;
288         bme280.bus_read = BME280_I2C_bus_read;
289         bme280.dev_addr = BME280_I2C_ADDRESS2;
290         bme280.delay_msec = BME280_delay_msek;
291
292         return BME280_INIT_VALUE;
293 }
294
295 /*---------------------------------------------------------------------------*
296  * The following function is used to map the SPI bus read, write and delay
297  * with global structure bme280
298  *--------------------------------------------------------------------------*/
299 s8 SPI_routine(void) {
300 /*--------------------------------------------------------------------------*
301  *  By using bme280 the following structure parameter can be accessed
302  *      Bus write function pointer: BME280_WR_FUNC_PTR
303  *      Bus read function pointer: BME280_RD_FUNC_PTR
304  *      Delay function pointer: delay_msec
305  *--------------------------------------------------------------------------*/
306
307         bme280.bus_write = BME280_SPI_bus_write;
308         bme280.bus_read = BME280_SPI_bus_read;
309         bme280.delay_msec = BME280_delay_msek;
310
311         return BME280_INIT_VALUE;
312 }
313
314 /************** I2C/SPI buffer length ******/
315 #define I2C_BUFFER_LEN 8
316 #define SPI_BUFFER_LEN 5
317
318 /*-------------------------------------------------------------------*
319 *       This is a sample code for read and write the data by using I2C/SPI
320 *       Use either I2C or SPI based on your need
321 *       The device address defined in the bme280.h file
322 *-----------------------------------------------------------------------*/
323  /*     \Brief: The function is used as I2C bus write
324  *      \Return : Status of the I2C write
325  *      \param dev_addr : The device address of the sensor
326  *      \param reg_addr : Address of the first register, will data is going to be written
327  *      \param reg_data : It is a value hold in the array,
328  *              will be used for write the value into the register
329  *      \param cnt : The no of byte of data to be write
330  */
331 s8 BME280_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
332 {
333         s32 iError = BME280_INIT_VALUE;
334         u8 array[I2C_BUFFER_LEN];
335         u8 stringpos = BME280_INIT_VALUE;
336         array[BME280_INIT_VALUE] = reg_addr;
337         for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
338                 array[stringpos + BME280_DATA_INDEX] = *(reg_data + stringpos);
339         }
340         /*
341         * Please take the below function as your reference for
342         * write the data using I2C communication
343         * "IERROR = I2C_WRITE_STRING(DEV_ADDR, array, cnt+1)"
344         * add your I2C write function here
345         * iError is an return value of I2C read function
346         * Please select your valid return value
347         * In the driver SUCCESS defined as 0
348     * and FAILURE defined as -1
349         * Note :
350         * This is a full duplex operation,
351         * The first read data is discarded, for that extra write operation
352         * have to be initiated. For that cnt+1 operation done in the I2C write string function
353         * For more information please refer data sheet SPI communication:
354         */
355         return (s8)iError;
356 }
357
358  /*     \Brief: The function is used as I2C bus read
359  *      \Return : Status of the I2C read
360  *      \param dev_addr : The device address of the sensor
361  *      \param reg_addr : Address of the first register, will data is going to be read
362  *      \param reg_data : This data read from the sensor, which is hold in an array
363  *      \param cnt : The no of data byte of to be read
364  */
365 s8 BME280_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
366 {
367         s32 iError = BME280_INIT_VALUE;
368         u8 array[I2C_BUFFER_LEN] = {BME280_INIT_VALUE};
369         u8 stringpos = BME280_INIT_VALUE;
370         array[BME280_INIT_VALUE] = reg_addr;
371         /* Please take the below function as your reference
372          * for read the data using I2C communication
373          * add your I2C rad function here.
374          * "IERROR = I2C_WRITE_READ_STRING(DEV_ADDR, ARRAY, ARRAY, 1, CNT)"
375          * iError is an return value of SPI write function
376          * Please select your valid return value
377      * In the driver SUCCESS defined as 0
378      * and FAILURE defined as -1
379          */
380         for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
381                 *(reg_data + stringpos) = array[stringpos];
382         }
383         return (s8)iError;
384 }
385
386 /*      \Brief: The function is used as SPI bus read
387  *      \Return : Status of the SPI read
388  *      \param dev_addr : The device address of the sensor
389  *      \param reg_addr : Address of the first register, will data is going to be read
390  *      \param reg_data : This data read from the sensor, which is hold in an array
391  *      \param cnt : The no of byte of data to be read
392  */
393 s8 BME280_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
394 {
395         s32 iError=BME280_INIT_VALUE;
396         u8 array[SPI_BUFFER_LEN]={0,};
397         u8 stringpos;
398         /*      For the SPI mode only 7 bits of register addresses are used.
399         The MSB of register address is declared the bit what functionality it is
400         read/write (read as 1/write as BME280_INIT_VALUE)*/
401         array[BME280_INIT_VALUE] = reg_addr|SPI_READ;/*read routine is initiated register address is mask with 0x80*/
402         /*
403         * Please take the below function as your reference for
404         * read the data using SPI communication
405         * " IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1)"
406         * add your SPI read function here
407         * iError is an return value of SPI read function
408         * Please select your valid return value
409         * In the driver SUCCESS defined as 0
410         * and FAILURE defined as -1
411         * Note :
412         * This is a full duplex operation,
413         * The first read data is discarded, for that extra write operation
414         * have to be initiated. For that cnt+1 operation done in the SPI read
415         * and write string function
416         * For more information please refer data sheet SPI communication:
417         */
418         for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
419                 *(reg_data + stringpos) = array[stringpos+BME280_DATA_INDEX];
420         }
421         return (s8)iError;
422 }
423
424 /*      \Brief: The function is used as SPI bus write
425  *      \Return : Status of the SPI write
426  *      \param dev_addr : The device address of the sensor
427  *      \param reg_addr : Address of the first register, where data is to be written
428  *      \param reg_data : It is a value hold in the array,
429  *              will be used for write the value into the register
430  *      \param cnt : The no of byte of data to be write
431  */
432 s8 BME280_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
433 {
434         s32 iError = BME280_INIT_VALUE;
435         u8 array[SPI_BUFFER_LEN * BME280_ADDRESS_INDEX];
436         u8 stringpos = BME280_INIT_VALUE;
437         u8 index = BME280_INIT_VALUE;
438         for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) {
439                 /* the operation of (reg_addr++)&0x7F done as per the
440                 SPI communication protocol specified in the data sheet*/
441                 index = stringpos * BME280_ADDRESS_INDEX;
442                 array[index] = (reg_addr++) & SPI_WRITE;
443                 array[index + BME280_DATA_INDEX] = *(reg_data + stringpos);
444         }
445         /* Please take the below function as your reference
446          * for write the data using SPI communication
447          * add your SPI write function here.
448          * "IERROR = SPI_WRITE_STRING(ARRAY, CNT*2)"
449          * iError is an return value of SPI write function
450          * Please select your valid return value
451          * In the driver SUCCESS defined as 0
452          * and FAILURE defined as -1
453          */
454         return (s8)iError;
455 }
456
457 /*      Brief : The delay routine
458  *      \param : delay in ms
459 */
460 void BME280_delay_msek(u32 msek)
461 {
462         /*Here you can write your own delay routine*/
463 }
464 #endif