uni

University stuff
git clone git://git.margiolis.net/uni.git
Log | Files | Refs | README | LICENSE

bme280.c (4780B)


      1 #include "bme280.h"
      2 #include "i2c.h"
      3 #include "tmr0.h"
      4 
      5 #define MODE_WRITE 0
      6 #define MODE_READ 1
      7 
      8 #define BME280_DELAY		100
      9 
     10 #define BME280_SAMPLE_SKIP	0x00
     11 #define BME280_SAMPLE_X1	0x01
     12 #define BME280_FILTER_OFF	0x00
     13 #define BME280_STANDBY_0_5	0x00
     14 #define BME280_MODE_NORMAL	0x03
     15 #define BME280_RESET_POWERON	0xb6
     16 
     17 #define BME280_ADDR		0xee
     18 #define BME280_CHIPID		0x60
     19 
     20 #define BME280_REG_DIG_T1	0x88
     21 #define BME280_REG_DIG_T2	0x8a
     22 #define BME280_REG_DIG_T3	0x8c
     23 
     24 #define BME280_REG_DIG_H1	0xa1
     25 #define BME280_REG_DIG_H2	0xe1
     26 #define BME280_REG_DIG_H3	0xe3
     27 #define BME280_REG_DIG_H4	0xe4
     28 #define BME280_REG_DIG_H5	0xe5
     29 #define BME280_REG_DIG_H6	0xe7
     30 
     31 #define BME280_REG_CHIPID	0xd0
     32 #define BME280_REG_SOFTRESET	0xe0
     33 
     34 #define BME280_REG_CTLHUM	0xf2
     35 #define BME280_REG_STATUS	0xf3
     36 #define BME280_REG_CTL		0xf4
     37 #define BME280_REG_CONFIG	0xf5
     38 #define BME280_REG_PRESS_MSB	0xf7
     39 
     40 struct bme280_calib {
     41 	uint16_t	dig_t1;
     42 	int16_t		dig_t2;
     43 	int16_t 	dig_t3;
     44 	/* Pressure fields are not used to preserve space. */
     45 	uint8_t 	dig_h1;
     46 	int16_t 	dig_h2;
     47 	uint8_t 	dig_h3;
     48 	int16_t 	dig_h4;
     49 	int16_t 	dig_h5;
     50 	int8_t  	dig_h6;
     51 };
     52 
     53 static void	bme280_write(uint8_t, uint8_t);
     54 static uint8_t	bme280_read8(uint8_t);
     55 static uint16_t	bme280_read16(uint8_t);
     56 static void	bme280_update(void);
     57 
     58 static struct bme280_calib cal;
     59 static int32_t adc_t, adc_h, t_fine;
     60 
     61 static void
     62 bme280_write(uint8_t reg, uint8_t dat)
     63 {
     64 	i2c_start();
     65 	i2c_write(BME280_ADDR | MODE_WRITE);
     66 	i2c_write(reg);
     67 	i2c_write(dat);
     68 	i2c_stop();
     69 }
     70 
     71 static uint8_t
     72 bme280_read8(uint8_t reg)
     73 {
     74 	uint8_t c;
     75 
     76 	i2c_start();
     77 	i2c_write(BME280_ADDR | MODE_WRITE);
     78 	i2c_write(reg);
     79 	i2c_restart();
     80 	i2c_write(BME280_ADDR | MODE_READ);
     81 	c = i2c_read(0);
     82 	i2c_stop();
     83 	return (c);
     84 }
     85 
     86 static uint16_t
     87 bme280_read16(uint8_t reg)
     88 {
     89 	uint16_t c;
     90 
     91 	i2c_start();
     92 	i2c_write(BME280_ADDR | MODE_WRITE);
     93 	i2c_write(reg);
     94 	i2c_restart();
     95 	i2c_write(BME280_ADDR | MODE_READ);
     96 	c = i2c_read(1);
     97 	c |= i2c_read(0) << 8;
     98 	i2c_stop();
     99 	return (c);
    100 }
    101 
    102 static void
    103 bme280_update(void)
    104 {
    105 	union {
    106 		uint8_t a[4];
    107 		uint32_t v;
    108 	} r;
    109 
    110 	i2c_start();
    111 	i2c_write(BME280_ADDR | MODE_WRITE);
    112 	i2c_write(BME280_REG_PRESS_MSB);
    113 	i2c_restart();
    114 	i2c_write(BME280_ADDR | MODE_READ);
    115 
    116 	/* Ignore pressure */
    117 	(void)i2c_read(1);
    118 	(void)i2c_read(1);
    119 	(void)i2c_read(1);
    120 
    121 	r.a[3] = 0x00;
    122 	r.a[2] = i2c_read(1);
    123 	r.a[1] = i2c_read(1);
    124 	r.a[0] = i2c_read(1);
    125 	adc_t = (r.v >> 4) & 0xfffff;
    126 
    127 	r.a[2] = 0x00;
    128 	r.a[1] = i2c_read(1);
    129 	r.a[0] = i2c_read(0);
    130 	adc_h = r.v & 0xffff;
    131 
    132 	i2c_stop();
    133 }
    134 
    135 int
    136 bme280_init(void)
    137 {
    138 	if (bme280_read8(BME280_REG_CHIPID) != BME280_CHIPID)
    139 		return (-1);
    140 	bme280_write(BME280_REG_SOFTRESET, BME280_RESET_POWERON);
    141 	tmr0_delay_ms(BME280_DELAY);
    142 	while ((bme280_read8(BME280_REG_STATUS) & 0x01) == 0x01)
    143 		tmr0_delay_ms(BME280_DELAY);
    144 
    145 	cal.dig_t1 = bme280_read16(BME280_REG_DIG_T1);
    146 	cal.dig_t2 = bme280_read16(BME280_REG_DIG_T2);
    147 	cal.dig_t3 = bme280_read16(BME280_REG_DIG_T3);
    148 
    149 	cal.dig_h1 = bme280_read8(BME280_REG_DIG_H1);
    150 	cal.dig_h2 = bme280_read16(BME280_REG_DIG_H2);
    151 	cal.dig_h3 = bme280_read8(BME280_REG_DIG_H3);
    152 	cal.dig_h4 = ((uint16_t)bme280_read8(BME280_REG_DIG_H4) << 4) |
    153 	    (bme280_read8(BME280_REG_DIG_H4 + 1) & 0x0f);
    154 	if (cal.dig_h4 & 0x0800)	/* H4 < 0 */
    155 		cal.dig_h4 |= 0xf000;
    156 	cal.dig_h5 = ((uint16_t)bme280_read8(BME280_REG_DIG_H5 + 1) << 4) |
    157 	    (bme280_read8(BME280_REG_DIG_H5) >> 4);
    158 	if (cal.dig_h5 & 0x0800)	/* H5 < 0 */
    159 		cal.dig_h5 |= 0xf000;
    160 	cal.dig_h6 = bme280_read8(BME280_REG_DIG_H6);
    161 
    162 	bme280_write(BME280_REG_CTLHUM, BME280_SAMPLE_X1);
    163 	bme280_write(BME280_REG_CONFIG, ((BME280_STANDBY_0_5 << 5) |
    164 	    (BME280_FILTER_OFF << 2)) & 0xfc);
    165 	bme280_write(BME280_REG_CTL, ((BME280_SAMPLE_X1 << 5) |
    166 	    (BME280_SAMPLE_SKIP << 2)) | BME280_MODE_NORMAL);
    167 
    168 	tmr0_delay_ms(BME280_DELAY);
    169 
    170 	return (0);
    171 }
    172 
    173 /* Black magic taken (stolen) from BME280's datasheet. */
    174 int32_t
    175 bme280_read_temp(void)
    176 {
    177 	int32_t v1, v2;
    178 
    179 	bme280_update();
    180 	v1 = ((((adc_t >> 3) - ((int32_t)cal.dig_t1 << 1))) *
    181 	    ((int32_t)cal.dig_t2)) >> 11;
    182 	v2 = (((((adc_t >> 4) - ((int32_t)cal.dig_t1)) *
    183 	    ((adc_t >> 4) - ((int32_t)cal.dig_t1))) >> 12) *
    184 	    ((int32_t)cal.dig_t3)) >> 14;
    185 
    186 	t_fine = v1 + v2;
    187 
    188 	return ((t_fine * 5 + 128) / 256);
    189 }
    190 
    191 uint32_t
    192 bme280_read_humid(void)
    193 {
    194 	int32_t v = 0;
    195 
    196 	bme280_update();
    197 	v = (t_fine - ((int32_t)76800));
    198  
    199 	v = (((((adc_h << 14) - (((int32_t)cal.dig_h4) << 20) -
    200 	    (((int32_t)cal.dig_h5) * v)) + ((int32_t)16384)) >> 15) *
    201 	    (((((((v * ((int32_t)cal.dig_h6)) >> 10) *
    202 	    (((v * ((int32_t)cal.dig_h3)) >> 11) + ((int32_t)32768))) >> 10) +
    203 	    ((int32_t)2097152)) * ((int32_t)cal.dig_h2) + 8192) >> 14));
    204 
    205 	v = (v - (((((v >> 15) * (v >> 15)) >> 7) * ((int32_t)cal.dig_h1)) >> 4));
    206 	v = (v < 0 ? 0 : v);
    207 	v = (v > 419430400 ? 419430400 : v);
    208    
    209 	return ((uint32_t)(v >> 12));
    210 }