Skip to content

Commit d4e9e5f

Browse files
mah-eiSmartcarlescufi
authored andcommitted
drivers: sensor: Added driver for the Würth Elektronik WSEN-TIDS sensor
Added sample for the WSEN-TIDS temperature sensor. Signed-off-by: Matthias Hauser <[email protected]>
1 parent 6ecc6c3 commit d4e9e5f

File tree

9 files changed

+651
-0
lines changed

9 files changed

+651
-0
lines changed

drivers/sensor/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp)
113113
add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec)
114114
add_subdirectory_ifdef(CONFIG_WSEN_HIDS wsen_hids)
115115
add_subdirectory_ifdef(CONFIG_ITDS wsen_itds)
116+
add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids)
116117
add_subdirectory_ifdef(CONFIG_MCUX_ACMP mcux_acmp)
117118
add_subdirectory_ifdef(CONFIG_TACH_NPCX nuvoton_tach_npcx)
118119
add_subdirectory_ifdef(CONFIG_ADC_CMP_NPCX nuvoton_adc_cmp_npcx)

drivers/sensor/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ source "drivers/sensor/wsen_hids/Kconfig"
265265

266266
source "drivers/sensor/wsen_itds/Kconfig"
267267

268+
source "drivers/sensor/wsen_tids/Kconfig"
269+
268270
source "drivers/sensor/mcux_acmp/Kconfig"
269271

270272
source "drivers/sensor/nuvoton_tach_npcx/Kconfig"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
6+
zephyr_library_sources(wsen_tids.c)
7+
zephyr_library_sources_ifdef(CONFIG_WSEN_TIDS_TRIGGER wsen_tids_trigger.c)

drivers/sensor/wsen_tids/Kconfig

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
menuconfig WSEN_TIDS
5+
bool "WSEN-TIDS temperature sensor"
6+
default y
7+
depends on DT_HAS_WE_WSEN_TIDS_ENABLED
8+
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_TIDS),i2c)
9+
select HAS_WESENSORS
10+
help
11+
Enable driver for the WSEN-TIDS I2C-based temperature sensor.
12+
13+
if WSEN_TIDS
14+
15+
choice WSEN_TIDS_TRIGGER_MODE
16+
prompt "Trigger mode"
17+
default WSEN_TIDS_TRIGGER_NONE
18+
help
19+
Specify the type of triggering to be used by the driver.
20+
21+
config WSEN_TIDS_TRIGGER_NONE
22+
bool "No trigger"
23+
24+
config WSEN_TIDS_TRIGGER_GLOBAL_THREAD
25+
bool "Use global thread"
26+
depends on GPIO
27+
select WSEN_TIDS_TRIGGER
28+
29+
config WSEN_TIDS_TRIGGER_OWN_THREAD
30+
bool "Use own thread"
31+
depends on GPIO
32+
select WSEN_TIDS_TRIGGER
33+
34+
endchoice # WSEN_TIDS_TRIGGER_MODE
35+
36+
config WSEN_TIDS_TRIGGER
37+
bool
38+
39+
config WSEN_TIDS_THREAD_PRIORITY
40+
int "Thread priority"
41+
depends on WSEN_TIDS_TRIGGER_OWN_THREAD
42+
default 10
43+
help
44+
Priority of thread used by the driver to handle interrupts.
45+
46+
config WSEN_TIDS_THREAD_STACK_SIZE
47+
int "Thread stack size"
48+
depends on WSEN_TIDS_TRIGGER_OWN_THREAD
49+
default 1024
50+
help
51+
Stack size of thread used by the driver to handle interrupts.
52+
53+
endif # WSEN_TIDS

