drivers: bmp581: Add BMP581 driver

This commit adds source and header files required for bmp581 I2C driver.
I have used bmp581_user.h to add more usage related definitions
but bmp581.h to add hardware related definitions.

Signed-off-by: Talha Can Havadar <havadartalha@gmail.com>
Signed-off-by: Gerhard Jörges <joerges@metratec.com>
This commit is contained in:
Talha Can Havadar 2022-11-01 10:57:47 +01:00 committed by Anas Nashif
commit 4ce0555d90
9 changed files with 1016 additions and 0 deletions

View file

@ -30,6 +30,7 @@ add_subdirectory_ifdef(CONFIG_BMI270 bmi270)
add_subdirectory_ifdef(CONFIG_BMI323 bmi323)
add_subdirectory_ifdef(CONFIG_BMM150 bmm150)
add_subdirectory_ifdef(CONFIG_BMP388 bmp388)
add_subdirectory_ifdef(CONFIG_BMP581 bmp581)
add_subdirectory_ifdef(CONFIG_BQ274XX bq274xx)
add_subdirectory_ifdef(CONFIG_CCS811 ccs811)
add_subdirectory_ifdef(CONFIG_CURRENT_AMP current_amp)

View file

@ -110,6 +110,7 @@ source "drivers/sensor/bmi270/Kconfig"
source "drivers/sensor/bmi323/Kconfig"
source "drivers/sensor/bmm150/Kconfig"
source "drivers/sensor/bmp388/Kconfig"
source "drivers/sensor/bmp581/Kconfig"
source "drivers/sensor/bq274xx/Kconfig"
source "drivers/sensor/ccs811/Kconfig"
source "drivers/sensor/current_amp/Kconfig"

View file

@ -0,0 +1,8 @@
#
# Copyright (c) 2022 Badgerd Technologies B.V and its affiliates
#
# SPDX-License-Identifier: Apache-2.0
#
zephyr_library()
zephyr_library_sources(bmp581.c)

View file

@ -0,0 +1,11 @@
#
# Copyright (c) 2022 Badgerd Technologies B.V and its affiliates
#
# SPDX-License-Identifier: Apache-2.0
#
config BMP581
bool "BMP581 barometric pressure sensor"
depends on DT_HAS_BOSCH_BMP581_ENABLED
select I2C
default y

View file

