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 #ifdef CONFIG_SEQUENCE_32BITS_REGISTERS
34 uint32_t channel_reading[CONFIG_SEQUENCE_SAMPLES][CHANNEL_COUNT];
35 #else
36 uint16_t channel_reading[CONFIG_SEQUENCE_SAMPLES][CHANNEL_COUNT];
37 #endif
38
39 /* Options for the sequence sampling. */
40 const struct adc_sequence_options options = {
41 .extra_samplings = CONFIG_SEQUENCE_SAMPLES - 1,
42 .interval_us = 0,
43 };
44
45 /* Configure the sampling sequence to be made. */
46 struct adc_sequence sequence = {
47 .buffer = channel_reading,
48 /* buffer size in bytes, not number of samples */
49 .buffer_size = sizeof(channel_reading),
50 .resolution = CONFIG_SEQUENCE_RESOLUTION,
51 .oversampling = CONFIG_SEQUENCE_OVERSAMPLING,
52 .options = &options,
53 };
54
55 if (!device_is_ready(adc)) {
56 printf("ADC controller device %s not ready\n", adc->name);
57 return 0;
58 }
59
60 /* Configure channels individually prior to sampling. */
61 for (size_t i = 0U; i < CHANNEL_COUNT; i++) {
62 sequence.channels |= BIT(channel_cfgs[i].channel_id);
63 err = adc_channel_setup(adc, &channel_cfgs[i]);
64 if (err < 0) {
65 printf("Could not setup channel #%d (%d)\n", i, err);
66 return 0;
67 }
68 if ((vrefs_mv[i] == 0) && (channel_cfgs[i].reference == ADC_REF_INTERNAL)) {
69 vrefs_mv[i] = adc_ref_internal(adc);
70 }
71 }
72
73 #ifndef CONFIG_COVERAGE
74 while (1) {
75 #else
76 for (int k = 0; k < 10; k++) {
77 #endif
78 printf("ADC sequence reading [%u]:\n", count++);
79 k_msleep(1000);
80
81 err = adc_read(adc, &sequence);
82 if (err < 0) {
83 printf("Could not read (%d)\n", err);
84 continue;
85 }
86
87 for (size_t channel_index = 0U; channel_index < CHANNEL_COUNT; channel_index++) {
88 int32_t val_mv;
89
90 printf("- %s, channel %" PRId32 ", %" PRId32 " sequence samples:\n",
91 adc->name, channel_cfgs[channel_index].channel_id,
92 CONFIG_SEQUENCE_SAMPLES);
93 for (size_t sample_index = 0U; sample_index < CONFIG_SEQUENCE_SAMPLES;
94 sample_index++) {
95 uint8_t res = CONFIG_SEQUENCE_RESOLUTION;
96
97 /*
98 * If using differential mode, the 16/32 bit value
99 * in the ADC sample buffer should be a signed 2's
100 * complement value.
101 * Also reduce the resolution by 1 for the conversion
102 */
103 if (channel_cfgs[channel_index].differential) {
104 #ifdef CONFIG_SEQUENCE_32BITS_REGISTERS
105 val_mv = (int32_t)
106 channel_reading[sample_index][channel_index];
107 #else
108 val_mv = (int32_t)((int16_t)channel_reading[sample_index]
109 [channel_index]);
110 #endif
111 res -= 1;
112 } else {
113 val_mv = channel_reading[sample_index][channel_index];
114 }
115 printf("- - %" PRId32, val_mv);
116 err = adc_raw_to_millivolts(vrefs_mv[channel_index],
117 channel_cfgs[channel_index].gain,
118 res, &val_mv);
119
120 /* conversion to mV may not be supported, skip if not */
121 if ((err < 0) || vrefs_mv[channel_index] == 0) {
122 printf(" (value in mV not available)\n");
123 } else {
124 printf(" = %" PRId32 "mV\n", val_mv);
125 }
126 }
127 }
128 }
129
130 return 0;
131 }
132