Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions drivers/sensor/bme680/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#
# Copyright (c) 2018 Bosch Sensortec GmbH
# Copyright (c) 2022, Leonard Pollak
#
# SPDX-License-Identifier: Apache-2.0
#

zephyr_library()

zephyr_library_sources(bme680.c)
zephyr_library_sources(bme680.c bme680_i2c.c bme680_spi.c)
6 changes: 4 additions & 2 deletions drivers/sensor/bme680/Kconfig
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# BME680 temperature, pressure, humidity and gas sensor configuration options

# Copyright (c) 2018 Bosch Sensortec GmbH
# Copyright (c) 2022, Leonard Pollak
#
# SPDX-License-Identifier: Apache-2.0

menuconfig BME680
bool "BME680 sensor"
depends on I2C
depends on I2C || SPI
help
Enable driver for BME680 I2C-based based temperature, pressure, humidity and gas sensor.
Enable driver for BME680 I2C- or SPI- based temperature, pressure, humidity and gas sensor.

if BME680

Expand Down
120 changes: 80 additions & 40 deletions drivers/sensor/bme680/bme680.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,54 @@

/*
* Copyright (c) 2018 Bosch Sensortec GmbH
* Copyright (c) 2022, Leonard Pollak
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT bosch_bme680

#include "bme680.h"
#include <drivers/gpio.h>
#include <drivers/i2c.h>
#include <init.h>
#include <kernel.h>
#include <sys/byteorder.h>
#include <sys/__assert.h>
#include <drivers/sensor.h>

#include <logging/log.h>

#include "bme680.h"

LOG_MODULE_REGISTER(bme680, CONFIG_SENSOR_LOG_LEVEL);

static int bme680_reg_read(const struct device *dev, uint8_t start,
uint8_t *buf, int size)

#if BME680_BUS_SPI
static inline bool bme680_is_on_spi(const struct device *dev)
{
const struct bme680_config *config = dev->config;

return config->bus_io == &bme680_bus_io_spi;
}
#endif

static inline int bme680_bus_check(const struct device *dev)
{
const struct bme680_config *config = dev->config;

return i2c_burst_read_dt(&config->bus, start, buf, size);
return config->bus_io->check(&config->bus);
}

static int bme680_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
static inline int bme680_reg_read(const struct device *dev,
uint8_t start, uint8_t *buf, int size)
{
const struct bme680_config *config = dev->config;

return i2c_reg_write_byte_dt(&config->bus, reg, val);
return config->bus_io->read(dev, start, buf, size);
}

static inline int bme680_reg_write(const struct device *dev, uint8_t reg,
uint8_t val)
{
const struct bme680_config *config = dev->config;

return config->bus_io->write(dev, reg, val);
}

static void bme680_calc_temp(struct bme680_data *data, uint32_t adc_temp)
Expand Down Expand Up @@ -292,7 +309,7 @@ static int bme680_read_compensation(const struct device *dev)
}

err = bme680_reg_read(dev, BME680_REG_COEFF2, &buff[BME680_LEN_COEFF1],
16);
BME680_LEN_COEFF2);
if (err < 0) {
return err;
}
Expand Down Expand Up @@ -342,11 +359,26 @@ static int bme680_read_compensation(const struct device *dev)
return 0;
}

static int bme680_chip_init(const struct device *dev)
static int bme680_init(const struct device *dev)
{
struct bme680_data *data = dev->data;
int err;

err = bme680_bus_check(dev);
if (err < 0) {
LOG_ERR("Bus not ready for '%s'", dev->name);
return err;
}

#if BME680_BUS_SPI
if (bme680_is_on_spi(dev)) {
err = bme680_reg_read(dev, BME680_REG_MEM_PAGE, &data->mem_page, 1);
if (err < 0) {
return err;
}
}
#endif

err = bme680_reg_read(dev, BME680_REG_CHIP_ID, &data->chip_id, 1);
if (err < 0) {
return err;
Expand All @@ -355,7 +387,7 @@ static int bme680_chip_init(const struct device *dev)
if (data->chip_id == BME680_CHIP_ID) {
LOG_DBG("BME680 chip detected");
} else {
LOG_ERR("Bad BME680 chip id 0x%x", data->chip_id);
LOG_ERR("Bad BME680 chip id: 0x%x", data->chip_id);
return -ENOTSUP;
}

Expand Down Expand Up @@ -394,40 +426,48 @@ static int bme680_chip_init(const struct device *dev)

err = bme680_reg_write(dev, BME680_REG_CTRL_MEAS,
BME680_CTRL_MEAS_VAL);
if (err < 0) {
return err;
}

return 0;
}

static int bme680_init(const struct device *dev)
{
const struct bme680_config *config = dev->config;

if (!device_is_ready(config->bus.bus)) {
LOG_ERR("I2C master %s not ready", config->bus.bus->name);
return -EINVAL;
}

if (bme680_chip_init(dev) < 0) {
return -EINVAL;
}

return 0;
return err;
}

static const struct sensor_driver_api bme680_api_funcs = {
.sample_fetch = bme680_sample_fetch,
.channel_get = bme680_channel_get,
};

static struct bme680_data bme680_data;
/* Initializes a struct bme680_config for an instance on a SPI bus. */
#define BME680_CONFIG_SPI(inst) \
{ \
.bus.spi = SPI_DT_SPEC_INST_GET( \
inst, BME680_SPI_OPERATION, 0), \
.bus_io = &bme680_bus_io_spi, \
}

