On Wed, May 02, 2018 at 05:36:33PM -0700, s_g...@telus.net wrote: > Thank you for the advice. I will try the patch, but I want to let the > current php build complete, which may take a few more days. > > Did you get the bme code I sent you? >
Yep, I just forgot about it, and now i did "over do" a bit with the necessary cleanup/refactoring.. oops, but no more ugly unions nor "forbidden hacks":) diff below does still miss a few things like BUGS from the man page, as i consider current hardcoded configuration, while useful for most cases, as a bug that should be fixed before ie. spi, HZ=1000, etc.. It could be used for even indoor navigation, so I think the sensor has plenty more potential, than what bme(4) does now offer, but i don't see why you couldn't offer it as-is, if you find it working after properly testing this version, on tech@, good luck:) -Artturi diff --git share/man/man4/Makefile share/man/man4/Makefile index 8004d8b575d..3ac02b89788 100644 --- share/man/man4/Makefile +++ share/man/man4/Makefile @@ -15,7 +15,7 @@ MAN= aac.4 ac97.4 acphy.4 acrtc.4 \ auacer.4 audio.4 aue.4 auglx.4 auich.4 auixp.4 autri.4 auvia.4 \ axe.4 axen.4 axppmic.4 azalia.4 \ bce.4 bcmaux.4 bcmdog.4 bcmrng.4 bcmtemp.4 berkwdt.4 bge.4 \ - bgw.4 bio.4 bktr.4 bmtphy.4 bnx.4 \ + bgw.4 bio.4 bktr.4 bme.4 bmtphy.4 bnx.4 \ boca.4 bpf.4 brgphy.4 bridge.4 brswphy.4 bwfm.4 bwi.4 bytgpio.4 \ cac.4 cas.4 cardbus.4 carp.4 ccp.4 cd.4 cdce.4 cfxga.4 \ ch.4 chvgpio.4 ciphy.4 ciss.4 clcs.4 clct.4 cmpci.4 \ diff --git share/man/man4/bme.4 share/man/man4/bme.4 new file mode 100644 index 00000000000..bb48513d9dc --- /dev/null +++ share/man/man4/bme.4 @@ -0,0 +1,44 @@ +.\" $OpenBSD: tsl.4,v 1.10 2015/10/02 09:29:02 sobrado Exp $ +.\" +.\" Copyright (c) 2005 Mark Kettenis <kette...@openbsd.org> +.\" Copyright (c) 2018 Artturi Alm +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate$ +.Dt BME 4 +.Os +.Sh NAME +.Nm bme +.Nd Bosch BME280 Environmental sensor +.Sh SYNOPSIS +.Cd "bme* at iic?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the Bosch BME280 Environmental sensor. +These sensors contain combined digital humidity, pressure and temperature +sensing capabilities. +These values are made available through the +.Xr sysctl 8 +interface. +.Sh SEE ALSO +.Xr iic 4 , +.Xr intro 4 , +.Xr sensorsd 8 , +.Xr sysctl 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 6.4 . diff --git sys/arch/arm64/conf/GENERIC sys/arch/arm64/conf/GENERIC index d7b7dca12bf..37050606674 100644 --- sys/arch/arm64/conf/GENERIC +++ sys/arch/arm64/conf/GENERIC @@ -296,6 +296,7 @@ ch* at scsibus? uk* at scsibus? # I2C devices +bme* at iic? # BME280 environmental sensor islrtc* at iic? # ISL1208 RTC rkpmic* at iic? # RK808 PMIC diff --git sys/arch/armv7/conf/GENERIC sys/arch/armv7/conf/GENERIC index 052f73bf71f..fae08d5c8cd 100644 --- sys/arch/armv7/conf/GENERIC +++ sys/arch/armv7/conf/GENERIC @@ -178,7 +178,9 @@ iic* at rkiic? rktemp* at fdt? dwdog* at fdt? +# I2C devices axppmic* at iic? # axp209 pmic +bme* at iic? # BME280 environmental sensor crosec* at iic? wskbd* at crosec? mux 1 pcfrtc* at iic? diff --git sys/dev/fdt/bme.c sys/dev/fdt/bme.c new file mode 100644 index 00000000000..04a61dc7d19 --- /dev/null +++ sys/dev/fdt/bme.c @@ -0,0 +1,547 @@ +/* $OpenBSD: tsl2560.c,v 1.7 2008/04/18 01:17:51 deraadt Exp $ */ + +/* + * Copyright (c) 2005 Mark Kettenis + * Copyright (c) 2017 Artturi Alm + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kthread.h> +#include <sys/sensors.h> + +#include <dev/i2c/i2cvar.h> + +#include <machine/bus.h> +#include <machine/fdt.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/fdt.h> + +/* + * Register Name Address b7 b6 b5 b4 b3 b2 b1 b0 Reset state + * hum_lsb 0xFE hum_lsb<7:0> 0x00 + * hum_msb 0xFD hum_msb<7:0> 0x80 + * temp_xlsb 0xFC temp_xlsb<7:4> 0000 0x00 + * temp_lsb 0xFB temp_lsb<7:0> 0x00 + * temp_msb 0xFA temp_msb<7:0> 0x80 + * press_xlsb 0xF9 press_xlsb<7:4> 0000 0x00 + * press_lsb 0xF8 press_lsb<7:0> 0x00 + * press_msb 0xF7 press_msb<7:0> 0x80 + * config 0xF5 t_sb[2:0]filter[2:0]spi3w_en[0] 0x00 + * ctrl_meas 0xF4 osrs_p[2:0]osrs_t[2:0]mode[1:0] 0x00 + * status 0xF3 measuring[0]im_update[0] 0x00 + * ctrl_hum 0xF2 osrs_h[2:0] 0x00 + * calib26..calib41 0xE1-0xF0 calibration data individual + * reset 0xE0 reset[7:0] 0x00 + * id 0xD0 chip_id[7:0] 0x60 + * calib00..calib25 0x88-0xA1 calibration data individual +*/ + +#define BME280_CALIB00_23 0x88 +#define BME280_CALIB24 0xa1 +#define BME280_ID 0xd0 +#define BME280_RESET 0xe0 + /* soft reset magic value */ +#define BME280_RESET_MAGIC 0xb6 +#define BME280_CALIB25_31 0xe1 + /* changes become effective only after a write op to ctrl_meas */ +#define BME280_CTRL_HUM 0xf2 + +#define BME280_STATUS 0xf3 +#define BME280_STATUS_MASK 0x09 +#define BME280_STATUS_CONV 0x08 /* conversion running */ +#define BME280_STATUS_UPD 0x01 /* update in progress */ + +#define BME280_CTRL_MEAS 0xf4 +#define BME280_CTRL_MEAS_MODE_MASK 0x03 +#define BME280_CTRL_MEAS_MODE_SLEEP 0x00 +#define BME280_CTRL_MEAS_MODE_FORCED 0x01 +#define BME280_CTRL_MEAS_MODE_FORCE 0x02 +#define BME280_CTRL_MEAS_MODE_NORMAL 0x03 + /* writes in normal mode may be ignored, not so in sleep mode */ +#define BME280_CONFIG 0xf5 +#define BME280_CONFIG_SPI_EN 0x01 + +#define BME280_PRESS_MSB 0xf7 +#define BME280_PRESS_LSB 0xf8 +#define BME280_PRESS_XLSB 0xf9 +#define BME280_TEMP_MSB 0xfa +#define BME280_TEMP_LSB 0xfb +#define BME280_TEMP_XLSB 0xfc +#define BME280_HUM_MSB 0xfd +#define BME280_HUM_LSB 0xfe + +#define BME_OVERSAMPLING_SKIP 0x00 +#define BME_OVERSAMPLING_X1 0x01 +#define BME_OVERSAMPLING_X2 0x02 +#define BME_OVERSAMPLING_X4 0x03 +#define BME_OVERSAMPLING_X8 0x04 +#define BME_OVERSAMPLING_X16 0x05 + +#define BME_HUMI 0 +#define BME_TEMP 1 +#define BME_PRES 2 + +struct bme_softc { + struct device sc_dev; + i2c_tag_t sc_i2c; + i2c_addr_t sc_addr; + + struct ksensor sc_sensor[3]; + struct ksensordev sc_sensordev; + + int sc_calibrated; + int sc_configured; + + /* + * fine resolution temperature value for pressure and + * humidity compensation formulas. + */ + int32_t sc_t_fine; + /* calibration data */ + int32_t sc_t_trim[3]; + int64_t sc_p_trim[9]; + int32_t sc_h_trim[6]; +}; + +int bme_match(struct device *, void *, void *); +void bme_attach(struct device *, struct device *, void *); +void bme_deferred(void *); +void bme_refresh(void *); +void bme_softreset(struct bme_softc *, int); +void bme_configure(struct bme_softc *, int); +void bme_get_calib(struct bme_softc *, int); + +int32_t bme_comp_temp(struct bme_softc *, int32_t); +uint32_t bme_comp_pres(struct bme_softc *, int32_t); +uint32_t bme_comp_humi(struct bme_softc *, int32_t); + +static inline uint8_t bme_config_filter(int); +static inline uint8_t bme_config_standby(int); +static inline uint8_t bme_oversample(uint8_t, uint8_t); + +struct cfattach bme_ca = { + sizeof(struct bme_softc), bme_match, bme_attach +}; + +struct cfdriver bme_cd = { + NULL, "bme", DV_DULL +}; + +int +bme_match(struct device *parent, void *match, void *aux) +{ + struct i2c_attach_args *ia = aux; + int node = *(int *)ia->ia_cookie; + + return OF_is_compatible(node, "bosch,bme280"); +} + +void +bme_attach(struct device *parent, struct device *self, void *aux) +{ + struct bme_softc *sc = (struct bme_softc *)self; + struct i2c_attach_args *ia = aux; + int ieflags = I2C_F_POLL; + uint8_t reg_addr, data; + + sc->sc_i2c = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + + iic_acquire_bus(sc->sc_i2c, ieflags); + + sc->sc_calibrated = 0; + bme_softreset(sc, ieflags); + + reg_addr = BME280_ID; + if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, + sc->sc_addr, ®_addr, 1, &data, 1, ieflags)) { + iic_release_bus(sc->sc_i2c, ieflags); + printf(": failed to read ID register\n"); + return; + } + + iic_release_bus(sc->sc_i2c, ieflags); + + switch (data) { + default: + printf(": unknown value in ID register 0x%x\n", data); + return; + case 0x58: + case 0x57: + case 0x56: + /* XXX atleast somehow register compatible with BMP280 */ + printf(": sorry, no BMP280 support yet\n"); + return; + case 0x60: + printf(": BME280 %x\n", data); + break; + } + + kthread_create_deferred(bme_deferred, sc); +} + +void +bme_deferred(void *arg) +{ + struct bme_softc *sc = arg; + int ieflags = I2C_F_POLL; /* XXX cold ? I2C_F_POLL : 0 */ + int i; + + iic_acquire_bus(sc->sc_i2c, ieflags); + + bme_configure(sc, ieflags); +#ifdef DIAGNOSTIC + if (sc->sc_configured != 1) /* non-fatal */ + printf("%s: failed to configure\n", sc->sc_dev.dv_xname); +#endif + + bme_get_calib(sc, ieflags); + + iic_release_bus(sc->sc_i2c, ieflags); + + if (sc->sc_calibrated != 1) { + printf("%s: failed to read calibration data\n", + sc->sc_dev.dv_xname); + /* fatal; and retrying feels bloat, fix your i2c "wiring" */ + return; /* XXX can't defer failure to config_detach.. :( */ + } + + if (sensor_task_register(sc, bme_refresh, 1) == NULL) { + printf("%s: unable to register update task\n", + sc->sc_dev.dv_xname); + return; + } + + /* Initialize sensor data. */ + strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensordev.xname)); + sc->sc_sensor[BME_HUMI].type = SENSOR_HUMIDITY; + sc->sc_sensor[BME_TEMP].type = SENSOR_TEMP; + sc->sc_sensor[BME_PRES].type = SENSOR_PRESSURE; + + for (i = 0; i < 3; i++) { + sc->sc_sensor[i].flags = SENSOR_FINVALID; + sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); + } + sensordev_install(&sc->sc_sensordev); +} + +void +bme_refresh(void *arg) +{ + struct bme_softc *sc = arg; + int32_t raw[3] = { 0, 0, 0 }; + int ieflags = I2C_F_POLL; /* XXX cold ? I2C_F_POLL : 0 */ + uint8_t addr; + uint8_t data[8]; + + iic_acquire_bus(sc->sc_i2c, ieflags); + + if (sc->sc_configured == 0) { + bme_configure(sc, ieflags); + if (sc->sc_configured != 1) { +#ifdef DIAGNOSTIC + printf("%s: failed to configure - resetting\n", + sc->sc_dev.dv_xname); +#endif + bme_softreset(sc, ieflags); + goto fail_out; + } + } + + /* + * read raw uncompensated values in a single read "burst", + * to keep data register shadowing functional in the normal-mode + * we're configured to, as we don't really synchronize with the + * sensor, so we have no need to read the status register at all. + */ + addr = BME280_PRESS_MSB; + if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &addr, 1, &data, sizeof data, ieflags)) { + printf("%s: failed to read data - resetting\n", + sc->sc_dev.dv_xname); + bme_softreset(sc, ieflags); + bme_configure(sc, ieflags); + goto fail_out; + } + + iic_release_bus(sc->sc_i2c, ieflags); + + /* got raw */ + raw[BME_HUMI] = (data[6] << 8) | data[7]; + raw[BME_TEMP] = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4); + raw[BME_PRES] = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); + + /* do compensate raw values */ + sc->sc_sensor[BME_TEMP].value = bme_comp_temp(sc, raw[BME_TEMP]); + sc->sc_sensor[BME_PRES].value = bme_comp_pres(sc, raw[BME_PRES]); + sc->sc_sensor[BME_HUMI].value = bme_comp_humi(sc, raw[BME_HUMI]); + + sc->sc_sensor[BME_TEMP].flags &= ~SENSOR_FINVALID; + sc->sc_sensor[BME_PRES].flags &= ~SENSOR_FINVALID; + sc->sc_sensor[BME_HUMI].flags &= ~SENSOR_FINVALID; + return; +fail_out: + iic_release_bus(sc->sc_i2c, ieflags); + sc->sc_sensor[BME_TEMP].flags |= SENSOR_FINVALID; + sc->sc_sensor[BME_PRES].flags |= SENSOR_FINVALID; + sc->sc_sensor[BME_HUMI].flags |= SENSOR_FINVALID; +} + +void +bme_get_calib(struct bme_softc *sc, int ieflags) +{ + int i, j; + uint8_t addr; + uint8_t calib[32]; + + /* read calibration data */ + addr = BME280_CALIB00_23; + if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &addr, 1, &calib[0], 24, ieflags)) + return; + + addr = BME280_CALIB24; + if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &addr, 1, &calib[24], 1, ieflags)) + return; + + addr = BME280_CALIB25_31; + if (iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &addr, 1, &calib[25], 7, ieflags)) + return; + + /* adjust calibration data for later compensations */ + for (i = 0, j = 0; i < 3; j += 2) + sc->sc_t_trim[i++] = (calib[j + 1] << 8) | calib[j]; + for (i = 0, j = 6; i < 9; j += 2) + sc->sc_p_trim[i++] = (calib[j + 1] << 8) | calib[j]; + sc->sc_h_trim[(i = 0)] = calib[24]; + sc->sc_h_trim[++i] = (calib[26] << 8) | calib[25]; + sc->sc_h_trim[++i] = calib[27]; + sc->sc_h_trim[++i] = (calib[28] << 4) | (calib[29] & 0xf); + sc->sc_h_trim[++i] = (calib[30] << 4) | ((calib[29] & 0xf0) >> 4); + sc->sc_h_trim[++i] = calib[31]; + + for (i = 1; i < 3; i++) + if (sc->sc_t_trim[i] & 0x8000) + sc->sc_t_trim[i] = (-sc->sc_t_trim[i] ^ 0xffff) + 1; + for (j = 1; j < 9; j++) + if (sc->sc_p_trim[j] & 0x8000) + sc->sc_p_trim[j] = (-sc->sc_p_trim[j] ^ 0xffff) + 1; + for (i = 1; i < 6; i++) /* XXX last one is signed char? */ + if (sc->sc_h_trim[i] & 0x8000) /* so will never match this */ + sc->sc_h_trim[i] = (-sc->sc_h_trim[i] ^ 0xffff) + 1; + + sc->sc_calibrated = 1; +} + +/* + * this is not really required, as the chip should be in this + * condition already after Power-On-Reset (POR), and we configure + * everything without reading current values in correct order, + * so i decided to let this fail as void, trusting sc_configured=0 will + * fix configuration registers later anyway. + */ +void +bme_softreset(struct bme_softc *sc, int ieflags) +{ + uint8_t addr = BME280_RESET; + uint8_t data = BME280_RESET_MAGIC; + + sc->sc_configured = 0; + + if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &addr, 1, &data, 1, ieflags)) { +#ifdef DIAGNOSTIC + printf("%s: failed to write softreset\n", sc->sc_dev.dv_xname); +#endif + return; + } + /* + * XXX should this have some delay here? SoC-performance do vary.. + */ +} + +void +bme_configure(struct bme_softc *sc, int ieflags) +{ + uint8_t addr, data; + + /* XXX do seek for devicetree bindings, for config parameters */ + + addr = BME280_CTRL_HUM; + data = bme_oversample(1, BME_HUMI); + if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &addr, 1, &data, 1, ieflags)) + return; + + addr = BME280_CONFIG; + data = bme_config_filter(0) | bme_config_standby(1000000); + if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &addr, 1, &data, 1, ieflags)) + return; + + addr = BME280_CTRL_MEAS; + data = BME280_CTRL_MEAS_MODE_NORMAL | bme_oversample(1, BME_TEMP) | + bme_oversample(1, BME_PRES); + if (iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &addr, 1, &data, 1, ieflags)) + return; + + sc->sc_configured = 1; +} + +int32_t +bme_comp_temp(struct bme_softc *sc, int32_t raw) +{ + int32_t t1 = sc->sc_t_trim[0]; + int32_t t2 = sc->sc_t_trim[1]; + int32_t t3 = sc->sc_t_trim[2]; + int32_t var1 = ((((raw >> 3) - (t1 << 1))) * t2) >> 11; + int32_t var2 = (((((raw >> 4) - t1) * ((raw >> 4) - t1)) >> 12) * t3) + >> 14; + int32_t rv_t; + + sc->sc_t_fine = var1 + var2; + rv_t = (sc->sc_t_fine * 5 + 128) >> 8; + rv_t = (rv_t + 27315) * 10000; /* for micro Kelvin */ + return rv_t; +} + +uint32_t +bme_comp_pres(struct bme_softc *sc, int32_t raw) +{ + int64_t var1 = (int64_t)sc->sc_t_fine; + int64_t var2; + int64_t pa; + + var1 -= 128000; + var2 = var1 * var1 * sc->sc_p_trim[5]; + var2 = var2 + ((var1 * sc->sc_p_trim[4]) << 17); + var2 = var2 + (sc->sc_p_trim[3] << 35); + + var1 = ((var1 * var1 * sc->sc_p_trim[2]) >> 8) + + ((var1 * sc->sc_p_trim[1]) << 12); + + var1 = ((((int64_t)1) << 47) + var1) * sc->sc_p_trim[0] >> 33; + if (var1 == 0) + return 0; + + pa = 1048576 - raw; + pa = (((pa << 31) - var2) * 3125) / var1; + var1 = (sc->sc_p_trim[8] * (pa >> 13) * (pa >> 13)) >> 25; + var2 = (sc->sc_p_trim[7] * pa) >> 19; + pa = ((pa + var1 + var2) >> 8) + (sc->sc_p_trim[6] << 4); + pa /= 256; + return (uint32_t)pa; +} + +uint32_t +bme_comp_humi(struct bme_softc *sc, int32_t raw) +{ + int32_t rh = (int32_t)sc->sc_t_fine; + + rh -= 76800; + rh = (((((raw << 14) - (sc->sc_h_trim[3] << 20) - + (sc->sc_h_trim[4] * rh)) + 16384) >> 15) * + (((((((rh * sc->sc_h_trim[5]) >> 10) * + (((rh * sc->sc_h_trim[2]) >> 11) + 32768)) >> 10) + + 2097152) * sc->sc_h_trim[1] + 8192) >> 14)); + rh -= (((((rh >> 15) * (rh >> 15)) >> 7) * sc->sc_h_trim[0]) >> 4); + if (rh < 0) + rh = 0; + if (rh > 419430400) + rh = 419430400; + rh >>= 12; + rh = (rh * 1000) / 1024; + return (uint32_t)rh; +} + +uint8_t +bme_config_filter(int filter_coeff) +{ + switch (filter_coeff) { + default: + case 0: /* filter off */ + return 0x00; + case 2: + return 0x01; + case 4: + return 0x02; + case 8: + return 0x03; + case 16: + return 0x04; + } +} + +uint8_t +bme_config_standby(int us) +{ + switch (us) { + case 500: + return 0x00U << 5; + case 10000: + return 0x06U << 5; + case 20000: + return 0x07U << 5; + case 62500: + return 0x01U << 5; + case 125000: + return 0x02U << 5; + case 250000: + return 0x03U << 5; + case 500000: + return 0x04U << 5; + default: + case 1000000: + return 0x05U << 5; + } +} + +uint8_t +bme_oversample(uint8_t over_sample, uint8_t sensor) +{ + uint8_t off = 0; + + switch (sensor) { + case BME_PRES: + off += 3; + case BME_TEMP: + off += 2; + case BME_HUMI: + break; + default: + return 0; + } + + switch (over_sample) { + default: + case 0: + return BME_OVERSAMPLING_SKIP; + case 1: + return BME_OVERSAMPLING_X1 << off; + case 2: + return BME_OVERSAMPLING_X2 << off; + case 4: + return BME_OVERSAMPLING_X4 << off; + case 16: + return BME_OVERSAMPLING_X16 << off; + } +} diff --git sys/dev/fdt/files.fdt sys/dev/fdt/files.fdt index 995c17ca45a..8b49c6563db 100644 --- sys/dev/fdt/files.fdt +++ sys/dev/fdt/files.fdt @@ -45,6 +45,10 @@ attach axppmic at i2c attach axppmic at rsb with axppmic_rsb file dev/fdt/axppmic.c axppmic +device bme +attach bme at i2c +file dev/fdt/bme.c bme + device sypwr attach sypwr at i2c file dev/fdt/sypwr.c sypwr