New I2C devices
[owSlave2.git] / common / I2C / BME680.c
1 // Copyright (c) 2015, Tobias Mueller tm(at)tm3d.de
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //  * Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
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
13 //    distribution.
14 //  * All advertising materials mentioning features or use of this
15 //    software must display the following acknowledgement: This product
16 //    includes software developed by tm3d.de and its contributors.
17 //  * Neither the name of tm3d.de nor the names of its contributors may
18 //    be used to endorse or promote products derived from this software
19 //    without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #ifdef  __4MHZ__
33 #define F_CPU 4000000UL
34 #else
35 #define F_CPU 8000000UL
36 #endif
37 #include <avr/io.h>
38
39
40 /** Array Index to Field data mapping for Calibration Data*/
41 #define BME680_T2_LSB_REG       (1)
42 #define BME680_T2_MSB_REG       (2)
43 #define BME680_T3_REG           (3)
44 #define BME680_P1_LSB_REG       (5)
45 #define BME680_P1_MSB_REG       (6)
46 #define BME680_P2_LSB_REG       (7)
47 #define BME680_P2_MSB_REG       (8)
48 #define BME680_P3_REG           (9)
49 #define BME680_P4_LSB_REG       (11)
50 #define BME680_P4_MSB_REG       (12)
51 #define BME680_P5_LSB_REG       (13)
52 #define BME680_P5_MSB_REG       (14)
53 #define BME680_P7_REG           (15)
54 #define BME680_P6_REG           (16)
55 #define BME680_P8_LSB_REG       (19)
56 #define BME680_P8_MSB_REG       (20)
57 #define BME680_P9_LSB_REG       (21)
58 #define BME680_P9_MSB_REG       (22)
59 #define BME680_P10_REG          (23)
60 #define BME680_H2_MSB_REG       (25)
61 #define BME680_H2_LSB_REG       (26)
62 #define BME680_H1_LSB_REG       (26)
63 #define BME680_H1_MSB_REG       (27)
64 #define BME680_H3_REG           (28)
65 #define BME680_H4_REG           (29)
66 #define BME680_H5_REG           (30)
67 #define BME680_H6_REG           (31)
68 #define BME680_H7_REG           (32)
69 #define BME680_T1_LSB_REG       (33)
70 #define BME680_T1_MSB_REG       (34)
71 #define BME680_GH2_LSB_REG      (35)
72 #define BME680_GH2_MSB_REG      (36)
73 #define BME680_GH1_REG          (37)
74 #define BME680_GH3_REG  (38)
75
76
77 #include <util/delay.h>
78 #include <avr/pgmspace.h>
79
80 #include "USI_TWI_Master.h"
81 #include "BME680.h"
82
83 #define WC 0b11101100
84 #define RC 0b11101101
85 typedef union {
86         volatile uint8_t d[41];
87         struct {
88                 uint8_t fr1;
89                 int16_t t2;
90                 int8_t t3;
91                 uint8_t fr2; //4
92                 uint16_t p1;
93                 int16_t p2; //7
94                 int8_t p3;
95                 uint8_t fr3; //10
96                 int16_t p4;
97                 int16_t p5;
98                 int8_t p7;
99                 int8_t p6;
100                 uint8_t fr4[2]; //17-18
101                 int16_t p8;
102                 int16_t p9;
103                 uint8_t p10;
104                 uint8_t fr5; //24
105                 uint16_t h2_; //25 +26
106                 uint8_t h1_;  //halb und halb 26+27
107                 int8_t h3;
108                 int8_t h4;
109                 int8_t h5;
110                 uint8_t h6;
111                 int8_t h7;//32
112                 uint16_t t1;
113                 int16_t gh2;
114                 int8_t gh1;
115                 int8_t gh3; //38
116                 int8_t fr6;// 39;
117                 int8_t fr7; //40;
118                 uint16_t h2; //Berechnung
119                 uint16_t h1; //Berechnung       
120                 int32_t t_fine; //Berechnung bei Temperaturmessung      
121                 uint8_t  res_heat_range;/**<resistance calculation*/
122                 int8_t  res_heat_val; /**<correction factor*/
123                 int8_t  range_switching_error;/**<range switching error*/
124                 int8_t ltemp; //letzte Temperatur
125         };
126 } calib_t;
127
128 volatile calib_t calib;
129
130
131 #define BME680_CALIB_I2C_ADDR_1                         (0x89)
132 #define BME680_CALIB_I2C_ADDR_2                         (0xE1)
133 #define BME680_PAGE0_I2C_ID_REG                         (0xD0)
134 #define BME680_CALIB_DATA_LENGTH_GAS                    (25)
135 #define BME680_CALIB_DATA_LENGTH                        (16)
136
137
138 #define BME680_MAX_HUMIDITY_VALUE               (102400)
139 #define BME680_MIN_HUMIDITY_VALUE               (0)
140
141
142 //ME680_CALIB_I2C_ADDR_1,
143 //                                              a_data_u8,
144 //                                              BME680_CALIB_DATA_LENGTH_GAS);
145                                 /* read the humidity and gas
146                                 calibration data*/
147 /*                              com_status = (enum bme680_return_type)
148                                              bme680->bme680_bus_read(
149                                              bme680->dev_addr,
150                                              BME680_CALIB_I2C_ADDR_2,
151                                             (a_data_u8 +
152                                             BME680_CALIB_DATA_LENGTH_GAS),
153                                             BME680_CALIB_DATA_LENGTH);
154
155
156
157                                                 */
158
159
160 void setup_read(uint8_t addr) {
161         I2c_StartCondition();
162         I2c_WriteByte(WC);
163         I2c_WriteByte(addr);  //Ctrl hum
164         I2c_StartCondition();
165         I2c_WriteByte (RC);
166         
167 }
168
169 void setup_write(uint8_t addr) {
170         I2c_StartCondition();
171         I2c_WriteByte(WC);
172         I2c_WriteByte(addr);  //Ctrl hum
173 }
174
175
176 uint8_t readone(uint8_t addr) {
177         setup_read(addr);
178         uint8_t b=I2c_ReadByte(NO_ACK);
179         I2c_StopCondition();
180         return b;
181 }
182
183 void writeone(uint8_t addr,uint8_t b) {
184         setup_write(addr);
185         I2c_WriteByte(b);  //Ctrl hum
186         I2c_StopCondition();
187 }
188
189 int8_t initBME680() {
190         uint8_t b1=readone(0xD0);
191         setup_read(BME680_CALIB_I2C_ADDR_1);
192         for(uint8_t i=0;i<BME680_CALIB_DATA_LENGTH_GAS-1;i++) {
193                 calib.d[i]=I2c_ReadByte(ACK);
194         }
195         calib.d[BME680_CALIB_DATA_LENGTH_GAS-1]=I2c_ReadByte(NO_ACK);
196         I2c_StopCondition();
197
198         setup_read(BME680_CALIB_I2C_ADDR_2);
199         for(uint8_t i=BME680_CALIB_DATA_LENGTH_GAS;i<BME680_CALIB_DATA_LENGTH_GAS+BME680_CALIB_DATA_LENGTH-1;i++) {
200                 calib.d[i]=I2c_ReadByte(ACK);
201         }
202         calib.d[BME680_CALIB_DATA_LENGTH_GAS+BME680_CALIB_DATA_LENGTH-1]=I2c_ReadByte(NO_ACK);
203         I2c_StopCondition();
204         calib.res_heat_range=(readone(0x02)&0x30)>>4;
205         calib.res_heat_val=readone(0);
206         calib.range_switching_error=(readone(0x04)& 0xF0)>>4;
207
208
209     calib.h1 = (uint16_t)(((((uint16_t)calib.d[ BME680_H1_MSB_REG]))
210                 << 4) | (calib.d[ BME680_H1_LSB_REG] &0x0F));
211         calib.h2 = (uint16_t)(((((uint16_t)calib.d[ BME680_H2_MSB_REG]))
212                 << 4) | ((calib.d[ BME680_H2_LSB_REG]) >> 4));
213
214         
215         /*
216         
217         I2c_StartCondition();
218         I2c_WriteByte(WC);
219         I2c_WriteByte(0x72);  //Ctrl hum
220         I2c_WriteByte(0x01); //1x oversembling hum
221         I2c_WriteByte(0x74);  //Ctrl hum
222         I2c_WriteByte(0b01010101); //2x oversembling t - 16x oversemmping p - mode cont
223         I2c_StopCondition();    
224
225         */
226         calib.ltemp=25;
227
228         return b1==0x61;
229
230 }
231
232
233 const float lookup_k1_range[16] PROGMEM = {
234         1, 1, 1, 1, 1,0.99, 1, 0.992,
235 1, 1, 0.998, 0.995, 1, 0.99, 1, 1};
236 const float lookup_k2_range[16] PROGMEM = {
237         8e6, 4e6, 2e6, 1e6,499500.4995, 248262.1648, 125000, 63004.03226,
238 31281.28128, 15625, 7812.5, 3906.25,1953.125,976.5625, 488.28125, 244.140625};
239
240 double bme680_compensate_gas_double(uint16_t gas_adc_u16, uint8_t gas_range_u8)
241 {
242         double gas_res_d = 0;
243
244         
245         
246         int8_t range_switching_error_val = 0;
247
248         double var1 = 0;
249         float a1= pgm_read_float(&(lookup_k1_range[gas_range_u8]));
250         float a2= pgm_read_float(&(lookup_k2_range[gas_range_u8]));
251
252         range_switching_error_val =     calib.range_switching_error;
253
254
255         var1 = (1340.0 + (5.0 * range_switching_error_val))*a1;
256         gas_res_d = var1*a2/(gas_adc_u16-512.0+var1);
257         return gas_res_d;
258 }
259
260
261 void readBMP680(int16_t *T,uint16_t *H,uint32_t *P,uint16_t *G){
262
263
264         
265         int32_t var1 ;
266         int32_t var2 ;
267         int32_t var3 ;
268         int32_t var4 ;
269         int32_t var5 ;
270         int32_t res_heat_x100 = 0;
271         uint8_t res_heat = 0;
272         uint16_t heater_temp_u16=350;
273         int16_t ambient_temp_s16=calib.ltemp;
274         if ((heater_temp_u16 >= 200) && (heater_temp_u16 <= 400)) {
275                 var1 = (((int32_t)ambient_temp_s16 *
276                 calib.gh3) / 10) << 8;
277                 var2 = (calib.gh1 + 784) *
278                 (((((calib.gh2 + 154009) *
279                 heater_temp_u16 * 5) / 100) + 3276800) / 10);
280                 var3 = var1 + (var2 >> 1);
281                 var4 = (var3 / (calib.res_heat_range + 4));
282
283                 var5 = (131 * calib.res_heat_val) + 65536;
284
285                 res_heat_x100 = (int32_t)(((var4 / var5) - 250) * 34);
286                 res_heat = (uint8_t) ((res_heat_x100 + 50) / 100);
287         }
288         uint16_t duration=100;
289         uint8_t factor = 0;
290
291         while ((duration) > 0x3F) {
292                 (duration) = (duration) >> 2;
293                 factor += 1;
294         }
295         (duration) = (duration) + (factor * 64);
296
297         //I2c_WriteByte(0x74);  //Ctrl hum
298         //I2c_WriteByte(0b01010101); //2x oversembling t - 16x oversemmping p - mode cont
299         // [71] <- 10;  [72] <- 04;  [73] <- 0C;  [74] <- 91;  [75] <- 00;
300         // [70] <- 00     [71] <- 10;  [72] <- 04;  [73] <- 0C;  [74] <- 91;  [75] <- 00;
301         setup_write(0x70);
302         I2c_WriteByte(0x00);
303         I2c_WriteByte(0x71);
304         I2c_WriteByte(0x10);
305         I2c_WriteByte(0x72);
306         I2c_WriteByte(0x04);
307         I2c_WriteByte(0x73);
308         I2c_WriteByte(0x0C);
309         I2c_WriteByte(0x74);
310         I2c_WriteByte(0x90);
311         I2c_WriteByte(0x75);
312         I2c_WriteByte(0x00);
313
314         I2c_WriteByte(0x5A);
315         I2c_WriteByte(res_heat);
316         I2c_WriteByte(0x64);
317         I2c_WriteByte(duration);
318         I2c_StopCondition();
319
320
321         writeone(0x74,0x91);
322         _delay_ms(1000);
323         
324         uint8_t bx=0x91;
325         while ((bx&0x01)==0x01) {
326                 bx=readone(0x74);
327                 _delay_ms(5);
328         }
329
330         //volatile uint8_t rs=readone(0x2B);
331         uint32_t Th,Hh,Ph;
332         setup_read(0x1F);
333         Ph=I2c_ReadByte(ACK);Ph=Ph<<8;
334         Ph|=I2c_ReadByte(ACK);Ph=Ph<<4;
335         Ph|=I2c_ReadByte(ACK)>>4;
336         Th=I2c_ReadByte(ACK);Th=Th<<8;
337         Th|=I2c_ReadByte(ACK);Th=Th<<4;
338         Th|=I2c_ReadByte(ACK)>>4;       
339         Hh=I2c_ReadByte(ACK);Hh=Hh<<8;
340         Hh|=I2c_ReadByte(NO_ACK);
341         I2c_StopCondition();
342         setup_read(0x2A);
343         volatile uint8_t g1=I2c_ReadByte(ACK);
344         volatile uint8_t g2=I2c_ReadByte(NO_ACK);
345         I2c_StopCondition();
346         *G=(((uint16_t)g1)<<2)|(g2>>6);
347         *P=*G;
348         *G= bme680_compensate_gas_double(*G,g2&0xF)/10.0;
349
350         int32_t temp_comp = 0;
351
352         var1 = ((int32_t)Th >> 3) -
353         ((int32_t)calib.t1 << 1);
354         var2 = (var1 * (int32_t)calib.t2) >> 11;
355         var3 = ((((var1 >> 1) * (var1 >> 1)) >> 12) *
356         ((int32_t)calib.t3 << 4)) >> 14;
357         calib.t_fine = var2 + var3;
358         temp_comp = ((calib.t_fine * 5) + 128) >> 8;
359
360         int32_t temp_scaled = 0;
361         int32_t var6    = 0;
362         int32_t humidity_comp = 0;
363
364         temp_scaled = (((int32_t)calib.t_fine * 5) + 128) >> 8;
365         var1 = (int32_t)Hh -
366                 ((int32_t)((int32_t)calib.h1 << 4)) -
367                 (((temp_scaled * (int32_t)calib.h3) /
368                 ((int32_t)100)) >> 1);
369
370         var2 = ((int32_t)calib.h2 *
371                 (((temp_scaled * (int32_t)calib.h4) /
372                 ((int32_t)100)) + (((temp_scaled *
373                 ((temp_scaled * (int32_t)calib.h5) /
374                 ((int32_t)100))) >> 6) / ((int32_t)100)) + (int32_t)(1 << 14))) >> 10;
375
376         var3 = var1 * var2;
377
378         var4 = ((((int32_t)calib.h6) << 7) +
379                 ((temp_scaled * (int32_t)calib.h7) /
380                 ((int32_t)100))) >> 4;
381
382         var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
383         var6 = (var4 * var5) >> 1;
384
385         humidity_comp = (var3 + var6) >> 12;
386         if (humidity_comp > BME680_MAX_HUMIDITY_VALUE)
387                 humidity_comp = BME680_MAX_HUMIDITY_VALUE;
388                 else if (humidity_comp < BME680_MIN_HUMIDITY_VALUE)
389                 humidity_comp = BME680_MIN_HUMIDITY_VALUE;
390
391     int32_t pressure_comp = 0;//int -> 5684
392
393     var1 = (((int32_t)calib.t_fine) >> 1) - (int32_t)64000;
394     var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) *
395     (int32_t)calib.p6) >> 2;
396     var2 = var2 + ((var1 * (int32_t)calib.p5) << 1);
397     var2 = (var2 >> 2) + ((int32_t)calib.p4 << 16);
398     var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
399     ((int32_t)calib.p3 << 5)) >> 3) +
400     (((int32_t)calib.p2 * var1) >> 1);
401     var1 = var1 >> 18;
402     var1 = (((int32_t)32768 + var1) * (int32_t)calib.p1) >> 15;
403     pressure_comp = (int32_t)1048576 - Ph;
404     pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125));
405     var4 = ((int32_t)1 << 31);
406     if (pressure_comp >= var4)
407     pressure_comp = ((pressure_comp / (uint32_t)var1) << 1);
408     else
409     pressure_comp = ((pressure_comp << 1) / (uint32_t)var1);
410     var1 = ((int32_t)calib.p9 * (int32_t)(((pressure_comp >> 3) *
411     (pressure_comp >> 3)) >> 13)) >> 12;
412     var2 = ((int32_t)(pressure_comp >> 2) *
413     (int32_t)calib.p8) >> 13;
414     var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) *
415     (int32_t)(pressure_comp >> 8) *
416     (int32_t)calib.p10) >> 17;
417
418     pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 +
419     ((int32_t)calib.p7 << 7)) >> 4);
420
421
422
423
424         
425         *T=(int16_t)temp_comp;
426         calib.ltemp=temp_comp/100;
427         //*P=pressure_comp;
428         *H=(uint16_t)(humidity_comp/10);
429         //*P=rs;
430         *T=g1;
431         *H=g2;
432         //*P=
433
434
435 }
436