Skip to content

Commit aee5c1a

Browse files
committed
drivers: sensor: tmp11x: add trigger function for alert
Allows to configure the alert or therm mode for triggers based on the low/high temperature treshholds Signed-off-by: Tobias Meyer <[email protected]>
1 parent 366d45f commit aee5c1a

File tree

11 files changed

+378
-13
lines changed

11 files changed

+378
-13
lines changed

drivers/sensor/ti/tmp11x/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
zephyr_library()
44

55
zephyr_library_sources(tmp11x.c)
6+
zephyr_library_sources_ifdef(CONFIG_TMP11X_TRIGGER tmp11x_trigger.c)

drivers/sensor/ti/tmp11x/Kconfig

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,46 @@ config TMP11X
1010
select I2C
1111
help
1212
Enable driver for TMP116, TMP117 and TMP119 temperature sensors.
13+
14+
choice
15+
prompt "TMP11X Alert Pin Trigger Mode"
16+
default TMP11X_TRIGGER_GLOBAL_THREAD
17+
depends on TMP11X
18+
19+
config TMP11X_TRIGGER_NONE
20+
bool "No trigger"
21+
22+
config TMP11X_TRIGGER_GLOBAL_THREAD
23+
bool "Use global thread"
24+
depends on GPIO
25+
select TMP11X_TRIGGER
26+
27+
config TMP11X_TRIGGER_OWN_THREAD
28+
bool "Use own thread"
29+
depends on GPIO
30+
select TMP11X_TRIGGER
31+
32+
endchoice
33+
34+
config TMP11X_TRIGGER
35+
bool
36+
depends on GPIO
37+
help
38+
Enable support for the TMP11X alert pin functionality.
39+
The alert pin can be configured to trigger when temperature
40+
exceeds configurable high/low thresholds. This is supported
41+
on TMP116, TMP117, and TMP119 devices.
42+
43+
config TMP11X_THREAD_PRIORITY
44+
int "Thread priority"
45+
depends on TMP11X_TRIGGER_OWN_THREAD
46+
default 10
47+
help
48+
Priority of thread used by the driver to handle interrupts.
49+
50+
config TMP11X_THREAD_STACK_SIZE
51+
int "Thread stack size"
52+
depends on TMP11X_TRIGGER_OWN_THREAD
53+
default 1024
54+
help
55+
Stack size of thread used by the driver to handle interrupts.

drivers/sensor/ti/tmp11x/tmp11x.c

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,31 @@ static inline bool tmp11x_is_offset_supported(const struct tmp11x_data *drv_data
7171
return drv_data->id == TMP117_DEVICE_ID || drv_data->id == TMP119_DEVICE_ID;
7272
}
7373