drivers/sensor/wsen_tids/wsen_tids.c

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT we_wsen_tids
8+
9+
#include <stdlib.h>
10+
11+
#include <zephyr/sys/__assert.h>
12+
#include <zephyr/sys/byteorder.h>
13+
#include <zephyr/logging/log.h>
14+
15+
#include "wsen_tids.h"
16+
17+
LOG_MODULE_REGISTER(WSEN_TIDS, CONFIG_SENSOR_LOG_LEVEL);
18+
19+
/*
20+
* List of supported output data rates. Index into this list is used as
21+
* argument for TIDS_setOutputDataRate()
22+
*/
23+
static const int32_t tids_odr_list[] = {
24+
25,
25+
50,
26+
100,
27+
200,
28+
};
29+
30+
static int tids_sample_fetch(const struct device *dev, enum sensor_channel chan)
31+
{
32+
struct tids_data *data = dev->data;
33+
int16_t raw_temperature;
34+
35+
if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_AMBIENT_TEMP)) {
36+
LOG_ERR("Fetching is not supported on channel %d.", chan);
37+
return -EINVAL;
38+
}
39+
40+
if (TIDS_getRawTemperature(&data->sensor_interface, &raw_temperature) != WE_SUCCESS) {
41+
LOG_ERR("Failed to fetch data sample");
42+
return -EIO;
43+
}
44+
45+
data->temperature = raw_temperature;
46+
47+
return 0;
48+
}
49+
50+
static int tids_channel_get(const struct device *dev, enum sensor_channel chan,
51+
struct sensor_value *val)
52+
{
53+
struct tids_data *data = dev->data;
54+
55+
if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
56+
/* Convert temperature from 0.01 degrees Celsius to degrees Celsius */
57+
val->val1 = data->temperature / 100;
58+
val->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100);
59+
} else {
60+
return -ENOTSUP;
61+
}
62+
63+
return 0;
64+
}
65+
66+
/* Set output data rate. See tids_odr_list for allowed values. */
67+
static int tids_odr_set(const struct device *dev, const struct sensor_value *odr)
68+
{
69+
struct tids_data *data = dev->data;
70+
int odr_index;
71+
72+
for (odr_index = 0; odr_index < ARRAY_SIZE(tids_odr_list); odr_index++) {
73+
if (odr->val1 == tids_odr_list[odr_index] && odr->val2 == 0) {
74+
break;
75+
}
76+
}
77+
78+
if (odr_index == ARRAY_SIZE(tids_odr_list)) {
79+
/* ODR not allowed (was not found in tids_odr_list) */
80+
LOG_ERR("Bad sampling frequency %d.%d", odr->val1, abs(odr->val2));
81+
return -EINVAL;
82+
}
83+
84+
if (TIDS_setOutputDataRate(&data->sensor_interface, (TIDS_outputDataRate_t)odr_index) !=
85+
WE_SUCCESS) {
86+
LOG_ERR("Failed to set output data rate");
87+
return -EIO;
88+
}
89+
90+
return 0;
91+
}
92+
93+
static int tids_attr_set(const struct device *dev, enum sensor_channel chan,
94+
enum sensor_attribute attr, const struct sensor_value *val)
95+
{
96+
if (chan != SENSOR_CHAN_ALL) {
97+
LOG_WRN("attr_set() is not supported on channel %d.", chan);
98+
return -ENOTSUP;
99+
}
100+
101+
switch (attr) {
102+
case SENSOR_ATTR_SAMPLING_FREQUENCY:
103+
return tids_odr_set(dev, val);
104+
105+
#ifdef CONFIG_WSEN_TIDS_TRIGGER
106+
case SENSOR_ATTR_LOWER_THRESH:
107+
return tids_threshold_set(dev, val, false);
108+
109+
case SENSOR_ATTR_UPPER_THRESH:
110+
return tids_threshold_set(dev, val, true);
111+
#endif /* CONFIG_WSEN_TIDS_TRIGGER */
112+
113+
default:
114+
LOG_ERR("Operation not supported.");
115+
return -ENOTSUP;
116+
}
117+
}
118+
119+
static const struct sensor_driver_api tids_driver_api = {
120+
.attr_set = tids_attr_set,
121+
#if CONFIG_WSEN_TIDS_TRIGGER
122+
.trigger_set = tids_trigger_set,
123+
#endif
124+
.sample_fetch = tids_sample_fetch,
125+
.channel_get = tids_channel_get,
126+
};
127+
128+
static int tids_init(const struct device *dev)
129+
{
130+
const struct tids_config *const config = dev->config;
131+
struct tids_data *data = dev->data;
132+
int status;
133+
uint8_t device_id;
134+
struct sensor_value odr;
135+
136+
/* Initialize WE sensor interface */
137+
TIDS_getDefaultInterface(&data->sensor_interface);
138+
data->sensor_interface.interfaceType = WE_i2c;
139+
data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
140+
141+
/* First communication test - check device ID */
142+
if (TIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) {
143+
LOG_ERR("Failed to read device ID.");
144+
return -EIO;
145+
}
146+
147+
if (device_id != TIDS_DEVICE_ID_VALUE) {
148+
LOG_ERR("Invalid device ID 0x%x.", device_id);
149+
return -EIO;
150+
}
151+
152+
/* Reset the sensor with an arbitrary off time of 5 us */
153+
TIDS_softReset(&data->sensor_interface, TIDS_enable);
154+
k_sleep(K_USEC(5));
155+
TIDS_softReset(&data->sensor_interface, TIDS_disable);
156+
157+
odr.val1 = tids_odr_list[config->odr];
158+
odr.val2 = 0;
159+
status = tids_odr_set(dev, &odr);
160+
if (status < 0) {
161+
LOG_ERR("Failed to set output data rate.");
162+
return status;
163+
}
164+
165+
if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
166+
LOG_ERR("Failed to enable block data update.");
167+
return -EIO;
168+
}
169+
170+
if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
171+
LOG_ERR("Failed to enable continuous mode.");
172+
return -EIO;
173+
}
174+
175+
#ifdef CONFIG_WSEN_TIDS_TRIGGER
176+
status = tids_init_interrupt(dev);
177+
if (status < 0) {
178+
LOG_ERR("Failed to initialize threshold interrupt.");
179+
return status;
180+
}
181+
#endif
182+
183+
return 0;
184+
}
185+
186+
#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
187+
#warning "TIDS driver enabled without any devices"
188+
#endif
189+
190+
/*
191+
* Device creation macros
192+
*/
193+
194+
#define TIDS_DEVICE_INIT(inst) \
195+
SENSOR_DEVICE_DT_INST_DEFINE(inst, \
196+
tids_init, \
197+
NULL, \
198+
&tids_data_##inst, \
199+
&tids_config_##inst, \
200+
POST_KERNEL, \
201+
CONFIG_SENSOR_INIT_PRIORITY, \
202+
&tids_driver_api);
203+
204+
#ifdef CONFIG_WSEN_TIDS_TRIGGER
205+
#define TIDS_CFG_IRQ(inst) \
206+
.gpio_threshold = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \
207+
.high_threshold = DT_INST_PROP(inst, temp_high_threshold), \
208+
.low_threshold = DT_INST_PROP(inst, temp_low_threshold)
209+
#else
210+
#define TIDS_CFG_IRQ(inst)
211+
#endif /* CONFIG_WSEN_TIDS_TRIGGER */
212+
213+
/*
214+
* Main instantiation macro.
215+
*/
216+
#define TIDS_DEFINE(inst) \
217+
static struct tids_data tids_data_##inst; \
218+
static const struct tids_config tids_config_##inst = \
219+
{ \
220+
.bus_cfg = { \
221+
.i2c = I2C_DT_SPEC_INST_GET(inst), \
222+
}, \
223+
.odr = (TIDS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr)), \
224+
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int_gpios), \
225+
(TIDS_CFG_IRQ(inst)), ()) \
226+
}; \
227+
TIDS_DEVICE_INIT(inst)
228+
229+
DT_INST_FOREACH_STATUS_OKAY(TIDS_DEFINE)

