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