1 /*
2  * Copyright (c) 2023 STMicroelectronics
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/adc.h>
11 #include <zephyr/sys/printk.h>
12 
13 #define SLEEP_TIME_MS   2000
14 
15 #if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
16 	!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
17 #error "No suitable devicetree overlay specified"
18 #endif
19 
20 #define DT_SPEC_AND_COMMA(node_id, prop, idx) \
21 	ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
22 
23 /* Data of ADC io-channels specified in devicetree. */
24 static const struct adc_dt_spec adc_channels[] = {
25 	DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels,
26 			     DT_SPEC_AND_COMMA)
27 };
28 
main(void)29 int main(void)
30 {
31 	int err;
32 	uint32_t count = 0;
33 	uint16_t buf;
34 	struct adc_sequence sequence = {
35 		.buffer = &buf,
36 		/* buffer size in bytes, not number of samples */
37 		.buffer_size = sizeof(buf),
38 	};
39 
40 	/* Configure channels individually prior to sampling. */
41 	for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
42 		if (!adc_is_ready_dt(&adc_channels[i])) {
43 			printk("ADC controller device %s not ready\n", adc_channels[i].dev->name);
44 			return 0;
45 		}
46 
47 		err = adc_channel_setup_dt(&adc_channels[i]);
48 		if (err < 0) {
49 			printk("Could not setup channel #%d (%d)\n", i, err);
50 			return 0;
51 		}
52 	}
53 
54 	printk("Device ready\n");
55 
56 	while (true) {
57 		printk("ADC reading[%u]:\n", count++);
58 		for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
59 			int32_t val_mv;
60 
61 			printk("- %s, channel %d: ",
62 			       adc_channels[i].dev->name,
63 			       adc_channels[i].channel_id);
64 
65 			(void)adc_sequence_init_dt(&adc_channels[i], &sequence);
66 
67 			err = adc_read_dt(&adc_channels[i], &sequence);
68 			if (err < 0) {
69 				printk("Could not read (%d)\n", err);
70 				continue;
71 			}
72 
73 			/*
74 			 * If using differential mode, the 16 bit value
75 			 * in the ADC sample buffer should be a signed 2's
76 			 * complement value.
77 			 */
78 			if (adc_channels[i].channel_cfg.differential) {
79 				val_mv = (int32_t)((int16_t)buf);
80 			} else {
81 				val_mv = (int32_t)buf;
82 			}
83 			printk("%"PRId32, val_mv);
84 			err = adc_raw_to_millivolts_dt(&adc_channels[i],
85 						       &val_mv);
86 			/* conversion to mV may not be supported, skip if not */
87 			if (err < 0) {
88 				printk(" (value in mV not available)\n");
89 			} else {
90 				printk(" = %"PRId32" mV\n", val_mv);
91 			}
92 		}
93 
94 		k_msleep(SLEEP_TIME_MS);
95 	}
96 	return 0;
97 }
98