1 /*
2  * Copyright (c) 2016, 2017 Intel Corporation
3  * Copyright (c) 2017 IpTronix S.r.l.
4  * Copyright (c) 2021 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #ifndef ZEPHYR_DRIVERS_SENSOR_BME280_BME280_H_
10 #define ZEPHYR_DRIVERS_SENSOR_BME280_BME280_H_
11 
12 #include <zephyr/types.h>
13 #include <zephyr/device.h>
14 #include <zephyr/devicetree.h>
15 #include <zephyr/drivers/spi.h>
16 #include <zephyr/drivers/i2c.h>
17 #include <zephyr/drivers/sensor.h>
18 #include <zephyr/rtio/rtio.h>
19 
20 #define DT_DRV_COMPAT bosch_bme280
21 
22 #define BME280_BUS_SPI DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
23 #define BME280_BUS_I2C DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
24 
25 union bme280_bus {
26 #if BME280_BUS_SPI
27 	struct spi_dt_spec spi;
28 #endif
29 #if BME280_BUS_I2C
30 	struct i2c_dt_spec i2c;
31 #endif
32 };
33 
34 typedef int (*bme280_bus_check_fn)(const union bme280_bus *bus);
35 typedef int (*bme280_reg_read_fn)(const union bme280_bus *bus, uint8_t start, uint8_t *buf,
36 				  int size);
37 typedef int (*bme280_reg_write_fn)(const union bme280_bus *bus, uint8_t reg, uint8_t val);
38 
39 struct bme280_bus_io {
40 	bme280_bus_check_fn check;
41 	bme280_reg_read_fn read;
42 	bme280_reg_write_fn write;
43 };
44 
45 #if BME280_BUS_SPI
46 #define BME280_SPI_OPERATION (SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA)
47 extern const struct bme280_bus_io bme280_bus_io_spi;
48 #endif
49 
50 #if BME280_BUS_I2C
51 extern const struct bme280_bus_io bme280_bus_io_i2c;
52 #endif
53 
54 #define BME280_REG_PRESS_MSB      0xF7
55 #define BME280_REG_COMP_START     0x88
56 #define BME280_REG_HUM_COMP_PART1 0xA1
57 #define BME280_REG_HUM_COMP_PART2 0xE1
58 #define BME280_REG_ID             0xD0
59 #define BME280_REG_CONFIG         0xF5
60 #define BME280_REG_CTRL_MEAS      0xF4
61 #define BME280_REG_CTRL_HUM       0xF2
62 #define BME280_REG_STATUS         0xF3
63 #define BME280_REG_RESET          0xE0
64 
65 #define BMP280_CHIP_ID_SAMPLE_1 0x56
66 #define BMP280_CHIP_ID_SAMPLE_2 0x57
67 #define BMP280_CHIP_ID_MP       0x58
68 #define BME280_CHIP_ID          0x60
69 #define BME280_MODE_SLEEP       0x00
70 #define BME280_MODE_FORCED      0x01
71 #define BME280_MODE_NORMAL      0x03
72 #define BME280_SPI_3W_DISABLE   0x00
73 #define BME280_CMD_SOFT_RESET   0xB6
74 #define BME280_STATUS_MEASURING 0x08
75 #define BME280_STATUS_IM_UPDATE 0x01
76 
77 #if defined CONFIG_BME280_MODE_NORMAL
78 #define BME280_MODE BME280_MODE_NORMAL
79 #elif defined CONFIG_BME280_MODE_FORCED
80 #define BME280_MODE BME280_MODE_FORCED
81 #endif
82 
83 #if defined CONFIG_BME280_TEMP_OVER_1X
84 #define BME280_TEMP_OVER        (1 << 5)
85 #define BME280_TEMP_SAMPLE_TIME 2
86 #elif defined CONFIG_BME280_TEMP_OVER_2X
87 #define BME280_TEMP_OVER        (2 << 5)
88 #define BME280_TEMP_SAMPLE_TIME 4
89 #elif defined CONFIG_BME280_TEMP_OVER_4X
90 #define BME280_TEMP_OVER        (3 << 5)
91 #define BME280_TEMP_SAMPLE_TIME 8
92 #elif defined CONFIG_BME280_TEMP_OVER_8X
93 #define BME280_TEMP_OVER        (4 << 5)
94 #define BME280_TEMP_SAMPLE_TIME 16
95 #elif defined CONFIG_BME280_TEMP_OVER_16X
96 #define BME280_TEMP_OVER        (5 << 5)
97 #define BME280_TEMP_SAMPLE_TIME 32
98 #endif
99 
100 #if defined CONFIG_BME280_PRESS_OVER_1X
101 #define BME280_PRESS_OVER        (1 << 2)
102 #define BME280_PRESS_SAMPLE_TIME 2
103 #elif defined CONFIG_BME280_PRESS_OVER_2X
104 #define BME280_PRESS_OVER        (2 << 2)
105 #define BME280_PRESS_SAMPLE_TIME 4
106 #elif defined CONFIG_BME280_PRESS_OVER_4X
107 #define BME280_PRESS_OVER        (3 << 2)
108 #define BME280_PRESS_SAMPLE_TIME 8
109 #elif defined CONFIG_BME280_PRESS_OVER_8X
110 #define BME280_PRESS_OVER        (4 << 2)
111 #define BME280_PRESS_SAMPLE_TIME 16
112 #elif defined CONFIG_BME280_PRESS_OVER_16X
113 #define BME280_PRESS_OVER        (5 << 2)
114 #define BME280_PRESS_SAMPLE_TIME 32
115 #endif
116 
117 #if defined CONFIG_BME280_HUMIDITY_OVER_1X
118 #define BME280_HUMIDITY_OVER        1
119 #define BME280_HUMIDITY_SAMPLE_TIME 2
120 #elif defined CONFIG_BME280_HUMIDITY_OVER_2X
121 #define BME280_HUMIDITY_OVER        2
122 #define BME280_HUMIDITY_SAMPLE_TIME 4
123 #elif defined CONFIG_BME280_HUMIDITY_OVER_4X
124 #define BME280_HUMIDITY_OVER        3
125 #define BME280_HUMIDITY_SAMPLE_TIME 8
126 #elif defined CONFIG_BME280_HUMIDITY_OVER_8X
127 #define BME280_HUMIDITY_OVER        4
128 #define BME280_HUMIDITY_SAMPLE_TIME 16
129 #elif defined CONFIG_BME280_HUMIDITY_OVER_16X
130 #define BME280_HUMIDITY_OVER        5
131 #define BME280_HUMIDITY_SAMPLE_TIME 32
132 #endif
133 
134 #if defined CONFIG_BME280_STANDBY_05MS
135 #define BME280_STANDBY 0
136 #elif defined CONFIG_BME280_STANDBY_62MS
137 #define BME280_STANDBY (1 << 5)
138 #elif defined CONFIG_BME280_STANDBY_125MS
139 #define BME280_STANDBY (2 << 5)
140 #elif defined CONFIG_BME280_STANDBY_250MS
141 #define BME280_STANDBY (3 << 5)
142 #elif defined CONFIG_BME280_STANDBY_500MS
143 #define BME280_STANDBY (4 << 5)
144 #elif defined CONFIG_BME280_STANDBY_1000MS
145 #define BME280_STANDBY (5 << 5)
146 #elif defined CONFIG_BME280_STANDBY_2000MS
147 #define BME280_STANDBY (6 << 5)
148 #elif defined CONFIG_BME280_STANDBY_4000MS
149 #define BME280_STANDBY (7 << 5)
150 #endif
151 
152 #if defined CONFIG_BME280_FILTER_OFF
153 #define BME280_FILTER 0
154 #elif defined CONFIG_BME280_FILTER_2
155 #define BME280_FILTER (1 << 2)
156 #elif defined CONFIG_BME280_FILTER_4
157 #define BME280_FILTER (2 << 2)
158 #elif defined CONFIG_BME280_FILTER_8
159 #define BME280_FILTER (3 << 2)
160 #elif defined CONFIG_BME280_FILTER_16
161 #define BME280_FILTER (4 << 2)
162 #endif
163 
164 #define BME280_CTRL_MEAS_VAL (BME280_PRESS_OVER | BME280_TEMP_OVER | BME280_MODE)
165 #define BME280_CONFIG_VAL    (BME280_STANDBY | BME280_FILTER | BME280_SPI_3W_DISABLE)
166 
167 #define BME280_CTRL_MEAS_OFF_VAL (BME280_PRESS_OVER | BME280_TEMP_OVER | BME280_MODE_SLEEP)
168 
169 /* Convert to Q15.16 */
170 #define BME280_TEMP_CONV      100
171 #define BME280_TEMP_SHIFT     16
172 /* Treat UQ24.8 as Q23.8
173  * Need to divide by 1000 to convert to kPa
174  */
175 #define BME280_PRESS_CONV_KPA 1000
176 #define BME280_PRESS_SHIFT    23
177 /* Treat UQ22.10 as Q21.10 */
178 #define BME280_HUM_SHIFT      21
179 
180 struct bme280_reading {
181 	/* Compensated values. */
182 	int32_t comp_temp;
183 	uint32_t comp_press;
184 	uint32_t comp_humidity;
185 };
186 
187 struct bme280_data {
188 	/* Compensation parameters. */
189 	uint16_t dig_t1;
190 	int16_t dig_t2;
191 	int16_t dig_t3;
192 	uint16_t dig_p1;
193 	int16_t dig_p2;
194 	int16_t dig_p3;
195 	int16_t dig_p4;
196 	int16_t dig_p5;
197 	int16_t dig_p6;
198 	int16_t dig_p7;
199 	int16_t dig_p8;
200 	int16_t dig_p9;
201 	uint8_t dig_h1;
202 	int16_t dig_h2;
203 	uint8_t dig_h3;
204 	int16_t dig_h4;
205 	int16_t dig_h5;
206 	int8_t dig_h6;
207 
208 	/* Carryover between temperature and pressure/humidity compensation. */
209 	int32_t t_fine;
210 
211 	uint8_t chip_id;
212 
213 	struct bme280_reading reading;
214 };
215 
216 /*
217  * RTIO
218  */
219 
220 struct bme280_decoder_header {
221 	uint64_t timestamp;
222 } __attribute__((__packed__));
223 
224 struct bme280_encoded_data {
225 	struct bme280_decoder_header header;
226 	struct {
227 		/** Set if `temp` has data */
228 		uint8_t has_temp: 1;
229 		/** Set if `press` has data */
230 		uint8_t has_press: 1;
231 		/** Set if `humidity` has data */
232 		uint8_t has_humidity: 1;
233 	} __attribute__((__packed__));
234 	struct bme280_reading reading;
235 };
236 
237 int bme280_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder);
238 
239 void bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe);
240 
241 int bme280_sample_fetch(const struct device *dev, enum sensor_channel chan);
242 
243 int bme280_sample_fetch_helper(const struct device *dev, enum sensor_channel chan,
244 			       struct bme280_reading *reading);
245 
246 #endif /* ZEPHYR_DRIVERS_SENSOR_BME280_BME280_H_ */
247