diff --git a/drivers/sensor/tmp112/Kconfig b/drivers/sensor/tmp112/Kconfig index cce19e2c6cb..09be7ee7596 100644 --- a/drivers/sensor/tmp112/Kconfig +++ b/drivers/sensor/tmp112/Kconfig @@ -12,3 +12,17 @@ config TMP112 The TMP102 is compatible with the TMP112 but is less accurate and has been successfully tested with this driver. + +config TMP112_FULL_SCALE_RUNTIME + bool "Allow to set extended mode at runtime" + default y + help + When set extended mode can be selected using tmp112_attr_set + with SENSOR_ATTR_FULL_SCALE and value to set either 128 or 150 + +config TMP112_SAMPLING_FREQUENCY_RUNTIME + bool "Allow to set conversion rate at runtime" + default y + help + When set conversion rate can be set at runtime using sensor_attr_set + with SENSOR_ATTR_SAMPLING_FREQUENCY diff --git a/drivers/sensor/tmp112/tmp112.c b/drivers/sensor/tmp112/tmp112.c index a8990d7cc78..9d033154867 100644 --- a/drivers/sensor/tmp112/tmp112.c +++ b/drivers/sensor/tmp112/tmp112.c @@ -14,29 +14,10 @@ #include #include #include +#include "tmp112.h" LOG_MODULE_REGISTER(TMP112, CONFIG_SENSOR_LOG_LEVEL); - -#define TMP112_REG_TEMPERATURE 0x00 -#define TMP112_D0_BIT BIT(0) - -#define TMP112_REG_CONFIG 0x01 -#define TMP112_EM_BIT BIT(4) -#define TMP112_CR0_BIT BIT(6) -#define TMP112_CR1_BIT BIT(7) - -/* scale in micro degrees Celsius */ -#define TMP112_TEMP_SCALE 62500 - -struct tmp112_data { - int16_t sample; -}; - -struct tmp112_config { - struct i2c_dt_spec bus; -}; - static int tmp112_reg_read(const struct tmp112_config *cfg, uint8_t reg, uint16_t *val) { @@ -59,20 +40,25 @@ static int tmp112_reg_write(const struct tmp112_config *cfg, return i2c_burst_write_dt(&cfg->bus, reg, (uint8_t *)&val_be, 2); } -static int tmp112_reg_update(const struct tmp112_config *cfg, uint8_t reg, - uint16_t mask, uint16_t val) +static uint16_t set_config_flags(struct tmp112_data *data, uint16_t mask, + uint16_t value) { - uint16_t old_val = 0U; - uint16_t new_val; + return (data->config_reg & ~mask) | (value & mask); +} - if (tmp112_reg_read(cfg, reg, &old_val) < 0) { - return -EIO; +static int tmp112_update_config(const struct device *dev, uint16_t mask, + uint16_t val) +{ + int rc; + struct tmp112_data *data = dev->data; + const uint16_t new_val = set_config_flags(data, mask, val); + + rc = tmp112_reg_write(dev->config, TMP112_REG_CONFIG, new_val); + if (rc == 0) { + data->config_reg = val; } - new_val = old_val & ~mask; - new_val |= val & mask; - - return tmp112_reg_write(cfg, reg, new_val); + return rc; } static int tmp112_attr_set(const struct device *dev, @@ -80,7 +66,6 @@ static int tmp112_attr_set(const struct device *dev, enum sensor_attribute attr, const struct sensor_value *val) { - const struct tmp112_config *cfg = dev->config; uint16_t value; uint16_t cr; @@ -89,26 +74,26 @@ static int tmp112_attr_set(const struct device *dev, } switch (attr) { +#if CONFIG_TMP112_FULL_SCALE_RUNTIME case SENSOR_ATTR_FULL_SCALE: /* the sensor supports two ranges -55 to 128 and -55 to 150 */ /* the value contains the upper limit */ if (val->val1 == 128) { value = 0x0000; } else if (val->val1 == 150) { - value = TMP112_EM_BIT; + value = TMP112_CONFIG_EM; } else { return -ENOTSUP; } - if (tmp112_reg_update(cfg, TMP112_REG_CONFIG, - TMP112_EM_BIT, value) < 0) { + if (tmp112_update_config(dev, TMP112_CONFIG_EM, value) < 0) { LOG_DBG("Failed to set attribute!"); return -EIO; } - - return 0; - + break; +#endif case SENSOR_ATTR_SAMPLING_FREQUENCY: +#if CONFIG_TMP112_SAMPLING_FREQUENCY_RUNTIME /* conversion rate in mHz */ cr = val->val1 * 1000 + val->val2 / 1000; @@ -116,33 +101,32 @@ static int tmp112_attr_set(const struct device *dev, /* conversion rate */ switch (cr) { case 250: - value = 0x0000; + value = TMP112_CONV_RATE(TMP112_CONV_RATE_025); break; case 1000: - value = TMP112_CR0_BIT; + value = TMP112_CONV_RATE(TMP112_CONV_RATE_1000); break; case 4000: - value = TMP112_CR1_BIT; + value = TMP112_CONV_RATE(TMP112_CONV_RATE_4); break; case 8000: - value = TMP112_CR0_BIT | TMP112_CR1_BIT; + value = TMP112_CONV_RATE(TMP112_CONV_RATE_8); break; default: return -ENOTSUP; } - if (tmp112_reg_update(cfg, TMP112_REG_CONFIG, - TMP112_CR0_BIT | TMP112_CR1_BIT, - value) < 0) { + if (tmp112_update_config(dev, TMP112_CONV_RATE_MASK, value) < 0) { LOG_DBG("Failed to set attribute!"); return -EIO; } - return 0; + break; +#endif default: return -ENOTSUP; @@ -164,10 +148,12 @@ static int tmp112_sample_fetch(const struct device *dev, return -EIO; } - if (val & TMP112_D0_BIT) { - drv_data->sample = arithmetic_shift_right((int16_t)val, 3); + if (val & TMP112_DATA_EXTENDED) { + drv_data->sample = arithmetic_shift_right((int16_t)val, + TMP112_DATA_EXTENDED_SHIFT); } else { - drv_data->sample = arithmetic_shift_right((int16_t)val, 4); + drv_data->sample = arithmetic_shift_right((int16_t)val, + TMP112_DATA_NORMAL_SHIFT); } return 0; @@ -200,22 +186,30 @@ static const struct sensor_driver_api tmp112_driver_api = { int tmp112_init(const struct device *dev) { const struct tmp112_config *cfg = dev->config; + struct tmp112_data *data = dev->data; if (!device_is_ready(cfg->bus.bus)) { LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name); return -EINVAL; } - return 0; + data->config_reg = TMP112_CONV_RATE(cfg->cr) | TMP112_CONV_RES_MASK + | (cfg->extended_mode ? TMP112_CONFIG_EM : 0); + + return tmp112_update_config(dev, 0, 0); } -#define TMP112_INST(inst) \ -static struct tmp112_data tmp112_data_##inst; \ -static const struct tmp112_config tmp112_config_##inst = { \ - .bus = I2C_DT_SPEC_INST_GET(inst) \ -}; \ -DEVICE_DT_INST_DEFINE(inst, tmp112_init, NULL, &tmp112_data_##inst, \ - &tmp112_config_##inst, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, &tmp112_driver_api); + +#define TMP112_INST(inst) \ + static struct tmp112_data tmp112_data_##inst; \ + static const struct tmp112_config tmp112_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .cr = DT_ENUM_IDX(DT_DRV_INST(inst), conversion_rate), \ + .extended_mode = DT_INST_PROP(inst, extended_mode), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, tmp112_init, NULL, &tmp112_data_##inst, \ + &tmp112_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &tmp112_driver_api); DT_INST_FOREACH_STATUS_OKAY(TMP112_INST) diff --git a/drivers/sensor/tmp112/tmp112.h b/drivers/sensor/tmp112/tmp112.h new file mode 100644 index 00000000000..28f79fe6b1f --- /dev/null +++ b/drivers/sensor/tmp112/tmp112.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 Innoseis BV + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_TMP112_TMP112_H_ +#define ZEPHYR_DRIVERS_SENSOR_TMP112_TMP112_H_ + +#include +#include + +#define TMP112_REG_TEMPERATURE 0x00 +#define TMP112_DATA_INVALID_BIT (BIT(1) | BIT(2)) +#define TMP112_DATA_EXTENDED (BIT(0)) +#define TMP112_DATA_EXTENDED_SHIFT 3 +#define TMP112_DATA_NORMAL_SHIFT 4 + + +#define TMP112_REG_CONFIG 0x01 +#define TMP112_CONFIG_EM BIT(4) + +#define TMP112_ALERT_EN_BIT BIT(5) +#define TMP112_CONV_RATE_SHIFT 6 +#define TMP112_CONV_RATE_MASK (BIT_MASK(2) << TMP112_CONV_RATE_SHIFT) +#define TMP112_CONV_RATE_025 0 +#define TMP112_CONV_RATE_1000 1 +#define TMP112_CONV_RATE_4 2 +#define TMP112_CONV_RATE_8 3 + +#define TMP112_CONV_RATE(cr) ((cr) << TMP112_CONV_RATE_SHIFT) + +#define TMP112_CONV_RES_SHIFT 13 +#define TMP112_CONV_RES_MASK (BIT_MASK(2) << TMP112_CONV_RES_SHIFT) + +#define TMP112_ONE_SHOT BIT(15) + +#define TMP112_REG_TLOW 0x02 +#define TMP112_REG_THIGH 0x03 + +/* scale in micro degrees Celsius */ +#define TMP112_TEMP_SCALE 62500 + +struct tmp112_data { + int16_t sample; + uint16_t config_reg; +}; + +struct tmp112_config { + const struct i2c_dt_spec bus; + uint8_t cr; + bool extended_mode : 1; +}; + +#endif diff --git a/dts/bindings/sensor/ti,tmp112.yaml b/dts/bindings/sensor/ti,tmp112.yaml index 53c69408497..4e303803f25 100644 --- a/dts/bindings/sensor/ti,tmp112.yaml +++ b/dts/bindings/sensor/ti,tmp112.yaml @@ -8,3 +8,17 @@ description: | compatible: "ti,tmp112" include: i2c-device.yaml + +properties: + conversion-rate: + description: Conversion rate in mHz (milli-Hertz) + type: int + default: 4000 + enum: + - 250 + - 1000 + - 4000 + - 8000 + extended-mode: + description: When true use 13-bit data format allowing measuring temperature up to 128°C + type: boolean