1 /* Bosch BMP180 pressure sensor
2 *
3 * Copyright (c) 2024 , Chris Ruehl
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Datasheet:
8 * https://www.mouser.hk/datasheet/2/783/BST-BMP180-DS000-1509579.pdf
9 */
10
11 #include <math.h>
12 #include <zephyr/device.h>
13 #include <zephyr/devicetree.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/sensor.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/pm/device.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/util.h>
20
21 #include "bmp180.h"
22
23 #define DT_DRV_COMPAT bosch_bmp180
24
25 LOG_MODULE_REGISTER(BMP180, CONFIG_SENSOR_LOG_LEVEL);
26
27 /*
28 * byte swap added for signed (int16_t)
29 * and named _u16 and _s16 to make clear what its used for
30 * macro from include/zephyr/sys/byteorder.h
31 */
32 #define BSWAP_u16(x) sys_cpu_to_be16(x)
33 #define BSWAP_s16(x) ((int16_t) sys_cpu_to_be16(x))
34
35 /* Calibration Registers structure */
36 struct bmp180_cal_data {
37 int16_t ac1;
38 int16_t ac2;
39 int16_t ac3;
40 uint16_t ac4;
41 uint16_t ac5;
42 uint16_t ac6;
43 int16_t b1;
44 int16_t b2;
45 int16_t mb;
46 int16_t mc;
47 int16_t md;
48 } __packed;
49
50 struct bmp180_config {
51 const struct i2c_dt_spec i2c;
52 };
53
54 struct bmp180_data {
55 uint8_t osr_pressure;
56 int32_t raw_press;
57 int32_t raw_temp;
58 int32_t comp_temp;
59 struct bmp180_cal_data cal;
60 };
61
bmp180_bus_check(const struct device * dev)62 static inline int bmp180_bus_check(const struct device *dev)
63 {
64 const struct bmp180_config *cfg = dev->config;
65
66 return i2c_is_ready_dt(&cfg->i2c) ? 0 : -ENODEV;
67 }
68
bmp180_reg_read(const struct device * dev,uint8_t start,uint8_t * buf,int size)69 static inline int bmp180_reg_read(const struct device *dev, uint8_t start,
70 uint8_t *buf, int size)
71 {
72 const struct bmp180_config *cfg = dev->config;
73
74 return i2c_burst_read_dt(&cfg->i2c, start, buf, size);
75 }
76
bmp180_reg_write(const struct device * dev,uint8_t reg,uint8_t val)77 static inline int bmp180_reg_write(const struct device *dev, uint8_t reg,
78 uint8_t val)
79 {
80 const struct bmp180_config *cfg = dev->config;
81
82 return i2c_reg_write_byte_dt(&cfg->i2c, reg, val);
83 }
84
85 #ifdef CONFIG_BMP180_OSR_RUNTIME
bmp180_attr_set_oversampling(const struct device * dev,enum sensor_channel chan,uint16_t val)86 static int bmp180_attr_set_oversampling(const struct device *dev,
87 enum sensor_channel chan, uint16_t val)
88 {
89 struct bmp180_data *data = dev->data;
90
91 /* Value must be a positive value 0-3 */
92 if ((chan != SENSOR_CHAN_PRESS) || (val > 3)) {
93 return -EINVAL;
94 }
95
96 data->osr_pressure = val;
97
98 return 0;
99 }
100 #endif /* CONFIG_BMP180_OSR_RUNTIME */
101
bmp180_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)102 static int bmp180_attr_set(const struct device *dev, enum sensor_channel chan,
103 enum sensor_attribute attr,
104 const struct sensor_value *val)
105 {
106 int ret;
107
108 #ifdef CONFIG_PM_DEVICE
109 enum pm_device_state state;
110
111 (void)pm_device_state_get(dev, &state);
112 if (state != PM_DEVICE_STATE_ACTIVE) {
113 return -EBUSY;
114 }
115 #endif /* CONFIG_PM_DEVICE */
116
117 switch (attr) {
118 #ifdef CONFIG_BMP180_OSR_RUNTIME
119 case SENSOR_ATTR_OVERSAMPLING:
120 ret = bmp180_attr_set_oversampling(dev, chan, val->val1);
121 break;
122 #endif /* CONFIG_BMP180_OSR_RUNTIME */
123
124 default:
125 ret = -EINVAL;
126 }
127
128 return ret;
129 }
130
bmp180_conv_ready(const struct device * dev,uint32_t time_wait_ms)131 static inline int bmp180_conv_ready(const struct device *dev, uint32_t time_wait_ms)
132 {
133 int ret;
134 uint8_t ctrlreg;
135 uint8_t retry = 2;
136
137 k_sleep(K_MSEC(time_wait_ms));
138
139 /*
140 * for the first while read 'delay+1' ms which is the convension time
141 * descripted in the data-sheet in case the register not yet ready wait again
142 * and return error if retry exhaused
143 */
144 while (true) {
145 k_sleep(K_MSEC(1));
146 ret = bmp180_reg_read(dev, BMP180_REG_MEAS_CTRL, &ctrlreg, 1);
147 if (ret) {
148 return ret;
149 }
150
151 /* bit 5 is 1 until data registers are ready */
152 if ((ctrlreg & BMP180_STATUS_CMD_RDY) == 0) {
153 break;
154 }
155
156 --retry;
157 if (retry == 0) {
158 return -ETIMEDOUT;
159 }
160 }
161
162 return 0;
163 }
164
read_raw_temperature(const struct device * dev)165 static int read_raw_temperature(const struct device *dev)
166 {
167 int ret;
168 uint8_t reg16[2];
169 struct bmp180_data *data = dev->data;
170
171 /* send temperature measurement command */
172 ret = bmp180_reg_write(dev, BMP180_REG_MEAS_CTRL, BMP180_CMD_GET_TEMPERATURE);
173 if (ret) {
174 return ret;
175 }
176
177 ret = bmp180_conv_ready(dev, BMP180_CMD_GET_TEMP_DELAY);
178 if (ret) {
179 return ret;
180 }
181
182 /* read msb and lsb */
183 ret = bmp180_reg_read(dev, BMP180_REG_MSB, (uint8_t *)®16, 2);
184 if (ret) {
185 return ret;
186 }
187
188 data->raw_temp = (int32_t)(sys_get_be16(reg16));
189 data->comp_temp = 0;
190
191 return 0;
192 }
193
read_raw_pressure(const struct device * dev)194 static int read_raw_pressure(const struct device *dev)
195 {
196 int ret;
197 uint8_t ctrlreg;
198 uint8_t reg24[3];
199 uint32_t delay;
200 int32_t pressure;
201 struct bmp180_data *data = dev->data;
202
203 switch (data->osr_pressure) {
204 case BMP180_ULTRALOWPOWER:
205 ctrlreg = BMP180_CMD_GET_OSS0_PRESS;
206 delay = BMP180_CMD_GET_OSS0_DELAY;
207 break;
208 case BMP180_STANDARD:
209 ctrlreg = BMP180_CMD_GET_OSS1_PRESS;
210 delay = BMP180_CMD_GET_OSS1_DELAY;
211 break;
212 case BMP180_HIGHRES:
213 ctrlreg = BMP180_CMD_GET_OSS2_PRESS;
214 delay = BMP180_CMD_GET_OSS2_DELAY;
215 break;
216 case BMP180_ULTRAHIGH:
217 ctrlreg = BMP180_CMD_GET_OSS3_PRESS;
218 delay = BMP180_CMD_GET_OSS3_DELAY;
219 break;
220 default:
221 return -EINVAL;
222 }
223
224 ret = bmp180_reg_write(dev, BMP180_REG_MEAS_CTRL, ctrlreg);
225 if (ret) {
226 return ret;
227 }
228
229 ret = bmp180_conv_ready(dev, delay);
230 if (ret) {
231 return ret;
232 }
233
234 /* read msb,lsb and xlsb */
235 ret = bmp180_reg_read(dev, BMP180_REG_MSB, (uint8_t *)®24, 3);
236 if (ret) {
237 return ret;
238 }
239
240 pressure = (int32_t)sys_get_be24(reg24);
241 pressure >>= (8 - data->osr_pressure);
242 data->raw_press = pressure;
243
244 return 0;
245 }
246
bmp180_sample_fetch(const struct device * dev,enum sensor_channel chan)247 static int bmp180_sample_fetch(const struct device *dev,
248 enum sensor_channel chan)
249 {
250 int ret = 0;
251
252 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
253
254 #ifdef CONFIG_PM_DEVICE
255 enum pm_device_state state;
256
257 (void)pm_device_state_get(dev, &state);
258 if (state != PM_DEVICE_STATE_ACTIVE) {
259 return -EBUSY;
260 }
261 #endif /* CONFIG_PM_DEVICE */
262
263 pm_device_busy_set(dev);
264
265 ret = read_raw_temperature(dev);
266 if (ret < 0) {
267 goto error;
268 }
269
270 ret = read_raw_pressure(dev);
271
272 error:
273 pm_device_busy_clear(dev);
274 return ret;
275 }
276
bmp180_compensate_temp(struct bmp180_data * data)277 static void bmp180_compensate_temp(struct bmp180_data *data)
278 {
279 int32_t partial_data1;
280 int32_t partial_data2;
281 struct bmp180_cal_data *cal = &data->cal;
282
283 partial_data1 = (data->raw_temp - cal->ac6) * cal->ac5 / 0x8000;
284 partial_data2 = cal->mc * 0x800 / (partial_data1 + cal->md);
285
286 /* Store for pressure calculation */
287 data->comp_temp = (partial_data1 + partial_data2);
288 }
289
bmp180_temp_channel_get(const struct device * dev,struct sensor_value * val)290 static int bmp180_temp_channel_get(const struct device *dev,
291 struct sensor_value *val)
292 {
293 struct bmp180_data *data = dev->data;
294
295 if (data->comp_temp == 0) {
296 bmp180_compensate_temp(data);
297 }
298
299 float ftmp = ((data->comp_temp + 8) >> 4) / 10.0;
300 int64_t tmp = (int64_t)floorf(ftmp * 1000000);
301
302 val->val1 = tmp / 1000000;
303 val->val2 = tmp % 1000000;
304
305 return 0;
306 }
307
bmp180_compensate_press(struct bmp180_data * data)308 static uint32_t bmp180_compensate_press(struct bmp180_data *data)
309 {
310 uint64_t partial_B7;
311 uint64_t partial_B4;
312 int32_t partial_X1;
313 int32_t partial_X2;
314 int32_t partial_X3;
315 int32_t partial_B3;
316 int32_t partial_B6;
317 uint32_t comp_press;
318 int32_t raw_pressure = data->raw_press;
319 struct bmp180_cal_data *cal = &data->cal;
320
321 partial_B6 = data->comp_temp - 4000;
322 partial_X1 = cal->b2 * partial_B6 * (float)(1.0f * partial_B6 / 0x800000);
323 partial_X2 = (cal->ac2 * partial_B6) / 0x800;
324 partial_X3 = partial_X1 + partial_X2;
325 partial_B3 = (((cal->ac1 * 4 + partial_X3) << data->osr_pressure) + 2) / 4;
326
327 partial_X1 = (cal->ac3 * partial_B6) / 0x2000;
328 partial_X2 = cal->b1 * partial_B6 * (float)(1.0f * partial_B6 / 0x8000000);
329 partial_X3 = (partial_X1 + partial_X2 + 2) / 4;
330 partial_B4 = (uint64_t)(cal->ac4 * ((int64_t)(partial_X3) + 32768)) >> 15;
331 partial_B7 = (uint64_t)(raw_pressure - partial_B3) * (50000 >> data->osr_pressure);
332
333 comp_press = (uint32_t)(partial_B7 / partial_B4 * 2);
334
335 partial_X1 = comp_press * (float)(1.0f * comp_press / 0x10000);
336 partial_X1 = (partial_X1 * 3038) / 0x10000;
337 partial_X2 = ((int32_t)(-7357 * comp_press)) / 0x10000;
338 comp_press += (partial_X1 + partial_X2 + 3791) / 16;
339
340 /* returned value is Pa */
341 return comp_press;
342 }
343
bmp180_press_channel_get(const struct device * dev,struct sensor_value * val)344 static int bmp180_press_channel_get(const struct device *dev,
345 struct sensor_value *val)
346 {
347 struct bmp180_data *data = dev->data;
348
349 if (data->comp_temp == 0) {
350 bmp180_compensate_temp(data);
351 }
352
353 uint32_t tmp = bmp180_compensate_press(data);
354
355 /* tmp is Pa. Convert to kPa as specified in sensor
356 * interface.
357 */
358 val->val1 = tmp / 1000;
359 val->val2 = (tmp % 1000) * 1000;
360
361 return 0;
362 }
363
bmp180_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)364 static int bmp180_channel_get(const struct device *dev,
365 enum sensor_channel chan,
366 struct sensor_value *val)
367 {
368 switch (chan) {
369 case SENSOR_CHAN_PRESS:
370 bmp180_press_channel_get(dev, val);
371 break;
372
373 case SENSOR_CHAN_DIE_TEMP:
374 bmp180_temp_channel_get(dev, val);
375 break;
376
377 default:
378 LOG_DBG("Channel not supported.");
379 return -ENOTSUP;
380 }
381
382 return 0;
383 }
384
385
bmp180_get_calibration_data(const struct device * dev)386 static int bmp180_get_calibration_data(const struct device *dev)
387 {
388 struct bmp180_data *data = dev->data;
389 struct bmp180_cal_data *cal = &data->cal;
390
391 if (bmp180_reg_read(dev, BMP180_REG_CALIB0, (uint8_t *)cal,
392 sizeof(struct bmp180_cal_data)) < 0) {
393 return -EIO;
394 }
395
396 cal->ac1 = BSWAP_s16(cal->ac1);
397 cal->ac2 = BSWAP_s16(cal->ac2);
398 cal->ac3 = BSWAP_s16(cal->ac3);
399 cal->ac4 = BSWAP_u16(cal->ac4);
400 cal->ac5 = BSWAP_u16(cal->ac5);
401 cal->ac6 = BSWAP_u16(cal->ac6);
402 cal->b1 = BSWAP_s16(cal->b1);
403 cal->b2 = BSWAP_s16(cal->b2);
404 cal->mb = BSWAP_s16(cal->mb);
405 cal->mc = BSWAP_s16(cal->mc);
406 cal->md = BSWAP_s16(cal->md);
407
408 return 0;
409 }
410
411 #ifdef CONFIG_PM_DEVICE
bmp180_pm_action(const struct device * dev,enum pm_device_action action)412 static int bmp180_pm_action(const struct device *dev,
413 enum pm_device_action action)
414 {
415 /* no power saving feature in bmp180 */
416 return 0;
417 }
418 #endif /* CONFIG_PM_DEVICE */
419
420 static DEVICE_API(sensor, bmp180_api) = {
421 .attr_set = bmp180_attr_set,
422 .sample_fetch = bmp180_sample_fetch,
423 .channel_get = bmp180_channel_get,
424 };
425
bmp180_init(const struct device * dev)426 static int bmp180_init(const struct device *dev)
427 {
428 uint8_t val = 0U;
429
430 if (bmp180_bus_check(dev) < 0) {
431 LOG_DBG("bus check failed");
432 return -ENODEV;
433 }
434
435 /* reboot the chip */
436 if (bmp180_reg_write(dev, BMP180_REG_CMD, BMP180_CMD_SOFT_RESET) < 0) {
437 LOG_ERR("Cannot reboot chip.");
438 return -EIO;
439 }
440
441 k_sleep(K_MSEC(2));
442
443 if (bmp180_reg_read(dev, BMP180_REG_CHIPID, &val, 1) < 0) {
444 LOG_ERR("Failed to read chip id.");
445 return -EIO;
446 }
447
448 if (val != BMP180_CHIP_ID) {
449 LOG_ERR("Unsupported chip detected (0x%x)!", val);
450 return -ENODEV;
451 }
452
453 /* Read calibration data */
454 if (bmp180_get_calibration_data(dev) < 0) {
455 LOG_ERR("Failed to read calibration data.");
456 return -EIO;
457 }
458
459 return 0;
460 }
461
462 #define BMP180_INST(inst) \
463 static struct bmp180_data bmp180_data_##inst = {\
464 .osr_pressure = DT_INST_ENUM_IDX(inst, osr_press),\
465 };\
466 static const struct bmp180_config bmp180_config_##inst = {\
467 .i2c = I2C_DT_SPEC_INST_GET(inst),\
468 };\
469 PM_DEVICE_DT_INST_DEFINE(inst, bmp180_pm_action);\
470 SENSOR_DEVICE_DT_INST_DEFINE(inst, bmp180_init, PM_DEVICE_DT_INST_GET(inst),\
471 &bmp180_data_##inst, &bmp180_config_##inst,\
472 POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,\
473 &bmp180_api);
474
475 DT_INST_FOREACH_STATUS_OKAY(BMP180_INST)
476