@ -0,0 +1,560 @@
/*
* Copyright (c) 2022 Badgerd Technologies B.V.
* Copyright (c) 2023 Metratec GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "bmp581.h"
#include <math.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/init.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/check.h>
LOG_MODULE_REGISTER(bmp581, CONFIG_SENSOR_LOG_LEVEL);
#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
#warning "BMP581 driver enabled without any devices"
#endif
static int power_up_check(const struct device *dev);
static int get_nvm_status(uint8_t *nvm_status, const struct device *dev);
static int get_interrupt_status(uint8_t *int_status, const struct device *dev);
static int validate_chip_id(struct bmp581_data *drv);
static int get_osr_odr_press_config(struct bmp581_osr_odr_press_config *osr_odr_press_cfg,
const struct device *dev);
static int set_osr_config(const struct sensor_value *osr, enum sensor_channel chan,
const struct device *dev);
static int set_odr_config(const struct sensor_value *odr, const struct device *dev);
static int soft_reset(const struct device *dev);
static int set_iir_config(const struct sensor_value *iir, const struct device *dev);
static int get_power_mode(enum bmp5_powermode *powermode, const struct device *dev);
static int set_power_mode(enum bmp5_powermode powermode, const struct device *dev);
static int set_power_mode(enum bmp5_powermode powermode, const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = BMP5_OK;
uint8_t odr = 0;
enum bmp5_powermode current_powermode;
CHECKIF(dev == NULL) {
return -EINVAL;
}
ret = get_power_mode(&current_powermode, dev);
if (ret != BMP5_OK) {
LOG_ERR("Couldnt set the power mode because something went wrong when getting the "
"current power mode.");
return ret;
}
if (current_powermode != BMP5_POWERMODE_STANDBY) {
/*
* 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);
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);
if (ret != BMP5_OK) {
LOG_DBG("Failed to set power mode to BMP5_POWERMODE_STANDBY.");
return ret;
}
}
}
/* lets update the power mode */
switch (powermode) {
case BMP5_POWERMODE_STANDBY:
/* this change is already done so we can just return */
ret = BMP5_OK;
break;
case BMP5_POWERMODE_DEEP_STANDBY:
LOG_DBG("Setting power mode to DEEP STANDBY is not supported, current power mode "
"is BMP5_POWERMODE_STANDBY.");
ret = -ENOTSUP;
break;
case BMP5_POWERMODE_NORMAL:
case BMP5_POWERMODE_FORCED:
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);
break;
default:
/* invalid power mode */
ret = -EINVAL;
break;
}
return ret;
}
static int get_power_mode(enum bmp5_powermode *powermode, const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = BMP5_OK;
CHECKIF(powermode == NULL || dev == NULL) {
return -EINVAL;
}
uint8_t reg = 0;
uint8_t raw_power_mode = 0;
ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &reg);
if (ret != BMP5_OK) {
LOG_DBG("Failed to read odr config to get power mode!");
return ret;
}
raw_power_mode = BMP5_GET_BITS_POS_0(reg, BMP5_POWERMODE);
switch (raw_power_mode) {
case BMP5_POWERMODE_STANDBY: {
/* Getting deep disable status */
uint8_t deep_dis = BMP5_GET_BITSLICE(reg, BMP5_DEEP_DISABLE);
/* Checking deepstandby status only when powermode is in standby mode */
/* If deep_dis = 0(BMP5_DEEP_ENABLED) then deepstandby mode is enabled.
* If deep_dis = 1(BMP5_DEEP_DISABLED) then deepstandby mode is disabled
*/
if (deep_dis == BMP5_DEEP_ENABLED) {
/* TODO: check if it is really deep standby */
*powermode = BMP5_POWERMODE_DEEP_STANDBY;
} else {
*powermode = BMP5_POWERMODE_STANDBY;
}
break;
}
case BMP5_POWERMODE_NORMAL:
*powermode = BMP5_POWERMODE_NORMAL;
break;
case BMP5_POWERMODE_FORCED:
*powermode = BMP5_POWERMODE_FORCED;
break;
case BMP5_POWERMODE_CONTINUOUS:
*powermode = BMP5_POWERMODE_CONTINUOUS;
break;
default:
/* invalid power mode */
ret = -EINVAL;
LOG_DBG("Something went wrong invalid powermode!");
break;
}
return ret;
}
static int power_up_check(const struct device *dev)
{
int8_t rslt = 0;
uint8_t nvm_status = 0;
CHECKIF(dev == NULL) {
return -EINVAL;
}
rslt = get_nvm_status(&nvm_status, dev);
if (rslt == BMP5_OK) {
/* Check if nvm_rdy status = 1 and nvm_err status = 0 to proceed */
if ((nvm_status & BMP5_INT_NVM_RDY) && (!(nvm_status & BMP5_INT_NVM_ERR))) {
rslt = BMP5_OK;
} else {
rslt = -EFAULT;
}
}
return rslt;
}
static int get_interrupt_status(uint8_t *int_status, const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
CHECKIF(int_status == NULL || dev == NULL) {
return -EINVAL;
}
return i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_INT_STATUS, int_status);
}
static int get_nvm_status(uint8_t *nvm_status, const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
CHECKIF(nvm_status == NULL || dev == NULL) {
return -EINVAL;
}
return i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_STATUS, nvm_status);
}
static int validate_chip_id(struct bmp581_data *drv)
{
int8_t rslt = 0;
CHECKIF(drv == NULL) {
return -EINVAL;
}
if ((drv->chip_id == BMP5_CHIP_ID_PRIM) || (drv->chip_id == BMP5_CHIP_ID_SEC)) {
rslt = BMP5_OK;
} else {
drv->chip_id = 0;
rslt = -ENODEV;
}
return rslt;
}
/*!
* This API gets the configuration for oversampling of temperature, oversampling of
* pressure and ODR configuration along with pressure enable.
*/
static int get_osr_odr_press_config(struct bmp581_osr_odr_press_config *osr_odr_press_cfg,
const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
/* Variable to store the function result */
int8_t rslt = 0;
/* Variable to store OSR and ODR config */
uint8_t reg_data[2] = {0};
CHECKIF(osr_odr_press_cfg == NULL || dev == NULL) {
return -EINVAL;
}
/* Get OSR and ODR configuration in burst read */
rslt = i2c_burst_read_dt(&conf->i2c, 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->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_config(const struct sensor_value *osr, enum sensor_channel chan,
const struct device *dev)
{
CHECKIF(osr == NULL || dev == NULL) {
return -EINVAL;
}
struct bmp581_data *drv = (struct bmp581_data *)dev->data;
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = 0;
uint8_t oversampling = osr->val1;
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);
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_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_EN, press_en);
break;
case SENSOR_CHAN_AMBIENT_TEMP:
osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OS, oversampling);
break;
default:
ret = -ENOTSUP;
break;
}
if (ret == BMP5_OK) {
ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, osr_val);
get_osr_odr_press_config(&drv->osr_odr_press_config, dev);
}
}
return ret;
}
static int set_odr_config(const struct sensor_value *odr, const struct device *dev)
{
CHECKIF(odr == NULL || dev == NULL) {
return -EINVAL;
}
struct bmp581_data *drv = (struct bmp581_data *)dev->data;
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = 0;
uint8_t odr_val = 0;
ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &odr_val);
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);
get_osr_odr_press_config(&drv->osr_odr_press_config, dev);
return ret;
}
static int soft_reset(const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = 0;
const uint8_t reset_cmd = BMP5_SOFT_RESET_CMD;
uint8_t int_status = 0;
CHECKIF(dev == NULL) {
return -EINVAL;
}
ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_CMD, reset_cmd);
if (ret == BMP5_OK) {
k_usleep(BMP5_DELAY_US_SOFT_RESET);
ret = get_interrupt_status(&int_status, dev);
if (ret == BMP5_OK) {
if (int_status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE) {
ret = BMP5_OK;
} else {
ret = -EFAULT;
}
}
} else {
LOG_DBG("Failed perform soft-reset.");
}
return ret;
}
static int bmp581_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
CHECKIF(dev == NULL) {
return -EINVAL;
}
if (chan != SENSOR_CHAN_ALL) {
return -ENOTSUP;
}
struct bmp581_data *drv = (struct bmp581_data *)dev->data;
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
uint8_t data[6];
int ret = 0;
ret = i2c_burst_read_dt(&conf->i2c, 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()
*/
drv->last_sample.temperature.val1 = data[2];
drv->last_sample.temperature.val2 = (data[1] << 8 | data[0]) * 10;
if (drv->osr_odr_press_config.press_en == BMP5_ENABLE) {
uint32_t raw_pressure = (uint32_t)((uint32_t)(data[5] << 16) |
(uint16_t)(data[4] << 8) | data[3]);
/* convert raw sensor data to sensor_value. Shift the decimal part by
* 4 decimal places to compensate for the conversion in
* sensor_value_to_double()
*/
drv->last_sample.pressure.val1 = raw_pressure >> 6;
drv->last_sample.pressure.val2 = (raw_pressure & BIT_MASK(6)) * 10000;
} else {
drv->last_sample.pressure.val1 = 0;
drv->last_sample.pressure.val2 = 0;
}
}
return ret;
}
static int bmp581_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
CHECKIF(dev == NULL || val == NULL) {
return -EINVAL;
}
struct bmp581_data *drv = (struct bmp581_data *)dev->data;
switch (chan) {
case SENSOR_CHAN_PRESS:
/* returns pressure in Pa */
*val = drv->last_sample.pressure;
return BMP5_OK;
case SENSOR_CHAN_AMBIENT_TEMP:
/* returns temperature in Celcius */
*val = drv->last_sample.temperature;
return BMP5_OK;
default:
return -ENOTSUP;
}
}
static int set_iir_config(const struct sensor_value *iir, const struct device *dev)
{
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = BMP5_OK;
CHECKIF((iir == NULL) | (dev == NULL)) {
return -EINVAL;
}
/* Variable to store existing powermode */
enum bmp5_powermode prev_powermode;
ret = get_power_mode(&prev_powermode, dev);
if (ret != BMP5_OK) {
LOG_DBG("Not able to get current power mode.");
return ret;
}
/* IIR configuration is writable only during STANDBY mode(as per datasheet) */
set_power_mode(BMP5_POWERMODE_STANDBY, dev);
/* update IIR config */
uint8_t dsp_config[2];
ret = i2c_burst_read_dt(&conf->i2c, BMP5_REG_DSP_CONFIG, dsp_config, 2);
if (ret != BMP5_OK) {
LOG_DBG("Failed to read dsp config register.");
return ret;
}
/* Put IIR filtered values in data registers */
dsp_config[0] = BMP5_SET_BITSLICE(dsp_config[0], BMP5_SHDW_SET_IIR_TEMP, BMP5_ENABLE);
dsp_config[0] = BMP5_SET_BITSLICE(dsp_config[0], BMP5_SHDW_SET_IIR_PRESS, BMP5_ENABLE);
/* Configure IIR filter */
dsp_config[1] = iir->val1;
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);
if (ret != BMP5_OK) {
LOG_DBG("Failed to configure IIR filter.");
return ret;
}
/* Restore previous power mode if it is not standby already */
if (prev_powermode != BMP5_POWERMODE_STANDBY) {
ret = set_power_mode(prev_powermode, dev);
}
return ret;
}
static int bmp581_attr_set(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, const struct sensor_value *val)
{
CHECKIF(dev == NULL || val == NULL) {
return -EINVAL;
}
int ret;
switch ((int)attr) {
case SENSOR_ATTR_SAMPLING_FREQUENCY:
ret = set_odr_config(val, dev);
break;
case SENSOR_ATTR_OVERSAMPLING:
ret = set_osr_config(val, chan, dev);
break;
case BMP5_ATTR_POWER_MODE: {
enum bmp5_powermode powermode = (enum bmp5_powermode)val->val1;
ret = set_power_mode(powermode, dev);
break;
}
case BMP5_ATTR_IIR_CONFIG:
ret = set_iir_config(val, dev);
break;
default:
ret = -ENOTSUP;
break;
}
return ret;
}
static int bmp581_init(const struct device *dev)
{
CHECKIF(dev == NULL) {
return -EINVAL;
}
struct bmp581_data *drv = (struct bmp581_data *)dev->data;
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = -1;
/* 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);
if (ret != BMP5_OK) {
return ret;
}
if (drv->chip_id != 0) {
ret = power_up_check(dev);
if (ret == BMP5_OK) {
ret = validate_chip_id(drv);
if (ret != BMP5_OK) {
LOG_ERR("Unexpected chip id (%x). Expected (%x or %x)",
drv->chip_id, BMP5_CHIP_ID_PRIM, BMP5_CHIP_ID_SEC);
}
}
} else {
/* that means something went wrong */
LOG_ERR("Unexpected chip id (%x). Expected (%x or %x)", drv->chip_id,
BMP5_CHIP_ID_PRIM, BMP5_CHIP_ID_SEC);
return -EINVAL;
}
return ret;
}
static const struct sensor_driver_api bmp581_driver_api = {.sample_fetch = bmp581_sample_fetch,
.channel_get = bmp581_channel_get,
.attr_set = bmp581_attr_set};
#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); \
\
SENSOR_DEVICE_DT_INST_DEFINE(i, bmp581_init, NULL, &bmp581_data_##i, &bmp581_config_##i, \
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
&bmp581_driver_api);
DT_INST_FOREACH_STATUS_OKAY(BMP581_INIT)

