1 /*
2  * Copyright (c) 2024 Centro de Inovacao EDGE
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/adc.h>
8 #include <zephyr/kernel.h>
9 
10 /* ADC node from the devicetree. */
11 #define ADC_NODE DT_ALIAS(adc0)
12 
13 /* Auxiliary macro to obtain channel vref, if available. */
14 #define CHANNEL_VREF(node_id) DT_PROP_OR(node_id, zephyr_vref_mv, 0)
15 
16 /* Data of ADC device specified in devicetree. */
17 static const struct device *adc = DEVICE_DT_GET(ADC_NODE);
18 
19 /* Data array of ADC channels for the specified ADC. */
20 static const struct adc_channel_cfg channel_cfgs[] = {
21 	DT_FOREACH_CHILD_SEP(ADC_NODE, ADC_CHANNEL_CFG_DT, (,))};
22 
23 /* Data array of ADC channel voltage references. */
24 static uint32_t vrefs_mv[] = {DT_FOREACH_CHILD_SEP(ADC_NODE, CHANNEL_VREF, (,))};
25 
26 /* Get the number of channels defined on the DTS. */
27 #define CHANNEL_COUNT ARRAY_SIZE(channel_cfgs)
28 
main(void)29 int main(void)
30 {
31 	int err;
32 	uint32_t count = 0;
33 	uint16_t channel_reading[CONFIG_SEQUENCE_SAMPLES][CHANNEL_COUNT];
34 
35 	/* Options for the sequence sampling. */
36 	const struct adc_sequence_options options = {
37 		.extra_samplings = CONFIG_SEQUENCE_SAMPLES - 1,
38 		.interval_us = 0,
39 	};
40 
41 	/* Configure the sampling sequence to be made. */
42 	struct adc_sequence sequence = {
43 		.buffer = channel_reading,
44 		/* buffer size in bytes, not number of samples */
45 		.buffer_size = sizeof(channel_reading),
46 		.resolution = CONFIG_SEQUENCE_RESOLUTION,
47 		.options = &options,
48 	};
49 
50 	if (!device_is_ready(adc)) {
51 		printf("ADC controller device %s not ready\n", adc->name);
52 		return 0;
53 	}
54 
55 	/* Configure channels individually prior to sampling. */
56 	for (size_t i = 0U; i < CHANNEL_COUNT; i++) {
57 		sequence.channels |= BIT(channel_cfgs[i].channel_id);
58 		err = adc_channel_setup(adc, &channel_cfgs[i]);
59 		if (err < 0) {
60 			printf("Could not setup channel #%d (%d)\n", i, err);
61 			return 0;
62 		}
63 		if (channel_cfgs[i].reference == ADC_REF_INTERNAL) {
64 			vrefs_mv[i] = adc_ref_internal(adc);
65 		}
66 	}
67 
68 #ifndef CONFIG_COVERAGE
69 	while (1) {
70 #else
71 	for (int k = 0; k < 10; k++) {
72 #endif
73 		printf("ADC sequence reading [%u]:\n", count++);
74 		k_msleep(1000);
75 
76 		err = adc_read(adc, &sequence);
77 		if (err < 0) {
78 			printf("Could not read (%d)\n", err);
79 			continue;
80 		}
81 
82 		for (size_t channel_index = 0U; channel_index < CHANNEL_COUNT; channel_index++) {
83 			int32_t val_mv;
84 
85 			printf("- %s, channel %" PRId32 ", %" PRId32 " sequence samples:\n",
86 			       adc->name, channel_cfgs[channel_index].channel_id,
87 			       CONFIG_SEQUENCE_SAMPLES);
88 			for (size_t sample_index = 0U; sample_index < CONFIG_SEQUENCE_SAMPLES;
89 			     sample_index++) {
90 
91 				val_mv = channel_reading[sample_index][channel_index];
92 
93 				printf("- - %" PRId32, val_mv);
94 				err = adc_raw_to_millivolts(vrefs_mv[channel_index],
95 							    channel_cfgs[channel_index].gain,
96 							    CONFIG_SEQUENCE_RESOLUTION, &val_mv);
97 
98 				/* conversion to mV may not be supported, skip if not */
99 				if ((err < 0) || vrefs_mv[channel_index] == 0) {
100 					printf(" (value in mV not available)\n");
101 				} else {
102 					printf(" = %" PRId32 "mV\n", val_mv);
103 				}
104 			}
105 		}
106 	}
107 
108 	return 0;
109 }
110