]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_boot.c
pin command, add user configurable i/o pins
[z180-stamp.git] / avr / cmd_boot.c
1
2 /*
3 * Misc boot support
4 */
5 #include "common.h"
6 #include <stdlib.h>
7 #include <limits.h>
8 #include <ctype.h>
9 #include <util/delay.h>
10 #include <avr/pgmspace.h>
11
12 #include "command.h"
13 #include "getopt-min.h"
14 #include "z80-if.h"
15 #include "pin.h"
16 #include "debug.h"
17
18 /* ugly hack to get Z180 loadfile into flash memory */
19 #define const const FLASH
20 #include "../z180/hdrom.h"
21 #undef const
22
23
24
25 static void z80_load_mem(void)
26 {
27 unsigned sec = 0;
28 uint32_t sec_base = hdrom_start;
29
30 printf_P(PSTR("Loading Z180 memory... \n"));
31
32 while (sec < hdrom_sections) {
33 printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"),
34 hdrom_address[sec],
35 hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
36 hdrom_length_of_sections[sec]);
37
38 z80_bus_cmd(Request);
39 z80_write_block((const FLASH unsigned char *) &hdrom[sec_base], /* src */
40 hdrom_address[sec], /* dest */
41 hdrom_length_of_sections[sec]); /* len */
42 z80_bus_cmd(Release);
43 sec_base+=hdrom_length_of_sections[sec];
44 sec++;
45 }
46 }
47
48 command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
49 {
50 (void) cmdtp; (void) flag; (void) argc; (void) argv;
51
52 if (z80_bus_state() & ZST_RUNNING) {
53 printf_P(PSTR("## Can't load while CPU is running!\n"));
54 return CMD_RET_FAILURE;
55 }
56
57 z80_load_mem();
58
59 return CMD_RET_SUCCESS;
60 }
61
62
63 command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
64 {
65 uint16_t count=1;
66
67 (void) cmdtp; (void) flag;
68
69 if (!(z80_bus_state() & ZST_RUNNING)) {
70 printf_P(PSTR("## CPU is not running!\n"));
71 return CMD_RET_FAILURE;
72 }
73
74 if (argc > 1)
75 count = (uint16_t) strtoul(argv[2], NULL, 16);
76
77 z80_bus_cmd(Request);
78 while (count--)
79 z80_bus_cmd(M_Cycle);
80
81 return CMD_RET_SUCCESS;
82 }
83
84
85 command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
86 {
87 uint32_t addr;
88
89 (void) cmdtp; (void) flag;
90
91 if (argc < 2)
92 return CMD_RET_USAGE;
93 addr = strtoul(argv[1], NULL, 16);
94 if (addr >= (1UL<<16)) {
95 printf_P(PSTR("## Startaddress 0x%05lx too high.\n"
96 " (Out of logical address space (0x00000-0x0ffff))\n"),
97 addr);
98 return CMD_RET_FAILURE;
99 }
100
101 if (z80_bus_state() & ZST_RUNNING) {
102 printf_P(PSTR("## CPU allready running!\n"));
103 return CMD_RET_FAILURE;
104 }
105
106 printf_P(PSTR("## Starting application at 0x%04lx ...\n"), addr);
107
108 if (addr != 0) {
109 uint8_t tmp[3];
110 uint_fast8_t i;
111
112 z80_bus_cmd(Request);
113 for (i = 0; i < 3; i++)
114 tmp[i] = z80_read(i);
115 z80_write(0, 0xc3);
116 z80_write(1, addr);
117 z80_write(2, (addr >> 8));
118
119 z80_bus_cmd(Run);
120 z80_bus_cmd(M_Cycle);
121 z80_bus_cmd(M_Cycle);
122 for (i = 0; i < 3; i++)
123 z80_write(i, tmp[i]);
124 } else
125 z80_bus_cmd(Run);
126
127 z80_bus_cmd(Release);
128
129 return CMD_RET_SUCCESS;
130 }
131
132 command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
133 {
134 (void) cmdtp; (void) flag; (void) argc; (void) argv;
135
136 printf_P(PSTR("## CPU now in reset state.\n"));
137
138 z80_bus_cmd(Reset);
139 return CMD_RET_SUCCESS;
140 }
141
142 command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
143 {
144 (void) cmdtp; (void) flag; (void) argc; (void) argv;
145
146 z80_bus_cmd(Restart);
147
148 return CMD_RET_SUCCESS;
149 }
150
151 #if 0
152 command_ret_t do_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
153 {
154 long freq;
155 char *endp;
156
157 (void) cmdtp; (void) flag;
158
159 if (argc == 2) {
160 if (toupper(argv[1][0]) == 'L')
161 freq = 0;
162 else if (toupper(argv[1][0]) == 'H')
163 freq = LONG_MAX;
164 else {
165 freq = strtol(argv[1], &endp, 10);
166 switch (*endp) {
167 case 'M':
168 freq *= 1000;
169 case 'K':
170 freq *= 1000;
171 endp++;
172 case '\0':
173 if (*endp == '\0')
174 break;
175 default:
176 printf_P(PSTR("invalid value\n"));
177 return CMD_RET_USAGE;
178 }
179
180 if (freq == 0) {
181 printf_P(PSTR("CPU clock cannot be 0\n"));
182 return CMD_RET_USAGE;
183 }
184
185
186 /* if (freq > (long) F_CPU / 2) {
187 printf_P(PSTR("Max CPU clock freq. is: %luHz\n"), F_CPU/2);
188 return CMD_RET_USAGE;
189 }
190 */
191 }
192 if (z80_clock_set(freq) < 0) {
193 printf_P(PSTR("Setting CPU clock freq. to %luHz failed.\n"),
194 freq);
195 }
196 }
197
198 printf_P(PSTR("CPU clock: %luHz\n"), z80_clock_get());
199
200
201 return CMD_RET_SUCCESS;
202 }
203
204 command_ret_t do_clock2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
205 {
206 long value;
207 char *endp;
208 uint8_t div_flag = 0;
209
210 (void) cmdtp; (void) flag;
211
212 if (argc >= 2) {
213 if (argv[1][0] == '-' && argv[1][1] == 'd') {
214 div_flag = 1;
215 argc--;
216 argv++;
217 }
218 }
219
220 if (argc == 2) {
221 if (toupper(argv[1][0]) == 'L')
222 value = 0;
223 else if (toupper(argv[1][0]) == 'H')
224 value = LONG_MAX;
225 else {
226 value = strtol(argv[1], &endp, 10);
227 switch (*endp) {
228 case 'M':
229 value *= 1000;
230 case 'K':
231 value *= 1000;
232 endp++;
233 case '\0':
234 if (*endp == '\0')
235 break;
236 default:
237 printf_P(PSTR("invalid value\n"));
238 return CMD_RET_USAGE;
239 }
240
241 if (value == 0) {
242 printf_P(PSTR("clk2 cannot be 0\n"));
243 return CMD_RET_USAGE;
244 }
245
246 if (div_flag) {
247 if (value > 256*1024L) {
248 printf_P(PSTR("Max clk2 divider is: %lu\n"), 256*1024L);
249 return CMD_RET_USAGE;
250 }
251 } else {
252 if (value > (long) F_CPU / 2) {
253 printf_P(PSTR("Max clk2 freq. is: %luHz\n"), F_CPU/2);
254 return CMD_RET_USAGE;
255 }
256 }
257 }
258 if (div_flag ? z80_clock2_divset(value) : z80_clock2_set(value) < 0) {
259 printf_P(PSTR("Setting clk2 freq. to %luHz failed.\n"),
260 value);
261 }
262 }
263
264 printf_P(PSTR("clk2: %luHz\n"), z80_clock2_get());
265
266
267 return CMD_RET_SUCCESS;
268 }
269 #endif
270
271 // {INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} pinmode_t;
272
273
274 static void print_blanks(uint_fast8_t count)
275 {
276 while(count--)
277 putchar(' ');
278 }
279
280 static const FLASH char * const FLASH pinconf_str[] = {
281 FSTR("Input"),
282 FSTR("Pullup"),
283 FSTR("Output"),
284 FSTR("Clock"),
285 };
286
287 static const FLASH char * const FLASH pinlevel_str[] = {
288 FSTR("Low"),
289 FSTR("High"),
290 FSTR(""),
291 };
292
293 int print_pin(int pin, int multi)
294 {
295 int pinconf;
296 const FLASH char *levelp;
297 long div;
298
299 pinconf = pin_config_get(pin);
300 if (pinconf == OUTPUT_TIMER) {
301 div = pin_clockdiv_get(pin);
302 levelp = pinlevel_str[2];
303 } else
304 levelp = pinlevel_str[pin_read(pin)];
305
306 if (multi) {
307 printf_P(PSTR("%3d "), pin);
308 my_puts_P(pinconf_str[pinconf]);
309 print_blanks(8 - strlen_P(pinconf_str[pinconf]));
310 my_puts_P(levelp);
311 print_blanks(6 - strlen_P(levelp));
312 if (pinconf == OUTPUT_TIMER)
313 printf_P(PSTR("%7ld %8ld"),
314 div, F_CPU/div);
315 } else {
316 printf_P(PSTR("Pin %d: "), pin);
317 my_puts_P(pinconf_str[pinconf]);
318 printf_P(PSTR(", "));
319 my_puts_P(levelp);
320
321 if (pinconf == OUTPUT_TIMER)
322 printf_P(PSTR("divide by %ld (%ldHz)"),
323 div, F_CPU/div);
324 }
325 printf_P(PSTR("\n"));
326
327 return 0;
328 }
329
330
331 /*
332 * TODO: - pin groups
333 * - error if pin "config clock" on pins without clock
334 * - stat for single pin (group)
335 */
336
337 command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
338 {
339 int opt, pin;
340 unsigned long value;
341 char *endp;
342 char printheader = 1;
343
344 (void) cmdtp; (void) flag;
345
346 /* reset getopt() */
347 optind = 1;
348
349 while ((opt = getopt(argc, argv, PSTR("s"))) != -1) {
350 switch (opt) {
351 case 's':
352 printheader = 0;
353 break;
354 default: /* '?' */
355 return CMD_RET_USAGE;
356 }
357 }
358
359 // if ((argc - optind) % 2 != 0)
360 // return CMD_RET_USAGE;
361
362 debug("argc: %d, optind: %d\n", argc, optind);
363
364 switch (argc - optind) {
365 case 0:
366 if (printheader)
367 printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n"
368 "-----------------------------------------\n"));
369 for (pin = 0; pin < PIN_MAX; pin++)
370 print_pin(pin, 1);
371
372 return CMD_RET_SUCCESS;
373 break;
374 case 1:
375 pin = strtol(argv[optind], &endp, 10);
376 print_pin(pin, 0);
377 return CMD_RET_SUCCESS;
378 break;
379 }
380
381 while (optind < argc ) {
382 uint8_t hz_flag = 0;
383
384 pin = strtol(argv[optind++], &endp, 10);
385
386 switch (toupper(argv[optind][0])) {
387 case 'L':
388 case 'H':
389 pin_write(pin, toupper(argv[optind][0]) == 'H');
390 pin_config(pin, OUTPUT);
391 break;
392 case 'P':
393 pin_config(pin, INPUT_PULLUP);
394 break;
395 case 'I':
396 case 'T':
397 pin_config(pin, INPUT);
398 break;
399
400 default:
401 value = strtoul(argv[optind], &endp, 10);
402 switch (*endp) {
403 case 'M':
404 value *= 1000;
405 case 'K':
406 value *= 1000;
407 endp++;
408 }
409
410 if (*endp && strcmp_P(endp, PSTR("Hz")) == 0) {
411 hz_flag = 1;
412 endp += 2;
413 }
414
415 if (*endp != '\0') {
416 printf_P(PSTR("invalid parameter: '%s'\n"), argv[optind]);
417 return CMD_RET_USAGE;
418 }
419
420 if (value == 0) {
421 printf_P(PSTR("invalid value: %lu \n"));
422 return CMD_RET_USAGE;
423 }
424
425 if (hz_flag) {
426 if (value > F_CPU / 2) {
427 printf_P(PSTR("Max frequency is: %luHz\n"), F_CPU/2);
428 return CMD_RET_USAGE;
429 }
430 value = F_CPU/value;
431 }
432
433
434 debug("** setting pin '%d' to '%lu'\n", pin, value);
435 if (pin_clockdiv_set(pin, value) < 0) {
436 printf_P(PSTR("Setting pin %d to %lu failed.\n"),
437 pin, value);
438 }
439 }
440
441 optind++;
442 }
443
444
445 return CMD_RET_SUCCESS;
446 }
447