1 /*
2  * Copyright (c) 2023 Ian Morris
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #include <zephyr/device.h>
11 #include <zephyr/sys/util_macro.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/drivers/sensor.h>
14 #include <zephyr/drivers/sensor_data_types.h>
15 #include <zephyr/rtio/rtio.h>
16 #include <zephyr/dsp/print_format.h>
17 
18 #define DHT_ALIAS(i) DT_ALIAS(_CONCAT(dht, i))
19 #define DHT_DEVICE(i, _)                                                      \
20 	IF_ENABLED(DT_NODE_EXISTS(DHT_ALIAS(i)), (DEVICE_DT_GET(DHT_ALIAS(i)),))
21 
22 /* Support up to 10 temperature/humidity sensors */
23 static const struct device *const sensors[] = {LISTIFY(10, DHT_DEVICE, ())};
24 
25 #define DHT_IODEV(i, _)                                                      \
26 	IF_ENABLED(DT_NODE_EXISTS(DHT_ALIAS(i)),                                 \
27 		(SENSOR_DT_READ_IODEV(_CONCAT(dht_iodev, i), DHT_ALIAS(i),           \
28 		{SENSOR_CHAN_AMBIENT_TEMP, 0},                                       \
29 		{SENSOR_CHAN_HUMIDITY, 0})))
30 
31 LISTIFY(10, DHT_IODEV, (;));
32 
33 #define DHT_IODEV_REF(i, _)                                                   \
34 	COND_CODE_1(DT_NODE_EXISTS(DHT_ALIAS(i)), (CONCAT(&dht_iodev, i)), (NULL))
35 
36 static struct rtio_iodev *dht_iodev[] = { LISTIFY(10, DHT_IODEV_REF, (,)) };
37 
38 RTIO_DEFINE(dht_ctx, 1, 1);
39 
main(void)40 int main(void)
41 {
42 	int rc;
43 
44 	for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) {
45 		if (!device_is_ready(sensors[i])) {
46 			printk("sensor: device %s not ready.\n", sensors[i]->name);
47 			return 0;
48 		}
49 	}
50 
51 	while (1) {
52 		for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) {
53 			struct device *dev = (struct device *) sensors[i];
54 
55 			uint8_t buf[128];
56 
57 			rc = sensor_read(dht_iodev[i], &dht_ctx, buf, 128);
58 
59 			if (rc != 0) {
60 				printk("%s: sensor_read() failed: %d\n", dev->name, rc);
61 				return rc;
62 			}
63 
64 			const struct sensor_decoder_api *decoder;
65 
66 			rc = sensor_get_decoder(dev, &decoder);
67 
68 			if (rc != 0) {
69 				printk("%s: sensor_get_decode() failed: %d\n", dev->name, rc);
70 				return rc;
71 			}
72 
73 			uint32_t temp_fit = 0;
74 			struct sensor_q31_data temp_data = {0};
75 
76 			decoder->decode(buf,
77 					(struct sensor_chan_spec) {SENSOR_CHAN_AMBIENT_TEMP, 0},
78 					&temp_fit, 1, &temp_data);
79 
80 			uint32_t hum_fit = 0;
81 			struct sensor_q31_data hum_data = {0};
82 
83 			decoder->decode(buf,
84 					(struct sensor_chan_spec) {SENSOR_CHAN_HUMIDITY, 0},
85 					&hum_fit, 1, &hum_data);
86 
87 			printk("%16s: temp is %s%d.%d °C humidity is %s%d.%d %%RH\n", dev->name,
88 				PRIq_arg(temp_data.readings[0].temperature, 2, temp_data.shift),
89 				PRIq_arg(hum_data.readings[0].humidity, 2, hum_data.shift));
90 		}
91 		k_msleep(1000);
92 	}
93 	return 0;
94 }
95