1 /*
2 * Copyright (c) 2025 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_2521020222501
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_2521020222501.h"
16
17 LOG_MODULE_REGISTER(WSEN_TIDS_2521020222501, CONFIG_SENSOR_LOG_LEVEL);
18
19 static const struct sensor_value tids_2521020222501_odr_list[] = {{.val1 = 0, .val2 = 0},
20 {.val1 = 25, .val2 = 0},
21 {.val1 = 50, .val2 = 0},
22 {.val1 = 100, .val2 = 0},
23 {.val1 = 200, .val2 = 0}};
24
tids_2521020222501_sample_fetch(const struct device * dev,enum sensor_channel chan)25 static int tids_2521020222501_sample_fetch(const struct device *dev, enum sensor_channel chan)
26 {
27 struct tids_2521020222501_data *data = dev->data;
28 int16_t raw_temperature;
29
30 switch (chan) {
31 case SENSOR_CHAN_ALL:
32 case SENSOR_CHAN_AMBIENT_TEMP:
33 break;
34 default:
35 LOG_ERR("Fetching is not supported on channel %d.", chan);
36 return -ENOTSUP;
37 }
38 if (data->sensor_odr == ((uint8_t)tids_2521020222501_odr_list[0].val1)) {
39
40 TIDS_softReset(&data->sensor_interface, TIDS_enable);
41
42 k_sleep(K_USEC(5));
43
44 TIDS_softReset(&data->sensor_interface, TIDS_disable);
45
46 if (TIDS_enableOneShot(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
47 LOG_ERR("Failed to enable one shot");
48 return -EIO;
49 }
50
51 TIDS_state_t busy = TIDS_enable;
52
53 do {
54 if (TIDS_isBusy(&data->sensor_interface, &busy) != WE_SUCCESS) {
55 LOG_ERR("Failed to check for data ready");
56 return -EIO;
57 }
58 } while (TIDS_enable == busy);
59 }
60
61 if (TIDS_getRawTemperature(&data->sensor_interface, &raw_temperature) != WE_SUCCESS) {
62 LOG_ERR("Failed to fetch data sample");
63 return -EIO;
64 }
65
66 data->temperature = raw_temperature;
67
68 return 0;
69 }
70
tids_2521020222501_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)71 static int tids_2521020222501_channel_get(const struct device *dev, enum sensor_channel chan,
72 struct sensor_value *val)
73 {
74 struct tids_2521020222501_data *data = dev->data;
75
76 switch (chan) {
77 case SENSOR_CHAN_AMBIENT_TEMP:
78 /* Convert temperature from 0.01 degrees Celsius to degrees Celsius */
79 val->val1 = data->temperature / 100;
80 val->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100);
81 break;
82 default:
83 LOG_ERR("Channel not supported %d", chan);
84 return -ENOTSUP;
85 }
86
87 return 0;
88 }
89
90 /* Set output data rate. See tids_2521020222501_odr_list for allowed values. */
tids_2521020222501_odr_set(const struct device * dev,const struct sensor_value * odr)91 static int tids_2521020222501_odr_set(const struct device *dev, const struct sensor_value *odr)
92 {
93 struct tids_2521020222501_data *data = dev->data;
94
95 int odr_index;
96
97 for (odr_index = 0; odr_index < ARRAY_SIZE(tids_2521020222501_odr_list); odr_index++) {
98 if (odr->val1 == tids_2521020222501_odr_list[odr_index].val1 &&
99 odr->val2 == tids_2521020222501_odr_list[odr_index].val2) {
100 break;
101 }
102 }
103
104 if (odr_index == ARRAY_SIZE(tids_2521020222501_odr_list)) {
105 /* ODR not allowed (was not found in tids_2521020222501_odr_list) */
106 LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2);
107 return -EINVAL;
108 }
109
110 if (odr->val1 == tids_2521020222501_odr_list[0].val1) {
111 if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_disable) !=
112 WE_SUCCESS) {
113 LOG_ERR("Failed to enable block data update.");
114 return -EIO;
115 }
116
117 if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_disable) !=
118 WE_SUCCESS) {
119 LOG_ERR("Failed to enable continuous mode.");
120 return -EIO;
121 }
122 } else {
123 if (TIDS_setOutputDataRate(&data->sensor_interface,
124 (TIDS_outputDataRate_t)(odr->val1 - 1)) != WE_SUCCESS) {
125 LOG_ERR("Failed to set output data rate");
126 return -EIO;
127 }
128
129 if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_enable) !=
130 WE_SUCCESS) {
131 LOG_ERR("Failed to enable block data update.");
132 return -EIO;
133 }
134
135 if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
136 LOG_ERR("Failed to enable continuous mode.");
137 return -EIO;
138 }
139 }
140
141 data->sensor_odr = (uint8_t)odr->val1;
142
143 return 0;
144 }
145
146 /* Get output data rate. */
tids_2521020222501_odr_get(const struct device * dev,struct sensor_value * odr)147 static int tids_2521020222501_odr_get(const struct device *dev, struct sensor_value *odr)
148 {
149
150 struct tids_2521020222501_data *data = dev->data;
151
152 TIDS_state_t continuous_mode_state;
153
154 if (TIDS_isContinuousModeEnabled(&data->sensor_interface, &continuous_mode_state) !=
155 WE_SUCCESS) {
156 LOG_ERR("Failed to get continuous mode.");
157 return -EIO;
158 }
159
160 if (continuous_mode_state == TIDS_disable) {
161 odr->val1 = tids_2521020222501_odr_list[0].val1;
162 } else {
163 TIDS_outputDataRate_t odrIndex;
164
165 if (TIDS_getOutputDataRate(&data->sensor_interface, &odrIndex) != WE_SUCCESS) {
166 LOG_ERR("Failed to get output data rate");
167 return -EIO;
168 }
169
170 odr->val1 = tids_2521020222501_odr_list[odrIndex + 1].val1;
171 }
172
173 data->sensor_odr = (uint8_t)odr->val1;
174
175 odr->val2 = 0;
176
177 return 0;
178 }
179
tids_2521020222501_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)180 static int tids_2521020222501_attr_set(const struct device *dev, enum sensor_channel chan,
181 enum sensor_attribute attr, const struct sensor_value *val)
182 {
183
184 switch (chan) {
185 case SENSOR_CHAN_ALL:
186 case SENSOR_CHAN_AMBIENT_TEMP:
187 break;
188 default:
189 LOG_ERR("attr_set() is not supported on channel %d.", chan);
190 return -ENOTSUP;
191 }
192
193 switch (attr) {
194 case SENSOR_ATTR_SAMPLING_FREQUENCY:
195 return tids_2521020222501_odr_set(dev, val);
196 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
197 case SENSOR_ATTR_LOWER_THRESH:
198 return tids_2521020222501_threshold_lower_set(dev, val);
199 case SENSOR_ATTR_UPPER_THRESH:
200 return tids_2521020222501_threshold_upper_set(dev, val);
201 #endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */
202
203 default:
204 LOG_ERR("Operation not supported.");
205 return -ENOTSUP;
206 }
207 }
208
tids_2521020222501_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)209 static int tids_2521020222501_attr_get(const struct device *dev, enum sensor_channel chan,
210 enum sensor_attribute attr, struct sensor_value *val)
211 {
212
213 if (val == NULL) {
214 LOG_WRN("address of passed value is NULL.");
215 return -EFAULT;
216 }
217
218 switch (chan) {
219 case SENSOR_CHAN_ALL:
220 case SENSOR_CHAN_AMBIENT_TEMP:
221 break;
222 default:
223 LOG_ERR("attr_get() is not supported on channel %d.", chan);
224 return -ENOTSUP;
225 }
226
227 switch (attr) {
228 case SENSOR_ATTR_SAMPLING_FREQUENCY:
229 return tids_2521020222501_odr_get(dev, val);
230 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
231 case SENSOR_ATTR_LOWER_THRESH:
232 return tids_2521020222501_threshold_lower_get(dev, val);
233 case SENSOR_ATTR_UPPER_THRESH:
234 return tids_2521020222501_threshold_upper_get(dev, val);
235 #endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */
236 default:
237 LOG_ERR("Operation not supported.");
238 return -ENOTSUP;
239 }
240
241 return 0;
242 }
243
244 static DEVICE_API(sensor, tids_2521020222501_driver_api) = {
245 .attr_set = tids_2521020222501_attr_set,
246 #if CONFIG_WSEN_TIDS_2521020222501_TRIGGER
247 .trigger_set = tids_2521020222501_trigger_set,
248 #endif
249 .attr_get = tids_2521020222501_attr_get,
250 .sample_fetch = tids_2521020222501_sample_fetch,
251 .channel_get = tids_2521020222501_channel_get,
252 };
253
tids_2521020222501_init(const struct device * dev)254 static int tids_2521020222501_init(const struct device *dev)
255 {
256 const struct tids_2521020222501_config *const config = dev->config;
257 struct tids_2521020222501_data *data = dev->data;
258 uint8_t device_id;
259
260 /* Initialize WE sensor interface */
261 TIDS_getDefaultInterface(&data->sensor_interface);
262 data->sensor_interface.interfaceType = WE_i2c;
263 if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) {
264 LOG_ERR("I2C bus device not ready");
265 return -ENODEV;
266 }
267 data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
268
269 /* Needed after power up */
270 k_sleep(K_MSEC(12));
271
272 /* First communication test - check device ID */
273 if (TIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) {
274 LOG_ERR("Failed to read device ID.");
275 return -EIO;
276 }
277
278 if (device_id != TIDS_DEVICE_ID_VALUE) {
279 LOG_ERR("Invalid device ID 0x%x.", device_id);
280 return -EIO;
281 }
282
283 /* Reset the sensor with an arbitrary off time of 5 us */
284 TIDS_softReset(&data->sensor_interface, TIDS_enable);
285 k_sleep(K_USEC(5));
286 TIDS_softReset(&data->sensor_interface, TIDS_disable);
287
288 if (tids_2521020222501_odr_set(dev, &tids_2521020222501_odr_list[config->odr]) < 0) {
289 LOG_ERR("Failed to set output data rate.");
290 return -EIO;
291 }
292
293 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
294 if (tids_2521020222501_init_interrupt(dev) < 0) {
295 LOG_ERR("Failed to initialize interrupt.");
296 return -EIO;
297 }
298 #endif
299
300 return 0;
301 }
302
303 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
304 #define TIDS_2521020222501_CFG_IRQ(inst) \
305 .interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, interrupt_gpios), \
306 .high_threshold = DT_INST_PROP(inst, temp_high_threshold), \
307 .low_threshold = DT_INST_PROP(inst, temp_low_threshold)
308 #else
309 #define TIDS_2521020222501_CFG_IRQ(inst)
310 #endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */
311
312 /*
313 * Main instantiation macro.
314 */
315 #define TIDS_2521020222501_DEFINE(inst) \
316 static struct tids_2521020222501_data tids_2521020222501_data_##inst; \
317 static const struct tids_2521020222501_config tids_2521020222501_config_##inst = { \
318 .bus_cfg = \
319 { \
320 .i2c = I2C_DT_SPEC_INST_GET(inst), \
321 }, \
322 .odr = (uint8_t)(DT_INST_ENUM_IDX(inst, odr)), \
323 COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, interrupt_gpios), \
324 (TIDS_2521020222501_CFG_IRQ(inst)), ())}; \
325 SENSOR_DEVICE_DT_INST_DEFINE(inst, tids_2521020222501_init, NULL, \
326 &tids_2521020222501_data_##inst, \
327 &tids_2521020222501_config_##inst, POST_KERNEL, \
328 CONFIG_SENSOR_INIT_PRIORITY, &tids_2521020222501_driver_api);
329
330 DT_INST_FOREACH_STATUS_OKAY(TIDS_2521020222501_DEFINE)
331