Skip to content

Commit 568dd96

Browse files
Leonard Pollakcarlescufi
authored andcommitted
drivers: sensor: bme680: Add SPI interface
This enables the SPI interface for the BME680 sensor driver. Signed-off-by: Leonard Pollak <[email protected]>
1 parent 90b3eeb commit 568dd96

File tree

7 files changed

+308
-28
lines changed

7 files changed

+308
-28
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
#
21
# Copyright (c) 2018 Bosch Sensortec GmbH
2+
# Copyright (c) 2022, Leonard Pollak
33
#
44
# SPDX-License-Identifier: Apache-2.0
55
#
66

77
zephyr_library()
88

9-
zephyr_library_sources(bme680.c)
9+
zephyr_library_sources(bme680.c bme680_i2c.c bme680_spi.c)

drivers/sensor/bme680/Kconfig

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
# BME680 temperature, pressure, humidity and gas sensor configuration options
22

33
# Copyright (c) 2018 Bosch Sensortec GmbH
4+
# Copyright (c) 2022, Leonard Pollak
5+
#
46
# SPDX-License-Identifier: Apache-2.0
57

68
menuconfig BME680
79
bool "BME680 sensor"
8-
depends on I2C
10+
depends on I2C || SPI
911
help
10-
Enable driver for BME680 I2C-based based temperature, pressure, humidity and gas sensor.
12+
Enable driver for BME680 I2C- or SPI- based temperature, pressure, humidity and gas sensor.
1113

1214
if BME680
1315

drivers/sensor/bme680/bme680.c

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,49 @@
1111
* SPDX-License-Identifier: Apache-2.0
1212
*/
1313

14-
#define DT_DRV_COMPAT bosch_bme680
15-
16-
#include "bme680.h"
1714
#include <drivers/gpio.h>
18-
#include <drivers/i2c.h>
1915
#include <init.h>
2016
#include <kernel.h>
2117
#include <sys/byteorder.h>
2218
#include <sys/__assert.h>
2319
#include <drivers/sensor.h>
24-
2520
#include <logging/log.h>
21+
22+
#include "bme680.h"
23+
2624
LOG_MODULE_REGISTER(bme680, CONFIG_SENSOR_LOG_LEVEL);
2725

28-
static int bme680_reg_read(const struct device *dev, uint8_t start,
29-
uint8_t *buf, int size)
26+
27+
#if BME680_BUS_SPI
28+
static inline bool bme680_is_on_spi(const struct device *dev)
3029
{
3130
const struct bme680_config *config = dev->config;
3231

33-
return i2c_burst_read_dt(&config->bus, start, buf, size);
32+
return config->bus_io == &bme680_bus_io_spi;
3433
}
34+
#endif
3535

36-
static int bme680_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
36+
static inline int bme680_bus_check(const struct device *dev)
3737
{
3838
const struct bme680_config *config = dev->config;
3939

40-
return i2c_reg_write_byte_dt(&config->bus, reg, val);
40+
return config->bus_io->check(&config->bus);
41+
}
42+
43+
static inline int bme680_reg_read(const struct device *dev,
44+
uint8_t start, uint8_t *buf, int size)
45+
{
46+
const struct bme680_config *config = dev->config;
47+
48+
return config->bus_io->read(dev, start, buf, size);
49+
}
50+
51+
static inline int bme680_reg_write(const struct device *dev, uint8_t reg,
52+
uint8_t val)
53+
{
54+
const struct bme680_config *config = dev->config;
55+
56+
return config->bus_io->write(dev, reg, val);
4157
}
4258

