1 /*
2  * Copyright (c) 2020 Henrik Brix Andersen <henrik@brixandersen.dk>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief DAC shell commands.
10  */
11 
12 #include <zephyr/shell/shell.h>
13 #include <zephyr/drivers/dac.h>
14 #include <stdlib.h>
15 
16 struct args_index {
17 	uint8_t device;
18 	uint8_t channel;
19 	uint8_t value;
20 	uint8_t resolution;
21 	uint8_t options;
22 };
23 
24 static const struct args_index args_indx = {
25 	.device = 1,
26 	.channel = 2,
27 	.value = 3,
28 	.resolution = 3,
29 	.options = 4,
30 };
31 
cmd_setup(const struct shell * sh,size_t argc,char ** argv)32 static int cmd_setup(const struct shell *sh, size_t argc, char **argv)
33 {
34 	struct dac_channel_cfg cfg = {0};
35 	const struct device *dac;
36 	int argidx;
37 	int err;
38 
39 	dac = shell_device_get_binding(argv[args_indx.device]);
40 	if (!dac) {
41 		shell_error(sh, "DAC device not found");
42 		return -EINVAL;
43 	}
44 
45 	cfg.channel_id = strtoul(argv[args_indx.channel], NULL, 0);
46 	cfg.resolution = strtoul(argv[args_indx.resolution], NULL, 0);
47 
48 	argidx = args_indx.options;
49 	while (argidx < argc && strncmp(argv[argidx], "-", 1) == 0) {
50 		if (strcmp(argv[argidx], "-b") == 0) {
51 			cfg.buffered = true;
52 			argidx++;
53 		} else if (strcmp(argv[argidx], "-i") == 0) {
54 			cfg.internal = true;
55 			argidx++;
56 		} else {
57 			shell_error(sh, "unsupported option %s", argv[argidx]);
58 			shell_help(sh);
59 			return SHELL_CMD_HELP_PRINTED;
60 		}
61 	}
62 
63 	err = dac_channel_setup(dac, &cfg);
64 	if (err) {
65 		shell_error(sh, "Failed to setup DAC channel (err %d)", err);
66 		return err;
67 	}
68 
69 	return 0;
70 }
71 
cmd_write_value(const struct shell * sh,size_t argc,char ** argv)72 static int cmd_write_value(const struct shell *sh, size_t argc, char **argv)
73 {
74 	const struct device *dac;
75 	uint8_t channel;
76 	uint32_t value;
77 	int err;
78 
79 	dac = shell_device_get_binding(argv[args_indx.device]);
80 	if (!dac) {
81 		shell_error(sh, "DAC device not found");
82 		return -EINVAL;
83 	}
84 
85 	channel = strtoul(argv[args_indx.channel], NULL, 0);
86 	value = strtoul(argv[args_indx.value], NULL, 0);
87 
88 	err = dac_write_value(dac, channel, value);
89 	if (err) {
90 		shell_error(sh, "Failed to write DAC value (err %d)", err);
91 		return err;
92 	}
93 
94 	return 0;
95 }
96 
device_is_dac(const struct device * dev)97 static bool device_is_dac(const struct device *dev)
98 {
99 	return DEVICE_API_IS(dac, dev);
100 }
101 
device_name_get(size_t idx,struct shell_static_entry * entry)102 static void device_name_get(size_t idx, struct shell_static_entry *entry)
103 {
104 	const struct device *dev = shell_device_filter(idx, device_is_dac);
105 
106 	entry->syntax = (dev != NULL) ? dev->name : NULL;
107 	entry->handler = NULL;
108 	entry->help = NULL;
109 	entry->subcmd = NULL;
110 }
111 
112 SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
113 
114 SHELL_STATIC_SUBCMD_SET_CREATE(dac_cmds,
115 	SHELL_CMD_ARG(setup, &dsub_device_name,
116 		      SHELL_HELP("Setup DAC channel", "<device> <channel> <resolution> [-b] [-i]\n"
117 						      "-b Enable output buffer\n"
118 						      "-i Connect internally"),
119 		      cmd_setup, 4, 2),
120 	SHELL_CMD_ARG(write_value, &dsub_device_name,
121 		      SHELL_HELP("Write DAC value", "<device> <channel> <value>"), cmd_write_value,
122 		      4, 0),
123 	SHELL_SUBCMD_SET_END
124 );
125 
126 SHELL_CMD_REGISTER(dac, &dac_cmds, "DAC shell commands", NULL);
127