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