4359
static void bme680_calc_temp(struct bme680_data *data, uint32_t adc_temp)
@@ -346,13 +362,22 @@ static int bme680_read_compensation(const struct device *dev)
346362
static int bme680_init(const struct device *dev)
347363
{
348364
struct bme680_data *data = dev->data;
349-
const struct bme680_config *config = dev->config;
350365
int err;
351366

352-
if (!device_is_ready(config->bus.bus)) {
353-
LOG_ERR("I2C master %s not ready", config->bus.bus->name);
354-
return -EINVAL;
367+
err = bme680_bus_check(dev);
368+
if (err < 0) {
369+
LOG_ERR("Bus not ready for '%s'", dev->name);
370+
return err;
371+
}
372+
373+
#if BME680_BUS_SPI
374+
if (bme680_is_on_spi(dev)) {
375+
err = bme680_reg_read(dev, BME680_REG_MEM_PAGE, &data->mem_page, 1);
376+
if (err < 0) {
377+
return err;
378+
}
355379
}
380+
#endif
356381

357382
err = bme680_reg_read(dev, BME680_REG_CHIP_ID, &data->chip_id, 1);
358383
if (err < 0) {
@@ -410,12 +435,39 @@ static const struct sensor_driver_api bme680_api_funcs = {
410435
.channel_get = bme680_channel_get,
411436
};
412437

413-
static struct bme680_data bme680_data;
438+
/* Initializes a struct bme680_config for an instance on a SPI bus. */
439+
#define BME680_CONFIG_SPI(inst) \
440+
{ \
441+
.bus.spi = SPI_DT_SPEC_INST_GET( \
442+
inst, BME680_SPI_OPERATION, 0), \
443+
.bus_io = &bme680_bus_io_spi, \
444+
}
414445

415-
static const struct bme680_config bme680_config = {
416-
.bus = I2C_DT_SPEC_INST_GET(0)
417-
};
446+
/* Initializes a struct bme680_config for an instance on an I2C bus. */
447+
#define BME680_CONFIG_I2C(inst) \
448+
{ \
449+
.bus.i2c = I2C_DT_SPEC_INST_GET(inst), \
450+
.bus_io = &bme680_bus_io_i2c, \
451+
}
418452

419-
DEVICE_DT_INST_DEFINE(0, bme680_init, NULL, &bme680_data,
420-
&bme680_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
421-
&bme680_api_funcs);
453+
/*
454+
* Main instantiation macro, which selects the correct bus-specific
455+
* instantiation macros for the instance.
456+
*/
457+
#define BME680_DEFINE(inst) \
458+
static struct bme680_data bme680_data_##inst; \
459+
static const struct bme680_config bme680_config_##inst = \
460+
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
461+
(BME680_CONFIG_SPI(inst)), \
462+
(BME680_CONFIG_I2C(inst))); \
463+
DEVICE_DT_INST_DEFINE(inst, \
464+
bme680_init, \
465+
NULL, \
466+
&bme680_data_##inst, \
467+
&bme680_config_##inst, \
468+
POST_KERNEL, \
469+
CONFIG_SENSOR_INIT_PRIORITY, \
470+
&bme680_api_funcs);
471+
472+
/* Create the struct device for every status "okay" node in the devicetree. */
473+
DT_INST_FOREACH_STATUS_OKAY(BME680_DEFINE)

drivers/sensor/bme680/bme680.h

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,51 @@
1010

1111
#include <zephyr/types.h>
1212
#include <device.h>
13+
#include <devicetree.h>
14+
#include <drivers/spi.h>
1315
#include <drivers/i2c.h>
1416

17+
#define DT_DRV_COMPAT bosch_bme680
18+
19+
#define BME680_BUS_SPI DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
20+
#define BME680_BUS_I2C DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
21+
22+
union bme680_bus {
23+
#if BME680_BUS_SPI
24+
struct spi_dt_spec spi;
25+
#endif
26+
#if BME680_BUS_I2C
27+
struct i2c_dt_spec i2c;
28+
#endif
29+
};
30+
31+
typedef int (*bme680_bus_check_fn)(const union bme680_bus *bus);
32+
typedef int (*bme680_reg_read_fn)(const struct device *dev,
33+
uint8_t start, uint8_t *buf, int size);
34+
typedef int (*bme680_reg_write_fn)(const struct device *dev,
35+
uint8_t reg, uint8_t val);
36+
37+
struct bme680_bus_io {
38+
bme680_bus_check_fn check;
39+
bme680_reg_read_fn read;
40+
bme680_reg_write_fn write;
41+
};
42+
43+
#if BME680_BUS_SPI
44+
#define BME680_SPI_OPERATION (SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL \
45+
| SPI_MODE_CPHA | SPI_OP_MODE_MASTER)
46+
extern const struct bme680_bus_io bme680_bus_io_spi;
47+
#endif
48+
49+
#if BME680_BUS_I2C
50+
extern const struct bme680_bus_io bme680_bus_io_i2c;
51+
#endif
52+
53+
struct bme680_config {
54+
union bme680_bus bus;
55+
const struct bme680_bus_io *bus_io;
56+
};
57+
1558
#define BME680_CHIP_ID 0x61
1659

1760
#define BME680_LEN_FIELD 15
@@ -44,6 +87,12 @@
4487
#define BME680_MSK_RANGE_SW_ERR 0xf0
4588
#define BME680_MSK_HEATR_STAB 0x10
4689

90+
#define BME680_SPI_READ_BIT 0x80
91+
#define BME680_SPI_WRITE_MSK 0x7f
92+
93+
#define BME680_MEM_PAGE1 0x00
94+
#define BME680_MEM_PAGE0 0x10
95+
4796
#if defined CONFIG_BME680_TEMP_OVER_1X
4897
#define BME680_TEMP_OVER (1 << 5)
4998
#elif defined CONFIG_BME680_TEMP_OVER_2X
@@ -163,10 +212,10 @@ struct bme680_data {
163212
int32_t t_fine;
164213

165214
uint8_t chip_id;
166-
};
167215

168-
struct bme680_config {
169-
struct i2c_dt_spec bus;
216+
#if BME680_BUS_SPI
217+
uint8_t mem_page;
218+
#endif
170219
};
171220

172221
#endif /* __ZEPHYR_DRIVERS_SENSOR_BME680_H__ */

drivers/sensor/bme680/bme680_i2c.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2016, 2017 Intel Corporation
3+
* Copyright (c) 2017 IpTronix S.r.l.
4+
* Copyright (c) 2021 Nordic Semiconductor ASA
5+
* Copyright (c) 2022, Leonard Pollak
6+
*
7+
* SPDX-License-Identifier: Apache-2.0
8+
*/
9+
10+
/*
11+
* Bus-specific functionality for BME680s accessed via I2C.
12+
*/
13+
14+
#include "bme680.h"
15+
16+
#if BME680_BUS_I2C
17+
static int bme680_bus_check_i2c(const union bme680_bus *bus)
18+
{
19+
return device_is_ready(bus->i2c.bus) ? 0 : -ENODEV;
20+
}
21+
22+
static int bme680_reg_read_i2c(const struct device *dev,
23+
uint8_t start, uint8_t *buf, int size)
24+
{
25+
const struct bme680_config *config = dev->config;
26+
27+
return i2c_burst_read_dt(&config->bus.i2c, start, buf, size);
28+
}
29+
30+
static int bme680_reg_write_i2c(const struct device *dev,
31+
uint8_t reg, uint8_t val)
32+
{
33+
const struct bme680_config *config = dev->config;
34+
35+
return i2c_reg_write_byte_dt(&config->bus.i2c, reg, val);
36+
}
37+
38+
const struct bme680_bus_io bme680_bus_io_i2c = {
39+
.check = bme680_bus_check_i2c,
40+
.read = bme680_reg_read_i2c,
41+
.write = bme680_reg_write_i2c,
42+
};
43+
#endif /* BME680_BUS_I2C */

0 commit comments

Comments
 (0)