diff --git a/drivers/sensor/bosch/bmp581/CMakeLists.txt b/drivers/sensor/bosch/bmp581/CMakeLists.txt index 2f471fda359a0..40d1a4a9f0203 100644 --- a/drivers/sensor/bosch/bmp581/CMakeLists.txt +++ b/drivers/sensor/bosch/bmp581/CMakeLists.txt @@ -5,4 +5,15 @@ # zephyr_library() -zephyr_library_sources(bmp581.c) +zephyr_library_include_directories(.) +zephyr_library_sources( + bmp581.c + bmp581_bus.c +) +zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API + bmp581_decoder.c +) + +zephyr_library_sources_ifdef(CONFIG_BMP581_STREAM + bmp581_stream.c +) diff --git a/drivers/sensor/bosch/bmp581/Kconfig b/drivers/sensor/bosch/bmp581/Kconfig index 325276b7a97a8..f9768d9321f9c 100644 --- a/drivers/sensor/bosch/bmp581/Kconfig +++ b/drivers/sensor/bosch/bmp581/Kconfig @@ -1,5 +1,7 @@ # # Copyright (c) 2022 Badgerd Technologies B.V and its affiliates +# Copyright (c) 2025 Croxel, Inc. +# Copyright (c) 2025 CogniPilot Foundation # # SPDX-License-Identifier: Apache-2.0 # @@ -8,4 +10,12 @@ config BMP581 bool "BMP581 barometric pressure sensor" depends on DT_HAS_BOSCH_BMP581_ENABLED select I2C + select I2C_RTIO default y + +config BMP581_STREAM + bool "Streaming mode" + default y + depends on SENSOR_ASYNC_API + depends on GPIO + depends on $(dt_compat_any_has_prop,$(DT_COMPAT_BOSCH_BMP581),int-gpios) diff --git a/drivers/sensor/bosch/bmp581/bmp581.c b/drivers/sensor/bosch/bmp581/bmp581.c index eb6d80b58b318..7258d8f6fd8b9 100644 --- a/drivers/sensor/bosch/bmp581/bmp581.c +++ b/drivers/sensor/bosch/bmp581/bmp581.c @@ -6,6 +6,9 @@ */ #include "bmp581.h" +#include "bmp581_bus.h" +#include "bmp581_decoder.h" +#include "bmp581_stream.h" #include @@ -60,14 +63,13 @@ static int set_power_mode(enum bmp5_powermode powermode, const struct device *de * Device should be set to standby before transitioning to forced mode or normal * mode or continuous mode. */ - - ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &odr); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_ODR_CONFIG, &odr, 1); if (ret == BMP5_OK) { /* Setting deep_dis = 1(BMP5_DEEP_DISABLED) disables the deep standby mode */ odr = BMP5_SET_BITSLICE(odr, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED); odr = BMP5_SET_BITS_POS_0(odr, BMP5_POWERMODE, BMP5_POWERMODE_STANDBY); - ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, odr); + ret = bmp581_reg_write_rtio(&conf->bus, BMP5_REG_ODR_CONFIG, &odr, 1); if (ret != BMP5_OK) { LOG_DBG("Failed to set power mode to BMP5_POWERMODE_STANDBY."); @@ -92,7 +94,7 @@ static int set_power_mode(enum bmp5_powermode powermode, const struct device *de case BMP5_POWERMODE_CONTINUOUS: odr = BMP5_SET_BITSLICE(odr, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED); odr = BMP5_SET_BITS_POS_0(odr, BMP5_POWERMODE, powermode); - ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, odr); + ret = bmp581_reg_write_rtio(&conf->bus, BMP5_REG_ODR_CONFIG, &odr, 1); break; default: /* invalid power mode */ @@ -116,7 +118,7 @@ static int get_power_mode(enum bmp5_powermode *powermode, const struct device *d uint8_t reg = 0; uint8_t raw_power_mode = 0; - ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, ®); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_ODR_CONFIG, ®, 1); if (ret != BMP5_OK) { LOG_DBG("Failed to read odr config to get power mode!"); return ret; @@ -195,7 +197,7 @@ static int get_interrupt_status(uint8_t *int_status, const struct device *dev) conf = (const struct bmp581_config *)dev->config; - return i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_INT_STATUS, int_status); + return bmp581_reg_read_rtio(&conf->bus, BMP5_REG_INT_STATUS, int_status, 1); } static int get_nvm_status(uint8_t *nvm_status, const struct device *dev) @@ -208,7 +210,7 @@ static int get_nvm_status(uint8_t *nvm_status, const struct device *dev) conf = (const struct bmp581_config *)dev->config; - return i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_STATUS, nvm_status); + return bmp581_reg_read_rtio(&conf->bus, BMP5_REG_STATUS, nvm_status, 1); } static int validate_chip_id(struct bmp581_data *drv) @@ -251,18 +253,45 @@ static int get_osr_odr_press_config(struct bmp581_osr_odr_press_config *osr_odr_ conf = (const struct bmp581_config *)dev->config; /* Get OSR and ODR configuration in burst read */ - rslt = i2c_burst_read_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, reg_data, 2); + rslt = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_OSR_CONFIG, reg_data, 2); if (rslt == BMP5_OK) { - osr_odr_press_cfg->osr_t = BMP5_GET_BITS_POS_0(reg_data[0], BMP5_TEMP_OS); - osr_odr_press_cfg->osr_p = BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_OS); + osr_odr_press_cfg->osr_t = BMP5_GET_BITS_POS_0(reg_data[0], BMP5_TEMP_OSR); + osr_odr_press_cfg->osr_p = BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_OSR); osr_odr_press_cfg->press_en = BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_EN); - osr_odr_press_cfg->odr = BMP5_GET_BITSLICE(reg_data[1], BMP5_ODR); } return rslt; } +static int set_osr_odr_press_config(const struct bmp581_osr_odr_press_config *osr_odr_press_cfg, + const struct device *dev) +{ + const struct bmp581_config *cfg = (const struct bmp581_config *)dev->config; + uint8_t reg_data[2] = {0}; + + reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_TEMP_OSR, osr_odr_press_cfg->osr_t); + reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_PRESS_OSR, osr_odr_press_cfg->osr_p); + reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_PRESS_EN, osr_odr_press_cfg->press_en); + + reg_data[1] = BMP5_SET_BITSLICE(reg_data[1], BMP5_POWERMODE, osr_odr_press_cfg->power_mode); + reg_data[1] = BMP5_SET_BITSLICE(reg_data[1], BMP5_ODR, osr_odr_press_cfg->odr); + + return bmp581_reg_write_rtio(&cfg->bus, BMP5_REG_OSR_CONFIG, reg_data, sizeof(reg_data)); +} + +static int set_iir_filters_config(const struct bmp581_osr_odr_press_config *osr_odr_press_cfg, + const struct device *dev) +{ + const struct bmp581_config *cfg = (const struct bmp581_config *)dev->config; + uint8_t reg_data = 0; + + reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_SET_IIR_TEMP, osr_odr_press_cfg->iir_t); + reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_SET_IIR_PRESS, osr_odr_press_cfg->iir_p); + + return bmp581_reg_write_rtio(&cfg->bus, BMP5_REG_DSP_IIR, ®_data, 1); +} + static int set_osr_config(const struct sensor_value *osr, enum sensor_channel chan, const struct device *dev) { @@ -278,20 +307,20 @@ static int set_osr_config(const struct sensor_value *osr, enum sensor_channel ch uint8_t press_en = osr->val2 != 0; /* if it is not 0 then pressure is enabled */ uint8_t osr_val = 0; - ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, &osr_val); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_OSR_CONFIG, &osr_val, 1); if (ret == BMP5_OK) { switch (chan) { case SENSOR_CHAN_ALL: - osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OS, oversampling); - osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_OS, oversampling); + osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OSR, oversampling); + osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_OSR, oversampling); osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_EN, press_en); break; case SENSOR_CHAN_PRESS: - osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_OS, oversampling); + osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_OSR, oversampling); osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_EN, press_en); break; case SENSOR_CHAN_AMBIENT_TEMP: - osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OS, oversampling); + osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OSR, oversampling); break; default: ret = -ENOTSUP; @@ -299,7 +328,7 @@ static int set_osr_config(const struct sensor_value *osr, enum sensor_channel ch } if (ret == BMP5_OK) { - ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, osr_val); + ret = bmp581_reg_write_rtio(&conf->bus, BMP5_REG_OSR_CONFIG, &osr_val, 1); get_osr_odr_press_config(&drv->osr_odr_press_config, dev); } } @@ -318,12 +347,12 @@ static int set_odr_config(const struct sensor_value *odr, const struct device *d int ret = 0; uint8_t odr_val = 0; - ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &odr_val); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_ODR_CONFIG, &odr_val, 1); if (ret != BMP5_OK) { return ret; } odr_val = BMP5_SET_BITSLICE(odr_val, BMP5_ODR, odr->val1); - ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, odr_val); + ret = bmp581_reg_write_rtio(&conf->bus, BMP5_REG_ODR_CONFIG, &odr_val, 1); get_osr_odr_press_config(&drv->osr_odr_press_config, dev); return ret; @@ -340,7 +369,7 @@ static int soft_reset(const struct device *dev) return -EINVAL; } - ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_CMD, reset_cmd); + ret = bmp581_reg_write_rtio(&conf->bus, BMP5_REG_CMD, &reset_cmd, 1); if (ret == BMP5_OK) { k_usleep(BMP5_DELAY_US_SOFT_RESET); @@ -374,7 +403,7 @@ static int bmp581_sample_fetch(const struct device *dev, enum sensor_channel cha uint8_t data[6]; int ret = 0; - ret = i2c_burst_read_dt(&conf->i2c, BMP5_REG_TEMP_DATA_XLSB, data, 6); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_TEMP_DATA_XLSB, data, 6); if (ret == BMP5_OK) { /* convert raw sensor data to sensor_value. Shift the decimal part by 1 decimal * place to compensate for the conversion in sensor_value_to_double() @@ -446,7 +475,7 @@ static int set_iir_config(const struct sensor_value *iir, const struct device *d /* update IIR config */ uint8_t dsp_config[2]; - ret = i2c_burst_read_dt(&conf->i2c, BMP5_REG_DSP_CONFIG, dsp_config, 2); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_DSP_CONFIG, dsp_config, 2); if (ret != BMP5_OK) { LOG_DBG("Failed to read dsp config register."); return ret; @@ -460,7 +489,7 @@ static int set_iir_config(const struct sensor_value *iir, const struct device *d dsp_config[1] = BMP5_SET_BITSLICE(dsp_config[1], BMP5_SET_IIR_PRESS, iir->val2); /* Set IIR configuration */ - ret = i2c_burst_write_dt(&conf->i2c, BMP5_REG_DSP_CONFIG, dsp_config, 2); + ret = bmp581_reg_write_rtio(&conf->bus, BMP5_REG_DSP_CONFIG, dsp_config, 2); if (ret != BMP5_OK) { LOG_DBG("Failed to configure IIR filter."); @@ -519,12 +548,11 @@ static int bmp581_init(const struct device *dev) /* Reset the chip id. */ drv->chip_id = 0; - memset(&drv->osr_odr_press_config, 0, sizeof(drv->osr_odr_press_config)); memset(&drv->last_sample, 0, sizeof(drv->last_sample)); soft_reset(dev); - ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_CHIP_ID, &drv->chip_id); + ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_CHIP_ID, &drv->chip_id, 1); if (ret != BMP5_OK) { return ret; } @@ -544,23 +572,159 @@ static int bmp581_init(const struct device *dev) BMP5_CHIP_ID_PRIM, BMP5_CHIP_ID_SEC); return -EINVAL; } + + ret = set_iir_filters_config(&drv->osr_odr_press_config, dev); + if (ret != 0) { + LOG_ERR("Failed to set initial IIR settings: %d", ret); + return ret; + } + + ret = set_osr_odr_press_config(&drv->osr_odr_press_config, dev); + if (ret != 0) { + LOG_ERR("Failed to set initial ODR OSR settings: %d", ret); + return ret; + } + + if (IS_ENABLED(CONFIG_BMP581_STREAM)) { + ret = bmp581_stream_init(dev); + if (ret != 0) { + LOG_ERR("Failed to initialize streaming support: %d", ret); + return ret; + } + } + return ret; } +#ifdef CONFIG_SENSOR_ASYNC_API + +static void bmp581_complete_result(struct rtio *ctx, const struct rtio_sqe *sqe, void *arg) +{ + struct rtio_iodev_sqe *iodev_sqe = (struct rtio_iodev_sqe *)arg; + struct rtio_cqe *cqe; + int err = 0; + + do { + cqe = rtio_cqe_consume(ctx); + if (cqe != NULL) { + err = cqe->result; + rtio_cqe_release(ctx, cqe); + } + } while (cqe != NULL); + + if (err != 0) { + rtio_iodev_sqe_err(iodev_sqe, err); + } else { + rtio_iodev_sqe_ok(iodev_sqe, 0); + } +} + +static void bmp581_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + uint32_t min_buf_len = sizeof(struct bmp581_encoded_data); + int err; + uint8_t *buf; + uint32_t buf_len; + struct bmp581_encoded_data *edata; + const struct bmp581_config *conf = dev->config; + + err = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); + CHECKIF((err < 0) || (buf_len < min_buf_len) || !buf) { + LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + + edata = (struct bmp581_encoded_data *)buf; + + err = bmp581_encode(dev, cfg, 0, buf); + if (err != 0) { + LOG_ERR("Failed to encode sensor data"); + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + + struct rtio_sqe *read_sqe; + + err = bmp581_prep_reg_read_rtio_async(&conf->bus, BMP5_REG_TEMP_DATA_XLSB, + edata->payload, sizeof(edata->payload), + &read_sqe); + if (err < 0) { + LOG_ERR("Failed to prepare async read operation"); + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + read_sqe->flags |= RTIO_SQE_CHAINED; + + struct rtio_sqe *complete_sqe = rtio_sqe_acquire(conf->bus.rtio.ctx); + + if (!complete_sqe) { + LOG_ERR("Failed to acquire completion SQE"); + rtio_iodev_sqe_err(iodev_sqe, -ENOMEM); + rtio_sqe_drop_all(conf->bus.rtio.ctx); + return; + } + + rtio_sqe_prep_callback_no_cqe(complete_sqe, + bmp581_complete_result, + iodev_sqe, + (void *)dev); + + rtio_submit(conf->bus.rtio.ctx, 0); +} + +static void bmp581_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + + if (!cfg->is_streaming) { + bmp581_submit_one_shot(dev, iodev_sqe); + } else if (IS_ENABLED(CONFIG_BMP581_STREAM)) { + bmp581_stream_submit(dev, iodev_sqe); + } else { + LOG_ERR("Streaming not supported"); + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + } +} + +#endif /* #ifdef CONFIG_SENSOR_ASYNC_API */ + static DEVICE_API(sensor, bmp581_driver_api) = { .sample_fetch = bmp581_sample_fetch, .channel_get = bmp581_channel_get, .attr_set = bmp581_attr_set, +#ifdef CONFIG_SENSOR_ASYNC_API + .submit = bmp581_submit, + .get_decoder = bmp581_get_decoder, +#endif }; -#define BMP581_CONFIG(i) \ - static const struct bmp581_config bmp581_config_##i = { \ - .i2c = I2C_DT_SPEC_INST_GET(i), \ - } - #define BMP581_INIT(i) \ - static struct bmp581_data bmp581_data_##i; \ - BMP581_CONFIG(i); \ + \ + RTIO_DEFINE(bmp581_rtio_ctx_##i, 8, 8); \ + I2C_DT_IODEV_DEFINE(bmp581_bus_##i, DT_DRV_INST(i)); \ + \ + static struct bmp581_data bmp581_data_##i = { \ + .osr_odr_press_config = { \ + .press_en = 1, \ + .odr = DT_INST_PROP(i, odr), \ + .osr_t = DT_INST_PROP(i, temp_osr), \ + .osr_p = DT_INST_PROP(i, press_osr), \ + .iir_t = DT_INST_PROP(i, temp_iir), \ + .iir_p = DT_INST_PROP(i, press_iir), \ + .power_mode = DT_INST_PROP(i, power_mode), \ + }, \ + }; \ + \ + static const struct bmp581_config bmp581_config_##i = { \ + .bus.rtio = { \ + .ctx = &bmp581_rtio_ctx_##i, \ + .iodev = &bmp581_bus_##i, \ + .type = BMP581_BUS_TYPE_I2C, \ + }, \ + .int_gpio = GPIO_DT_SPEC_INST_GET_OR(i, int_gpios, {0}), \ + }; \ \ SENSOR_DEVICE_DT_INST_DEFINE(i, bmp581_init, NULL, &bmp581_data_##i, &bmp581_config_##i, \ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ diff --git a/drivers/sensor/bosch/bmp581/bmp581.h b/drivers/sensor/bosch/bmp581/bmp581.h index cdbe7f7e0b8f9..befdf24f4f589 100644 --- a/drivers/sensor/bosch/bmp581/bmp581.h +++ b/drivers/sensor/bosch/bmp581/bmp581.h @@ -20,6 +20,8 @@ #include #include +#include "bmp581_bus.h" + #define DT_DRV_COMPAT bosch_bmp581 /* UTILITY MACROS */ @@ -149,6 +151,7 @@ /* Interrupt configurations */ #define BMP5_INT_MODE_MSK 0x01 +#define BMP5_INT_MODE_POS 0 #define BMP5_INT_POL_MSK 0x02 #define BMP5_INT_POL_POS 1 @@ -160,6 +163,7 @@ #define BMP5_INT_EN_POS 3 #define BMP5_INT_DRDY_EN_MSK 0x01 +#define BMP5_INT_DRDY_EN_POS 0 #define BMP5_INT_FIFO_FULL_EN_MSK 0x02 #define BMP5_INT_FIFO_FULL_EN_POS 1 @@ -175,10 +179,11 @@ #define BMP5_ODR_POS 2 /* OSR configurations */ -#define BMP5_TEMP_OS_MSK 0x07 +#define BMP5_TEMP_OSR_MSK 0x07 +#define BMP5_TEMP_OSR_POS 0 -#define BMP5_PRESS_OS_MSK 0x38 -#define BMP5_PRESS_OS_POS 3 +#define BMP5_PRESS_OSR_MSK 0x38 +#define BMP5_PRESS_OSR_POS 3 /* Pressure enable */ #define BMP5_PRESS_EN_MSK 0x40 @@ -186,6 +191,7 @@ /* IIR configurations */ #define BMP5_SET_IIR_TEMP_MSK 0x07 +#define BMP5_SET_IIR_TEMP_POS 0 #define BMP5_SET_IIR_PRESS_MSK 0x38 #define BMP5_SET_IIR_PRESS_POS 3 @@ -219,6 +225,7 @@ /* Powermode */ #define BMP5_POWERMODE_MSK 0x03 +#define BMP5_POWERMODE_POS 0 #define BMP5_DEEP_DISABLE_MSK 0x80 #define BMP5_DEEP_DISABLE_POS 7 @@ -266,27 +273,27 @@ struct bmp581_osr_odr_press_config { /*! Temperature oversampling * Assignable macros : - * - BMP5_OVERSAMPLING_1X - * - BMP5_OVERSAMPLING_2X - * - BMP5_OVERSAMPLING_4X - * - BMP5_OVERSAMPLING_8X - * - BMP5_OVERSAMPLING_16X - * - BMP5_OVERSAMPLING_32X - * - BMP5_OVERSAMPLING_64X - * - BMP5_OVERSAMPLING_128X + * - BMP581_DT_OVERSAMPLING_1X + * - BMP581_DT_OVERSAMPLING_2X + * - BMP581_DT_OVERSAMPLING_4X + * - BMP581_DT_OVERSAMPLING_8X + * - BMP581_DT_OVERSAMPLING_16X + * - BMP581_DT_OVERSAMPLING_32X + * - BMP581_DT_OVERSAMPLING_64X + * - BMP581_DT_OVERSAMPLING_128X */ uint8_t osr_t; /*! Pressure oversampling * Assignable macros : - * - BMP5_OVERSAMPLING_1X - * - BMP5_OVERSAMPLING_2X - * - BMP5_OVERSAMPLING_4X - * - BMP5_OVERSAMPLING_8X - * - BMP5_OVERSAMPLING_16X - * - BMP5_OVERSAMPLING_32X - * - BMP5_OVERSAMPLING_64X - * - BMP5_OVERSAMPLING_128X + * - BMP581_DT_OVERSAMPLING_1X + * - BMP581_DT_OVERSAMPLING_2X + * - BMP581_DT_OVERSAMPLING_4X + * - BMP581_DT_OVERSAMPLING_8X + * - BMP581_DT_OVERSAMPLING_16X + * - BMP581_DT_OVERSAMPLING_32X + * - BMP581_DT_OVERSAMPLING_64X + * - BMP581_DT_OVERSAMPLING_128X */ uint8_t osr_p; @@ -298,6 +305,10 @@ struct bmp581_osr_odr_press_config { /*! Output Data Rate */ uint8_t odr; + + uint8_t iir_t; + uint8_t iir_p; + uint8_t power_mode; }; struct bmp581_sample { @@ -305,14 +316,23 @@ struct bmp581_sample { struct sensor_value temperature; }; +struct bmp581_stream { + const struct device *dev; + struct gpio_callback cb; + struct rtio_iodev_sqe *iodev_sqe; + atomic_t state; +}; + struct bmp581_data { uint8_t chip_id; struct bmp581_sample last_sample; struct bmp581_osr_odr_press_config osr_odr_press_config; + struct bmp581_stream stream; }; struct bmp581_config { - struct i2c_dt_spec i2c; + struct bmp581_bus bus; + struct gpio_dt_spec int_gpio; }; #endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_H_ */ diff --git a/drivers/sensor/bosch/bmp581/bmp581_bus.c b/drivers/sensor/bosch/bmp581/bmp581_bus.c new file mode 100644 index 0000000000000..f3df5a388b060 --- /dev/null +++ b/drivers/sensor/bosch/bmp581/bmp581_bus.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 Croxel, Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bmp581_bus.h" + +int bmp581_prep_reg_read_rtio_async(const struct bmp581_bus *bus, + uint8_t reg, uint8_t *buf, size_t size, + struct rtio_sqe **out) +{ + struct rtio *ctx = bus->rtio.ctx; + struct rtio_iodev *iodev = bus->rtio.iodev; + struct rtio_sqe *write_reg_sqe = rtio_sqe_acquire(ctx); + struct rtio_sqe *read_buf_sqe = rtio_sqe_acquire(ctx); + + if (!write_reg_sqe || !read_buf_sqe) { + rtio_sqe_drop_all(ctx); + return -ENOMEM; + } + + rtio_sqe_prep_tiny_write(write_reg_sqe, iodev, RTIO_PRIO_NORM, ®, 1, NULL); + write_reg_sqe->flags |= RTIO_SQE_TRANSACTION; + rtio_sqe_prep_read(read_buf_sqe, iodev, RTIO_PRIO_NORM, buf, size, NULL); + if (bus->rtio.type == BMP581_BUS_TYPE_I2C) { + read_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + } + + /** Send back last SQE so it can be concatenated later. */ + if (out) { + *out = read_buf_sqe; + } + + return 2; +} + +int bmp581_prep_reg_write_rtio_async(const struct bmp581_bus *bus, + uint8_t reg, const uint8_t *buf, size_t size, + struct rtio_sqe **out) +{ + struct rtio *ctx = bus->rtio.ctx; + struct rtio_iodev *iodev = bus->rtio.iodev; + struct rtio_sqe *write_reg_sqe = rtio_sqe_acquire(ctx); + struct rtio_sqe *write_buf_sqe = rtio_sqe_acquire(ctx); + + if (!write_reg_sqe || !write_buf_sqe) { + rtio_sqe_drop_all(ctx); + return -ENOMEM; + } + + /** More than 7 won't work with tiny-write */ + if (size > 7) { + return -EINVAL; + } + + rtio_sqe_prep_tiny_write(write_reg_sqe, iodev, RTIO_PRIO_NORM, ®, 1, NULL); + write_reg_sqe->flags |= RTIO_SQE_TRANSACTION; + rtio_sqe_prep_tiny_write(write_buf_sqe, iodev, RTIO_PRIO_NORM, buf, size, NULL); + if (bus->rtio.type == BMP581_BUS_TYPE_I2C) { + write_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP; + } + + /** Send back last SQE so it can be concatenated later. */ + if (out) { + *out = write_buf_sqe; + } + + return 2; +} + +int bmp581_reg_read_rtio(const struct bmp581_bus *bus, uint8_t start, uint8_t *buf, int size) +{ + struct rtio *ctx = bus->rtio.ctx; + struct rtio_cqe *cqe; + int ret; + + ret = bmp581_prep_reg_read_rtio_async(bus, start, buf, size, NULL); + if (ret < 0) { + return ret; + } + + ret = rtio_submit(ctx, ret); + if (ret) { + return ret; + } + + do { + cqe = rtio_cqe_consume(ctx); + if (cqe != NULL) { + ret = cqe->result; + rtio_cqe_release(ctx, cqe); + } + } while (cqe != NULL); + + return ret; +} + +int bmp581_reg_write_rtio(const struct bmp581_bus *bus, uint8_t reg, const uint8_t *buf, int size) +{ + struct rtio *ctx = bus->rtio.ctx; + struct rtio_cqe *cqe; + int ret; + + ret = bmp581_prep_reg_write_rtio_async(bus, reg, buf, size, NULL); + if (ret < 0) { + return ret; + } + + ret = rtio_submit(ctx, ret); + if (ret) { + return ret; + } + + do { + cqe = rtio_cqe_consume(ctx); + if (cqe != NULL) { + ret = cqe->result; + rtio_cqe_release(ctx, cqe); + } + } while (cqe != NULL); + + return ret; +} diff --git a/drivers/sensor/bosch/bmp581/bmp581_bus.h b/drivers/sensor/bosch/bmp581/bmp581_bus.h new file mode 100644 index 0000000000000..7e7921a223ea1 --- /dev/null +++ b/drivers/sensor/bosch/bmp581/bmp581_bus.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Croxel, Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_BUS_H_ +#define ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_BUS_H_ + +#include +#include + +enum bmp581_bus_type { + BMP581_BUS_TYPE_I2C, +}; + +struct bmp581_bus { + struct { + struct rtio *ctx; + struct rtio_iodev *iodev; + enum bmp581_bus_type type; + } rtio; +}; + +int bmp581_prep_reg_read_rtio_async(const struct bmp581_bus *bus, + uint8_t reg, uint8_t *buf, size_t size, + struct rtio_sqe **out); + +int bmp581_prep_reg_write_rtio_async(const struct bmp581_bus *bus, + uint8_t reg, const uint8_t *buf, size_t size, + struct rtio_sqe **out); + +int bmp581_reg_read_rtio(const struct bmp581_bus *bus, uint8_t start, uint8_t *buf, int size); + +int bmp581_reg_write_rtio(const struct bmp581_bus *bus, uint8_t reg, const uint8_t *buf, int size); + +#endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_BUS_H_ */ diff --git a/drivers/sensor/bosch/bmp581/bmp581_decoder.c b/drivers/sensor/bosch/bmp581/bmp581_decoder.c new file mode 100644 index 0000000000000..e0bb631962bc8 --- /dev/null +++ b/drivers/sensor/bosch/bmp581/bmp581_decoder.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2025 Croxel, Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "bmp581.h" +#include "bmp581_decoder.h" + +#include +LOG_MODULE_REGISTER(BMP581_DECODER, CONFIG_SENSOR_LOG_LEVEL); + +static uint8_t bmp581_encode_channel(enum sensor_channel chan) +{ + uint8_t encode_bmask = 0; + + switch (chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + encode_bmask |= BIT(0); + break; + case SENSOR_CHAN_PRESS: + encode_bmask |= BIT(1); + break; + case SENSOR_CHAN_ALL: + encode_bmask |= BIT(0) | BIT(1); + break; + default: + break; + } + + return encode_bmask; +} + +int bmp581_encode(const struct device *dev, + const struct sensor_read_config *read_config, + uint8_t trigger_status, + uint8_t *buf) +{ + struct bmp581_encoded_data *edata = (struct bmp581_encoded_data *)buf; + struct bmp581_data *data = dev->data; + uint64_t cycles; + int err; + + edata->header.channels = 0; + edata->header.press_en = data->osr_odr_press_config.press_en; + + if (trigger_status) { + edata->header.channels |= bmp581_encode_channel(SENSOR_CHAN_ALL); + } else { + const struct sensor_chan_spec *const channels = read_config->channels; + size_t num_channels = read_config->count; + + for (size_t i = 0; i < num_channels; i++) { + edata->header.channels |= bmp581_encode_channel(channels[i].chan_type); + } + } + + err = sensor_clock_get_cycles(&cycles); + if (err != 0) { + return err; + } + + edata->header.events = trigger_status ? BIT(0) : 0; + edata->header.timestamp = sensor_clock_cycles_to_ns(cycles); + + return 0; +} + +static int bmp581_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) +{ + const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer; + + if (chan_spec.chan_idx != 0) { + return -ENOTSUP; + } + + uint8_t channel_request = bmp581_encode_channel(chan_spec.chan_type); + + /* Filter unknown channels and having no data */ + if ((edata->header.channels & channel_request) != channel_request) { + return -ENODATA; + } + + *frame_count = 1; + return 0; +} + +static int bmp581_decoder_get_size_info(struct sensor_chan_spec chan_spec, + size_t *base_size, + size_t *frame_size) +{ + switch (chan_spec.chan_type) { + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_PRESS: + *base_size = sizeof(struct sensor_q31_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; + default: + return -ENOTSUP; + } +} + +static int bmp581_decoder_decode(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint32_t *fit, + uint16_t max_count, + void *data_out) +{ + const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer; + uint8_t channel_request; + + if (*fit != 0) { + return 0; + } + + if (max_count == 0 || chan_spec.chan_idx != 0) { + return -EINVAL; + } + + channel_request = bmp581_encode_channel(chan_spec.chan_type); + if ((channel_request & edata->header.channels) != channel_request) { + return -ENODATA; + } + + struct sensor_q31_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + + switch (chan_spec.chan_type) { + case SENSOR_CHAN_AMBIENT_TEMP: { + /* Temperature is in data[2:0], data[2] is integer part */ + uint32_t raw_temp = ((uint32_t)edata->payload[2] << 16) | + ((uint16_t)edata->payload[1] << 8) | + edata->payload[0]; + int32_t raw_temp_signed = sign_extend(raw_temp, 23); + + out->shift = (31 - 16); /* 16 left shifts gives us the value in celsius */ + out->readings[0].value = raw_temp_signed; + break; + } + case SENSOR_CHAN_PRESS: + if (!edata->header.press_en) { + return -ENODATA; + } + /* Shift by 10 bits because we'll divide by 1000 to make it kPa */ + uint64_t raw_press = (((uint32_t)edata->payload[5] << 16) | + ((uint16_t)edata->payload[4] << 8) | + edata->payload[3]); + + int64_t raw_press_signed = sign_extend_64(raw_press, 23); + + raw_press_signed *= 1024; + raw_press_signed /= 1000; + + /* Original value was in Pa by left-shifting 6 spaces, but + * we've multiplied by 2^10 to not lose precision when + * converting to kPa. Hence, left-shift 16 spaces. + */ + out->shift = (31 - 6 - 10); + out->readings[0].value = (int32_t)raw_press_signed; + break; + default: + return -EINVAL; + } + + *fit = 1; + return 1; +} + +static bool bmp581_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger) +{ + const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer; + + if ((trigger == SENSOR_TRIG_DATA_READY) && (edata->header.events != 0)) { + return true; + } + + return false; +} + +SENSOR_DECODER_API_DT_DEFINE() = { + .get_frame_count = bmp581_decoder_get_frame_count, + .get_size_info = bmp581_decoder_get_size_info, + .decode = bmp581_decoder_decode, + .has_trigger = bmp581_decoder_has_trigger, +}; + +int bmp581_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) +{ + ARG_UNUSED(dev); + *decoder = &SENSOR_DECODER_NAME(); + return 0; +} diff --git a/drivers/sensor/bosch/bmp581/bmp581_decoder.h b/drivers/sensor/bosch/bmp581/bmp581_decoder.h new file mode 100644 index 0000000000000..3150408d30536 --- /dev/null +++ b/drivers/sensor/bosch/bmp581/bmp581_decoder.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Croxel, Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_BMP581_DECODER_H_ +#define ZEPHYR_DRIVERS_SENSOR_BMP581_DECODER_H_ + +#include +#include +#include "bmp581.h" + +struct bmp581_encoded_data { + struct { + uint8_t channels; + uint8_t events; + uint64_t timestamp; + uint8_t press_en; + } header; + uint8_t payload[6]; /* 3 bytes temp + 3 bytes press */ +}; + +int bmp581_encode(const struct device *dev, + const struct sensor_read_config *read_config, + uint8_t trigger_status, + uint8_t *buf); + +int bmp581_get_decoder(const struct device *dev, + const struct sensor_decoder_api **decoder); + +#endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_DECODER_H_ */ diff --git a/drivers/sensor/bosch/bmp581/bmp581_stream.c b/drivers/sensor/bosch/bmp581/bmp581_stream.c new file mode 100644 index 0000000000000..0b66c704e6d01 --- /dev/null +++ b/drivers/sensor/bosch/bmp581/bmp581_stream.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2025 Croxel Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include + +#include "bmp581.h" +#include "bmp581_stream.h" +#include "bmp581_decoder.h" + +#include +LOG_MODULE_REGISTER(BMP581_STREAM, CONFIG_SENSOR_LOG_LEVEL); + +enum bmp581_stream_state { + BMP581_STREAM_OFF = 0, + BMP581_STREAM_ON = 1, + BMP581_STREAM_BUSY = 2, +}; + +static void bmp581_stream_event_complete(struct rtio *ctx, const struct rtio_sqe *sqe, void *arg0) +{ + struct rtio_iodev_sqe *iodev_sqe = (struct rtio_iodev_sqe *)arg0; + const struct device *dev = (const struct device *)sqe->userdata; + struct bmp581_data *data = dev->data; + uint8_t *buf; + uint32_t buf_len; + struct rtio_cqe *cqe; + int err = 0; + + do { + cqe = rtio_cqe_consume(ctx); + if (cqe == NULL) { + continue; + } + + if (err == 0) { + err = cqe->result; + } + rtio_cqe_release(ctx, cqe); + } while (cqe != NULL); + + if (err != 0) { + goto bmp581_stream_evt_finish; + } + + err = rtio_sqe_rx_buf(iodev_sqe, 0, 0, &buf, &buf_len); + + CHECKIF(err != 0 || !buf || buf_len < sizeof(struct bmp581_encoded_data)) { + LOG_ERR("Couldn't get encoded buffer on completion"); + err = -EIO; + goto bmp581_stream_evt_finish; + } + + err = bmp581_encode(dev, (struct sensor_read_config *)iodev_sqe->sqe.iodev->data, + 0x01, buf); + if (err != 0) { + LOG_ERR("Failed to encode frame: %d", err); + goto bmp581_stream_evt_finish; + } + +bmp581_stream_evt_finish: + atomic_set(&data->stream.state, BMP581_STREAM_ON); + + if (err < 0) { + rtio_iodev_sqe_err(iodev_sqe, err); + } else { + rtio_iodev_sqe_ok(iodev_sqe, 0); + } +} + +static void bmp581_event_handler(const struct device *dev) +{ + struct bmp581_data *data = dev->data; + const struct bmp581_config *cfg = dev->config; + struct rtio_iodev_sqe *iodev_sqe = data->stream.iodev_sqe; + uint8_t *buf = NULL; + uint32_t buf_len = 0; + int err; + + CHECKIF(!data->stream.iodev_sqe || FIELD_GET(RTIO_SQE_CANCELED, iodev_sqe->sqe.flags)) { + + uint8_t val = 0; + + LOG_WRN("Callback triggered with no streaming submission - Disabling interrupts"); + + (void)gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_DISABLE); + + err = bmp581_prep_reg_write_rtio_async(&cfg->bus, BMP5_REG_INT_SOURCE, &val, 1, + NULL); + if (err >= 0) { + rtio_submit(cfg->bus.rtio.ctx, 0); + } + + (void)atomic_set(&data->stream.state, BMP581_STREAM_OFF); + + return; + } + + CHECKIF(atomic_cas(&data->stream.state, BMP581_STREAM_ON, BMP581_STREAM_BUSY) == false) { + LOG_WRN("Callback triggered while stream is busy. Ignoring request"); + return; + } + + err = rtio_sqe_rx_buf(iodev_sqe, + sizeof(struct bmp581_encoded_data), + sizeof(struct bmp581_encoded_data), + &buf, &buf_len); + CHECKIF(err != 0 || buf_len < sizeof(struct bmp581_encoded_data)) { + LOG_ERR("Failed to allocate BMP581 encoded buffer: %d", err); + rtio_iodev_sqe_err(iodev_sqe, -ENOMEM); + return; + } + + struct bmp581_encoded_data *edata = (struct bmp581_encoded_data *)buf; + struct rtio_sqe *read_sqe = NULL; + struct rtio_sqe *cb_sqe; + + err = bmp581_prep_reg_read_rtio_async(&cfg->bus, BMP5_REG_TEMP_DATA_XLSB, + edata->payload, sizeof(edata->payload), + &read_sqe); + CHECKIF(err < 0 || !read_sqe) { + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + read_sqe->flags |= RTIO_SQE_CHAINED; + + cb_sqe = rtio_sqe_acquire(cfg->bus.rtio.ctx); + if (cb_sqe == NULL) { + LOG_ERR("Failed to acquire callback SQE"); + rtio_iodev_sqe_err(iodev_sqe, -ENOMEM); + return; + } + + rtio_sqe_prep_callback_no_cqe(cb_sqe, bmp581_stream_event_complete, + iodev_sqe, (void *)dev); + + rtio_submit(cfg->bus.rtio.ctx, 0); +} + +static void bmp581_gpio_callback(const struct device *port, struct gpio_callback *cb, uint32_t pin) +{ + struct bmp581_stream *stream = CONTAINER_OF(cb, struct bmp581_stream, cb); + const struct device *dev = stream->dev; + + bmp581_event_handler(dev); +} + +void bmp581_stream_submit(const struct device *dev, + struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *read_config = iodev_sqe->sqe.iodev->data; + struct bmp581_data *data = dev->data; + const struct bmp581_config *cfg = dev->config; + int err; + + if ((read_config->count != 1) || + (read_config->triggers[0].trigger != SENSOR_TRIG_DATA_READY)) { + LOG_ERR("Only SENSOR_TRIG_DATA_READY is supported"); + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + return; + } + + data->stream.iodev_sqe = iodev_sqe; + + if (atomic_cas(&data->stream.state, BMP581_STREAM_OFF, BMP581_STREAM_ON)) { + /* Enable DRDY interrupt */ + struct rtio_sqe *int_src_sqe; + uint8_t val = 0; + + val = BMP5_SET_BITSLICE(val, BMP5_INT_DRDY_EN, 1); + + err = bmp581_prep_reg_write_rtio_async(&cfg->bus, BMP5_REG_INT_SOURCE, &val, 1, + &int_src_sqe); + if (err < 0) { + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + int_src_sqe->flags |= RTIO_SQE_CHAINED; + + val = BMP5_SET_BITSLICE(val, BMP5_INT_MODE, BMP5_INT_MODE_PULSED); + val = BMP5_SET_BITSLICE(val, BMP5_INT_POL, BMP5_INT_POL_ACTIVE_HIGH); + val = BMP5_SET_BITSLICE(val, BMP5_INT_OD, BMP5_INT_OD_PUSHPULL); + val = BMP5_SET_BITSLICE(val, BMP5_INT_EN, 1); + + err = bmp581_prep_reg_write_rtio_async(&cfg->bus, BMP5_REG_INT_CONFIG, &val, 1, + NULL); + if (err < 0) { + rtio_iodev_sqe_err(iodev_sqe, err); + return; + } + + (void)rtio_submit(cfg->bus.rtio.ctx, 0); + + err = gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (err < 0) { + rtio_iodev_sqe_err(iodev_sqe, err); + } + } +} + +int bmp581_stream_init(const struct device *dev) +{ + struct bmp581_data *data = dev->data; + const struct bmp581_config *cfg = dev->config; + int err; + + data->stream.dev = dev; + atomic_set(&data->stream.state, BMP581_STREAM_OFF); + + if (!device_is_ready(cfg->int_gpio.port)) { + LOG_ERR("DRDY GPIO device is not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT); + if (err < 0) { + return err; + } + + gpio_init_callback(&data->stream.cb, bmp581_gpio_callback, BIT(cfg->int_gpio.pin)); + + err = gpio_add_callback(cfg->int_gpio.port, &data->stream.cb); + if (err < 0) { + return err; + } + + err = gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_DISABLE); + if (err < 0) { + return err; + } + + return 0; +} diff --git a/drivers/sensor/bosch/bmp581/bmp581_stream.h b/drivers/sensor/bosch/bmp581/bmp581_stream.h new file mode 100644 index 0000000000000..1c43965b96419 --- /dev/null +++ b/drivers/sensor/bosch/bmp581/bmp581_stream.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Croxel Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_BMP581_STREAM_H_ +#define ZEPHYR_DRIVERS_SENSOR_BMP581_STREAM_H_ + +#include +#include + +int bmp581_stream_init(const struct device *dev); + +void bmp581_stream_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); + +#endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_STREAM_H_ */ diff --git a/dts/bindings/sensor/bosch,bmp581.yaml b/dts/bindings/sensor/bosch,bmp581.yaml index 5afad7eea466b..4650b40fa5c44 100644 --- a/dts/bindings/sensor/bosch,bmp581.yaml +++ b/dts/bindings/sensor/bosch,bmp581.yaml @@ -2,6 +2,22 @@ description: | The BMP581 is a Barometric pressure sensor. See more info at: https://www.bosch-sensortec.com/products/environmental-sensors/pressure-sensors/bmp581/ + When setting the sensor DTS properties, make sure to include + bmp581.h and use the macros defined there. + + Example: + #include + + bmp581@46 { + ... + odr = ; + press-osr = ; + temp-osr = ; + press-iir = ; + temp-iir = ; + power-mode = ; + }; + compatible: "bosch,bmp581" include: [sensor-device.yaml, i2c-device.yaml] @@ -13,3 +29,120 @@ properties: The interrupt pin of BMP581 is open-drain, active low. If connected directly to the MCU, the pin should be configured as pull-up, active low. + + odr: + type: int + default: 0x1C # BMP581_DT_ODR_1_HZ + description: | + Output data rate. Please note this is only valid on BMP581_DT_MODE_NORMAL. + Default is power-on reset. + enum: + - 0x00 # BMP581_DT_ODR_240_HZ + - 0x01 # BMP581_DT_ODR_218_5_HZ + - 0x02 # BMP581_DT_ODR_199_1_HZ + - 0x03 # BMP581_DT_ODR_179_2_HZ + - 0x04 # BMP581_DT_ODR_160_HZ + - 0x05 # BMP581_DT_ODR_149_3_HZ + - 0x06 # BMP581_DT_ODR_140_HZ + - 0x07 # BMP581_DT_ODR_129_8_HZ + - 0x08 # BMP581_DT_ODR_120_HZ + - 0x09 # BMP581_DT_ODR_110_1_HZ + - 0x0A # BMP581_DT_ODR_100_2_HZ + - 0x0B # BMP581_DT_ODR_89_6_HZ + - 0x0C # BMP581_DT_ODR_80_HZ + - 0x0D # BMP581_DT_ODR_70_HZ + - 0x0E # BMP581_DT_ODR_60_HZ + - 0x0F # BMP581_DT_ODR_50_HZ + - 0x10 # BMP581_DT_ODR_45_HZ + - 0x11 # BMP581_DT_ODR_40_HZ + - 0x12 # BMP581_DT_ODR_35_HZ + - 0x13 # BMP581_DT_ODR_30_HZ + - 0x14 # BMP581_DT_ODR_25_HZ + - 0x15 # BMP581_DT_ODR_20_HZ + - 0x16 # BMP581_DT_ODR_15_HZ + - 0x17 # BMP581_DT_ODR_10_HZ + - 0x18 # BMP581_DT_ODR_5_HZ + - 0x19 # BMP581_DT_ODR_4_HZ + - 0x1A # BMP581_DT_ODR_3_HZ + - 0x1B # BMP581_DT_ODR_2_HZ + - 0x1C # BMP581_DT_ODR_1_HZ + - 0x1D # BMP581_DT_ODR_0_5_HZ + - 0x1E # BMP581_DT_ODR_0_250_HZ + - 0x1F # BMP581_DT_ODR_0_125_HZ + + press-osr: + type: int + default: 0x00 # BMP581_DT_OVERSAMPLING_1X + description: | + Pressure oversampling rate. + Default is power-on reset. + enum: + - 0x00 # BMP581_DT_OVERSAMPLING_1X + - 0x01 # BMP581_DT_OVERSAMPLING_2X + - 0x02 # BMP581_DT_OVERSAMPLING_4X + - 0x03 # BMP581_DT_OVERSAMPLING_8X + - 0x04 # BMP581_DT_OVERSAMPLING_16X + - 0x05 # BMP581_DT_OVERSAMPLING_32X + - 0x06 # BMP581_DT_OVERSAMPLING_64X + - 0x07 # BMP581_DT_OVERSAMPLING_128X + + temp-osr: + type: int + default: 0x00 # BMP581_DT_OVERSAMPLING_1X + description: | + Temperature oversampling rate. + Default is power-on reset. + enum: + - 0x00 # BMP581_DT_OVERSAMPLING_1X + - 0x01 # BMP581_DT_OVERSAMPLING_2X + - 0x02 # BMP581_DT_OVERSAMPLING_4X + - 0x03 # BMP581_DT_OVERSAMPLING_8X + - 0x04 # BMP581_DT_OVERSAMPLING_16X + - 0x05 # BMP581_DT_OVERSAMPLING_32X + - 0x06 # BMP581_DT_OVERSAMPLING_64X + - 0x07 # BMP581_DT_OVERSAMPLING_128X + + power-mode: + type: int + default: 1 # BMP581_DT_MODE_NORMAL + description: | + Power mode. + Default favors ease of use by simply setting ODR and OSR. Otherwise user + needs to look into driver details, as the other modes require some quirks + (e.g: Forced mode does not just work). + enum: + - 1 # BMP581_DT_MODE_NORMAL + - 2 # BMP581_DT_MODE_FORCED + - 3 # BMP581_DT_MODE_CONTINUOUS + + press-iir: + type: int + default: 0x00 # BMP581_DT_IIR_FILTER_BYPASS + description: | + Pressure IIR filter coefficient. + Default is power-on reset (bypass). + enum: + - 0x00 # BMP581_DT_IIR_FILTER_BYPASS + - 0x01 # BMP581_DT_IIR_FILTER_COEFF_1 + - 0x02 # BMP581_DT_IIR_FILTER_COEFF_3 + - 0x03 # BMP581_DT_IIR_FILTER_COEFF_7 + - 0x04 # BMP581_DT_IIR_FILTER_COEFF_15 + - 0x05 # BMP581_DT_IIR_FILTER_COEFF_31 + - 0x06 # BMP581_DT_IIR_FILTER_COEFF_63 + - 0x07 # BMP581_DT_IIR_FILTER_COEFF_127 + + temp-iir: + type: int + default: 0x00 # BMP581_DT_IIR_FILTER_BYPASS + description: | + Temperature IIR filter coefficient. + Default is power-on reset (bypass). + enum: + - 0x00 # BMP581_DT_IIR_FILTER_BYPASS + - 0x01 # BMP581_DT_IIR_FILTER_COEFF_1 + - 0x02 # BMP581_DT_IIR_FILTER_COEFF_3 + - 0x03 # BMP581_DT_IIR_FILTER_COEFF_7 + - 0x04 # BMP581_DT_IIR_FILTER_COEFF_15 + - 0x05 # BMP581_DT_IIR_FILTER_COEFF_31 + - 0x06 # BMP581_DT_IIR_FILTER_COEFF_63 + - 0x07 # BMP581_DT_IIR_FILTER_COEFF_127 diff --git a/include/zephyr/drivers/sensor/bmp581_user.h b/include/zephyr/drivers/sensor/bmp581_user.h index e0fd000c8c067..27c36dbca8b1a 100644 --- a/include/zephyr/drivers/sensor/bmp581_user.h +++ b/include/zephyr/drivers/sensor/bmp581_user.h @@ -13,62 +13,7 @@ #define ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMP581_USER_H_ #include - -#define BMP5_SEA_LEVEL_PRESSURE_PA 101325 - -/* ODR settings */ -#define BMP5_ODR_240_HZ 0x00 -#define BMP5_ODR_218_5_HZ 0x01 -#define BMP5_ODR_199_1_HZ 0x02 -#define BMP5_ODR_179_2_HZ 0x03 -#define BMP5_ODR_160_HZ 0x04 -#define BMP5_ODR_149_3_HZ 0x05 -#define BMP5_ODR_140_HZ 0x06 -#define BMP5_ODR_129_8_HZ 0x07 -#define BMP5_ODR_120_HZ 0x08 -#define BMP5_ODR_110_1_HZ 0x09 -#define BMP5_ODR_100_2_HZ 0x0A -#define BMP5_ODR_89_6_HZ 0x0B -#define BMP5_ODR_80_HZ 0x0C -#define BMP5_ODR_70_HZ 0x0D -#define BMP5_ODR_60_HZ 0x0E -#define BMP5_ODR_50_HZ 0x0F -#define BMP5_ODR_45_HZ 0x10 -#define BMP5_ODR_40_HZ 0x11 -#define BMP5_ODR_35_HZ 0x12 -#define BMP5_ODR_30_HZ 0x13 -#define BMP5_ODR_25_HZ 0x14 -#define BMP5_ODR_20_HZ 0x15 -#define BMP5_ODR_15_HZ 0x16 -#define BMP5_ODR_10_HZ 0x17 -#define BMP5_ODR_05_HZ 0x18 -#define BMP5_ODR_04_HZ 0x19 -#define BMP5_ODR_03_HZ 0x1A -#define BMP5_ODR_02_HZ 0x1B -#define BMP5_ODR_01_HZ 0x1C -#define BMP5_ODR_0_5_HZ 0x1D -#define BMP5_ODR_0_250_HZ 0x1E -#define BMP5_ODR_0_125_HZ 0x1F - -/* Oversampling for temperature and pressure */ -#define BMP5_OVERSAMPLING_1X 0x00 -#define BMP5_OVERSAMPLING_2X 0x01 -#define BMP5_OVERSAMPLING_4X 0x02 -#define BMP5_OVERSAMPLING_8X 0x03 -#define BMP5_OVERSAMPLING_16X 0x04 -#define BMP5_OVERSAMPLING_32X 0x05 -#define BMP5_OVERSAMPLING_64X 0x06 -#define BMP5_OVERSAMPLING_128X 0x07 - -/* IIR filter for temperature and pressure */ -#define BMP5_IIR_FILTER_BYPASS 0x00 -#define BMP5_IIR_FILTER_COEFF_1 0x01 -#define BMP5_IIR_FILTER_COEFF_3 0x02 -#define BMP5_IIR_FILTER_COEFF_7 0x03 -#define BMP5_IIR_FILTER_COEFF_15 0x04 -#define BMP5_IIR_FILTER_COEFF_31 0x05 -#define BMP5_IIR_FILTER_COEFF_63 0x06 -#define BMP5_IIR_FILTER_COEFF_127 0x07 +#include /* Custom ATTR values */ diff --git a/include/zephyr/dt-bindings/sensor/bmp581.h b/include/zephyr/dt-bindings/sensor/bmp581.h new file mode 100644 index 0000000000000..03a1a025005fa --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/bmp581.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 Croxel Inc. + * Copyright (c) 2025 CogniPilot Foundation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_BOSCH_BMP581_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_BOSCH_BMP581_H_ + +/** + * @defgroup bmp581 Bosch BMP581 DT Options + * @ingroup sensor_interface + * @{ + */ + +/** + * @defgroup BMP581_POWER_MODES Sensor power modes + * @{ + */ +#define BMP581_DT_MODE_NORMAL 1 +#define BMP581_DT_MODE_FORCED 2 +#define BMP581_DT_MODE_CONTINUOUS 3 +/** @} */ + +/** + * @defgroup BMP581_OUTPUT_DATA_RATE Output data rate options + * @{ + */ +#define BMP581_DT_ODR_240_HZ 0x00 +#define BMP581_DT_ODR_218_5_HZ 0x01 +#define BMP581_DT_ODR_199_1_HZ 0x02 +#define BMP581_DT_ODR_179_2_HZ 0x03 +#define BMP581_DT_ODR_160_HZ 0x04 +#define BMP581_DT_ODR_149_3_HZ 0x05 +#define BMP581_DT_ODR_140_HZ 0x06 +#define BMP581_DT_ODR_129_8_HZ 0x07 +#define BMP581_DT_ODR_120_HZ 0x08 +#define BMP581_DT_ODR_110_1_HZ 0x09 +#define BMP581_DT_ODR_100_2_HZ 0x0A +#define BMP581_DT_ODR_89_6_HZ 0x0B +#define BMP581_DT_ODR_80_HZ 0x0C +#define BMP581_DT_ODR_70_HZ 0x0D +#define BMP581_DT_ODR_60_HZ 0x0E +#define BMP581_DT_ODR_50_HZ 0x0F +#define BMP581_DT_ODR_45_HZ 0x10 +#define BMP581_DT_ODR_40_HZ 0x11 +#define BMP581_DT_ODR_35_HZ 0x12 +#define BMP581_DT_ODR_30_HZ 0x13 +#define BMP581_DT_ODR_25_HZ 0x14 +#define BMP581_DT_ODR_20_HZ 0x15 +#define BMP581_DT_ODR_15_HZ 0x16 +#define BMP581_DT_ODR_10_HZ 0x17 +#define BMP581_DT_ODR_5_HZ 0x18 +#define BMP581_DT_ODR_4_HZ 0x19 +#define BMP581_DT_ODR_3_HZ 0x1A +#define BMP581_DT_ODR_2_HZ 0x1B +#define BMP581_DT_ODR_1_HZ 0x1C +#define BMP581_DT_ODR_0_5_HZ 0x1D +#define BMP581_DT_ODR_0_250_HZ 0x1E +#define BMP581_DT_ODR_0_125_HZ 0x1F +/** @} */ + +/** + * @defgroup BMP581_OVERSAMPLING Oversampling options. Valid for temperature and pressure. + * @{ + */ +#define BMP581_DT_OVERSAMPLING_1X 0x00 +#define BMP581_DT_OVERSAMPLING_2X 0x01 +#define BMP581_DT_OVERSAMPLING_4X 0x02 +#define BMP581_DT_OVERSAMPLING_8X 0x03 +#define BMP581_DT_OVERSAMPLING_16X 0x04 +#define BMP581_DT_OVERSAMPLING_32X 0x05 +#define BMP581_DT_OVERSAMPLING_64X 0x06 +#define BMP581_DT_OVERSAMPLING_128X 0x07 +/** @} */ + +/** + * @defgroup BMP581_IIR_FILTER IIR Filter options. Valid for temperature and pressure. + * @{ + */ +#define BMP581_DT_IIR_FILTER_BYPASS 0x00 +#define BMP581_DT_IIR_FILTER_COEFF_1 0x01 +#define BMP581_DT_IIR_FILTER_COEFF_3 0x02 +#define BMP581_DT_IIR_FILTER_COEFF_7 0x03 +#define BMP581_DT_IIR_FILTER_COEFF_15 0x04 +#define BMP581_DT_IIR_FILTER_COEFF_31 0x05 +#define BMP581_DT_IIR_FILTER_COEFF_63 0x06 +#define BMP581_DT_IIR_FILTER_COEFF_127 0x07 +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_BOSCH_BMP581_H_*/