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