74+
/**
75+
* @brief Convert sensor_value temperature to TMP11X register format
76+
*
77+
* This function converts a temperature from sensor_value format (val1 in degrees C,
78+
* val2 in micro-degrees C) to the TMP11X register format. It uses 64-bit arithmetic
79+
* to prevent overflow and clamps the result to the valid int16_t range.
80+
*
81+
* @param val Pointer to sensor_value containing temperature
82+
* @return Temperature value in TMP11X register format (int16_t)
83+
*/
84+
static inline int16_t tmp11x_sensor_value_to_reg_format(const struct sensor_value *val)
85+
{
86+
int64_t temp_micro = ((int64_t)val->val1 * 1000000) + val->val2;
87+
int64_t temp_scaled = (temp_micro * 10) / TMP11X_RESOLUTION;
88+
89+
/* Clamp to int16_t range */
90+
if (temp_scaled > INT16_MAX) {
91+
return INT16_MAX;
92+
} else if (temp_scaled < INT16_MIN) {
93+
return INT16_MIN;
94+
} else {
95+
return (int16_t)temp_scaled;
96+
}
97+
}
98+
7499
static bool check_eeprom_bounds(const struct device *dev, off_t offset,
75100
size_t len)
76101
{
@@ -310,8 +335,7 @@ static int tmp11x_attr_set(const struct device *dev,
310335
/*
311336
* The offset is encoded into the temperature register format.
312337
*/
313-
value = (((val->val1) * 10000000) + ((val->val2) * 10))
314-
/ (int32_t)TMP11X_RESOLUTION;
338+
value = tmp11x_sensor_value_to_reg_format(val);
315339

316340
return tmp11x_reg_write(dev, TMP117_REG_TEMP_OFFSET, value);
317341

@@ -347,6 +371,34 @@ static int tmp11x_attr_set(const struct device *dev,
347371
case SENSOR_ATTR_TMP11X_ONE_SHOT_MODE:
348372
return tmp11x_write_config(dev, TMP11X_CFGR_MODE, TMP11X_MODE_ONE_SHOT);
349373

374+
#ifdef CONFIG_TMP11X_TRIGGER
375+
case SENSOR_ATTR_TMP11X_ALERT_PIN_POLARITY:
376+
if (val->val1 == TMP11X_ALERT_PIN_ACTIVE_HIGH) {
377+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_POL,
378+
TMP11X_CFGR_ALERT_PIN_POL);
379+
} else {
380+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_POL, 0);
381+
}
382+
383+
case SENSOR_ATTR_TMP11X_ALERT_PIN_MODE:
384+
if (val->val1 == TMP11X_ALERT_PIN_THERM_MODE) {
385+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_MODE,
386+
TMP11X_CFGR_ALERT_PIN_MODE);
387+
} else {
388+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_MODE, 0);
389+
}
390+
391+
case SENSOR_ATTR_UPPER_THRESH:
392+
/* Convert temperature to register format */
393+
value = tmp11x_sensor_value_to_reg_format(val);
394+
return tmp11x_reg_write(dev, TMP11X_REG_HIGH_LIM, value);
395+
396+
case SENSOR_ATTR_LOWER_THRESH:
397+
/* Convert temperature to register format */
398+
value = tmp11x_sensor_value_to_reg_format(val);
399+
return tmp11x_reg_write(dev, TMP11X_REG_LOW_LIM, value);
400+
#endif /* CONFIG_TMP11X_TRIGGER */
401+
350402
default:
351403
return -ENOTSUP;
352404
}
@@ -385,6 +437,25 @@ static int tmp11x_attr_get(const struct device *dev, enum sensor_channel chan,
385437
}
386438

387439
return rc;
440+
441+
#ifdef CONFIG_TMP11X_TRIGGER
442+
case SENSOR_ATTR_UPPER_THRESH:
443+
rc = tmp11x_reg_read(dev, TMP11X_REG_HIGH_LIM, &data);
444+
if (rc == 0) {
445+
tmp11x_temperature_to_sensor_value(data, val);
446+
}
447+
448+
return rc;
449+
450+
case SENSOR_ATTR_LOWER_THRESH:
451+
rc = tmp11x_reg_read(dev, TMP11X_REG_LOW_LIM, &data);
452+
if (rc == 0) {
453+
tmp11x_temperature_to_sensor_value(data, val);
454+
}
455+
456+
return rc;
457+
#endif /* CONFIG_TMP11X_TRIGGER */
458+
388459
default:
389460
return -ENOTSUP;
390461
}
@@ -394,7 +465,10 @@ static DEVICE_API(sensor, tmp11x_driver_api) = {
394465
.attr_set = tmp11x_attr_set,
395466
.attr_get = tmp11x_attr_get,
396467
.sample_fetch = tmp11x_sample_fetch,
397-
.channel_get = tmp11x_channel_get
468+
.channel_get = tmp11x_channel_get,
469+
#ifdef CONFIG_TMP11X_TRIGGER
470+
.trigger_set = tmp11x_trigger_set,
471+
#endif
398472
};
399473

400474
static int tmp11x_init(const struct device *dev)
@@ -424,18 +498,28 @@ static int tmp11x_init(const struct device *dev)
424498

425499
rc = tmp11x_write_config(dev, TMP11X_CFGR_AVG, cfg->oversampling);
426500

501+
#ifdef CONFIG_TMP11X_TRIGGER
502+
drv_data->dev = dev;
503+
rc = tmp11x_init_interrupt(dev);
504+
if (rc < 0) {
505+
LOG_ERR("%s: Failed to initialize alert pin", dev->name);
506+
return rc;
507+
}
508+
#endif /* CONFIG_TMP11X_TRIGGER */
509+
427510
return rc;
428511
}
429512

