1 /*
2  * Copyright (c) 2018 Prevas A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/shell/shell.h>
8 #include <stdlib.h>
9 #include <zephyr/drivers/adc.h>
10 #include <ctype.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/devicetree.h>
13 
14 
15 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(adc_shell);
18 
19 #define CMD_HELP_ACQ_TIME 			\
20 	"Configure acquisition time."		\
21 	"\nUsage: acq_time <time> <unit>"	\
22 	"\nunits: us, ns, ticks\n"
23 
24 #define CMD_HELP_CHANNEL			\
25 	"Configure ADC channel\n"		\
26 
27 #define CMD_HELP_CH_ID				\
28 	"Configure channel id\n"		\
29 	"Usage: id <channel_id>\n"
30 
31 #define CMD_HELP_DIFF				\
32 	"Configure differential\n"		\
33 	"Usage: differential <0||1>\n"
34 
35 #define CMD_HELP_CH_NEG				\
36 	"Configure channel negative input\n"	\
37 	"Usage: negative <negative_input_id>\n"
38 
39 #define CMD_HELP_CH_POS				\
40 	"Configure channel positive input\n"	\
41 	"Usage: positive <positive_input_id>\n"
42 
43 #define CMD_HELP_READ				\
44 	"Read adc value\n"			\
45 	"Usage: read <channel>\n"
46 
47 #define CMD_HELP_RES				\
48 	"Configure resolution\n"		\
49 	"Usage: resolution <resolution>\n"
50 
51 #define CMD_HELP_REF	"Configure reference\n"
52 #define CMD_HELP_GAIN	"Configure gain.\n"
53 #define CMD_HELP_PRINT	"Print current configuration"
54 
55 #define ADC_HDL_LIST_ENTRY(node_id)                                                                \
56 	{                                                                                          \
57 		.dev = DEVICE_DT_GET(node_id),                                                     \
58 		.channel_config =                                                                  \
59 			{                                                                          \
60 				.gain = ADC_GAIN_1,                                                \
61 				.reference = ADC_REF_INTERNAL,                                     \
62 				.acquisition_time = ADC_ACQ_TIME_DEFAULT,                          \
63 				.channel_id = 0,                                                   \
64 			},                                                                         \
65 		.resolution = 0,                                                                   \
66 	},
67 
68 #define CHOSEN_STR_LEN 20
69 static char chosen_reference[CHOSEN_STR_LEN + 1] = "INTERNAL";
70 static char chosen_gain[CHOSEN_STR_LEN + 1] = "1";
71 
72 static struct adc_hdl {
73 	const struct device *dev;
74 	struct adc_channel_cfg channel_config;
75 	uint8_t resolution;
76 } adc_list[] = {
77 	/* zephyr-keep-sorted-start */
78 	DT_FOREACH_STATUS_OKAY(adi_ad4114_adc, ADC_HDL_LIST_ENTRY)
79 	DT_FOREACH_STATUS_OKAY(adi_ad559x_adc, ADC_HDL_LIST_ENTRY)
80 	DT_FOREACH_STATUS_OKAY(adi_ad7124_adc, ADC_HDL_LIST_ENTRY)
81 	DT_FOREACH_STATUS_OKAY(atmel_sam0_adc, ADC_HDL_LIST_ENTRY)
82 	DT_FOREACH_STATUS_OKAY(atmel_sam_adc, ADC_HDL_LIST_ENTRY)
83 	DT_FOREACH_STATUS_OKAY(atmel_sam_afec, ADC_HDL_LIST_ENTRY)
84 	DT_FOREACH_STATUS_OKAY(espressif_esp32_adc, ADC_HDL_LIST_ENTRY)
85 	DT_FOREACH_STATUS_OKAY(gd_gd32_adc, ADC_HDL_LIST_ENTRY)
86 	DT_FOREACH_STATUS_OKAY(infineon_cat1_adc, ADC_HDL_LIST_ENTRY)
87 	DT_FOREACH_STATUS_OKAY(infineon_xmc4xxx_adc, ADC_HDL_LIST_ENTRY)
88 	DT_FOREACH_STATUS_OKAY(ite_it51xxx_adc, ADC_HDL_LIST_ENTRY)
89 	DT_FOREACH_STATUS_OKAY(ite_it8xxx2_adc, ADC_HDL_LIST_ENTRY)
90 	DT_FOREACH_STATUS_OKAY(lltc_ltc2451, ADC_HDL_LIST_ENTRY)
91 	DT_FOREACH_STATUS_OKAY(maxim_max11102, ADC_HDL_LIST_ENTRY)
92 	DT_FOREACH_STATUS_OKAY(maxim_max11103, ADC_HDL_LIST_ENTRY)
93 	DT_FOREACH_STATUS_OKAY(maxim_max11105, ADC_HDL_LIST_ENTRY)
94 	DT_FOREACH_STATUS_OKAY(maxim_max11106, ADC_HDL_LIST_ENTRY)
95 	DT_FOREACH_STATUS_OKAY(maxim_max11110, ADC_HDL_LIST_ENTRY)
96 	DT_FOREACH_STATUS_OKAY(maxim_max11111, ADC_HDL_LIST_ENTRY)
97 	DT_FOREACH_STATUS_OKAY(maxim_max11115, ADC_HDL_LIST_ENTRY)
98 	DT_FOREACH_STATUS_OKAY(maxim_max11116, ADC_HDL_LIST_ENTRY)
99 	DT_FOREACH_STATUS_OKAY(maxim_max11117, ADC_HDL_LIST_ENTRY)
100 	DT_FOREACH_STATUS_OKAY(maxim_max11253, ADC_HDL_LIST_ENTRY)
101 	DT_FOREACH_STATUS_OKAY(maxim_max11254, ADC_HDL_LIST_ENTRY)
102 	DT_FOREACH_STATUS_OKAY(microchip_mcp3204, ADC_HDL_LIST_ENTRY)
103 	DT_FOREACH_STATUS_OKAY(microchip_mcp3208, ADC_HDL_LIST_ENTRY)
104 	DT_FOREACH_STATUS_OKAY(microchip_xec_adc, ADC_HDL_LIST_ENTRY)
105 	DT_FOREACH_STATUS_OKAY(nordic_nrf_adc, ADC_HDL_LIST_ENTRY)
106 	DT_FOREACH_STATUS_OKAY(nordic_nrf_saadc, ADC_HDL_LIST_ENTRY)
107 	DT_FOREACH_STATUS_OKAY(nuvoton_npcx_adc, ADC_HDL_LIST_ENTRY)
108 	DT_FOREACH_STATUS_OKAY(nuvoton_numaker_adc, ADC_HDL_LIST_ENTRY)
109 	DT_FOREACH_STATUS_OKAY(nxp_adc12, ADC_HDL_LIST_ENTRY)
110 	DT_FOREACH_STATUS_OKAY(nxp_gau_adc, ADC_HDL_LIST_ENTRY)
111 	DT_FOREACH_STATUS_OKAY(nxp_kinetis_adc16, ADC_HDL_LIST_ENTRY)
112 	DT_FOREACH_STATUS_OKAY(nxp_lpc_lpadc, ADC_HDL_LIST_ENTRY)
113 	DT_FOREACH_STATUS_OKAY(nxp_mcux_12b1msps_sar, ADC_HDL_LIST_ENTRY)
114 	DT_FOREACH_STATUS_OKAY(nxp_s32_adc_sar, ADC_HDL_LIST_ENTRY)
115 	DT_FOREACH_STATUS_OKAY(nxp_vf610_adc, ADC_HDL_LIST_ENTRY)
116 	DT_FOREACH_STATUS_OKAY(raspberrypi_pico_adc, ADC_HDL_LIST_ENTRY)
117 	DT_FOREACH_STATUS_OKAY(renesas_smartbond_adc, ADC_HDL_LIST_ENTRY)
118 	DT_FOREACH_STATUS_OKAY(renesas_smartbond_sdadc, ADC_HDL_LIST_ENTRY)
119 	DT_FOREACH_STATUS_OKAY(silabs_gecko_adc, ADC_HDL_LIST_ENTRY)
120 	DT_FOREACH_STATUS_OKAY(silabs_gecko_iadc, ADC_HDL_LIST_ENTRY)
121 	DT_FOREACH_STATUS_OKAY(st_stm32_adc, ADC_HDL_LIST_ENTRY)
122 	DT_FOREACH_STATUS_OKAY(st_stm32f1_adc, ADC_HDL_LIST_ENTRY)
123 	DT_FOREACH_STATUS_OKAY(st_stm32f4_adc, ADC_HDL_LIST_ENTRY)
124 	DT_FOREACH_STATUS_OKAY(telink_b91_adc, ADC_HDL_LIST_ENTRY)
125 	DT_FOREACH_STATUS_OKAY(ti_ads1013, ADC_HDL_LIST_ENTRY)
126 	DT_FOREACH_STATUS_OKAY(ti_ads1014, ADC_HDL_LIST_ENTRY)
127 	DT_FOREACH_STATUS_OKAY(ti_ads1015, ADC_HDL_LIST_ENTRY)
128 	DT_FOREACH_STATUS_OKAY(ti_ads1112, ADC_HDL_LIST_ENTRY)
129 	DT_FOREACH_STATUS_OKAY(ti_ads1113, ADC_HDL_LIST_ENTRY)
130 	DT_FOREACH_STATUS_OKAY(ti_ads1114, ADC_HDL_LIST_ENTRY)
131 	DT_FOREACH_STATUS_OKAY(ti_ads1115, ADC_HDL_LIST_ENTRY)
132 	DT_FOREACH_STATUS_OKAY(ti_ads1119, ADC_HDL_LIST_ENTRY)
133 	DT_FOREACH_STATUS_OKAY(ti_ads114s08, ADC_HDL_LIST_ENTRY)
134 	DT_FOREACH_STATUS_OKAY(ti_ads7052, ADC_HDL_LIST_ENTRY)
135 	DT_FOREACH_STATUS_OKAY(ti_cc13xx_cc26xx_adc, ADC_HDL_LIST_ENTRY)
136 	DT_FOREACH_STATUS_OKAY(ti_cc32xx_adc, ADC_HDL_LIST_ENTRY)
137 	DT_FOREACH_STATUS_OKAY(ti_lmp90077, ADC_HDL_LIST_ENTRY)
138 	DT_FOREACH_STATUS_OKAY(ti_lmp90078, ADC_HDL_LIST_ENTRY)
139 	DT_FOREACH_STATUS_OKAY(ti_lmp90079, ADC_HDL_LIST_ENTRY)
140 	DT_FOREACH_STATUS_OKAY(ti_lmp90080, ADC_HDL_LIST_ENTRY)
141 	DT_FOREACH_STATUS_OKAY(ti_lmp90097, ADC_HDL_LIST_ENTRY)
142 	DT_FOREACH_STATUS_OKAY(ti_lmp90098, ADC_HDL_LIST_ENTRY)
143 	DT_FOREACH_STATUS_OKAY(ti_lmp90099, ADC_HDL_LIST_ENTRY)
144 	DT_FOREACH_STATUS_OKAY(ti_lmp90100, ADC_HDL_LIST_ENTRY)
145 	DT_FOREACH_STATUS_OKAY(ti_tla2021, ADC_HDL_LIST_ENTRY)
146 	DT_FOREACH_STATUS_OKAY(ti_tla2022, ADC_HDL_LIST_ENTRY)
147 	DT_FOREACH_STATUS_OKAY(ti_tla2024, ADC_HDL_LIST_ENTRY)
148 	DT_FOREACH_STATUS_OKAY(zephyr_adc_emul, ADC_HDL_LIST_ENTRY)
149 	/* zephyr-keep-sorted-stop */
150 };
151 
get_adc(const char * device_label)152 static struct adc_hdl *get_adc(const char *device_label)
153 {
154 	for (int i = 0; i < ARRAY_SIZE(adc_list); i++) {
155 		if (!strcmp(device_label, adc_list[i].dev->name)) {
156 			return &adc_list[i];
157 		}
158 	}
159 
160 	/* This will never happen because ADC was prompted by shell */
161 	__ASSERT_NO_MSG(false);
162 	return NULL;
163 }
164 
cmd_adc_ch_id(const struct shell * sh,size_t argc,char ** argv)165 static int cmd_adc_ch_id(const struct shell *sh, size_t argc, char **argv)
166 {
167 	/* -2: index of ADC label name */
168 	struct adc_hdl *adc = get_adc(argv[-2]);
169 	int retval = 0;
170 
171 	if (!device_is_ready(adc->dev)) {
172 		shell_error(sh, "ADC device not ready");
173 		return -ENODEV;
174 	}
175 
176 	if (isdigit((unsigned char)argv[1][0]) == 0) {
177 		shell_error(sh, "<channel> must be digits");
178 		return -EINVAL;
179 	}
180 
181 	adc->channel_config.channel_id = (uint8_t)strtol(argv[1], NULL, 10);
182 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
183 	LOG_DBG("Channel setup returned %i", retval);
184 
185 	return retval;
186 }
187 
cmd_adc_ch_diff(const struct shell * sh,size_t argc,char ** argv)188 static int cmd_adc_ch_diff(const struct shell *sh, size_t argc, char **argv)
189 {
190 	/* -2: index of ADC label name */
191 	struct adc_hdl *adc = get_adc(argv[-2]);
192 	int retval = 0;
193 	char *endptr;
194 	long diff;
195 
196 	if (!device_is_ready(adc->dev)) {
197 		shell_error(sh, "ADC device not ready");
198 		return -ENODEV;
199 	}
200 
201 	endptr = argv[1];
202 	diff = strtol(argv[1], &endptr, 10);
203 	if ((endptr == argv[1]) || ((diff != 0) && (diff != 1))) {
204 		shell_error(sh, "<differential> must be 0 or 1");
205 		return -EINVAL;
206 	}
207 
208 	adc->channel_config.differential = (uint8_t)diff;
209 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
210 	LOG_DBG("Channel setup returned %i", retval);
211 
212 	return retval;
213 }
214 
cmd_adc_ch_neg(const struct shell * sh,size_t argc,char ** argv)215 static int cmd_adc_ch_neg(const struct shell *sh, size_t argc, char **argv)
216 {
217 #if CONFIG_ADC_CONFIGURABLE_INPUTS
218 	/* -2: index of ADC label name */
219 	struct adc_hdl *adc = get_adc(argv[-2]);
220 	int retval = 0;
221 
222 	if (!device_is_ready(adc->dev)) {
223 		shell_error(sh, "ADC device not ready");
224 		return -ENODEV;
225 	}
226 
227 	if (isdigit((unsigned char)argv[1][0]) == 0) {
228 		shell_error(sh, "<negative input> must be digits");
229 		return -EINVAL;
230 	}
231 
232 	adc->channel_config.input_negative = (uint8_t)strtol(argv[1], NULL, 10);
233 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
234 	LOG_DBG("Channel setup returned %i", retval);
235 
236 	return retval;
237 #else
238 	return -EINVAL;
239 #endif
240 }
241 
cmd_adc_ch_pos(const struct shell * sh,size_t argc,char ** argv)242 static int cmd_adc_ch_pos(const struct shell *sh, size_t argc, char **argv)
243 {
244 #if CONFIG_ADC_CONFIGURABLE_INPUTS
245 	/* -2: index of ADC label name */
246 	struct adc_hdl *adc = get_adc(argv[-2]);
247 	int retval = 0;
248 
249 	if (!device_is_ready(adc->dev)) {
250 		shell_error(sh, "ADC device not ready");
251 		return -ENODEV;
252 	}
253 
254 	if (isdigit((unsigned char)argv[1][0]) == 0) {
255 		shell_error(sh, "<positive input> must be digits");
256 		return -EINVAL;
257 	}
258 
259 	adc->channel_config.input_positive = (uint8_t)strtol(argv[1], NULL, 10);
260 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
261 	LOG_DBG("Channel setup returned %i", retval);
262 
263 	return retval;
264 #else
265 	return -EINVAL;
266 #endif
267 }
268 
cmd_adc_gain(const struct shell * sh,size_t argc,char ** argv,void * data)269 static int cmd_adc_gain(const struct shell *sh, size_t argc, char **argv,
270 			void *data)
271 {
272 	/* -2: index of ADC label name */
273 	struct adc_hdl *adc = get_adc(argv[-2]);
274 	enum adc_gain gain = (enum adc_gain)data;
275 	int retval = -EINVAL;
276 
277 	if (!device_is_ready(adc->dev)) {
278 		shell_error(sh, "ADC device not ready");
279 		return -ENODEV;
280 	}
281 
282 	adc->channel_config.gain = gain;
283 	int len = strlen(argv[0]) > CHOSEN_STR_LEN ? CHOSEN_STR_LEN
284 						   : strlen(argv[0]);
285 	memcpy(chosen_gain, argv[0], len);
286 	chosen_gain[len] = '\0';
287 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
288 	LOG_DBG("Channel setup returned %i", retval);
289 
290 	return retval;
291 }
292 
cmd_adc_acq(const struct shell * sh,size_t argc,char ** argv)293 static int cmd_adc_acq(const struct shell *sh, size_t argc, char **argv)
294 {
295 	/* -1 index of ADC label name */
296 	struct adc_hdl *adc = get_adc(argv[-1]);
297 	uint16_t acq_time;
298 	int retval;
299 
300 	if (!device_is_ready(adc->dev)) {
301 		shell_error(sh, "ADC device not ready");
302 		return -ENODEV;
303 	}
304 
305 	if (isdigit((unsigned char)argv[1][0]) == 0) {
306 		shell_error(sh, "<time> must be digits");
307 		return -EINVAL;
308 	}
309 
310 	acq_time = (uint16_t)strtol(argv[1], NULL, 10);
311 	if (!strcmp(argv[2], "us")) {
312 		adc->channel_config.acquisition_time =
313 			ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, acq_time);
314 	} else if (!strcmp(argv[2], "ns")) {
315 		adc->channel_config.acquisition_time =
316 			ADC_ACQ_TIME(ADC_ACQ_TIME_NANOSECONDS, acq_time);
317 	} else if (!strcmp(argv[2], "ticks")) {
318 		adc->channel_config.acquisition_time =
319 			ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS, acq_time);
320 	} else {
321 		adc->channel_config.acquisition_time =
322 			ADC_ACQ_TIME_DEFAULT;
323 	}
324 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
325 	LOG_DBG("Channel setup returned %i", retval);
326 
327 	return retval;
328 }
cmd_adc_reso(const struct shell * sh,size_t argc,char ** argv)329 static int cmd_adc_reso(const struct shell *sh, size_t argc, char **argv)
330 {
331 	/* -1 index of ADC label name */
332 	struct adc_hdl *adc = get_adc(argv[-1]);
333 	int retval;
334 
335 	if (!device_is_ready(adc->dev)) {
336 		shell_error(sh, "ADC device not ready");
337 		return -ENODEV;
338 	}
339 
340 	if (isdigit((unsigned char)argv[1][0]) == 0) {
341 		shell_error(sh, "<resolution> must be digits");
342 		return -EINVAL;
343 	}
344 
345 	adc->resolution = (uint8_t)strtol(argv[1], NULL, 10);
346 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
347 
348 	return retval;
349 }
350 
cmd_adc_ref(const struct shell * sh,size_t argc,char ** argv,void * data)351 static int cmd_adc_ref(const struct shell *sh, size_t argc, char **argv,
352 		       void *data)
353 {
354 	/* -2 index of ADC label name */
355 	struct adc_hdl *adc = get_adc(argv[-2]);
356 	enum adc_reference reference = (enum adc_reference)data;
357 	int retval = -EINVAL;
358 
359 	if (!device_is_ready(adc->dev)) {
360 		shell_error(sh, "ADC device not ready");
361 		return -ENODEV;
362 	}
363 
364 	int len = strlen(argv[0]) > CHOSEN_STR_LEN ? CHOSEN_STR_LEN
365 						   : strlen(argv[0]);
366 	memcpy(chosen_reference, argv[0], len);
367 	chosen_reference[len] = '\0';
368 
369 	adc->channel_config.reference = reference;
370 	retval = adc_channel_setup(adc->dev, &adc->channel_config);
371 	LOG_DBG("Channel setup returned %i", retval);
372 
373 	return retval;
374 }
375 
376 #define BUFFER_SIZE 1
cmd_adc_read(const struct shell * sh,size_t argc,char ** argv)377 static int cmd_adc_read(const struct shell *sh, size_t argc, char **argv)
378 {
379 	uint8_t adc_channel_id = strtol(argv[1], NULL, 10);
380 	/* -1 index of adc label name */
381 	struct adc_hdl *adc = get_adc(argv[-1]);
382 	int16_t m_sample_buffer[BUFFER_SIZE];
383 	int retval;
384 
385 	if (!device_is_ready(adc->dev)) {
386 		shell_error(sh, "ADC device not ready");
387 		return -ENODEV;
388 	}
389 
390 	adc->channel_config.channel_id = adc_channel_id;
391 	const struct adc_sequence sequence = {
392 		.channels	= BIT(adc->channel_config.channel_id),
393 		.buffer		= m_sample_buffer,
394 		.buffer_size	= sizeof(m_sample_buffer),
395 		.resolution	= adc->resolution,
396 	};
397 
398 	retval = adc_read(adc->dev, &sequence);
399 	if (retval >= 0) {
400 		shell_print(sh, "read: %i", m_sample_buffer[0]);
401 	}
402 
403 	return retval;
404 }
405 
cmd_adc_print(const struct shell * sh,size_t argc,char ** argv)406 static int cmd_adc_print(const struct shell *sh, size_t argc, char **argv)
407 {
408 	/* -1 index of ADC label name */
409 	struct adc_hdl *adc = get_adc(argv[-1]);
410 
411 	shell_print(sh, "%s:\n"
412 			   "Gain: %s\n"
413 			   "Reference: %s\n"
414 			   "Acquisition Time: %u\n"
415 			   "Channel ID: %u\n"
416 			   "Differential: %u\n"
417 			   "Resolution: %u",
418 			   adc->dev->name,
419 			   chosen_gain,
420 			   chosen_reference,
421 			   adc->channel_config.acquisition_time,
422 			   adc->channel_config.channel_id,
423 			   adc->channel_config.differential,
424 			   adc->resolution);
425 #if CONFIG_ADC_CONFIGURABLE_INPUTS
426 	shell_print(sh, "Input positive: %u",
427 		    adc->channel_config.input_positive);
428 	if (adc->channel_config.differential != 0) {
429 		shell_print(sh, "Input negative: %u",
430 			    adc->channel_config.input_negative);
431 	}
432 #endif
433 	return 0;
434 }
435 
436 SHELL_SUBCMD_DICT_SET_CREATE(sub_ref_cmds, cmd_adc_ref,
437 	(VDD_1, ADC_REF_VDD_1, "VDD"),
438 	(VDD_1_2, ADC_REF_VDD_1_2, "VDD/2"),
439 	(VDD_1_3, ADC_REF_VDD_1_3, "VDD/3"),
440 	(VDD_1_4, ADC_REF_VDD_1_4, "VDD/4"),
441 	(INTERNAL, ADC_REF_INTERNAL, "Internal"),
442 	(EXTERNAL_0, ADC_REF_EXTERNAL0, "External, input 0"),
443 	(EXTERNAL_1, ADC_REF_EXTERNAL1, "External, input 1")
444 );
445 
446 SHELL_SUBCMD_DICT_SET_CREATE(sub_gain_cmds, cmd_adc_gain,
447 	(GAIN_1_6, ADC_GAIN_1_6, "x 1/6"),
448 	(GAIN_1_5, ADC_GAIN_1_5, "x 1/5"),
449 	(GAIN_1_4, ADC_GAIN_1_4, "x 1/4"),
450 	(GAIN_1_3, ADC_GAIN_1_3, "x 1/3"),
451 	(GAIN_1_2, ADC_GAIN_1_2, "x 1/2"),
452 	(GAIN_2_3, ADC_GAIN_2_3, "x 2/3"),
453 	(GAIN_1, ADC_GAIN_1, "x 1"),
454 	(GAIN_2, ADC_GAIN_2, "x 2"),
455 	(GAIN_3, ADC_GAIN_3, "x 3"),
456 	(GAIN_4, ADC_GAIN_4, "x 4"),
457 	(GAIN_8, ADC_GAIN_8, "x 8"),
458 	(GAIN_16, ADC_GAIN_16, "x 16"),
459 	(GAIN_32, ADC_GAIN_32, "x 32"),
460 	(GAIN_64, ADC_GAIN_64, "x 64")
461 );
462 
463 SHELL_STATIC_SUBCMD_SET_CREATE(sub_channel_cmds,
464 	SHELL_CMD_ARG(id, NULL, CMD_HELP_CH_ID, cmd_adc_ch_id, 2, 0),
465 	SHELL_CMD_ARG(differential, NULL, CMD_HELP_DIFF, cmd_adc_ch_diff, 2, 0),
466 	SHELL_COND_CMD_ARG(CONFIG_ADC_CONFIGURABLE_INPUTS,
467 		negative, NULL, CMD_HELP_CH_NEG, cmd_adc_ch_neg, 2, 0),
468 	SHELL_COND_CMD_ARG(CONFIG_ADC_CONFIGURABLE_INPUTS,
469 		positive, NULL, CMD_HELP_CH_POS, cmd_adc_ch_pos, 2, 0),
470 	SHELL_SUBCMD_SET_END
471 );
472 
473 SHELL_STATIC_SUBCMD_SET_CREATE(sub_adc_cmds,
474 	/* Alphabetically sorted. */
475 	SHELL_CMD_ARG(acq_time, NULL, CMD_HELP_ACQ_TIME, cmd_adc_acq, 3, 0),
476 	SHELL_CMD_ARG(channel, &sub_channel_cmds, CMD_HELP_CHANNEL, NULL, 3, 0),
477 	SHELL_CMD(gain, &sub_gain_cmds, CMD_HELP_GAIN, NULL),
478 	SHELL_CMD_ARG(print, NULL, CMD_HELP_PRINT, cmd_adc_print, 1, 0),
479 	SHELL_CMD_ARG(read, NULL, CMD_HELP_READ, cmd_adc_read, 2, 0),
480 	SHELL_CMD(reference, &sub_ref_cmds, CMD_HELP_REF, NULL),
481 	SHELL_CMD_ARG(resolution, NULL, CMD_HELP_RES, cmd_adc_reso, 2, 0),
482 	SHELL_SUBCMD_SET_END /* Array terminated. */
483 );
484 
cmd_adc_dev_get(size_t idx,struct shell_static_entry * entry)485 static void cmd_adc_dev_get(size_t idx, struct shell_static_entry *entry)
486 {
487 	if (idx < ARRAY_SIZE(adc_list)) {
488 		entry->syntax  = adc_list[idx].dev->name;
489 		entry->handler = NULL;
490 		entry->subcmd  = &sub_adc_cmds;
491 		entry->help    = "Select subcommand for ADC property label.";
492 	} else {
493 		entry->syntax  = NULL;
494 	}
495 }
496 SHELL_DYNAMIC_CMD_CREATE(sub_adc_dev, cmd_adc_dev_get);
497 
498 SHELL_CMD_REGISTER(adc, &sub_adc_dev, "ADC commands", NULL);
499