]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_cpu.c
z80_measure_phi WIP
[z180-stamp.git] / avr / cmd_cpu.c
CommitLineData
226d3221
L
1/*
2 * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7#include "cmd_cpu.h"
8//#include <ctype.h>
dbc1de70 9#include <util/atomic.h>
226d3221
L
10
11#include "z80-if.h"
12#include "con-utils.h"
2c60e1dc 13#include "env.h"
51dd0948
L
14#include "eval_arg.h"
15#include "timer.h"
16#include "getopt-min.h"
2c60e1dc 17#include "debug.h"
226d3221
L
18
19/* hack to get Z180 loadfile into flash memory */
20#define const const FLASH
21#include "../z180/cpuinfo.h"
22#undef const
23
24
dbc1de70
L
25/*
26 * delay for <count> ms...
27 */
28static void test_delay(uint32_t count)
29{
30 uint32_t ts = get_timer(0);
31
32 while (get_timer(ts) <= count);
33}
34
24ba732a 35uint32_t z80_measure_phi(uint_fast8_t cycles)
dbc1de70
L
36{
37 uint16_t ref_stop;
38 uint16_t ref_ovfl;
24ba732a
L
39 uint8_t x_ovfl;
40 uint8_t eimsk_save,eicrb_save;
41 uint32_t x_freq;
42
43
44 ATOMIC_BLOCK(ATOMIC_FORCEON) {
45 /* Save state and disable INT6 */
46 eimsk_save = EIMSK;
47 EIMSK &= ~_BV(INT6);
48 /* Save state and set INT6 for falling edge */
49 eicrb_save = EICRB;
50 EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
51 }
52
53 PRR1 &= ~_BV(PRTIM3);
54 TCCR3A = 0;
55 TCCR3B = 0b000<<CS30; /* stop counter */
56 TCNT3 = 0;
57 x_ovfl = 0;
58 TIFR3 = _BV(TOV3);
59 ref_ovfl = 0;
60
61 ATOMIC_BLOCK(ATOMIC_FORCEON) {
62 /* Reset pending int */
63 EIFR = _BV(INTF6);
64 /* Wait for falling edge */
65 while ((EIFR & _BV(INTF6)) == 0)
66 ;
67 TCCR3B = 0b110<<CS30; /* Count falling edges on T3 (==INT6) */
68 OCR4B = TCNT4;
69 TIFR4 = _BV(OCF4B); /* clear compare match flag */
70 }
71 while (ref_ovfl < 60) {
72 ATOMIC_BLOCK(ATOMIC_FORCEON) {
73 if ((TIFR4 & _BV(OCF4B)) != 0) {
74 TIFR4 = _BV(OCF4B);
75 ref_ovfl++;
76 }
77 if ((TIFR3 & _BV(TOV3)) != 0) {
78 TIFR3 = _BV(TOV3);
79 x_ovfl++;
80 }
81 }
82 }
83
84 ATOMIC_BLOCK(ATOMIC_FORCEON) {
85 EIFR = _BV(INTF6);
86 for (;;) {
87 if (EIFR & _BV(INTF6)) {
88 TCCR3B = 0b000<<CS30; /* stop counter */
89 ref_stop = TCNT4;
90 break;
91 }
92 if ((TIFR4 & _BV(OCF4B)) != 0) {
93 TIFR4 = _BV(OCF4B);
94 ref_ovfl++;
95 }
96 }
97 }
98
99 if ((TIFR3 & _BV(TOV3)) != 0) {
100 TIFR3 = _BV(TOV3);
101 x_ovfl++;
102 }
103
104 ATOMIC_BLOCK(ATOMIC_FORCEON) {
105 /* Restore INT6 */
106 EICRB = eicrb_save;
107 if ((eimsk_save & _BV(INT6)) != 0)
108 EIMSK |= _BV(INT6);
109 /* Reset pending int */
110 EIFR = _BV(INTF6);
111 }
112
113 uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
114 uint32_t x_cnt = TCNT3 + ((uint32_t) x_ovfl << 16);
115 uint64_t x_tmp = (uint64_t) 100000 * (x_cnt * cycles);
116
117 debug("TCNT3: %6u, ref_cnt: %9lu\n", TCNT3, ref_cnt);
118 debug("x_tmp: %lu %lu\n", (uint32_t) (x_tmp >> 32), (uint32_t) (x_tmp & 0xffffffff));
119
120 x_tmp = (x_tmp * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU) + (ref_cnt / 2)) / ref_cnt;
121
122 debug("x_tmp: %lu %lu\n", (uint32_t) (x_tmp >> 32), (uint32_t) (x_tmp & 0xffffffff));
123
124 /* round to 5 decimal digits */
125 int_fast8_t sc = 5;
126 while (x_tmp >= 100000) {
127 x_tmp = (x_tmp + 5)/10;
128 sc--;
129 }
130 x_freq = x_tmp;
131 while (sc < 0) {
132 x_freq *= 10;
133 sc++;
134 }
135 x_freq += (uint32_t) sc << 28;
136
137
138 /* Stop Timer */
139 TCCR3B = 0;
140 PRR1 |= _BV(PRTIM3);
141
142 return x_freq;
143}
144
145#if 0
146float z80_measure_phi(uint_fast8_t cycles, uint16_t wait_ms)
147{
148 uint16_t ref_stop;
149 uint16_t ref_ovfl;
150 uint8_t x_ovfl;
151 uint8_t eimsk_save,eicrb_save;
152 float x_freq;
153
154
155 ATOMIC_BLOCK(ATOMIC_FORCEON) {
156 /* Save state and disable INT6 */
157 eimsk_save = EIMSK;
158 EIMSK &= ~_BV(INT6);
159 /* Save state and set INT6 for falling edge */
160 eicrb_save = EICRB;
161 EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
162 }
163
164 PRR1 &= ~_BV(PRTIM3);
165 TCCR3A = 0;
166 TCCR3B = 0b000<<CS30; /* stop counter */
167 TCNT3 = 0;
168 x_ovfl = 0;
169 TIFR3 = _BV(TOV3);
170 ref_ovfl = 0;
171
172 ATOMIC_BLOCK(ATOMIC_FORCEON) {
173 /* Reset pending int */
174 EIFR = _BV(INTF6);
175 /* Wait for falling edge */
176 while ((EIFR & _BV(INTF6)) == 0)
177 ;
178 TCCR3B = 0b110<<CS30; /* Count falling edges on T3 (==INT6) */
179 OCR4B = TCNT4;
180 TIFR4 = _BV(OCF4B); /* clear compare match flag */
181 }
182 while (ref_ovfl < 60) {
183 ATOMIC_BLOCK(ATOMIC_FORCEON) {
184 if ((TIFR4 & _BV(OCF4B)) != 0) {
185 TIFR4 = _BV(OCF4B);
186 ref_ovfl++;
187 }
188 if ((TIFR3 & _BV(TOV3)) != 0) {
189 TIFR3 = _BV(TOV3);
190 x_ovfl++;
191 }
192 }
193 }
194
195 ATOMIC_BLOCK(ATOMIC_FORCEON) {
196 EIFR = _BV(INTF6);
197 for (;;) {
198 if (EIFR & _BV(INTF6)) {
199 TCCR3B = 0b000<<CS30; /* stop counter */
200 ref_stop = TCNT4;
201 break;
202 }
203 if ((TIFR4 & _BV(OCF4B)) != 0) {
204 TIFR4 = _BV(OCF4B);
205 ref_ovfl++;
206 }
207 }
208 }
209
210 if ((TIFR3 & _BV(TOV3)) != 0) {
211 TIFR3 = _BV(TOV3);
212 x_ovfl++;
213 }
214
215 ATOMIC_BLOCK(ATOMIC_FORCEON) {
216 /* Restore INT6 */
217 EICRB = eicrb_save;
218 if ((eimsk_save & _BV(INT6)) != 0)
219 EIMSK |= _BV(INT6);
220 /* Reset pending int */
221 EIFR = _BV(INTF6);
222 }
223
224 uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
225
226 uint32_t x_cnt = TCNT3 + ((uint32_t) x_ovfl << 16);
227 x_freq = x_cnt * cycles;
228
229 x_freq = (x_freq * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU)) / ref_cnt;
230
231 debug("TCNT3: %6u, ref_cnt: %9lu\n", TCNT3, ref_cnt);
232#if 0
233 debug("ref_start: %6u, ref_stop: %6u, ref_ovfl: %4u, ref_cnt: %9lu\n"
234 " TCNT3: %6u, x_cnt: %6lu, xfreq: %f\n",
235 OCR4B, ref_stop, ref_ovfl, ref_cnt,
236 TCNT3, x_cnt, x_freq);
237#endif
238
239
240 /* Stop Timer */
241 TCCR3B = 0;
242 PRR1 |= _BV(PRTIM3);
243
244 return x_freq;
245}
246#endif
247
248#if 0
249int32_t z80_measure_phi(uint_fast8_t cycles, uint16_t wait_ms)
250{
251 uint16_t ref_stop;
252 uint16_t ref_ovfl;
253 uint8_t x_ovfl;
dbc1de70 254 uint32_t x_freq;
f6154a39 255 uint8_t eimsk_save,eicrb_save;
dbc1de70
L
256
257
f6154a39
L
258 ATOMIC_BLOCK(ATOMIC_FORCEON) {
259 /* Save state and disable INT6 */
260 eimsk_save = EIMSK;
261 EIMSK &= ~_BV(INT6);
262 /* Save state and set INT6 for falling edge */
263 eicrb_save = EICRB;
264 EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
265 }
266
dbc1de70
L
267 PRR1 &= ~_BV(PRTIM3);
268 TCCR3A = 0;
269 TCCR3B = 0b000<<CS30; /* stop counter */
270 TCNT3 = 0;
24ba732a 271 x_ovfl = 0;
dbc1de70
L
272 TIFR3 = _BV(TOV3);
273 ref_ovfl = 0;
f6154a39 274
dbc1de70
L
275 ATOMIC_BLOCK(ATOMIC_FORCEON) {
276 /* Reset pending int */
277 EIFR = _BV(INTF6);
278 /* Wait for falling edge */
279 while ((EIFR & _BV(INTF6)) == 0)
280 ;
dbc1de70
L
281 OCR4B = TCNT4;
282 TCCR3B = 0b110<<CS30; /* Count falling edges on T3 (==INT6) */
283 TIFR4 = _BV(OCF4B); /* clear compare match flag */
284 }
285 while (ref_ovfl < 60) {
286 ATOMIC_BLOCK(ATOMIC_FORCEON) {
287 if ((TIFR4 & _BV(OCF4B)) != 0) {
288 TIFR4 = _BV(OCF4B);
289 ref_ovfl++;
290 }
24ba732a
L
291 if ((TIFR3 & _BV(TOV3)) != 0) {
292 TIFR3 = _BV(TOV3);
293 x_ovfl++;
294 }
295 }
296 }
297
298 ATOMIC_BLOCK(ATOMIC_FORCEON) {
299 EIFR = _BV(INTF6);
300 for (;;) {
301 if (EIFR & _BV(INTF6)) {
302 ref_stop = TCNT4;
303 TCCR3B = 0b000<<CS30; /* stop counter */
304 break;
305 }
306 if ((TIFR4 & _BV(OCF4B)) != 0) {
307 TIFR4 = _BV(OCF4B);
308 if (ref_ovfl)
309 ref_ovfl++;
310 }
dbc1de70
L
311 }
312 }
313
24ba732a 314#if 0
dbc1de70
L
315 ATOMIC_BLOCK(ATOMIC_FORCEON) {
316 EIFR = _BV(INTF6);
317 for (;;) {
318 if (EIFR & _BV(INTF6))
319 break;
320 if (TIFR4 & _BV(OCF4B)) {
321 if (EIFR & _BV(INTF6))
322 break;
323 TIFR4 = _BV(OCF4B);
324 if (EIFR & _BV(INTF6))
325 break;
326 ref_ovfl++;
327 if (EIFR & _BV(INTF6))
328 break;
329 if (ref_ovfl == 0)
330 break;
331 }
332 }
333 ref_stop = TCNT4;
334 TCCR3B = 0b000<<CS30; /* stop counter */
335 if ((TIFR4 & _BV(OCF4B)) != 0) {
336 TIFR4 = _BV(OCF4B);
337 if (ref_ovfl)
338 ref_ovfl++;
339 }
340 }
24ba732a
L
341#endif
342 if ((TIFR3 & _BV(TOV3)) != 0) {
343 TIFR3 = _BV(TOV3);
344 x_ovfl++;
345 }
dbc1de70
L
346
347 if (ref_ovfl == 0)
348 x_freq = 0xFFFFFFFE;
349 else
350 {
351 uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
352
24ba732a 353 x_freq = TCNT3 + ((uint32_t) x_ovfl << 16);
dbc1de70 354 uint32_t x_cnt = x_freq;
dbc1de70
L
355 x_freq *= cycles;
356
2c60e1dc 357 x_freq = ((uint64_t) x_freq * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU) + (ref_cnt / 2))/ ref_cnt;
dbc1de70 358
f6154a39 359 debug("ref_start: %6u, ref_stop: %6u, ref_ovfl: %4u, ref_cnt: %9lu\n"
24ba732a 360 " TCNT3: %6u, x_cnt: %6lu, xfreq: %9lu\n",
dbc1de70 361 OCR4B, ref_stop, ref_ovfl, ref_cnt,
24ba732a 362 TCNT3, x_cnt, x_freq);
dbc1de70
L
363
364 /* round to 5 decimal digits */
24ba732a 365 uint_fast8_t sc = 0;
dbc1de70
L
366 while (x_freq >= 100000UL) {
367 x_freq = (x_freq + 5)/10;
368 ++sc;
369 }
370 while (sc--)
371 x_freq *= 10;
372 }
373
374 /* Stop Timer */
375 TCCR3B = 0;
376 PRR1 |= _BV(PRTIM3);
377
f6154a39
L
378 ATOMIC_BLOCK(ATOMIC_FORCEON) {
379 /* Restore INT6 */
380#if 0 /* wtf? */
381 eicrb_save = EICRB;
382 EICRB = (EICRB & ~(0b11 << ISC60)) | (eicrb_save & (0b11 << ISC60));
383#endif
384 EICRB = eicrb_save;
385 if ((eimsk_save & _BV(INT6)) != 0)
386 EIMSK |= _BV(INT6);
387 /* Reset pending int */
388 EIFR = _BV(INTF6);
389 }
390
dbc1de70
L
391 return (int32_t) x_freq;
392}
24ba732a 393#endif
dbc1de70 394
226d3221
L
395static const FLASH char * const FLASH cpu_strings[] = {
396 FSTR("Unknown CPU"),
397 FSTR("8080"),
398 FSTR("8085"),
399 FSTR("Z80"),
400 FSTR("x180"),
401 FSTR("HD64180"),
402 FSTR("Z80180"),
403 FSTR("Z80S180"),
404};
405
406command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
407{
24ba732a 408 uint_fast8_t cputype;
226d3221
L
409 ERRNUM err = ESUCCESS;
410 uint8_t ram_save[cpuinfo_length];
411
412 if (z80_bus_state() & ZST_RUNNING) {
413 err = ERUNNING;
414 } else {
415 z80_bus_request_or_exit();
416 z80_read_block(ram_save, 0, cpuinfo_length);
417 z80_load_mem(0, cpuinfo,
418 &cpuinfo_sections,
419 cpuinfo_address,
420 cpuinfo_length_of_sections);
421 z80_bus_cmd(Release);
422
423 if (argv[1] && (argv[1][0] == 'n'))
424 goto donot;
425
426 z80_bus_cmd(Run);
427
428 clear_ctrlc(); /* forget any previous Control C */
24ba732a 429 uint_fast8_t done = 0;
226d3221
L
430 while (done != 0xFF) {
431 _delay_ms(8);
432 /* check for ctrl-c to abort... */
433 if (had_ctrlc() || ctrlc()) {
434 err = EINTR;
435 break;
436 }
437 z80_bus_cmd(Request);
438 done = z80_read(3);
439 if (done == 0xFF)
440 cputype = z80_read(4);
441 z80_bus_cmd(Release);
442 }
443 z80_bus_cmd(Reset);
444 z80_bus_cmd(Request);
445// z80_write_block(ram_save, 0, cpuinfo_length);
446 z80_bus_cmd(Release);
447 }
448
449donot:
450
451 if (err)
452 cmd_error(CMD_RET_FAILURE, err, NULL);
453
24ba732a
L
454 if (cputype >= ARRAY_SIZE(cpu_strings))
455 cputype = 0;
456 printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]);
226d3221
L
457
458 return CMD_RET_SUCCESS;
459}
51dd0948 460
51dd0948
L
461command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
462{
463
464 uint32_t pulsewidth = 10; /* ms */
465
51dd0948
L
466 int opt;
467 while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
468 switch (opt) {
469 case 't':
470 pulsewidth = eval_arg(optarg, NULL);
471 break;
472 default: /* '?' */
473 return CMD_RET_USAGE;
474 }
475 }
476
477 if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
478 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
479
480 clear_ctrlc(); /* forget any previous Control C */
481 do {
482 z80_bus_cmd(Request);
483 test_delay(pulsewidth);
484 z80_bus_cmd(Release);
485 test_delay(pulsewidth);
486 } while (!(had_ctrlc() || ctrlc()));
487
488 return CMD_RET_SUCCESS;
489}
490
dbc1de70
L
491command_ret_t do_bus_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
492{
493 char ch;
494
495#if 0
dbc1de70
L
496 int opt;
497 while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
498 switch (opt) {
499 case 't':
500 pulsewidth = eval_arg(optarg, NULL);
501 break;
502 default: /* '?' */
503 return CMD_RET_USAGE;
504 }
505 }
506#endif
507
508 my_puts_P(PSTR(
509 " 1: RESET 4: RUN r: Toggle /RESET\n"
510 " 2: REQUEST 5: RESTART b: Toggle /BUSREQ\n"
511 " 3: RELEASE 6: M_CYCLE\n"
512 "\n"
513 //"Bus state: "
514 ));
515
516 do {
517 ch = my_getchar(1);
518 if (ch >= 0) {
519 switch (ch) {
520 case '1': /* bus_cmd RESET */
521 case '2': /* bus_cmd REQUEST */
522 case '3': /* bus_cmd RELEASE */
523 case '4': /* bus_cmd RUN */
524 case '5': /* bus_cmd RESTART */
525 case '6': /* bus_cmd M_CYCLE */
526 z80_bus_cmd(ch - '1' + Reset);
527 break;
528 case 'r': /* Toggle RESET */
529 z80_toggle_reset();
530 break;
531 case 'b': /* Toggle BUSREQ */
532 z80_toggle_busreq();
533 break;
534 }
535 test_delay(10);
536 uint32_t cycles = z80_get_busreq_cycles();
537 printf_P(PSTR("\rState: %.2x, cycles: %lu, time: %luus "),
538 z80_bus_state(), cycles, (uint32_t) (cycles * 1000000LL / F_CPU));
539 }
540 } while (ch != 0x03);
541
542 putchar('\n');
543 return CMD_RET_SUCCESS;
544}
545
d66348b4
L
546command_ret_t do_busack_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
547{
548
549 if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
550 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
551
552 z80_bus_cmd(Request);
553 uint32_t result = z80_get_busreq_cycles();
554 test_delay(20);
555 z80_bus_cmd(Release);
556
557#if 0
558 long div;
559
560 pinconf = gpio_config_get(pin);
561 if (pinconf == OUTPUT_TIMER) {
562 div = gpio_clockdiv_get(pin);
dbc1de70 563 }
d66348b4
L
564#endif
565
566
567 printf_P(PSTR("cycles: %lu, time: %luus\n"), result, (uint32_t) (result * 1000000LL / F_CPU));
568
569 return CMD_RET_SUCCESS;
570}
571
f6154a39 572static const FLASH uint8_t loop_code[] = {
24ba732a
L
573/* 0000 */ 0x00, /* nop */
574/* 0001 */ 0xAF, /* xor a */
575/* 0005 */ 0xD3,0x32, /* out (032h),a ;DCNTL */
576/* 0002 */ 0xD3,0x36, /* out (036h),a ;RCR */
577/* */ /* */
578/* 0006 */ 0xD3,0x40, /* out (040H),a ;Ready */
579/* */ /* */
580/* */ /* ;Z80 Z180(0W) Z180(MaxW) */
581/* 0008 */ /* loop: ;-------------------------- */
582/* 0008 */ 0xDB,0x50, /* in a,(050h) ;11 10 +3*3 19 */
583/* 000A */ 0xC3,0x08,0x00 /* jp loop ;10 9 +3*3 18 */
584 /* ;-------------------------- */
585 /* ;21 19 37 */
2c60e1dc 586};
f6154a39 587
dbc1de70 588command_ret_t do_cpu_freq(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
51dd0948 589{
dbc1de70
L
590
591#define O_SILENT (1<<0)
592#define O_WENV (1<<1)
593#define O_LOAD_LOOP (1<<2)
594#define O_UNLOAD_LOOP (1<<3)
595
596 uint_fast8_t options = O_LOAD_LOOP | O_UNLOAD_LOOP;
24ba732a 597 uint_fast8_t lcycles = 19;
51dd0948
L
598 uint16_t timeout = 1000;
599
f6154a39 600 uint8_t mem_save[ARRAY_SIZE(loop_code)];
51dd0948 601
51dd0948 602 int opt;
dbc1de70 603 while ((opt = getopt(argc, argv, PSTR("swnuc:t:"))) != -1) {
51dd0948
L
604 switch (opt) {
605 case 's':
dbc1de70 606 options |= O_SILENT;
51dd0948
L
607 break;
608 case 'w':
dbc1de70 609 options |= O_WENV;
51dd0948
L
610 break;
611 case 'n':
dbc1de70
L
612 options &= ~O_LOAD_LOOP;
613 break;
614 case 'u':
615 options &= ~O_UNLOAD_LOOP;
51dd0948
L
616 break;
617 case 'c':
618 lcycles = eval_arg(optarg, NULL);
619 break;
620 case 't':
dbc1de70 621 timeout = eval_arg(optarg, NULL);
51dd0948
L
622 break;
623 default: /* '?' */
624 return CMD_RET_USAGE;
625 }
626 }
dbc1de70
L
627 if (argc - optind != 0)
628 return CMD_RET_USAGE;
51dd0948
L
629
630 if (z80_bus_state() & ZST_RUNNING) {
dbc1de70 631 if (!(options & O_SILENT))
51dd0948
L
632 printf_P(PSTR("Frequency measuring failed. CPU allready running!\n"));
633 return CMD_RET_FAILURE;
634 }
635
51dd0948
L
636
637 z80_bus_cmd(Request);
dbc1de70 638 if (options & O_LOAD_LOOP) {
f6154a39
L
639 z80_read_block(mem_save, 0, ARRAY_SIZE(loop_code));
640 z80_write_block_P(loop_code, 0, ARRAY_SIZE(loop_code));
51dd0948 641 }
dbc1de70 642 Stat &= ~S_IO_0X40; /* Reset pending int */
51dd0948 643 z80_bus_cmd(Release);
dbc1de70 644 z80_bus_cmd(Run);
51dd0948 645
dbc1de70
L
646 clear_ctrlc(); /* forget any previous Control C */
647 ERRNUM err = 0;
648
649 /* Wait for falling edge */
650 do {
651 /* check for ctrl-c to abort... */
652 if (had_ctrlc() || ctrlc()) {
653 err = EINTR;
654 break;
655 }
656 } while ((Stat & S_IO_0X40) == 0);
657
24ba732a 658 uint32_t cpu_freq;
dbc1de70 659 if (!err)
24ba732a 660 cpu_freq = z80_measure_phi(lcycles);
51dd0948
L
661
662 z80_bus_cmd(Reset);
dbc1de70
L
663 if (options & O_UNLOAD_LOOP) {
664 z80_bus_cmd(Request);
f6154a39 665 z80_write_block(mem_save, 0, ARRAY_SIZE(loop_code));
dbc1de70
L
666 z80_bus_cmd(Release);
667 }
dbc1de70
L
668 if (err)
669 cmd_error(CMD_RET_FAILURE, err, NULL);
51dd0948 670
dbc1de70 671 if (!(options & O_SILENT)) {
24ba732a
L
672 printf_P(PSTR("%lu %3u\n"), cpu_freq & 0x0fffffff, cpu_freq >> 28);
673
674// printf_P(PSTR("%f%S\n"), cpu_freq, cpu_freq < 0 ? PSTR("") : PSTR("Hz"));
dbc1de70
L
675// if (cpu_freq != 0)
676// else
677// printf_P(PSTR("No CPU clock or input frequency to low!\n"));
678 }
679#if 0
680 if (options & O_WENV) {
51dd0948 681 if (setenv_ulong(PSTR(ENV_CPU_FREQ), cpu_freq)) {
dbc1de70 682 if (!(options & O_SILENT))
51dd0948
L
683 printf_P(PSTR("'SETENV (%S, %lu)' failed!\n"), PSTR(ENV_CPU_FREQ), cpu_freq);
684 return CMD_RET_FAILURE;
685 }
686 }
dbc1de70 687#endif
51dd0948
L
688 return CMD_RET_SUCCESS;
689}
dbc1de70 690
51dd0948
L
691
692/*
693 * command table for fat subcommands
694 */
695
696cmd_tbl_t cmd_tbl_cpu[] = {
697CMD_TBL_ITEM(
698 chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpuchk,
699 "Check CPU",
700 ""
701),
dbc1de70
L
702CMD_TBL_ITEM(
703 buscmd, CONFIG_SYS_MAXARGS, CTBL_RPT, do_bus_test,
704 "Bus commands",
705 ""
706),
51dd0948
L
707CMD_TBL_ITEM(
708 test, CONFIG_SYS_MAXARGS, 1, do_cpu_test,
709 "Do bus request/release cycles",
710 "[-t pulsewidth]"
711),
d66348b4
L
712CMD_TBL_ITEM(
713 busack, 2, 1, do_busack_test,
714 "Get time from /Reset high to /BUSACK low",
715 ""
716),
51dd0948
L
717CMD_TBL_ITEM(
718 freq, CONFIG_SYS_MAXARGS, 1, do_cpu_freq,
719 "Measure cpu frequency",
dbc1de70
L
720 "[-qwn] [-c loopcycles] [-t timeout]\n"
721 " -q Be quiet\n"
722// " -w Write result to environment variable '"ENV_CPU_FREQ"'"
51dd0948 723),
dbc1de70 724
51dd0948
L
725CMD_TBL_ITEM(
726 help, CONFIG_SYS_MAXARGS, CTBL_RPT, do_help,
727 "Print sub command description/usage",
728 "\n"
729 " - print brief description of all sub commands\n"
730 "fat help command ...\n"
731 " - print detailed usage of sub cmd 'command'"
732),
733
734/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
735 {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help,
736 NULL,
737#ifdef CONFIG_SYS_LONGHELP
738 FSTR(""),
739#endif /* CONFIG_SYS_LONGHELP */
740 NULL,
741#ifdef CONFIG_AUTO_COMPLETE
742 NULL,
743#endif
744},
745/* Mark end of table */
746CMD_TBL_END(cmd_tbl_cpu)
747};
748
749
750command_ret_t do_cpu(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
751{
752 //puts_P(PSTR("Huch?"));
753
754 return CMD_RET_USAGE;
755}
756
757
dbc1de70 758#if 0 /* Z180 Single Step Functions */
51dd0948
L
759/*
760 * Z180 Single Step Functions
761 *
762 */
763
764
765#define P_RUN PORTG
766#define RUN 1
767#define DDR_RUN DDRG
768#define P_STEP PORTG
769#define STEP 0
770#define DDR_STEP DDRG
771#define P_WAIT PORTG
772#define WAIT 2
773#define DDR_WAIT DDRG
774/* All three signals are on the same Port (PortG) */
775#define PORT_SS PORTG
776#define DDR_SS DDRG
777#define PIN_SS PING
778
779static bool ss_available;
780
781int single_step_setup(void)
782{
783 ss_available = false;
784
785#if 0
786 if (z80_bus_state() & ZST_RUNNING ||
787 !(z80_bus_cmd(Request) & ZST_ACQUIRED))
788 return -1;
789#endif
790
791 /* STEP, RUN output, WAIT input */
792
793 PORT_SS |= _BV(RUN) | _BV(STEP);
794 DDR_SS |= _BV(RUN) | _BV(STEP);
795 DDR_SS &= ~_BV(WAIT);
796
797 /* RUN high, MREQ pulse --> WAIT should be low */
798 z80_mreq_pulse();
799
800 if ((PIN_SS & _BV(WAIT)) == 0) {
801
802 /* RUN high, STEP pulse --> WAIT should be high */
803 PIN_SS = _BV(STEP);
804 PIN_SS = _BV(STEP);
805 if ((PIN_SS & _BV(WAIT)) != 0) {
806
807 /* RUN high, MREQ pulse --> WAIT should be low */
808 z80_mreq_pulse();
809 if ((PIN_SS & _BV(WAIT)) == 0) {
810
811 /* RUN low --> WAIT should be high */
812 PIN_SS = _BV(RUN);
813 if ((PIN_SS & _BV(WAIT)) != 0) {
814
815 /* RUN low, STEP pulse --> WAIT should be high */
816 PIN_SS = _BV(STEP);
817 PIN_SS = _BV(STEP);
818 if ((PIN_SS & _BV(WAIT)) != 0) {
819
820 /* all tests passed */
821 ss_available = true;
822 }
823 }
824 }
825 }
826 }
827
828 if (!ss_available) {
829 DDR_SS &= ~(_BV(STEP) | _BV(RUN));
830 PORT_SS |= _BV(RUN) | _BV(STEP);
831 }
832
833 return ss_available ? 0 : -1;
834}
835#endif