430-
#define DEFINE_TMP11X(_num) \
431-
static struct tmp11x_data tmp11x_data_##_num; \
432-
static const struct tmp11x_dev_config tmp11x_config_##_num = { \
433-
.bus = I2C_DT_SPEC_INST_GET(_num), \
434-
.odr = DT_INST_PROP(_num, odr), \
435-
.oversampling = DT_INST_PROP(_num, oversampling), \
436-
}; \
437-
SENSOR_DEVICE_DT_INST_DEFINE(_num, tmp11x_init, NULL, \
438-
&tmp11x_data_##_num, &tmp11x_config_##_num, POST_KERNEL, \
439-
CONFIG_SENSOR_INIT_PRIORITY, &tmp11x_driver_api);
513+
#define DEFINE_TMP11X(_num) \
514+
static struct tmp11x_data tmp11x_data_##_num; \
515+
static const struct tmp11x_dev_config tmp11x_config_##_num = { \
516+
.bus = I2C_DT_SPEC_INST_GET(_num), \
517+
.odr = DT_INST_PROP(_num, odr), \
518+
.oversampling = DT_INST_PROP(_num, oversampling), \
519+
IF_ENABLED(CONFIG_TMP11X_TRIGGER, \
520+
(.alert_gpio = GPIO_DT_SPEC_INST_GET_OR(_num, alert_gpios, {}),)) }; \
521+
SENSOR_DEVICE_DT_INST_DEFINE(_num, tmp11x_init, NULL, &tmp11x_data_##_num, \
522+
&tmp11x_config_##_num, POST_KERNEL, \
523+
CONFIG_SENSOR_INIT_PRIORITY, &tmp11x_driver_api);
440524

441525
DT_INST_FOREACH_STATUS_OKAY(DEFINE_TMP11X)

drivers/sensor/ti/tmp11x/tmp11x.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
#define TMP11X_EEPROM_UL_UNLOCK BIT(15)
3636
#define TMP11X_EEPROM_UL_BUSY BIT(14)
3737

38+
/* Alert pin configuration bits */
39+
#define TMP11X_CFGR_ALERT_PIN_POL BIT(3) /* Alert pin polarity */
40+
#define TMP11X_CFGR_ALERT_PIN_MODE BIT(4) /* Alert pin mode (1=therm, 0=alert) */
41+
3842
#define TMP11X_AVG_1_SAMPLE 0
3943
#define TMP11X_AVG_8_SAMPLES BIT(5)
4044
#define TMP11X_AVG_32_SAMPLES BIT(6)
@@ -46,12 +50,39 @@
4650
struct tmp11x_data {
4751
uint16_t sample;
4852
uint16_t id;
53+
#ifdef CONFIG_TMP11X_TRIGGER
54+
const struct device *dev;
55+
struct gpio_callback alert_cb;
56+
sensor_trigger_handler_t alert_handler;
57+
const struct sensor_trigger *alert_trigger;
58+
59+
#if defined(CONFIG_TMP11X_TRIGGER_OWN_THREAD)
60+
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TMP11X_THREAD_STACK_SIZE);
61+
struct k_thread thread;
62+
struct k_sem gpio_sem;
63+
#elif defined(CONFIG_TMP11X_TRIGGER_GLOBAL_THREAD)
64+
struct k_work work;
65+
#endif /* CONFIG_TMP11X_TRIGGER_OWN_THREAD */
66+
#endif /* CONFIG_TMP11X_TRIGGER */
4967
};
5068

5169
struct tmp11x_dev_config {
5270
struct i2c_dt_spec bus;
5371
uint16_t odr;
5472
uint16_t oversampling;
73+
#ifdef CONFIG_TMP11X_TRIGGER
74+
struct gpio_dt_spec alert_gpio;
75+
#endif
5576
};
5677

78+
/* Function declarations */
79+
int tmp11x_write_config(const struct device *dev, uint16_t mask, uint16_t conf);
80+
int tmp11x_reg_read(const struct device *dev, uint8_t reg, uint16_t *val);
81+
82+
#ifdef CONFIG_TMP11X_TRIGGER
83+
int tmp11x_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
84+
sensor_trigger_handler_t handler);
85+
int tmp11x_init_interrupt(const struct device *dev);
86+
#endif
87+
5788
#endif /* ZEPHYR_DRIVERS_SENSOR_TMP11X_TMP11X_H_ */

0 commit comments

Comments
 (0)