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