View file

@ -0,0 +1,318 @@
/*
* Copyright (c) 2022 Badgerd Technologies B.V.
*
* SPDX-License-Identifier: Apache-2.0
*
* Driver is developed to be used with Zephyr. And it only supports i2c interface.
*
* Author: Talha Can Havadar <havadartalha@gmail.com>
*
*/
#ifndef ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_H_
#define ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_H_
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/util.h>
#include <zephyr/types.h>
#include <zephyr/drivers/sensor/bmp581_user.h>
#define DT_DRV_COMPAT bosch_bmp581
/* UTILITY MACROS */
#define BMP5_SET_LOW_BYTE 0x00FFu
#define BMP5_SET_HIGH_BYTE 0xFF00u
/* BIT SLICE GET AND SET FUNCTIONS */
#define BMP5_GET_BITSLICE(regvar, bitname) ((regvar & bitname##_MSK) >> bitname##_POS)
#define BMP5_SET_BITSLICE(regvar, bitname, val) \
((regvar & ~bitname##_MSK) | ((val << bitname##_POS) & bitname##_MSK))
#define BMP5_GET_LSB(var) (uint8_t)(var & BMP5_SET_LOW_BYTE)
#define BMP5_GET_MSB(var) (uint8_t)((var & BMP5_SET_HIGH_BYTE) >> 8)
#define BMP5_SET_BIT_VAL_0(reg_data, bitname) (reg_data & ~(bitname##_MSK))
#define BMP5_SET_BITS_POS_0(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | (data & bitname##_MSK))
#define BMP5_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
#define BMP5_OK 0
#define BMP5_ENABLE 1u
#define BMP5_DISABLE 0u
/* BMP5 Registers */
#define BMP5_REG_CHIP_ID 0x01
#define BMP5_REG_REV_ID 0x02
#define BMP5_REG_CHIP_STATUS 0x11
#define BMP5_REG_DRIVE_CONFIG 0x13
#define BMP5_REG_INT_CONFIG 0x14
#define BMP5_REG_INT_SOURCE 0x15
#define BMP5_REG_FIFO_CONFIG 0x16
#define BMP5_REG_FIFO_COUNT 0x17
#define BMP5_REG_FIFO_SEL 0x18
#define BMP5_REG_TEMP_DATA_XLSB 0x1D
#define BMP5_REG_TEMP_DATA_LSB 0x1E
#define BMP5_REG_TEMP_DATA_MSB 0x1F
#define BMP5_REG_PRESS_DATA_XLSB 0x20
#define BMP5_REG_PRESS_DATA_LSB 0x21
#define BMP5_REG_PRESS_DATA_MSB 0x22
#define BMP5_REG_INT_STATUS 0x27
#define BMP5_REG_STATUS 0x28
#define BMP5_REG_FIFO_DATA 0x29
#define BMP5_REG_NVM_ADDR 0x2B
#define BMP5_REG_NVM_DATA_LSB 0x2C
#define BMP5_REG_NVM_DATA_MSB 0x2D
#define BMP5_REG_DSP_CONFIG 0x30
#define BMP5_REG_DSP_IIR 0x31
#define BMP5_REG_OOR_THR_P_LSB 0x32
#define BMP5_REG_OOR_THR_P_MSB 0x33
#define BMP5_REG_OOR_RANGE 0x34
#define BMP5_REG_OOR_CONFIG 0x35
#define BMP5_REG_OSR_CONFIG 0x36
#define BMP5_REG_ODR_CONFIG 0x37
#define BMP5_REG_OSR_EFF 0x38
#define BMP5_REG_CMD 0x7E
/* endof BMP5 Registers */
/* Chip id of BMP5 */
#define BMP5_CHIP_ID_PRIM 0x50
#define BMP5_CHIP_ID_SEC 0x51
/* I2C addresses */
#define BMP5_I2C_ADDR_PRIM 0x46
#define BMP5_I2C_ADDR_SEC 0x47
/* NVM addresses */
#define BMP5_NVM_START_ADDR 0x20
#define BMP5_NVM_END_ADDR 0x22
/* Interface settings */
#define BMP5_SPI_RD_MASK 0x80
/* Delay definition */
#define BMP5_DELAY_US_SOFT_RESET 2000
#define BMP5_DELAY_US_STANDBY 2500
#define BMP5_DELAY_US_NVM_READY_READ 800
#define BMP5_DELAY_US_NVM_READY_WRITE 10000
/* Soft reset command */
#define BMP5_SOFT_RESET_CMD 0xB6
/*! NVM command */
#define BMP5_NVM_FIRST_CMND 0x5D
#define BMP5_NVM_READ_ENABLE_CMND 0xA5
#define BMP5_NVM_WRITE_ENABLE_CMND 0xA0
/* Deepstandby enable/disable */
#define BMP5_DEEP_ENABLED 0
#define BMP5_DEEP_DISABLED 1
/*! Fifo frame configuration */
#define BMP5_FIFO_EMPTY 0X7F
#define BMP5_FIFO_MAX_THRESHOLD_P_T_MODE 0x0F
#define BMP5_FIFO_MAX_THRESHOLD_P_MODE 0x1F
/* Macro is used to bypass both iir_t and iir_p together */
#define BMP5_IIR_BYPASS 0xC0
/* Pressure Out-of-range count limit */
#define BMP5_OOR_COUNT_LIMIT_1 0x00
#define BMP5_OOR_COUNT_LIMIT_3 0x01
#define BMP5_OOR_COUNT_LIMIT_7 0x02
#define BMP5_OOR_COUNT_LIMIT_15 0x03
/* Interrupt configurations */
#define BMP5_INT_MODE_PULSED 0
#define BMP5_INT_MODE_LATCHED 1
#define BMP5_INT_POL_ACTIVE_LOW 0
#define BMP5_INT_POL_ACTIVE_HIGH 1
#define BMP5_INT_OD_PUSHPULL 0
#define BMP5_INT_OD_OPENDRAIN 1
/* NVM and Interrupt status asserted macros */
#define BMP5_INT_ASSERTED_DRDY 0x01
#define BMP5_INT_ASSERTED_FIFO_FULL 0x02
#define BMP5_INT_ASSERTED_FIFO_THRES 0x04
#define BMP5_INT_ASSERTED_PRESSURE_OOR 0x08
#define BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE 0x10
#define BMP5_INT_NVM_RDY 0x02
#define BMP5_INT_NVM_ERR 0x04
#define BMP5_INT_NVM_CMD_ERR 0x08
/* Interrupt configurations */
#define BMP5_INT_MODE_MSK 0x01
#define BMP5_INT_POL_MSK 0x02
#define BMP5_INT_POL_POS 1
#define BMP5_INT_OD_MSK 0x04
#define BMP5_INT_OD_POS 2
#define BMP5_INT_EN_MSK 0x08
#define BMP5_INT_EN_POS 3
#define BMP5_INT_DRDY_EN_MSK 0x01
#define BMP5_INT_FIFO_FULL_EN_MSK 0x02
#define BMP5_INT_FIFO_FULL_EN_POS 1
#define BMP5_INT_FIFO_THRES_EN_MSK 0x04
#define BMP5_INT_FIFO_THRES_EN_POS 2
#define BMP5_INT_OOR_PRESS_EN_MSK 0x08
#define BMP5_INT_OOR_PRESS_EN_POS 3
/* ODR configuration */
#define BMP5_ODR_MSK 0x7C
#define BMP5_ODR_POS 2
/* OSR configurations */
#define BMP5_TEMP_OS_MSK 0x07
#define BMP5_PRESS_OS_MSK 0x38
#define BMP5_PRESS_OS_POS 3
/* Pressure enable */
#define BMP5_PRESS_EN_MSK 0x40
#define BMP5_PRESS_EN_POS 6
/* IIR configurations */
#define BMP5_SET_IIR_TEMP_MSK 0x07
#define BMP5_SET_IIR_PRESS_MSK 0x38
#define BMP5_SET_IIR_PRESS_POS 3
#define BMP5_OOR_SEL_IIR_PRESS_MSK 0x80
#define BMP5_OOR_SEL_IIR_PRESS_POS 7
#define BMP5_SHDW_SET_IIR_TEMP_MSK 0x08
#define BMP5_SHDW_SET_IIR_TEMP_POS 3
#define BMP5_SHDW_SET_IIR_PRESS_MSK 0x20
#define BMP5_SHDW_SET_IIR_PRESS_POS 5
#define BMP5_SET_FIFO_IIR_TEMP_MSK 0x10
#define BMP5_SET_FIFO_IIR_TEMP_POS 4
#define BMP5_SET_FIFO_IIR_PRESS_MSK 0x40
#define BMP5_SET_FIFO_IIR_PRESS_POS 6
#define BMP5_IIR_FLUSH_FORCED_EN_MSK 0x04
#define BMP5_IIR_FLUSH_FORCED_EN_POS 2
/* Effective OSR configurations and ODR valid status */
#define BMP5_OSR_TEMP_EFF_MSK 0x07
#define BMP5_OSR_PRESS_EFF_MSK 0x38
#define BMP5_OSR_PRESS_EFF_POS 3
#define BMP5_ODR_IS_VALID_MSK 0x80
#define BMP5_ODR_IS_VALID_POS 7
/* Powermode */
#define BMP5_POWERMODE_MSK 0x03
#define BMP5_DEEP_DISABLE_MSK 0x80
#define BMP5_DEEP_DISABLE_POS 7
/* Fifo configurations */
#define BMP5_FIFO_THRESHOLD_MSK 0x1F
#define BMP5_FIFO_MODE_MSK 0x20
#define BMP5_FIFO_MODE_POS 5
#define BMP5_FIFO_DEC_SEL_MSK 0x1C
#define BMP5_FIFO_DEC_SEL_POS 2
#define BMP5_FIFO_COUNT_MSK 0x3F
#define BMP5_FIFO_FRAME_SEL_MSK 0x03
/* Out-of-range configuration */
#define BMP5_OOR_THR_P_LSB_MSK 0x0000FF
#define BMP5_OOR_THR_P_MSB_MSK 0x00FF00
#define BMP5_OOR_THR_P_XMSB_MSK 0x010000
#define BMP5_OOR_THR_P_XMSB_POS 16
/* Macro to mask xmsb value of oor threshold from register(0x35) value */
#define BMP5_OOR_THR_P_XMSB_REG_MSK 0x01
#define BMP5_OOR_COUNT_LIMIT_MSK 0xC0
#define BMP5_OOR_COUNT_LIMIT_POS 6
/* NVM configuration */
#define BMP5_NVM_ADDR_MSK 0x3F
#define BMP5_NVM_PROG_EN_MSK 0x40
#define BMP5_NVM_PROG_EN_POS 6
#define BMP5_NVM_DATA_LSB_MSK 0x00FF
#define BMP5_NVM_DATA_MSB_MSK 0xFF00
/*!
* @brief OSR, ODR and pressure configuration structure
*/
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
*/
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
*/
uint8_t osr_p;
/*! Enable pressure
* BMP5_ENABLE = Enables pressure data
* BMP5_DISABLE = Disables pressure data
*/
uint8_t press_en;
/*! Output Data Rate */
uint8_t odr;
};
struct bmp581_sample {
struct sensor_value pressure;
struct sensor_value temperature;
};
struct bmp581_data {
uint8_t chip_id;
struct bmp581_sample last_sample;
struct bmp581_osr_odr_press_config osr_odr_press_config;
};
struct bmp581_config {
struct i2c_dt_spec i2c;
};
#endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_H_ */

View file

@ -0,0 +1,16 @@
description: |
The BMP581 is a Barometric pressure sensor. See more info at:
https://www.bosch-sensortec.com/products/environmental-sensors/pressure-sensors/bmp581/
compatible: "bosch,bmp581"
include: [sensor-device.yaml, i2c-device.yaml]
properties:
int-gpios:
type: phandle-array
required: false
description: Interrupt pin.
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.

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2022 Badgerd Technologies B.V.
*
* SPDX-License-Identifier: Apache-2.0
*
* Driver is developed to be used with Zephyr. And it only supports i2c interface.
*
* Author: Talha Can Havadar <havadartalha@gmail.com>
*
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMP581_USER_H_
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMP581_USER_H_
#include <zephyr/drivers/sensor.h>
#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
/* Custom ATTR values */
/* This is used to enable IIR config,
* keep in mind that disabling IIR back in runtime is not
* supported yet
*/
#define BMP5_ATTR_IIR_CONFIG (SENSOR_ATTR_PRIV_START + 1u)
#define BMP5_ATTR_POWER_MODE (SENSOR_ATTR_PRIV_START + 2u)
enum bmp5_powermode {
/*! Standby powermode */
BMP5_POWERMODE_STANDBY,
/*! Normal powermode */
BMP5_POWERMODE_NORMAL,
/*! Forced powermode */
BMP5_POWERMODE_FORCED,
/*! Continuous powermode */
BMP5_POWERMODE_CONTINUOUS,
/*! Deep standby powermode */
BMP5_POWERMODE_DEEP_STANDBY
};
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_BMP581_USER_H_ */

View file

@ -889,3 +889,9 @@ test_i2c_ags10: ags10@7e {
compatible = "aosong,ags10";
reg = <0x7e>;
};
test_i2c_bmp581: bmp581@7f {
compatible = "bosch,bmp581";
reg = <0x7f>;
int-gpios = <&test_gpio 0 0>;
};