From b7f33bd84f0cfaea6d3271f05c611a0d39608303 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Wed, 10 Jan 2018 15:03:29 +0100 Subject: [PATCH] drivers/bmx280: significant driver rework bugs fixed: - move global variables into device descriptor - guard bus access (use acquire and release) added functionality: - enable SPI mode structural improvements: - reduce stack usage - simplify the driver's structure - centralize bus access code - use assertions - cleanup includes - use shortcuts for bus access style changes: - fix line length - cleanup and improve doxygen - unify pointer notation (char *var over char* var) - unify (error) return messages - use `#ifdef MODULE_BME280` instead of `#if defined(BME..)` - unify debug messages -> using `[bmx28] x: msg` scheme --- drivers/Makefile.dep | 17 +- drivers/bmx280/bmx280.c | 567 ++++++++++++---------- drivers/bmx280/bmx280_saul.c | 6 +- drivers/bmx280/include/bmx280_internals.h | 136 ++++-- drivers/bmx280/include/bmx280_params.h | 57 ++- drivers/include/bmx280.h | 159 ++++-- makefiles/pseudomodules.inc.mk | 6 +- sys/auto_init/auto_init.c | 2 +- sys/auto_init/saul/auto_init_bmx280.c | 17 +- 9 files changed, 570 insertions(+), 397 deletions(-) diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 7db8a567eb..8a424566d7 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -75,16 +75,25 @@ ifneq (,$(filter bmp180,$(USEMODULE))) USEMODULE += xtimer endif -ifneq (,$(filter bmx055,$(USEMODULE))) - FEATURES_REQUIRED += periph_i2c +ifneq (,$(filter bm%280_spi,$(USEMODULE))) + FEATURES_REQUIRED += periph_spi + FEATURES_REQUIRED += periph_gpio + USEMODULE += bmx280 endif -ifneq (,$(filter bm%280,$(USEMODULE))) +ifneq (,$(filter bm%280_i2c,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c - USEMODULE += xtimer USEMODULE += bmx280 endif +ifneq (,$(filter bmx280,$(USEMODULE))) + USEMODULE += xtimer +endif + +ifneq (,$(filter bmx055,$(USEMODULE))) + FEATURES_REQUIRED += periph_i2c +endif + ifneq (,$(filter cc110%,$(USEMODULE))) USEMODULE += cc110x USEMODULE += cc1xxx_common diff --git a/drivers/bmx280/bmx280.c b/drivers/bmx280/bmx280.c index 186632312f..484c37b16c 100644 --- a/drivers/bmx280/bmx280.c +++ b/drivers/bmx280/bmx280.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 Kees Bakker, SODAQ * 2017 Inria + * 2018 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -12,9 +13,10 @@ * @{ * * @file - * @brief Device driver implementation for sensors BMX280 (BME280 and BMP280). + * @brief Device driver implementation for BME280 and BMP280 sensors * * @author Kees Bakker + * @author Hauke Petersen * * @} */ @@ -23,93 +25,322 @@ #include #include "log.h" +#include "assert.h" #include "bmx280.h" #include "bmx280_internals.h" -#include "bmx280_params.h" -#include "periph/i2c.h" #include "xtimer.h" #define ENABLE_DEBUG (0) #include "debug.h" -static int read_calibration_data(bmx280_t* dev); -static int do_measurement(const bmx280_t* dev); -static uint8_t get_ctrl_meas(const bmx280_t* dev); -static uint8_t get_status(const bmx280_t* dev); -static uint8_t read_u8_reg(const bmx280_t* dev, uint8_t reg); -static void write_u8_reg(const bmx280_t* dev, uint8_t reg, uint8_t b); -static uint16_t get_uint16_le(const uint8_t *buffer, size_t offset); -static int16_t get_int16_le(const uint8_t *buffer, size_t offset); - -#if ENABLE_DEBUG -static void dump_buffer(const char *txt, uint8_t *buffer, size_t size); -#define DUMP_BUFFER(txt, buffer, size) dump_buffer(txt, buffer, size) +#ifdef BMX280_USE_SPI +#define BUS (dev->params.spi) +#define CS (dev->params.cs) +#define CLK (dev->params.clk) +#define MODE SPI_MODE_0 +#define WRITE_MASK (0x7F) #else -#define DUMP_BUFFER(txt, buffer, size) +#define BUS (dev->params.i2c_dev) +#define ADDR (dev->params.i2c_addr) #endif -/** - * @brief Fine resolution temperature value, also needed for pressure and humidity. - */ -static int32_t t_fine; +/* shortcut for accessing byte x of the latest sensor reading */ +#define RAW_DATA (dev->last_reading) -/** - * @brief The measurement registers, including temperature, pressure and humidity - * - * A temporary buffer for the memory map 0xF7..0xFE - * These are read all at once and then used to compute the three sensor values. - */ -static uint8_t measurement_regs[8]; - -/*---------------------------------------------------------------------------* - * BMX280 Core API * - *---------------------------------------------------------------------------*/ - -int bmx280_init(bmx280_t* dev, const bmx280_params_t* params) +/* implementation for the driver's configured bus interface (I2C vs SPI) */ +#ifdef BMX280_USE_SPI /* using SPI mode */ +static inline int _acquire(const bmx280_t *dev) { - uint8_t chip_id; + if (spi_acquire(BUS, CS, MODE, CLK) != SPI_OK) { + return BMX280_ERR_BUS; + } + return BMX280_OK; +} - dev->params = *params; +static inline void _release(const bmx280_t *dev) +{ + spi_release(BUS); +} - /* Read chip ID */ - chip_id = read_u8_reg(dev, BMX280_CHIP_ID_REG); - if ((chip_id != BME280_CHIP_ID) && (chip_id != BMP280_CHIP_ID)) { - DEBUG("[Error] Did not detect a BMX280 at address %02x (%02x != %02x or %02x)\n", - dev->params.i2c_addr, chip_id, BME280_CHIP_ID, BMP280_CHIP_ID); - return BMX280_ERR_NODEV; +static int _read_reg(const bmx280_t *dev, uint8_t reg, uint8_t *data) +{ + *data = spi_transfer_reg(BUS, CS, reg, 0); + return BMX280_OK; +} + +static int _write_reg(const bmx280_t *dev, uint8_t reg, uint8_t data) +{ + (void)spi_transfer_reg(BUS, CS, (reg & WRITE_MASK), data); + return BMX280_OK; +} + +static int _read_burst(const bmx280_t *dev, uint8_t reg, void *buf, size_t len) +{ + spi_transfer_regs(BUS, CS, reg, NULL, buf, len); + return BMX280_OK; +} + +#else /* using I2C mode */ + +static inline int _acquire(const bmx280_t *dev) +{ + if (i2c_acquire(BUS) != 0) { + return BMX280_ERR_BUS; + } + return BMX280_OK; +} + +static inline void _release(const bmx280_t *dev) +{ + i2c_release(BUS); +} + +static int _read_reg(const bmx280_t *dev, uint8_t reg, uint8_t *data) +{ + if (i2c_read_reg(BUS, ADDR, reg, data, 0) != 0) { + return BMX280_ERR_BUS; + } + return BMX280_OK; +} + +static int _write_reg(const bmx280_t *dev, uint8_t reg, uint8_t data) +{ + if (i2c_write_reg(BUS, ADDR, reg, data, 0) != 0) { + return BMX280_ERR_BUS; + } + return BMX280_OK; +} + +static int _read_burst(const bmx280_t *dev, uint8_t reg, void *buf, size_t len) +{ + if (i2c_read_regs(BUS, ADDR, reg, buf, len, 0) != 0) { + return BMX280_ERR_BUS; + } + return BMX280_OK; +} + +#endif /* bus mode selection */ + +static uint16_t _to_u16_le(const uint8_t *buffer, size_t offset) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return (((uint16_t)buffer[offset + 1]) << 8) + buffer[offset]; +#else + return (((uint16_t)buffer[offset]) << 8) + buffer[offset + 1]; +#endif +} + +static int16_t _to_i16_le(const uint8_t *buffer, size_t offset) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return (((int16_t)buffer[offset + 1]) << 8) + buffer[offset]; +#else + return (((int16_t)buffer[offset]) << 8) + buffer[offset + 1]; +#endif +} + +/** + * @brief Read the calibration data from sensor ROM, it is in registers + * 0x88..0x9F, 0xA1, and 0xE1..0xE7 + */ +static int _read_calibration_data(bmx280_t *dev) +{ + /* no need to acquire a bus here, as this is done in the init function */ + + /* allocate some memory to store the largest block of calibration data */ + uint8_t buf[CALIB_T_P_LEN]; + + /* read humidity and temperature calibration data */ + if (_read_burst(dev, CALIB_T_P_BASE, buf, CALIB_T_P_LEN) != BMX280_OK) { + return BMX280_ERR_BUS; } - /* Read compensation data, 0x88..0x9F, 0xA1, 0xE1..0xE7 */ - if (read_calibration_data(dev)) { - DEBUG("[Error] Could not read calibration data\n"); - return BMX280_ERR_NOCAL; + /* convert calibration values to little endian format and save them */ + dev->calibration.dig_T1 = _to_u16_le(buf, OFFSET_T_P(BMX280_DIG_T1_LSB_REG)); + dev->calibration.dig_T2 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_T2_LSB_REG)); + dev->calibration.dig_T3 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_T3_LSB_REG)); + + dev->calibration.dig_P1 = _to_u16_le(buf, OFFSET_T_P(BMX280_DIG_P1_LSB_REG)); + dev->calibration.dig_P2 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P2_LSB_REG)); + dev->calibration.dig_P3 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P3_LSB_REG)); + dev->calibration.dig_P4 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P4_LSB_REG)); + dev->calibration.dig_P5 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P5_LSB_REG)); + dev->calibration.dig_P6 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P6_LSB_REG)); + dev->calibration.dig_P7 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P7_LSB_REG)); + dev->calibration.dig_P8 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P8_LSB_REG)); + dev->calibration.dig_P9 = _to_i16_le(buf, OFFSET_T_P(BMX280_DIG_P9_LSB_REG)); + +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) + /* read dig_H1 in a single read, as this value is not in the block with the + * rest of the humidity calibration values */ + if (_read_reg(dev, BME280_DIG_H1_REG, &dev->calibration.dig_H1) != BMX280_OK) { + return BMX280_ERR_BUS; } + /* read the block with the rest of the values */ + if (_read_burst(dev, CALIB_H_BASE, buf, CALIB_H_LEN) != BMX280_OK) { + return BMX280_ERR_BUS; + } + + /* parse the humidity compensation and store in device descriptor */ + dev->calibration.dig_H2 = _to_i16_le(buf, OFFSET_H(BME280_DIG_H2_LSB_REG)); + dev->calibration.dig_H3 = buf[OFFSET_H(BME280_DIG_H3_REG)]; + dev->calibration.dig_H4 = ((((int16_t)buf[OFFSET_H(BME280_DIG_H4_MSB_REG)]) << 4) + + (buf[OFFSET_H(BME280_DIG_H4_H5_REG)] & 0x0F)); + dev->calibration.dig_H5 = ((((int16_t)buf[OFFSET_H(BME280_DIG_H5_MSB_REG)]) << 4) + + ((buf[OFFSET_H(BME280_DIG_H4_H5_REG)] & 0xF0) >> 4)); + dev->calibration.dig_H6 = buf[OFFSET_H(BME280_DIG_H6_REG)]; +#endif + return BMX280_OK; } -/* - * Returns temperature in DegC, resolution is 0.01 DegC. - * t_fine carries fine temperature as global value +/** + * @brief Trigger a new measurement (if applicable) and read raw data */ -int16_t bmx280_read_temperature(const bmx280_t* dev) +static int _do_measurement(bmx280_t *dev) { - if (do_measurement(dev) < 0) { + uint8_t reg; + + /* get access to the bus */ + if (_acquire(dev) != BMX280_OK) { + goto err; + } + + /* if in FORCED mode, we need to manually trigger a measurement */ + if (dev->params.run_mode != BMX280_MODE_NORMAL) { + reg = ((dev->params.temp_oversample << MEAS_OSRS_T_POS) | + (dev->params.press_oversample << MEAS_OSRS_P_POS) | + BMX280_MODE_FORCED); + if (_write_reg(dev, BMX280_CTRL_MEAS_REG, reg) != BMX280_OK) { + goto err; + } + do { + if (_read_reg(dev, BMX280_STAT_REG, ®) != BMX280_OK) { + goto err; + } + } while (reg & STAT_MEASURING); + /* results are ready now */ + DEBUG("[bmx280] _do_measurement: measurement data ready\n"); + } + + /* read all raw data registers into data buffer */ + if (_read_burst(dev, DATA_BASE, RAW_DATA, BMX280_RAW_LEN) != BMX280_OK) { + goto err; + } + + /* we are done reading from the device, so release the bus again */ + _release(dev); + return BMX280_OK; + +err: + _release(dev); + return BMX280_ERR_BUS; +} + +int bmx280_init(bmx280_t *dev, const bmx280_params_t *params) +{ + assert(dev && params); + + dev->params = *params; + uint8_t reg; + + +#ifdef BMX280_USE_SPI + /* configure the chip-select pin */ + if (spi_init_cs(BUS, CS) != SPI_OK) { + DEBUG("[bmx280] error: unable to configure chip the select pin\n"); + return BMX280_ERR_BUS; + } +#endif + + /* acquire bus bus, this also tests the bus parameters in SPI mode */ + if (_acquire(dev) != BMX280_OK) { + DEBUG("[bmx280] error: unable to acquire bus\n"); + return BMX280_ERR_BUS; + } + + /* test the connection to the device by reading and verifying its chip ID */ + if (_read_reg(dev, BMX280_CHIP_ID_REG, ®) != BMX280_OK) { + DEBUG("[bmx280] error: unable to read chip ID from device\n"); + return BMX280_ERR_NODEV; + } + if (reg != BMX280_CHIP_ID_VAL) { + DEBUG("[bmx280] error: invalid chip ID (0x%02x)\n", (int)reg); + _release(dev); + return BMX280_ERR_NODEV; + } + + /* trigger a power-on reset sequence to reset all registers */ + if (_write_reg(dev, BMEX80_RST_REG, RESET_WORD) != BMX280_OK) { + goto err; + } + /* wait for reset sequence to finish */ + do { + if (_read_reg(dev, BMX280_STAT_REG, ®) != BMX280_OK) { + goto err; + } + } while (reg != 0); + + /* read the compensation data from the sensor's ROM */ + if (_read_calibration_data(dev) != BMX280_OK) { + DEBUG("[bmx280] error: could not read calibration data\n"); + goto err; + } + + /* write basic device configuration: t_sb and filter values */ + reg = (dev->params.t_sb | dev->params.filter); + if (_write_reg(dev, BMX280_CONFIG_REG, reg) != BMX280_OK) { + goto err; + } + +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) + /* ctrl_hum must be written before ctrl_meas for changes to become + * effective */ + reg = dev->params.humid_oversample; + if (_write_reg(dev, BME280_CTRL_HUM_REG, reg) != BMX280_OK) { + goto err; + } +#endif + + /* finally apply the temperature and pressure oversampling configuration and + * configure the run mode */ + reg = ((dev->params.temp_oversample << MEAS_OSRS_T_POS) | + (dev->params.press_oversample << MEAS_OSRS_P_POS) | + (dev->params.run_mode)); + if (_write_reg(dev, BMX280_CTRL_MEAS_REG, reg) != BMX280_OK) { + goto err; + } + + _release(dev); + return BMX280_OK; + +err: + _release(dev); + DEBUG("[bmx280] init: bus error while initializing device\n"); + return BMX280_ERR_BUS; +} + +int16_t bmx280_read_temperature(bmx280_t *dev) +{ + assert(dev); + + if (_do_measurement(dev) < 0) { return INT16_MIN; } const bmx280_calibration_t *cal = &dev->calibration; /* helper variable */ /* Read the uncompensated temperature */ - int32_t adc_T = (((uint32_t)measurement_regs[3 + 0]) << 12) | - (((uint32_t)measurement_regs[3 + 1]) << 4) | - ((((uint32_t)measurement_regs[3 + 2]) >> 4) & 0x0F); + int32_t adc_T = (((uint32_t)RAW_DATA[3 + 0]) << 12) | + (((uint32_t)RAW_DATA[3 + 1]) << 4) | + ((((uint32_t)RAW_DATA[3 + 2]) >> 4) & 0x0F); /* * Compensate the temperature value. - * The following is code from Bosch's BME280_driver bme280_compensate_temperature_int32() - * The variable names and the many defines have been modified to make the code - * more readable. + * The following is code from Bosch's BME280_driver + * bme280_compensate_temperature_int32(). The variable names and the many + * defines have been modified to make the code more readable. */ int32_t var1; int32_t var2; @@ -119,22 +350,21 @@ int16_t bmx280_read_temperature(const bmx280_t* dev) ((int32_t)cal->dig_T3)) >> 14; /* calculate t_fine (used for pressure and humidity too) */ - t_fine = var1 + var2; + dev->t_fine = var1 + var2; - return (t_fine * 5 + 128) >> 8; + return (dev->t_fine * 5 + 128) >> 8; } -/* - * Returns pressure in Pa - */ uint32_t bmx280_read_pressure(const bmx280_t *dev) { + assert(dev); + const bmx280_calibration_t *cal = &dev->calibration; /* helper variable */ /* Read the uncompensated pressure */ - int32_t adc_P = (((uint32_t)measurement_regs[0 + 0]) << 12) | - (((uint32_t)measurement_regs[0 + 1]) << 4) | - ((((uint32_t)measurement_regs[0 + 2]) >> 4) & 0x0F); + int32_t adc_P = (((uint32_t)RAW_DATA[0 + 0]) << 12) | + (((uint32_t)RAW_DATA[0 + 1]) << 4) | + ((((uint32_t)RAW_DATA[0 + 2]) >> 4) & 0x0F); int64_t var1; int64_t var2; @@ -142,11 +372,11 @@ uint32_t bmx280_read_pressure(const bmx280_t *dev) /* * Compensate the pressure value. - * The following is code from Bosch's BME280_driver bme280_compensate_pressure_int64() - * The variable names and the many defines have been modified to make the code - * more readable. + * The following is code from Bosch's BME280_driver + * bme280_compensate_pressure_int64(). The variable names and the many + * defines have been modified to make the code more readable. */ - var1 = ((int64_t)t_fine) - 128000; + var1 = ((int64_t)dev->t_fine) - 128000; var2 = var1 * var1 * (int64_t)cal->dig_P6; var2 = var2 + ((var1 * (int64_t)cal->dig_P5) << 17); var2 = var2 + (((int64_t)cal->dig_P4) << 35); @@ -166,27 +396,29 @@ uint32_t bmx280_read_pressure(const bmx280_t *dev) return p_acc >> 8; } -#if defined(MODULE_BME280) +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) uint16_t bme280_read_humidity(const bmx280_t *dev) { + assert(dev); + const bmx280_calibration_t *cal = &dev->calibration; /* helper variable */ /* Read the uncompensated pressure */ - int32_t adc_H = (((uint32_t)measurement_regs[6 + 0]) << 8) | - (((uint32_t)measurement_regs[6 + 1])); + int32_t adc_H = (((uint32_t)RAW_DATA[6 + 0]) << 8) | + (((uint32_t)RAW_DATA[6 + 1])); /* * Compensate the humidity value. - * The following is code from Bosch's BME280_driver bme280_compensate_humidity_int32() - * The variable names and the many defines have been modified to make the code - * more readable. + * The following is code from Bosch's BME280_driver + * bme280_compensate_humidity_int32(). The variable names and the many + * defines have been modified to make the code more readable. * The value is first computed as a value in %rH as unsigned 32bit integer * in Q22.10 format(22 integer 10 fractional bits). */ int32_t var1; /* calculate x1*/ - var1 = (t_fine - ((int32_t)76800)); + var1 = (dev->t_fine - ((int32_t)76800)); /* calculate x1*/ var1 = (((((adc_H << 14) - (((int32_t)cal->dig_H4) << 20) - (((int32_t)cal->dig_H5) * var1)) + ((int32_t)16384)) >> 15) * @@ -194,190 +426,9 @@ uint16_t bme280_read_humidity(const bmx280_t *dev) (((var1 * ((int32_t)cal->dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)cal->dig_H2) + 8192) >> 14)); var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)cal->dig_H1)) >> 4)); - var1 = (var1 < 0 ? 0 : var1); - var1 = (var1 > 419430400 ? 419430400 : var1); + var1 = (var1 < 0) ? 0 : var1; + var1 = (var1 > 419430400) ? 419430400 : var1; /* First multiply to avoid losing the accuracy after the shift by ten */ return (100 * ((uint32_t)var1 >> 12)) >> 10; } #endif - -/** - * Read compensation data, 0x88..0x9F, 0xA1, 0xE1..0xE7 - * - * This function reads all calibration bytes at once. These are - * the registers DIG_T1_LSB (0x88) upto and including DIG_H6 (0xE7). - */ -static int read_calibration_data(bmx280_t* dev) -{ - uint8_t buffer[128]; /* 128 should be enough to read all calibration bytes */ - int result; -#ifdef MODULE_BME280 - int nr_bytes_to_read = (BME280_DIG_H6_REG - BMX280_DIG_T1_LSB_REG) + 1; -#else - int nr_bytes_to_read = (BMX280_DIG_P9_MSB_REG - BMX280_DIG_T1_LSB_REG) + 1; -#endif - uint8_t offset = 0x88; - - memset(buffer, 0, sizeof(buffer)); - i2c_acquire(dev->params.i2c_dev); - result = i2c_read_regs(dev->params.i2c_dev, dev->params.i2c_addr, offset, - buffer, nr_bytes_to_read, 0); - i2c_release(dev->params.i2c_dev); - if (result != 0) { - LOG_ERROR("Unable to read calibration data\n"); - return -1; - } - DUMP_BUFFER("Raw Calibration Data", buffer, nr_bytes_to_read); - - /* All little endian */ - dev->calibration.dig_T1 = get_uint16_le(buffer, BMX280_DIG_T1_LSB_REG - offset); - dev->calibration.dig_T2 = get_int16_le(buffer, BMX280_DIG_T2_LSB_REG - offset); - dev->calibration.dig_T3 = get_int16_le(buffer, BMX280_DIG_T3_LSB_REG - offset); - - dev->calibration.dig_P1 = get_uint16_le(buffer, BMX280_DIG_P1_LSB_REG - offset); - dev->calibration.dig_P2 = get_int16_le(buffer, BMX280_DIG_P2_LSB_REG - offset); - dev->calibration.dig_P3 = get_int16_le(buffer, BMX280_DIG_P3_LSB_REG - offset); - dev->calibration.dig_P4 = get_int16_le(buffer, BMX280_DIG_P4_LSB_REG - offset); - dev->calibration.dig_P5 = get_int16_le(buffer, BMX280_DIG_P5_LSB_REG - offset); - dev->calibration.dig_P6 = get_int16_le(buffer, BMX280_DIG_P6_LSB_REG - offset); - dev->calibration.dig_P7 = get_int16_le(buffer, BMX280_DIG_P7_LSB_REG - offset); - dev->calibration.dig_P8 = get_int16_le(buffer, BMX280_DIG_P8_LSB_REG - offset); - dev->calibration.dig_P9 = get_int16_le(buffer, BMX280_DIG_P9_LSB_REG - offset); - -#if defined(MODULE_BME280) - dev->calibration.dig_H1 = buffer[BME280_DIG_H1_REG - offset]; - dev->calibration.dig_H2 = get_int16_le(buffer, BME280_DIG_H2_LSB_REG - offset); - dev->calibration.dig_H3 = buffer[BME280_DIG_H3_REG - offset]; - dev->calibration.dig_H4 = (((int16_t)buffer[BME280_DIG_H4_MSB_REG - offset]) << 4) + - (buffer[BME280_DIG_H4_H5_REG - offset] & 0x0F); - dev->calibration.dig_H5 = (((int16_t)buffer[BME280_DIG_H5_MSB_REG - offset]) << 4) + - ((buffer[BME280_DIG_H4_H5_REG - offset] & 0xF0) >> 4); - dev->calibration.dig_H6 = buffer[BME280_DIG_H6_REG - offset]; -#endif - - DEBUG("[INFO] Chip ID = 0x%02X\n", buffer[BMX280_CHIP_ID_REG - offset]); - - /* Config is only writable in sleep mode */ - i2c_acquire(dev->params.i2c_dev); - (void)i2c_write_reg(dev->params.i2c_dev, dev->params.i2c_addr, - BMX280_CTRL_MEAS_REG, 0, 0); - i2c_release(dev->params.i2c_dev); - - uint8_t b; - - /* Config Register */ - /* spi3w_en unused */ - b = ((dev->params.t_sb & 7) << 5) | ((dev->params.filter & 7) << 2); - write_u8_reg(dev, BMX280_CONFIG_REG, b); - -#if defined(MODULE_BME280) - /* - * Note from the datasheet about ctrl_hum: "Changes to this register only become effective - * after a write operation to "ctrl_meas". - * So, set ctrl_hum first. - */ - b = dev->params.humid_oversample & 7; - write_u8_reg(dev, BME280_CTRL_HUMIDITY_REG, b); -#endif - - b = ((dev->params.temp_oversample & 7) << 5) | - ((dev->params.press_oversample & 7) << 2) | - (dev->params.run_mode & 3); - write_u8_reg(dev, BMX280_CTRL_MEAS_REG, b); - - return 0; -} - -/** - * @brief Start a measurement and read the registers - */ -static int do_measurement(const bmx280_t* dev) -{ - /* - * If settings has FORCED mode, then the device go to sleep after - * it finished the measurement. To read again we have to set the - * run_mode back to FORCED. - */ - uint8_t ctrl_meas = get_ctrl_meas(dev); - uint8_t run_mode = ctrl_meas & 3; - if (run_mode != dev->params.run_mode) { - /* Set the run_mode back to what we want. */ - ctrl_meas &= ~3; - ctrl_meas |= dev->params.run_mode; - write_u8_reg(dev, BMX280_CTRL_MEAS_REG, ctrl_meas); - - /* Wait for measurement ready? */ - size_t count = 0; - while (count < 10 && (get_status(dev) & 0x08) != 0) { - ++count; - } - /* What to do when measuring is still on? */ - } - int result; - int nr_bytes_to_read = sizeof(measurement_regs); - uint8_t offset = BMX280_PRESSURE_MSB_REG; - - i2c_acquire(dev->params.i2c_dev); - result = i2c_read_regs(dev->params.i2c_dev, dev->params.i2c_addr, - offset, measurement_regs, nr_bytes_to_read, 0); - i2c_release(dev->params.i2c_dev); - if (result != 0) { - LOG_ERROR("Unable to read temperature data\n"); - return -1; - } - DUMP_BUFFER("Raw Sensor Data", measurement_regs, nr_bytes_to_read); - - return 0; -} - -static uint8_t get_ctrl_meas(const bmx280_t* dev) -{ - return read_u8_reg(dev, BMX280_CTRL_MEAS_REG); -} - -static uint8_t get_status(const bmx280_t* dev) -{ - return read_u8_reg(dev, BMX280_STAT_REG); -} - -static uint8_t read_u8_reg(const bmx280_t* dev, uint8_t reg) -{ - uint8_t b; - /* Assuming device is correct, it should return 1 (nr bytes) */ - i2c_acquire(dev->params.i2c_dev); - (void)i2c_read_reg(dev->params.i2c_dev, dev->params.i2c_addr, reg, &b, 0); - i2c_release(dev->params.i2c_dev); - return b; -} - -static void write_u8_reg(const bmx280_t* dev, uint8_t reg, uint8_t b) -{ - /* Assuming device is correct, it should return 1 (nr bytes) */ - i2c_acquire(dev->params.i2c_dev); - (void)i2c_write_reg(dev->params.i2c_dev, dev->params.i2c_addr, reg, b, 0); - i2c_release(dev->params.i2c_dev); -} - -static uint16_t get_uint16_le(const uint8_t *buffer, size_t offset) -{ - return (((uint16_t)buffer[offset + 1]) << 8) + buffer[offset]; -} - -static int16_t get_int16_le(const uint8_t *buffer, size_t offset) -{ - return (((int16_t)buffer[offset + 1]) << 8) + buffer[offset]; -} - -#if ENABLE_DEBUG -static void dump_buffer(const char *txt, uint8_t *buffer, size_t size) -{ - size_t ix; - DEBUG("%s\n", txt); - for (ix = 0; ix < size; ix++) { - DEBUG("%02X", buffer[ix]); - if ((ix + 1) == size || (((ix + 1) % 16) == 0)) { - DEBUG("\n"); - } - } -} -#endif diff --git a/drivers/bmx280/bmx280_saul.c b/drivers/bmx280/bmx280_saul.c index 5e217372aa..90a8dc76f7 100644 --- a/drivers/bmx280/bmx280_saul.c +++ b/drivers/bmx280/bmx280_saul.c @@ -26,7 +26,7 @@ static int read_temperature(const void *dev, phydat_t *res) { - res->val[0] = bmx280_read_temperature((const bmx280_t *)dev); + res->val[0] = bmx280_read_temperature((bmx280_t *)dev); res->unit = UNIT_TEMP_C; res->scale = -2; @@ -42,7 +42,7 @@ static int read_pressure(const void *dev, phydat_t *res) return 1; } -#ifdef MODULE_BME280 +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) static int read_relative_humidity(const void *dev, phydat_t *res) { res->val[0] = bme280_read_humidity((const bmx280_t *)dev); @@ -65,7 +65,7 @@ const saul_driver_t bmx280_pressure_saul_driver = { .type = SAUL_SENSE_PRESS, }; -#ifdef MODULE_BME280 +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) const saul_driver_t bme280_relative_humidity_saul_driver = { .read = read_relative_humidity, .write = saul_notsup, diff --git a/drivers/bmx280/include/bmx280_internals.h b/drivers/bmx280/include/bmx280_internals.h index 4c565f1e95..839d978c97 100644 --- a/drivers/bmx280/include/bmx280_internals.h +++ b/drivers/bmx280/include/bmx280_internals.h @@ -25,61 +25,101 @@ extern "C" { #endif +/** + * @name Device specific chip ID + * @{ + */ +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) +#define BMX280_CHIP_ID_VAL (0x60) +#else +#define BMX280_CHIP_ID_VAL (0x58) +#endif +/** @} */ + /** * @name BME280 registers * @{ */ -#define BME280_CHIP_ID 0x60 /* The identifier of the BME280 */ -#define BMP280_CHIP_ID 0x58 /* The identifier of the BMP280 */ -#define BMX280_CHIP_ID_REG 0xD0 -#define BMEX80_RST_REG 0xE0 /* Softreset Reg */ +#define BMX280_CHIP_ID_REG (0xD0) +#define BMEX80_RST_REG (0xE0) /* Softreset Reg */ -#define BMX280_DIG_T1_LSB_REG 0x88 -#define BMX280_DIG_T1_MSB_REG 0x89 -#define BMX280_DIG_T2_LSB_REG 0x8A -#define BMX280_DIG_T2_MSB_REG 0x8B -#define BMX280_DIG_T3_LSB_REG 0x8C -#define BMX280_DIG_T3_MSB_REG 0x8D -#define BMX280_DIG_P1_LSB_REG 0x8E -#define BMX280_DIG_P1_MSB_REG 0x8F -#define BMX280_DIG_P2_LSB_REG 0x90 -#define BMX280_DIG_P2_MSB_REG 0x91 -#define BMX280_DIG_P3_LSB_REG 0x92 -#define BMX280_DIG_P3_MSB_REG 0x93 -#define BMX280_DIG_P4_LSB_REG 0x94 -#define BMX280_DIG_P4_MSB_REG 0x95 -#define BMX280_DIG_P5_LSB_REG 0x96 -#define BMX280_DIG_P5_MSB_REG 0x97 -#define BMX280_DIG_P6_LSB_REG 0x98 -#define BMX280_DIG_P6_MSB_REG 0x99 -#define BMX280_DIG_P7_LSB_REG 0x9A -#define BMX280_DIG_P7_MSB_REG 0x9B -#define BMX280_DIG_P8_LSB_REG 0x9C -#define BMX280_DIG_P8_MSB_REG 0x9D -#define BMX280_DIG_P9_LSB_REG 0x9E -#define BMX280_DIG_P9_MSB_REG 0x9F +#define BMX280_DIG_T1_LSB_REG (0x88) +#define BMX280_DIG_T1_MSB_REG (0x89) +#define BMX280_DIG_T2_LSB_REG (0x8A) +#define BMX280_DIG_T2_MSB_REG (0x8B) +#define BMX280_DIG_T3_LSB_REG (0x8C) +#define BMX280_DIG_T3_MSB_REG (0x8D) +#define BMX280_DIG_P1_LSB_REG (0x8E) +#define BMX280_DIG_P1_MSB_REG (0x8F) +#define BMX280_DIG_P2_LSB_REG (0x90) +#define BMX280_DIG_P2_MSB_REG (0x91) +#define BMX280_DIG_P3_LSB_REG (0x92) +#define BMX280_DIG_P3_MSB_REG (0x93) +#define BMX280_DIG_P4_LSB_REG (0x94) +#define BMX280_DIG_P4_MSB_REG (0x95) +#define BMX280_DIG_P5_LSB_REG (0x96) +#define BMX280_DIG_P5_MSB_REG (0x97) +#define BMX280_DIG_P6_LSB_REG (0x98) +#define BMX280_DIG_P6_MSB_REG (0x99) +#define BMX280_DIG_P7_LSB_REG (0x9A) +#define BMX280_DIG_P7_MSB_REG (0x9B) +#define BMX280_DIG_P8_LSB_REG (0x9C) +#define BMX280_DIG_P8_MSB_REG (0x9D) +#define BMX280_DIG_P9_LSB_REG (0x9E) +#define BMX280_DIG_P9_MSB_REG (0x9F) -#define BME280_DIG_H1_REG 0xA1 -#define BME280_DIG_H2_LSB_REG 0xE1 -#define BME280_DIG_H2_MSB_REG 0xE2 -#define BME280_DIG_H3_REG 0xE3 -#define BME280_DIG_H4_MSB_REG 0xE4 /* H4[11:4] */ -#define BME280_DIG_H4_H5_REG 0xE5 /* H5[3:0] H4[3:0] */ -#define BME280_DIG_H5_MSB_REG 0xE6 /* H5[11:4] */ -#define BME280_DIG_H6_REG 0xE7 +#define BME280_DIG_H1_REG (0xA1) +#define BME280_DIG_H2_LSB_REG (0xE1) +#define BME280_DIG_H2_MSB_REG (0xE2) +#define BME280_DIG_H3_REG (0xE3) +#define BME280_DIG_H4_MSB_REG (0xE4) /* H4[11:4] */ +#define BME280_DIG_H4_H5_REG (0xE5) /* H5[3:0] H4[3:0] */ +#define BME280_DIG_H5_MSB_REG (0xE6) /* H5[11:4] */ +#define BME280_DIG_H6_REG (0xE7) -#define BMX280_STAT_REG 0xF3 /* Status Reg */ -#define BMX280_CTRL_MEAS_REG 0xF4 /* Ctrl Measure Reg */ -#define BMX280_CONFIG_REG 0xF5 /* Configuration Reg */ -#define BMX280_PRESSURE_MSB_REG 0xF7 /* Pressure MSB */ -#define BMX280_PRESSURE_LSB_REG 0xF8 /* Pressure LSB */ -#define BMX280_PRESSURE_XLSB_REG 0xF9 /* Pressure XLSB */ -#define BMX280_TEMPERATURE_MSB_REG 0xFA /* Temperature MSB */ -#define BMX280_TEMPERATURE_LSB_REG 0xFB /* Temperature LSB */ -#define BMX280_TEMPERATURE_XLSB_REG 0xFC /* Temperature XLSB */ -#define BME280_CTRL_HUMIDITY_REG 0xF2 /* Ctrl Humidity Reg */ -#define BME280_HUMIDITY_MSB_REG 0xFD /* Humidity MSB */ -#define BME280_HUMIDITY_LSB_REG 0xFE /* Humidity LSB */ +#define BMX280_STAT_REG (0xF3) /* Status Reg */ +#define BMX280_CTRL_MEAS_REG (0xF4) /* Ctrl Measure Reg */ +#define BMX280_CONFIG_REG (0xF5) /* Configuration Reg */ +#define BMX280_PRESSURE_MSB_REG (0xF7) /* Pressure MSB */ +#define BMX280_PRESSURE_LSB_REG (0xF8) /* Pressure LSB */ +#define BMX280_PRESSURE_XLSB_REG (0xF9) /* Pressure XLSB */ +#define BMX280_TEMPERATURE_MSB_REG (0xFA) /* Temperature MSB */ +#define BMX280_TEMPERATURE_LSB_REG (0xFB) /* Temperature LSB */ +#define BMX280_TEMPERATURE_XLSB_REG (0xFC) /* Temperature XLSB */ +#define BME280_CTRL_HUM_REG (0xF2) /* Ctrl Humidity Reg */ +#define BME280_HUMIDITY_MSB_REG (0xFD) /* Humidity MSB */ +#define BME280_HUMIDITY_LSB_REG (0xFE) /* Humidity LSB */ +/** @} */ + +/** + * @name Bitmasks for selected registers + * @{ + */ +#define MEAS_OSRS_T_POS (5U) +#define MEAS_OSRS_P_POS (2U) +#define STAT_MEASURING (1 << 3) +#define RESET_WORD (0xB6) +/** @} */ + +/** + * @name The base address for the row of data registers + * @{ + */ +#define DATA_BASE BMX280_PRESSURE_MSB_REG +/** @} */ + +/** + * @name Calibration data base addresses, block sizes, and offsets + * @{ + */ +#define CALIB_T_P_BASE (BMX280_DIG_T1_LSB_REG) +#define CALIB_T_P_LEN (17U) +#define OFFSET_T_P(x) (x - CALIB_T_P_BASE) +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) +#define CALIB_H_BASE (BME280_DIG_H2_LSB_REG) +#define CALIB_H_LEN (7U) +#define OFFSET_H(x) (x - CALIB_H_BASE) +#endif /** @} */ #ifdef __cplusplus diff --git a/drivers/bmx280/include/bmx280_params.h b/drivers/bmx280/include/bmx280_params.h index 4a6e574ff3..09296398d0 100644 --- a/drivers/bmx280/include/bmx280_params.h +++ b/drivers/bmx280/include/bmx280_params.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 Kees Bakker, SODAQ * 2017 Inria + * 2018 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -16,6 +17,7 @@ * * @author Kees Bakker * @author Alexandre Abadie + * @author Hauke Petersen */ #ifndef BMX280_PARAMS_H @@ -33,25 +35,54 @@ extern "C" { * @name Set default configuration parameters for the BMX280 * @{ */ +#ifdef BMX280_USE_SPI +/* SPI configuration */ +#ifndef BMX280_PARAM_SPI +#define BMX280_PARAM_SPI SPI_DEV(0) +#endif +#ifndef BMX280_PARAM_CLK +#define BMX280_PARAM_CLK SPI_CLK_5MHZ +#endif +#ifndef BMX280_PARAM_CS +#define BMX280_PARAM_CS GPIO_PIN(0, 0) +#endif +#else +/* I2C configuration */ #ifndef BMX280_PARAM_I2C_DEV -#define BMX280_PARAM_I2C_DEV I2C_DEV(0) +#define BMX280_PARAM_I2C_DEV I2C_DEV(0) #endif #ifndef BMX280_PARAM_I2C_ADDR -#define BMX280_PARAM_I2C_ADDR (0x77) +#define BMX280_PARAM_I2C_ADDR (0x77) +#endif #endif -/* Defaults for Weather Monitoring */ -#define BMX280_PARAMS_DEFAULT \ - { \ - .i2c_dev = BMX280_PARAM_I2C_DEV, \ - .i2c_addr = BMX280_PARAM_I2C_ADDR, \ - .t_sb = BMX280_SB_0_5, \ - .filter = BMX280_FILTER_OFF, \ +#define BMX280_PARAM_MISC \ + .t_sb = BMX280_SB_0_5, \ + .filter = BMX280_FILTER_OFF, \ .run_mode = BMX280_MODE_FORCED, \ .temp_oversample = BMX280_OSRS_X1, \ .press_oversample = BMX280_OSRS_X1, \ .humid_oversample = BMX280_OSRS_X1, \ + +/* Defaults for Weather Monitoring */ +#ifndef BMX280_PARAMS +#ifdef BMX280_USE_SPI +#define BMX280_PARAMS \ + { \ + .spi = BMX280_PARAM_SPI, \ + .clk = BMX280_PARAM_CLK, \ + .cs = BMX280_PARAM_CS, \ + BMX280_PARAM_MISC \ } +#else +#define BMX280_PARAMS \ + { \ + .i2c_dev = BMX280_PARAM_I2C_DEV, \ + .i2c_addr = BMX280_PARAM_I2C_ADDR, \ + BMX280_PARAM_MISC \ + } +#endif +#endif /**@}*/ /** @@ -59,11 +90,7 @@ extern "C" { */ static const bmx280_params_t bmx280_params[] = { -#ifdef BMX280_PARAMS_BOARD - BMX280_PARAMS_BOARD, -#else - BMX280_PARAMS_DEFAULT -#endif + BMX280_PARAMS }; /** @@ -80,7 +107,7 @@ static const bmx280_params_t bmx280_params[] = */ static const saul_reg_info_t bmx280_saul_reg_info[BMX280_NUMOF] = { -#if defined(MODULE_BME280) +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) { .name = "bme280" } #else { .name = "bmp280" } diff --git a/drivers/include/bmx280.h b/drivers/include/bmx280.h index 905a6bfb4a..c74fc4155f 100644 --- a/drivers/include/bmx280.h +++ b/drivers/include/bmx280.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 Kees Bakker, SODAQ * 2017 Inria + * 2018 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -8,10 +9,10 @@ */ /** - * @defgroup drivers_bmx280 BMP280/BME280 temperature, pressure and humidity sensor + * @defgroup drivers_bmx280 BMP280/BME280 temperature, pressure and humidity + * sensor * @ingroup drivers_sensors - * @ingroup drivers_saul - * @brief Device driver interface for the Bosch BMP280 and BME280 sensors. + * @brief Device driver interface for the Bosch BMP280 and BME280 sensors * * BMP280 and BME280 measure temperature in centi °C and pressure in Pa. BME280 * can also measure relative humidity in %. @@ -42,7 +43,7 @@ * * @{ * @file - * @brief Device driver interface for the BMX280 sensors (BMP280 and BME280). + * @brief Device driver interface for the BMP280 and BME280 sensors * * @details There are three sensor values that can be read: temperature, * pressure and humidity. The BME280 device usually measures them @@ -55,19 +56,35 @@ * * @author Kees Bakker * @author Alexandre Abadie + * @author Hauke Petersen */ #ifndef BMX280_H #define BMX280_H -#include +#include #include "saul.h" + +#if defined(MODULE_BME280_SPI) || defined(MODULE_BMP280_SPI) +#define BMX280_USE_SPI +#include "periph/spi.h" +#else #include "periph/i2c.h" +#endif #ifdef __cplusplus extern "C" { #endif +/** + * @brief Select the number or raw data bytes depending on the device type + */ +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) +#define BMX280_RAW_LEN (8U) +#else +#define BMX280_RAW_LEN (6U) +#endif + /** * @brief Calibration struct for the BMX280 sensor * @@ -100,35 +117,34 @@ typedef struct { * @brief Values for t_sb field of the BMX280 config register */ typedef enum { - BMX280_SB_0_5 = 0, - BMX280_SB_62_5 = 1, - BMX280_SB_125 = 2, - BMX280_SB_250 = 3, - BMX280_SB_500 = 4, - BMX280_SB_1000 = 5, - BMX280_SB_10 = 6, - BMX280_SB_20 = 7 + BMX280_SB_0_5 = 0x00, + BMX280_SB_62_5 = 0x20, + BMX280_SB_125 = 0x40, + BMX280_SB_250 = 0x60, + BMX280_SB_500 = 0x80, + BMX280_SB_1000 = 0xa0, + BMX280_SB_10 = 0xc0, + BMX280_SB_20 = 0xe0, } bmx280_t_sb_t; /** * @brief Values for filter field of the BMX280 config register */ typedef enum { - BMX280_FILTER_OFF = 0, - BMX280_FILTER_2 = 1, - BMX280_FILTER_4 = 2, - BMX280_FILTER_8 = 3, - BMX280_FILTER_16 = 4, + BMX280_FILTER_OFF = 0x00, + BMX280_FILTER_2 = 0x04, + BMX280_FILTER_4 = 0x08, + BMX280_FILTER_8 = 0x0c, + BMX280_FILTER_16 = 0x10, } bmx280_filter_t; /** * @brief Values for mode field of the BMX280 ctrl_meas register */ typedef enum { - BMX280_MODE_SLEEP = 0, - BMX280_MODE_FORCED = 1, - BMX280_MODE_FORCED2 = 2, /* Same as FORCED */ - BMX280_MODE_NORMAL = 3 + BMX280_MODE_SLEEP = 0x00, + BMX280_MODE_FORCED = 0x01, + BMX280_MODE_NORMAL = 0x03, } bmx280_mode_t; /** @@ -140,12 +156,12 @@ typedef enum { * - osrs_p field of the BMX280 ctrl_meas register */ typedef enum { - BMX280_OSRS_SKIPPED = 0, - BMX280_OSRS_X1 = 1, - BMX280_OSRS_X2 = 2, - BMX280_OSRS_X4 = 3, - BMX280_OSRS_X8 = 4, - BMX280_OSRS_X16 = 5, + BMX280_OSRS_SKIPPED = 0x00, + BMX280_OSRS_X1 = 0x01, + BMX280_OSRS_X2 = 0x02, + BMX280_OSRS_X4 = 0x03, + BMX280_OSRS_X8 = 0x04, + BMX280_OSRS_X16 = 0x05, } bmx280_osrs_t; /** @@ -154,9 +170,16 @@ typedef enum { * These parameters are needed to configure the device at startup. */ typedef struct { +#ifdef BMX280_USE_SPI + /* SPI configuration */ + spi_t spi; /**< SPI bus */ + spi_clk_t clk; /**< clock speed for the SPI bus */ + gpio_t cs; /**< chip select pin */ +#else /* I2C details */ i2c_t i2c_dev; /**< I2C device which is used */ uint8_t i2c_addr; /**< I2C address */ +#endif /* Config Register */ bmx280_t_sb_t t_sb; /**< standby */ @@ -178,6 +201,8 @@ typedef struct { typedef struct { bmx280_params_t params; /**< Device Parameters */ bmx280_calibration_t calibration; /**< Calibration Data */ + int32_t t_fine; /**< temperature compensation value */ + uint8_t last_reading[BMX280_RAW_LEN]; /**< cache the RAW data */ } bmx280_t; /** @@ -185,55 +210,85 @@ typedef struct { */ enum { BMX280_OK = 0, /**< everything was fine */ - BMX280_ERR_NODEV = -1, /**< did not detect BME280 or BMP280 */ - BMX280_ERR_NOCAL = -2, /**< could not read calibration data */ + BMX280_ERR_BUS = -1, /**< bus error */ + BMX280_ERR_NODEV = -2, /**< did not detect BME280 or BMP280 */ }; +/** + * @brief Export of SAUL interface for temperature sensor + */ +extern const saul_driver_t bmx280_temperature_saul_driver; + +/** + * @brief Export of SAUL interface for pressure sensor + */ +extern const saul_driver_t bmx280_pressure_saul_driver; + +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) +/** + * @brief Export of SAUL interface for humidity sensor + */ +extern const saul_driver_t bme280_relative_humidity_saul_driver; +#endif + /** * @brief Initialize the given BMX280 device * - * @param[out] dev Initialized device descriptor of BMX280 device - * @param[in] params The parameters for the BMX280 device (sampling rate, etc) + * @param[out] dev device descriptor of the given BMX280 device + * @param[in] params static configuration parameters * - * @return BMX280_OK on success - * @return BMX280_ERR_I2C - * @return BMX280_ERR_NODEV - * @return BMX280_ERR_NOCAL + * @return BMX280_OK on success + * @return BMX280_ERR_BUS on bus error + * @return BMX280_ERR_NODEV if no corresponding device was found on the bus */ int bmx280_init(bmx280_t* dev, const bmx280_params_t* params); /** - * @brief Read temperature value from the given BMX280 device, returned in centi °C + * @brief Read temperature value from the given BMX280 device * - * @param[in] dev Device descriptor of BMX280 device to read from + * The measured temperature is returned in centi °C (x.xx°C). * - * @returns The temperature in centi Celsius. In case of an error - * it returns INT16_MIN. + * @param[in] dev device to read from + * + * @return measured temperature in centi Celsius + * @return INT16_MIN on error */ -int16_t bmx280_read_temperature(const bmx280_t* dev); +int16_t bmx280_read_temperature(bmx280_t* dev); /** - * @brief Read air pressure value from the given BMX280 device, returned in PA + * @brief Read air pressure value from the given BMX280 device * - * @details This function should only be called after doing bmx280_read_temperature - * first. + * The air pressure is returned in PA (Pascal). * - * @param[in] dev Device descriptor of BMX280 device to read from + * This function returns the pressure data that was measured when + * bmx280_read_temperature() has been called last. So bmx280_read_temperature() + * has to be called before. * - * @returns The air pressure in Pa + * If bmx280_read_temperatue() did not succeed in acquiring a new set of sensor + * data, the result of this function is undefined. + * + * @param[in] dev device to read from + * + * @return air pressure in PA */ uint32_t bmx280_read_pressure(const bmx280_t *dev); -#if defined(MODULE_BME280) || defined(DOXYGEN) +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) || defined(DOXYGEN) /** - * @brief Read humidity value from the given BME280 device, returned in centi %RH + * @brief Read humidity value from the given BME280 device * - * @details This function should only be called after doing bmx280_read_temperature - * first. It's only available with BME280 sensor. + * The humidity is returned in centi %RH (x.xx% relative humidity). * - * @param[in] dev Device descriptor of BME280 device to read from + * This function returns the pressure data that was measured when + * bmx280_read_temperature() has been called last. So bmx280_read_temperature() + * has to be called before. * - * @returns Humidity in centi %RH (i.e. the percentage times 100) + * If bmx280_read_temperatue() did not succeed in acquiring a new set of sensor + * data, the result of this function is undefined. + * + * @param[in] dev device to read from + * + * @return humidity in centi %RH (i.e. the percentage times 100) */ uint16_t bme280_read_humidity(const bmx280_t *dev); #endif diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index c76418dcf5..f85d219b6a 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -102,8 +102,10 @@ PSEUDOMODULES += at86rfa1 PSEUDOMODULES += at86rfr2 # include variants of the BMX280 drivers as pseudo modules -PSEUDOMODULES += bmp280 -PSEUDOMODULES += bme280 +PSEUDOMODULES += bmp280_i2c +PSEUDOMODULES += bmp280_spi +PSEUDOMODULES += bme280_i2c +PSEUDOMODULES += bme280_spi # variants of TI ADCXX1C PSEUDOMODULES += adc081c diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 657f15fb8f..0a4ed3febc 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -382,7 +382,7 @@ void auto_init(void) extern void auto_init_bmp180(void); auto_init_bmp180(); #endif -#if defined(MODULE_BME280) || defined(MODULE_BMP280) +#ifdef MODULE_BMX280 extern void auto_init_bmx280(void); auto_init_bmx280(); #endif diff --git a/sys/auto_init/saul/auto_init_bmx280.c b/sys/auto_init/saul/auto_init_bmx280.c index 32d29661d3..ddb90bf125 100644 --- a/sys/auto_init/saul/auto_init_bmx280.c +++ b/sys/auto_init/saul/auto_init_bmx280.c @@ -20,7 +20,7 @@ * @} */ -#if defined(MODULE_BME280) || defined(MODULE_BMP280) +#ifdef MODULE_BMX280 #include "log.h" #include "saul_reg.h" @@ -33,21 +33,10 @@ */ static bmx280_t bmx280_devs[BMX280_NUMOF]; -/** - * @brief Reference the driver structs. - * @{ - */ -extern const saul_driver_t bmx280_temperature_saul_driver; -extern const saul_driver_t bmx280_pressure_saul_driver; -#if defined(MODULE_BME280) -extern const saul_driver_t bme280_relative_humidity_saul_driver; -#endif -/** @} */ - /** * @brief Memory for the SAUL registry entries */ -#if defined(MODULE_BME280) +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) #define SENSORS_NUMOF 3 #else #define SENSORS_NUMOF 2 @@ -79,7 +68,7 @@ void auto_init_bmx280(void) saul_reg_add(&saul_entries[se_ix]); se_ix++; -#if defined(MODULE_BME280) +#if defined(MODULE_BME280_SPI) || defined(MODULE_BME280_I2C) /* relative humidity */ saul_entries[se_ix].dev = &bmx280_devs[i]; saul_entries[se_ix].name = bmx280_saul_reg_info[i].name;