drivers/sensor/wsen_tids/wsen_tids.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_
8+
#define ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_
9+
10+
#include <zephyr/drivers/gpio.h>
11+
#include <zephyr/drivers/sensor.h>
12+
13+
#include <weplatform.h>
14+
15+
#include "WSEN_TIDS_2521020222501.h"
16+
17+
#include <zephyr/drivers/i2c.h>
18+
19+
struct tids_data {
20+
/* WE sensor interface configuration */
21+
WE_sensorInterface_t sensor_interface;
22+
23+
/* Last temperature sample */
24+
int16_t temperature;
25+
26+
#ifdef CONFIG_WSEN_TIDS_TRIGGER
27+
const struct device *dev;
28+
29+
/* Callback for high/low limit interrupts */
30+
struct gpio_callback threshold_cb;
31+
32+
struct sensor_trigger threshold_trigger;
33+
sensor_trigger_handler_t threshold_handler;
34+
35+
#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD)
36+
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_TIDS_THREAD_STACK_SIZE);
37+
struct k_thread thread;
38+
struct k_sem threshold_sem;
39+
#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD)
40+
struct k_work work;
41+
#endif
42+
#endif /* CONFIG_WSEN_TIDS_TRIGGER */
43+
};
44+
45+
struct tids_config {
46+
union {
47+
const struct i2c_dt_spec i2c;
48+
} bus_cfg;
49+
50+
/* Output data rate */
51+
const TIDS_outputDataRate_t odr;
52+
53+
#ifdef CONFIG_WSEN_TIDS_TRIGGER
54+
/* Interrupt pin used for high and low limit interrupt events */
55+
const struct gpio_dt_spec gpio_threshold;
56+
57+
/* High temperature interrupt threshold */
58+
const int high_threshold;
59+
60+
/* Low temperature interrupt threshold */
61+
const int low_threshold;
62+
#endif
63+
};
64+
65+
#ifdef CONFIG_WSEN_TIDS_TRIGGER
66+
int tids_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
67+
sensor_trigger_handler_t handler);
68+
69+
int tids_threshold_set(const struct device *dev, const struct sensor_value *thresh_value,
70+
bool upper);
71+
72+
int tids_init_interrupt(const struct device *dev);
73+
#endif
74+
75+
int tids_i2c_init(const struct device *dev);
76+
77+
#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_ */

0 commit comments

Comments
 (0)