static const struct bme680_config bme680_config = {
.bus = I2C_DT_SPEC_INST_GET(0)
};
/* Initializes a struct bme680_config for an instance on an I2C bus. */
#define BME680_CONFIG_I2C(inst) \
{ \
.bus.i2c = I2C_DT_SPEC_INST_GET(inst), \
.bus_io = &bme680_bus_io_i2c, \
}

DEVICE_DT_INST_DEFINE(0, bme680_init, NULL, &bme680_data,
&bme680_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
&bme680_api_funcs);
/*
* Main instantiation macro, which selects the correct bus-specific
* instantiation macros for the instance.
*/
#define BME680_DEFINE(inst) \
static struct bme680_data bme680_data_##inst; \
static const struct bme680_config bme680_config_##inst = \
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
(BME680_CONFIG_SPI(inst)), \
(BME680_CONFIG_I2C(inst))); \
DEVICE_DT_INST_DEFINE(inst, \
bme680_init, \
NULL, \
&bme680_data_##inst, \
&bme680_config_##inst, \
POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, \
&bme680_api_funcs);

/* Create the struct device for every status "okay" node in the devicetree. */
DT_INST_FOREACH_STATUS_OKAY(BME680_DEFINE)
69 changes: 60 additions & 9 deletions drivers/sensor/bme680/bme680.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,60 @@
/*
* Copyright (c) 2018 Bosch Sensortec GmbH
* Copyright (c) 2022, Leonard Pollak
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef __SENSOR_BME680_H__
#define __SENSOR_BME680_H__
#ifndef __ZEPHYR_DRIVERS_SENSOR_BME680_H__
#define __ZEPHYR_DRIVERS_SENSOR_BME680_H__

#include <zephyr/types.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/spi.h>
#include <drivers/i2c.h>

#define DT_DRV_COMPAT bosch_bme680

#define BME680_BUS_SPI DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
#define BME680_BUS_I2C DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)

union bme680_bus {
#if BME680_BUS_SPI
struct spi_dt_spec spi;
#endif
#if BME680_BUS_I2C
struct i2c_dt_spec i2c;
#endif
};

typedef int (*bme680_bus_check_fn)(const union bme680_bus *bus);
typedef int (*bme680_reg_read_fn)(const struct device *dev,
uint8_t start, uint8_t *buf, int size);
typedef int (*bme680_reg_write_fn)(const struct device *dev,
uint8_t reg, uint8_t val);

struct bme680_bus_io {
bme680_bus_check_fn check;
bme680_reg_read_fn read;
bme680_reg_write_fn write;
};

#if BME680_BUS_SPI
#define BME680_SPI_OPERATION (SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL \
| SPI_MODE_CPHA | SPI_OP_MODE_MASTER)
extern const struct bme680_bus_io bme680_bus_io_spi;
#endif

#if BME680_BUS_I2C
extern const struct bme680_bus_io bme680_bus_io_i2c;
#endif

struct bme680_config {
union bme680_bus bus;
const struct bme680_bus_io *bus_io;
};

#define BME680_CHIP_ID 0x61

#define BME680_LEN_FIELD 15
Expand All @@ -29,19 +74,25 @@
#define BME680_REG_CTRL_HUM 0x72
#define BME680_REG_CTRL_MEAS 0x74
#define BME680_REG_CONFIG 0x75
#define BME680_REG_MEM_PAGE 0xf3
#define BME680_REG_MEM_PAGE 0x73
#define BME680_REG_UNIQUE_ID 0x83
#define BME680_REG_COEFF1 0x8a
#define BME680_REG_CHIP_ID 0xd0
#define BME680_REG_SOFT_RESET 0xe0
#define BME680_REG_COEFF2 0xe1
#define BME680_REG_CHIP_ID 0xd0
#define BME680_REG_SOFT_RESET 0xe0

#define BME680_MSK_NEW_DATA 0x80
#define BME680_MSK_GAS_RANGE 0x0f
#define BME680_MSK_RH_RANGE 0x30
#define BME680_MSK_RANGE_SW_ERR 0xf0
#define BME680_MSK_HEATR_STAB 0x10

#define BME680_SPI_READ_BIT 0x80
#define BME680_SPI_WRITE_MSK 0x7f

#define BME680_MEM_PAGE1 0x00
#define BME680_MEM_PAGE0 0x10

#if defined CONFIG_BME680_TEMP_OVER_1X
#define BME680_TEMP_OVER (1 << 5)
#elif defined CONFIG_BME680_TEMP_OVER_2X
Expand Down Expand Up @@ -161,10 +212,10 @@ struct bme680_data {
int32_t t_fine;

uint8_t chip_id;
};

struct bme680_config {
struct i2c_dt_spec bus;
#if BME680_BUS_SPI
uint8_t mem_page;
#endif
};

#endif /* __SENSOR_BME680_H__ */
#endif /* __ZEPHYR_DRIVERS_SENSOR_BME680_H__ */
43 changes: 43 additions & 0 deletions drivers/sensor/bme680/bme680_i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2016, 2017 Intel Corporation
* Copyright (c) 2017 IpTronix S.r.l.
* Copyright (c) 2021 Nordic Semiconductor ASA
* Copyright (c) 2022, Leonard Pollak
*
* SPDX-License-Identifier: Apache-2.0
*/

/*
* Bus-specific functionality for BME680s accessed via I2C.
*/

#include "bme680.h"

#if BME680_BUS_I2C
static int bme680_bus_check_i2c(const union bme680_bus *bus)
{
return device_is_ready(bus->i2c.bus) ? 0 : -ENODEV;
}

static int bme680_reg_read_i2c(const struct device *dev,
uint8_t start, uint8_t *buf, int size)
{
const struct bme680_config *config = dev->config;

return i2c_burst_read_dt(&config->bus.i2c, start, buf, size);
}

static int bme680_reg_write_i2c(const struct device *dev,
uint8_t reg, uint8_t val)
{
const struct bme680_config *config = dev->config;

return i2c_reg_write_byte_dt(&config->bus.i2c, reg, val);
}

const struct bme680_bus_io bme680_bus_io_i2c = {
.check = bme680_bus_check_i2c,
.read = bme680_reg_read_i2c,
.write = bme680_reg_write_i2c,
};
#endif /* BME680_BUS_I2C */
Loading