]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_gpio.c
clean up includes
[z180-stamp.git] / avr / cmd_gpio.c
1 /*
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7 #include "cmd_gpio.h"
8 #include "print-utils.h"
9 #include "getopt-min.h"
10 #include "env.h"
11 #include "gpio.h"
12 //#include "debug.h"
13
14
15 static uint_fast8_t pinnames_get(char *pin_names[GPIO_MAX+1])
16 {
17 static const FLASH char delim1[] = {":= "};
18 static const FLASH char delim2[] = {", "};
19 uint_fast8_t width = 0;
20 char *lp;
21 uint_fast8_t i;
22
23 memset(pin_names, 0, (GPIO_MAX+1) * sizeof(char *));
24
25 /* TODO: enters endless loop on wrong parameters */
26
27 lp = getenv_str(PSTR(ENV_PINALIAS));
28 if (lp != NULL) {
29 pin_names[GPIO_MAX] = strdup(lp);
30 if (pin_names[GPIO_MAX] != NULL) {
31 char *ptr = strtok_P(pin_names[GPIO_MAX], delim1);
32 while (ptr != NULL) {
33 if (((i = strtoul(ptr, &lp, 10)) < GPIO_MAX) &&
34 lp != ptr &&
35 (ptr = strtok_P(NULL, delim2)) != NULL ) {
36 pin_names[i] = ptr;
37 ptr = strtok_P(NULL, delim1);
38 }
39 }
40
41 for (i = 0; i < GPIO_MAX; i++)
42 if (strlen(pin_names[i]) > width)
43 width = strlen(pin_names[i]);
44 }
45 }
46 return width;
47 }
48
49
50 static size_t xstrlen(char *s)
51 {
52 if (s == NULL)
53 return 0;
54 else
55 return strlen(s);
56 }
57
58 static const FLASH char * const FLASH pinconf_str[] = {
59 FSTR("?"),
60 FSTR("Input"),
61 FSTR("Pullup"),
62 FSTR("Output"),
63 FSTR("Clock"),
64 };
65
66 static const FLASH char * const FLASH pinlevel_str[] = {
67 FSTR("Low"),
68 FSTR("High"),
69 FSTR(""),
70 };
71
72 static void print_pin(uint8_t pin, uint_fast8_t multi, char *pin_names[], uint_fast8_t pn_width)
73 {
74 gpiomode_t pinconf;
75 const FLASH char *levelp;
76 long div;
77
78 pinconf = gpio_config_get(pin);
79 if (pinconf == OUTPUT_TIMER) {
80 div = gpio_clockdiv_get(pin);
81 levelp = pinlevel_str[2];
82 } else
83 levelp = pinlevel_str[gpio_read(pin)];
84
85 if (multi) {
86 printf_P(PSTR("%3d "), pin);
87 if (pn_width) {
88 printf_P(PSTR("%s "), pin_names[pin]);
89 print_blanks(pn_width - xstrlen(pin_names[pin]));
90 }
91 my_puts_P(pinconf_str[pinconf]);
92 print_blanks(7 - strlen_P(pinconf_str[pinconf]));
93 my_puts_P(levelp);
94 print_blanks(5 - strlen_P(levelp));
95 if (pinconf == OUTPUT_TIMER)
96 printf_P(PSTR("%8ld %8ld"),
97 div, F_CPU/div);
98 } else {
99 printf_P(PSTR("%d: \"%s\", "), pin, pin_names[pin] ? pin_names[pin] : 0);
100 my_puts_P(pinconf_str[pinconf]);
101 my_puts_P(PSTR(", "));
102 my_puts_P(levelp);
103
104 if (pinconf == OUTPUT_TIMER)
105 printf_P(PSTR("divide by %ld (%ldHz)"),
106 div, F_CPU/div);
107 }
108 my_puts_P(PSTR("\n"));
109 }
110
111 static int_fast8_t pinarg_insert(uint8_t pin, uint_fast8_t count, uint_fast8_t pinarg[])
112 {
113 uint_fast8_t pos;
114
115 if (pin >= GPIO_MAX)
116 return -1;
117
118 for (pos = 0; pos < count; pos++) {
119 if (pin == pinarg[pos])
120 return 0;
121 if (pin < pinarg[pos])
122 break;
123 }
124 for (uint_fast8_t i = count-1; i == pos ; i--)
125 pinarg[i+1] = pinarg[i];
126 pinarg[pos] = pin;
127
128 return 1;
129 }
130
131 static uint_fast8_t pinarg_get(char * arg, uint_fast8_t pinarg[])
132 {
133 char *endp;
134 uint_fast8_t pin1;
135 int_fast8_t rc;
136 uint_fast8_t count = 0;
137
138 while (1) {
139 pin1 = strtoul(arg, &endp, 10);
140 if (endp != arg && *endp == '-') {
141 arg = endp+1;
142 uint_fast8_t pin2 = (int) strtoul(arg, &endp, 10);
143 if (pin1 < pin2)
144 for (; pin1 < pin2; pin1++)
145 if ((rc = pinarg_insert(pin1, count, pinarg)) >= 0)
146 count += rc;
147 else
148 return 0;
149 else
150 return 0;
151 }
152 if (endp != arg) {
153 if ((*endp == ',' || *endp == '\0') &&
154 (rc = pinarg_insert(pin1, count, pinarg)) >= 0) {
155 count += rc;
156 if (*endp == '\0')
157 return count;
158 } else
159 return 0;
160 } else
161 return 0;
162
163 arg = endp+1;
164 }
165 }
166
167
168 command_ret_t do_gpio(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char *const argv[])
169 {
170 uint_fast8_t printheader = 1;
171 uint_fast8_t pinarg[GPIO_MAX];
172 uint_fast8_t pinargc;
173
174 int opt;
175 while ((opt = getopt(argc, argv, PSTR("s"))) != -1) {
176 switch (opt) {
177 case 's':
178 printheader = 0;
179 break;
180 default: /* '?' */
181 return CMD_RET_USAGE;
182 }
183 }
184
185 /* remaining arguments */
186 argc -= optind;
187
188 if (argc == 0) {
189 /* print config of all pins */
190 for (pinargc = 0; pinargc < GPIO_MAX; pinargc++)
191 pinarg[pinargc] = pinargc;
192 } else {
193 /* get first arg */
194 pinargc = pinarg_get(argv[optind++], pinarg);
195 if (pinargc == 0)
196 return CMD_RET_USAGE;
197 else
198 argc--;
199 }
200
201
202 if (argc == 0) {
203 /* no more args, print pin config */
204
205 char *pin_names[GPIO_MAX + 1];
206 uint_fast8_t pin_names_width = pinnames_get(pin_names);
207
208 if (pinargc == 1)
209 print_pin(pinarg[0], 0, pin_names, pin_names_width);
210 else {
211 if (printheader) {
212 if (pin_names_width > 0) {
213 if ( strlen("Name") > pin_names_width)
214 pin_names_width = strlen("Name");
215 char s[pin_names_width+1];
216 memset(s, ' ', pin_names_width);
217 s[pin_names_width] = '\0';
218 strncpy_P(s, PSTR("Name"), 4);
219 printf_P(PSTR("Pin %s Config Level Divider Frequency/Hz\n"),s);
220 memset(s, '-', pin_names_width);
221 printf_P(PSTR("----%s-----------------------------------\n"), s);
222 } else
223 printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n"
224 "--------------------------------------\n"));
225 }
226 for (uint_fast8_t i = 0; i < pinargc; i++)
227 print_pin(pinarg[i], 1, pin_names, pin_names_width);
228 }
229 if (pin_names[GPIO_MAX] != NULL)
230 free(pin_names[GPIO_MAX]);
231 return CMD_RET_SUCCESS;
232 }
233
234 /* arguments must be in pairs: pins conf */
235 if (argc % 2 != 1)
236 return CMD_RET_USAGE;
237
238 while (argc > 0) {
239 char *endp;
240 gpiomode_t mode = NONE;
241 int level = 0;
242 unsigned long value = 0;
243 uint8_t hz_flag = 0;
244
245 switch (toupper(argv[optind][0])) {
246 case 'H':
247 level = 1;
248 /* FALL TROUGH */
249 case 'L':
250 mode = OUTPUT;
251 break;
252 case 'P':
253 mode = INPUT_PULLUP;
254 break;
255 case 'I':
256 case 'T':
257 mode = INPUT;
258 break;
259
260 default:
261 value = strtoul(argv[optind], &endp, 10);
262 switch (*endp) {
263 case 'M':
264 value *= 1000;
265 /* FALL TROUGH */
266 case 'K':
267 value *= 1000;
268 endp++;
269 }
270
271 if (*endp && strcmp_P(endp, PSTR("Hz")) == 0) {
272 hz_flag = 1;
273 endp += 2;
274 }
275
276 if (*endp != '\0') {
277 printf_P(PSTR("invalid parameter: '%s'\n"), argv[optind]);
278 return CMD_RET_USAGE;
279 }
280
281 if (value == 0) {
282 printf_P(PSTR("invalid value: %lu \n"));
283 return CMD_RET_USAGE;
284 }
285
286 if (hz_flag) {
287 if (value > F_CPU / 2) {
288 printf_P(PSTR("Max frequency is: %luHz\n"), F_CPU/2);
289 return CMD_RET_USAGE;
290 }
291 value = F_CPU/value;
292 }
293 mode = OUTPUT_TIMER;
294
295 }
296
297 if (mode == NONE)
298 return CMD_RET_USAGE;
299
300 for (uint_fast8_t i = 0; i < pinargc; i++) {
301 switch (mode) {
302 case OUTPUT:
303 gpio_write(pinarg[i], level);
304 /* fall thru */
305 case INPUT:
306 case INPUT_PULLUP:
307 gpio_config(pinarg[i], mode);
308 break;
309 case OUTPUT_TIMER:
310 if (gpio_clockdiv_set(pinarg[i], value) < 0) {
311 printf_P(PSTR("Setting pin %d to %lu failed.\n"),
312 pinarg[i], value);
313 }
314 break;
315 default:
316 break;
317 }
318 }
319
320 optind++;
321 pinargc = pinarg_get(argv[optind++], pinarg);
322 argc -= 2;
323 }
324
325 return CMD_RET_SUCCESS;
326 }