drivers: sensor: add ti tmp108 driver support
Adding support for the TI TMP108 temperature sensor. This includes over/under temp interrupt support as well as one shot, continuous conversion and power down modes. Signed-off-by: Jimmy Johnson <catch22@fastmail.net>
This commit is contained in:
parent
d170079815
commit
5c28b218fa
11 changed files with 690 additions and 0 deletions
|
@ -89,6 +89,7 @@ add_subdirectory_ifdef(CONFIG_STTS751 stts751)
|
||||||
add_subdirectory_ifdef(CONFIG_SX9500 sx9500)
|
add_subdirectory_ifdef(CONFIG_SX9500 sx9500)
|
||||||
add_subdirectory_ifdef(CONFIG_TH02 th02)
|
add_subdirectory_ifdef(CONFIG_TH02 th02)
|
||||||
add_subdirectory_ifdef(CONFIG_TMP007 tmp007)
|
add_subdirectory_ifdef(CONFIG_TMP007 tmp007)
|
||||||
|
add_subdirectory_ifdef(CONFIG_TMP108 tmp108)
|
||||||
add_subdirectory_ifdef(CONFIG_TMP112 tmp112)
|
add_subdirectory_ifdef(CONFIG_TMP112 tmp112)
|
||||||
add_subdirectory_ifdef(CONFIG_TMP116 tmp116)
|
add_subdirectory_ifdef(CONFIG_TMP116 tmp116)
|
||||||
add_subdirectory_ifdef(CONFIG_VCNL4040 vcnl4040)
|
add_subdirectory_ifdef(CONFIG_VCNL4040 vcnl4040)
|
||||||
|
|
|
@ -216,6 +216,8 @@ source "drivers/sensor/th02/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/tmp007/Kconfig"
|
source "drivers/sensor/tmp007/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/sensor/tmp108/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/tmp112/Kconfig"
|
source "drivers/sensor/tmp112/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/tmp116/Kconfig"
|
source "drivers/sensor/tmp116/Kconfig"
|
||||||
|
|
5
drivers/sensor/tmp108/CMakeLists.txt
Normal file
5
drivers/sensor/tmp108/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
zephyr_library()
|
||||||
|
|
||||||
|
zephyr_library_sources(tmp108.c tmp108_trigger.c)
|
20
drivers/sensor/tmp108/Kconfig
Normal file
20
drivers/sensor/tmp108/Kconfig
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# TMP108 temperature sensor configuration options
|
||||||
|
|
||||||
|
# Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
menuconfig TMP108
|
||||||
|
bool "TMP108 Temperature Sensor"
|
||||||
|
depends on I2C
|
||||||
|
help
|
||||||
|
Enable driver for the TMP108 temperature sensor.
|
||||||
|
|
||||||
|
if TMP108
|
||||||
|
|
||||||
|
config TMP108_ALERT_INTERRUPTS
|
||||||
|
bool "Allow interrupts to service over and under temp alerts"
|
||||||
|
help
|
||||||
|
This will set up interrupts to service under and over temp alerts
|
||||||
|
see TMP108 spec sheet for more information on how these work.
|
||||||
|
|
||||||
|
endif # TMP108
|
401
drivers/sensor/tmp108/tmp108.c
Normal file
401
drivers/sensor/tmp108/tmp108.c
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT ti_tmp108
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/i2c.h>
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
#include <sys/util.h>
|
||||||
|
#include <sys/byteorder.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
#include "tmp108.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(TMP108, CONFIG_SENSOR_LOG_LEVEL);
|
||||||
|
|
||||||
|
/** TI conversion scale from 16 bit int temp value to float */
|
||||||
|
#define TMP108_TEMP_MULTIPLIER 62500
|
||||||
|
|
||||||
|
/** TMP typical conversion time of 27 ms after waking from sleep */
|
||||||
|
#define TMP108_WAKEUP_TIME_IN_MS 30
|
||||||
|
|
||||||
|
struct tmp108_config {
|
||||||
|
const struct i2c_dt_spec i2c_spec;
|
||||||
|
const struct gpio_dt_spec alert_gpio;
|
||||||
|
};
|
||||||
|
|
||||||
|
int tmp108_reg_read(const struct device *dev, uint8_t reg, uint16_t *val)
|
||||||
|
{
|
||||||
|
const struct tmp108_config *cfg = dev->config;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = i2c_burst_read_dt(&cfg->i2c_spec, reg, (uint8_t *) val, 2);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*val = sys_be16_to_cpu(*val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp108_reg_write(const struct device *dev, uint8_t reg, uint16_t val)
|
||||||
|
{
|
||||||
|
const struct tmp108_config *cfg = dev->config;
|
||||||
|
uint8_t tx_buf[3];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
tx_buf[0] = reg;
|
||||||
|
sys_put_be16(val, &tx_buf[1]);
|
||||||
|
|
||||||
|
result = i2c_write_dt(&cfg->i2c_spec, tx_buf, sizeof(tx_buf));
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp108_write_config(const struct device *dev, uint16_t mask, uint16_t conf)
|
||||||
|
{
|
||||||
|
uint16_t config = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = tmp108_reg_read(dev, TI_TMP108_REG_CONF, &config);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
config &= mask;
|
||||||
|
config |= conf;
|
||||||
|
|
||||||
|
result = tmp108_reg_write(dev, TI_TMP108_REG_CONF, config);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ti_tmp108_read_temp(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* clear previous temperature readings */
|
||||||
|
|
||||||
|
drv_data->sample = 0U;
|
||||||
|
|
||||||
|
/* Get the most recent temperature measurement */
|
||||||
|
|
||||||
|
result = tmp108_reg_read(dev, TI_TMP108_REG_TEMP, &drv_data->sample);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmp108_sample_fetch(const struct device *dev,
|
||||||
|
enum sensor_channel chan)
|
||||||
|
{
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If one shot mode is set, query chip for reading
|
||||||
|
* should be finished 30 ms later
|
||||||
|
*/
|
||||||
|
if (drv_data->one_shot_mode == true) {
|
||||||
|
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_MODE_MASK,
|
||||||
|
TI_TMP108_MODE_ONE_SHOT);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schedule read to start in 30 ms if mode change was successful
|
||||||
|
* the typical wakeup time given in the data sheet is 27
|
||||||
|
*/
|
||||||
|
result = k_work_schedule(&drv_data->scheduled_work,
|
||||||
|
K_MSEC(TMP108_WAKEUP_TIME_IN_MS));
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ti_tmp108_read_temp(dev);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmp108_channel_get(const struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
int32_t uval;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
uval = (int32_t)(drv_data->sample >> 4U) * TMP108_TEMP_MULTIPLIER;
|
||||||
|
val->val1 = uval / 1000000U;
|
||||||
|
val->val2 = uval % 1000000U;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmp108_attr_get(const struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
struct sensor_value *val)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_AMBIENT_TEMP && chan != SENSOR_CHAN_ALL) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((int) attr) {
|
||||||
|
case SENSOR_ATTR_CONFIGURATION:
|
||||||
|
result = tmp108_reg_read(dev,
|
||||||
|
TI_TMP108_REG_CONF,
|
||||||
|
(uint16_t *) &(val->val1));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmp108_attr_set(const struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
const struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
uint16_t mode = 0;
|
||||||
|
uint16_t reg_value = 0;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_AMBIENT_TEMP && chan != SENSOR_CHAN_ALL) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((int) attr) {
|
||||||
|
case SENSOR_ATTR_HYSTERESIS:
|
||||||
|
if (val->val1 < 1) {
|
||||||
|
mode = TI_TMP108_HYSTER_0_C;
|
||||||
|
} else if (val->val1 < 2) {
|
||||||
|
mode = TI_TMP108_HYSTER_1_C;
|
||||||
|
} else if (val->val1 < 4) {
|
||||||
|
mode = TI_TMP108_HYSTER_2_C;
|
||||||
|
} else {
|
||||||
|
mode = TI_TMP108_HYSTER_4_C;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_HYSTER_MASK,
|
||||||
|
mode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_ALERT:
|
||||||
|
/* Spec Sheet Errata: TM is set on reset not cleared */
|
||||||
|
if (val->val1 == 1) {
|
||||||
|
mode = TI_TMP108_CONF_TM_INT;
|
||||||
|
} else {
|
||||||
|
mode = TI_TMP108_CONF_TM_CMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_CONF_TM_MASK,
|
||||||
|
mode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_LOWER_THRESH:
|
||||||
|
reg_value = (val->val1 << 8) | (0x00FF & val->val2);
|
||||||
|
result = tmp108_reg_write(dev,
|
||||||
|
TI_TMP108_REG_LOW_LIMIT,
|
||||||
|
reg_value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_UPPER_THRESH:
|
||||||
|
reg_value = (val->val1 << 8) | (0x00FF & val->val2);
|
||||||
|
result = tmp108_reg_write(dev,
|
||||||
|
TI_TMP108_REG_HIGH_LIMIT,
|
||||||
|
reg_value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||||
|
if (val->val1 < 1) {
|
||||||
|
mode = TI_TMP108_FREQ_4_SECS;
|
||||||
|
} else if (val->val1 < 4) {
|
||||||
|
mode = TI_TMP108_FREQ_1_HZ;
|
||||||
|
} else if (val->val1 < 16) {
|
||||||
|
mode = TI_TMP108_FREQ_4_HZ;
|
||||||
|
} else {
|
||||||
|
mode = TI_TMP108_FREQ_16_HZ;
|
||||||
|
}
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_FREQ_MASK,
|
||||||
|
mode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_TMP108_SHUTDOWN_MODE:
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_MODE_MASK,
|
||||||
|
TI_TMP108_MODE_SHUTDOWN);
|
||||||
|
drv_data->one_shot_mode = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_TMP108_CONTINUOUS_CONVERSION_MODE:
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_MODE_MASK,
|
||||||
|
TI_TMP108_MODE_CONTINUOUS);
|
||||||
|
drv_data->one_shot_mode = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_TMP108_ONE_SHOT_MODE:
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_MODE_MASK,
|
||||||
|
TI_TMP108_MODE_ONE_SHOT);
|
||||||
|
drv_data->one_shot_mode = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SENSOR_ATTR_TMP108_ALERT_POLARITY:
|
||||||
|
if (val->val1 == 1) {
|
||||||
|
mode = TI_TMP108_CONF_POL_HIGH;
|
||||||
|
} else {
|
||||||
|
mode = TI_TMP108_CONF_POL_LOW;
|
||||||
|
}
|
||||||
|
result = tmp108_write_config(dev,
|
||||||
|
TI_TMP108_CONF_POL_MASK,
|
||||||
|
mode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct sensor_driver_api tmp108_driver_api = {
|
||||||
|
.attr_set = tmp108_attr_set,
|
||||||
|
.attr_get = tmp108_attr_get,
|
||||||
|
.sample_fetch = tmp108_sample_fetch,
|
||||||
|
.channel_get = tmp108_channel_get,
|
||||||
|
.trigger_set = tmp_108_trigger_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_TMP108_ALERT_INTERRUPTS
|
||||||
|
static int setup_interrupts(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
const struct tmp108_config *config = dev->config;
|
||||||
|
const struct gpio_dt_spec *alert_gpio = &config->alert_gpio;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!device_is_ready(alert_gpio->port)) {
|
||||||
|
LOG_ERR("tmp108: gpio controller %s not ready",
|
||||||
|
alert_gpio->port->name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gpio_pin_configure_dt(alert_gpio, GPIO_INPUT);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_init_callback(&drv_data->temp_alert_gpio_cb,
|
||||||
|
tmp108_trigger_handle_alert,
|
||||||
|
BIT(alert_gpio->pin));
|
||||||
|
|
||||||
|
result = gpio_add_callback(alert_gpio->port,
|
||||||
|
&drv_data->temp_alert_gpio_cb);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gpio_pin_interrupt_configure_dt(alert_gpio,
|
||||||
|
GPIO_INT_EDGE_BOTH);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int tmp108_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct tmp108_config *cfg = dev->config;
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (!device_is_ready(cfg->i2c_spec.bus)) {
|
||||||
|
LOG_ERR("I2C dev %s not ready", cfg->i2c_spec.bus->name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv_data->scheduled_work.work.handler = tmp108_trigger_handle_one_shot;
|
||||||
|
|
||||||
|
/* save this driver instance for passing to other functions */
|
||||||
|
drv_data->tmp108_dev = dev;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TMP108_ALERT_INTERRUPTS
|
||||||
|
result = setup_interrupts(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TMP108_DEFINE(inst) \
|
||||||
|
static struct tmp108_data tmp108_prv_data_##inst; \
|
||||||
|
static const struct tmp108_config tmp108_config_##inst = { \
|
||||||
|
.i2c_spec = I2C_DT_SPEC_INST_GET(inst), \
|
||||||
|
.alert_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, \
|
||||||
|
alert_gpios, { 0 }) \
|
||||||
|
}; \
|
||||||
|
DEVICE_DT_INST_DEFINE(inst, \
|
||||||
|
&tmp108_init, \
|
||||||
|
NULL, \
|
||||||
|
&tmp108_prv_data_##inst, \
|
||||||
|
&tmp108_config_##inst, \
|
||||||
|
POST_KERNEL, \
|
||||||
|
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||||
|
&tmp108_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(TMP108_DEFINE)
|
88
drivers/sensor/tmp108/tmp108.h
Normal file
88
drivers/sensor/tmp108/tmp108.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_SENSOR_TMP108_TMP108_H_
|
||||||
|
#define ZEPHYR_DRIVERS_SENSOR_TMP108_TMP108_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
#include <drivers/gpio.h>
|
||||||
|
#include <drivers/sensor/tmp108.h>
|
||||||
|
|
||||||
|
#define TI_TMP108_REG_TEMP 0x00 /** Temperature register */
|
||||||
|
#define TI_TMP108_REG_CONF 0x01 /** Configuration register */
|
||||||
|
#define TI_TMP108_REG_LOW_LIMIT 0x02 /** Low alert set register */
|
||||||
|
#define TI_TMP108_REG_HIGH_LIMIT 0x03 /** High alert set register */
|
||||||
|
|
||||||
|
|
||||||
|
#define TI_TMP108_CONF_M0 0x0100 /** Mode 1 configuration bit */
|
||||||
|
#define TI_TMP108_CONF_M1 0x0200 /** Mode 2 configuration bit */
|
||||||
|
#define TI_TMP108_CONF_CR0 0x2000 /** Conversion rate 1 configuration bit */
|
||||||
|
#define TI_TMP108_CONF_CR1 0x4000 /** Conversion rate 2 configuration bit */
|
||||||
|
#define TI_TMP108_CONF_POL 0x0080 /** Alert pin Polarity configuration bit */
|
||||||
|
#define TI_TMP108_CONF_TM 0x0400 /** Thermostat mode setting bit */
|
||||||
|
#define TI_TMP108_CONF_HYS1 0x0020 /** Temperature hysteresis config 1 bit */
|
||||||
|
#define TI_TMP108_CONF_HYS0 0x0010 /** Temperature hysteresis config 2 bit */
|
||||||
|
#define TI_TMP108_CONF_WFH OVER_TEMP_MASK
|
||||||
|
#define TI_TMP108_CONF_WFL UNDER_TEMP_MASK
|
||||||
|
|
||||||
|
#define TI_TMP108_MODE_SHUTDOWN 0
|
||||||
|
#define TI_TMP108_MODE_ONE_SHOT TI_TMP108_CONF_M0
|
||||||
|
#define TI_TMP108_MODE_CONTINUOUS TI_TMP108_CONF_M1
|
||||||
|
#define TI_TMP108_MODE_MASK ~(TI_TMP108_CONF_M1 | TI_TMP108_CONF_M1)
|
||||||
|
|
||||||
|
#define TI_TMP108_FREQ_4_SECS 0
|
||||||
|
#define TI_TMP108_FREQ_1_HZ TI_TMP108_CONF_CR0
|
||||||
|
#define TI_TMP108_FREQ_4_HZ TI_TMP108_CONF_CR1
|
||||||
|
#define TI_TMP108_FREQ_16_HZ (TI_TMP108_CONF_CR1 | TI_TMP108_CONF_CR0)
|
||||||
|
#define TI_TMP108_FREQ_MASK ~(TI_TMP108_CONF_M1 | TI_TMP108_CONF_M1)
|
||||||
|
|
||||||
|
#define TI_TMP108_CONF_POL_LOW 0
|
||||||
|
#define TI_TMP108_CONF_POL_HIGH TI_TMP108_CONF_POL
|
||||||
|
#define TI_TMP108_CONF_POL_MASK ~(TI_TMP108_CONF_POL)
|
||||||
|
|
||||||
|
#define TI_TMP108_CONF_TM_CMP 0
|
||||||
|
#define TI_TMP108_CONF_TM_INT TI_TMP108_CONF_TM
|
||||||
|
#define TI_TMP108_CONF_TM_MASK ~(TI_TMP108_CONF_TM)
|
||||||
|
|
||||||
|
#define TI_TMP108_HYSTER_0_C 0
|
||||||
|
#define TI_TMP108_HYSTER_1_C TI_TMP108_CONF_HYS0
|
||||||
|
#define TI_TMP108_HYSTER_2_C TI_TMP108_CONF_HYS1
|
||||||
|
#define TI_TMP108_HYSTER_4_C (TI_TMP108_CONF_HYS1 | TI_TMP108_CONF_HYS0)
|
||||||
|
#define TI_TMP108_HYSTER_MASK ~(TI_TMP108_CONF_HYS1 | TI_TMP108_CONF_HYS0)
|
||||||
|
|
||||||
|
struct tmp108_data {
|
||||||
|
const struct device *tmp108_dev;
|
||||||
|
|
||||||
|
uint16_t sample;
|
||||||
|
|
||||||
|
bool one_shot_mode;
|
||||||
|
|
||||||
|
struct k_work_delayable scheduled_work;
|
||||||
|
|
||||||
|
struct sensor_trigger temp_alert_trigger;
|
||||||
|
sensor_trigger_handler_t temp_alert_handler;
|
||||||
|
|
||||||
|
sensor_trigger_handler_t data_ready_handler;
|
||||||
|
struct sensor_trigger data_ready_trigger;
|
||||||
|
|
||||||
|
struct gpio_callback temp_alert_gpio_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
int tmp_108_trigger_set(const struct device *dev,
|
||||||
|
const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler);
|
||||||
|
|
||||||
|
int tmp108_reg_read(const struct device *dev, uint8_t reg, uint16_t *val);
|
||||||
|
|
||||||
|
int ti_tmp108_read_temp(const struct device *dev);
|
||||||
|
void tmp108_trigger_handle_one_shot(struct k_work *work);
|
||||||
|
void tmp108_trigger_handle_alert(const struct device *port,
|
||||||
|
struct gpio_callback *cb,
|
||||||
|
gpio_port_pins_t pins);
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_SENSOR_TMP108_TMP108_H_ */
|
104
drivers/sensor/tmp108/tmp108_trigger.c
Normal file
104
drivers/sensor/tmp108/tmp108_trigger.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
#include "tmp108.h"
|
||||||
|
|
||||||
|
#define TMP108_ONE_SHOT_RETRY_TIME_IN_MS 10
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(TMP108, CONFIG_SENSOR_LOG_LEVEL);
|
||||||
|
|
||||||
|
void tmp108_trigger_handle_one_shot(struct k_work *work)
|
||||||
|
{
|
||||||
|
struct k_work_delayable *delayable_work = CONTAINER_OF(work,
|
||||||
|
struct k_work_delayable,
|
||||||
|
work);
|
||||||
|
|
||||||
|
struct tmp108_data *drv_data = CONTAINER_OF(delayable_work,
|
||||||
|
struct tmp108_data,
|
||||||
|
scheduled_work);
|
||||||
|
|
||||||
|
struct sensor_trigger sensor_trigger_type = {
|
||||||
|
.chan = SENSOR_CHAN_AMBIENT_TEMP,
|
||||||
|
.type = SENSOR_TRIG_DATA_READY
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t config = 0;
|
||||||
|
bool shutdown_mode = false;
|
||||||
|
|
||||||
|
tmp108_reg_read(drv_data->tmp108_dev, TI_TMP108_REG_CONF, &config);
|
||||||
|
|
||||||
|
/* check shutdown mode which indicates a one shot read was successful */
|
||||||
|
|
||||||
|
shutdown_mode = (config & (TI_TMP108_CONF_M1 | TI_TMP108_CONF_M0)) == 0;
|
||||||
|
|
||||||
|
if (shutdown_mode == true) {
|
||||||
|
ti_tmp108_read_temp(drv_data->tmp108_dev);
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Temperature one shot mode read failed, retrying");
|
||||||
|
/* Typical wake up time is 27 ms, retry if the read fails
|
||||||
|
* assuming the chip should wake up and take a reading by the time
|
||||||
|
* 27 ms for the initial wake up time and call of this thread
|
||||||
|
* plus 10 ms time has passed
|
||||||
|
*/
|
||||||
|
k_work_reschedule(&drv_data->scheduled_work,
|
||||||
|
K_MSEC(TMP108_ONE_SHOT_RETRY_TIME_IN_MS));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Successful read, call set callbacks */
|
||||||
|
|
||||||
|
if (drv_data->data_ready_handler) {
|
||||||
|
drv_data->data_ready_handler(drv_data->tmp108_dev,
|
||||||
|
&sensor_trigger_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmp108_trigger_handle_alert(const struct device *gpio,
|
||||||
|
struct gpio_callback *cb,
|
||||||
|
gpio_port_pins_t pins)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct tmp108_data *drv_data = CONTAINER_OF(cb,
|
||||||
|
struct tmp108_data,
|
||||||
|
temp_alert_gpio_cb);
|
||||||
|
|
||||||
|
struct sensor_trigger sensor_trigger_type = {
|
||||||
|
.chan = SENSOR_CHAN_AMBIENT_TEMP,
|
||||||
|
.type = SENSOR_TRIG_THRESHOLD
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Successful read, call set callbacks */
|
||||||
|
|
||||||
|
if (drv_data->temp_alert_handler) {
|
||||||
|
drv_data->temp_alert_handler(drv_data->tmp108_dev,
|
||||||
|
&sensor_trigger_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmp_108_trigger_set(const struct device *dev,
|
||||||
|
const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler)
|
||||||
|
{
|
||||||
|
struct tmp108_data *drv_data = dev->data;
|
||||||
|
|
||||||
|
if (trig->type == SENSOR_TRIG_DATA_READY) {
|
||||||
|
drv_data->data_ready_handler = handler;
|
||||||
|
drv_data->data_ready_trigger = *trig;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trig->type == SENSOR_TRIG_THRESHOLD) {
|
||||||
|
drv_data->temp_alert_handler = handler;
|
||||||
|
drv_data->temp_alert_trigger = *trig;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
18
dts/bindings/sensor/ti,tmp108.yaml
Normal file
18
dts/bindings/sensor/ti,tmp108.yaml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
TMP108 Digital Temperature Sensor. See more info at
|
||||||
|
https://www.ti.com/product/TMP108
|
||||||
|
|
||||||
|
compatible: "ti,tmp108"
|
||||||
|
|
||||||
|
include: i2c-device.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
alert-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: false
|
||||||
|
description: |
|
||||||
|
Identifies the ALERT signal, which is active-low open drain when
|
||||||
|
produced by the sensor.
|
43
include/drivers/sensor/tmp108.h
Normal file
43
include/drivers/sensor/tmp108.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Jimmy Johnson <catch22@fastmail.net>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Extended public API for TI's TMP108 temperature sensor
|
||||||
|
*
|
||||||
|
* This exposes attributes for the TMP108 which can be used for
|
||||||
|
* setting the on-chip Temperature Mode and alert parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_TMP108_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_TMP108_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum sensor_attribute_tmp_108 {
|
||||||
|
/** Turn on power saving/one shot mode */
|
||||||
|
SENSOR_ATTR_TMP108_ONE_SHOT_MODE = SENSOR_ATTR_PRIV_START,
|
||||||
|
/** Shutdown the sensor */
|
||||||
|
SENSOR_ATTR_TMP108_SHUTDOWN_MODE,
|
||||||
|
/** Turn on continuous conversion */
|
||||||
|
SENSOR_ATTR_TMP108_CONTINUOUS_CONVERSION_MODE,
|
||||||
|
/** Set the alert pin polarity */
|
||||||
|
SENSOR_ATTR_TMP108_ALERT_POLARITY
|
||||||
|
};
|
||||||
|
|
||||||
|
/** a mask for the over temp alert bit in the status word*/
|
||||||
|
#define OVER_TEMP_MASK 0x1000U
|
||||||
|
|
||||||
|
/** a mask for the under temp alert bit in the status word*/
|
||||||
|
#define UNDER_TEMP_MASK 0x0800U
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_TMP108_H_ */
|
|
@ -526,6 +526,13 @@ test_i2c_tmp007: tmp007@44 {
|
||||||
int-gpios = <&test_gpio 0 0>;
|
int-gpios = <&test_gpio 0 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
test_i2c_tmp108: tmp108@48 {
|
||||||
|
compatible = "ti,tmp108";
|
||||||
|
label = "TMP108";
|
||||||
|
reg = <0x48>;
|
||||||
|
alert-gpios = <&test_gpio 0 0>;
|
||||||
|
};
|
||||||
|
|
||||||
test_i2c_tmp112: tmp112@45 {
|
test_i2c_tmp112: tmp112@45 {
|
||||||
compatible = "ti,tmp112";
|
compatible = "ti,tmp112";
|
||||||
label = "TMP112";
|
label = "TMP112";
|
||||||
|
|
|
@ -94,6 +94,7 @@ CONFIG_TH02=y
|
||||||
CONFIG_TI_HDC=y
|
CONFIG_TI_HDC=y
|
||||||
CONFIG_TI_HDC20XX=y
|
CONFIG_TI_HDC20XX=y
|
||||||
CONFIG_TMP007=y
|
CONFIG_TMP007=y
|
||||||
|
CONFIG_TMP108=y
|
||||||
CONFIG_TMP112=y
|
CONFIG_TMP112=y
|
||||||
CONFIG_TMP116=y
|
CONFIG_TMP116=y
|
||||||
CONFIG_VCNL4040=y
|
CONFIG_VCNL4040=y
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue