]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/z80-if.c
Init ports for single step logic on ECB adapter. Use timer 5 instead of timer 4 for...
[z180-stamp.git] / avr / z80-if.c
1 /*
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7 /**
8 *
9 * Pin assignments
10 *
11 * | Z180-Sig | AVR-Port | Dir |
12 * +------------+---------------+-------+
13 * | A0 | PA 0 | O |
14 * | A1 | PA 1 | O |
15 * | A2 | PA 2 | O |
16 * | A3 | PA 3 | O |
17 * | A4 | PA 4 | O |
18 * | A5 | PA 5 | O |
19 * | A6 | PA 6 | O |
20 * | A7 | PA 7 | O |
21 * | A8 | PC 0 | O |
22 * | A9 | PC 1 | O |
23 * | A10 | PC 2 | O |
24 * | A11 | PC 3 | O |
25 * | A12 | PC 4 | O |
26 * | A13 | PC 5 | O |
27 * | A14 | PC 6 | O |
28 * | A15 | PC 7 | O |
29 * | A16 | PE 2 | O |
30 * | A17 | PE 3 | O |
31 * | A18 | PE 4 | O |
32 * | D0 | PF 0 | I/O |
33 * | D1 | PF 1 | I/O |
34 * | D2 | PF 2 | I/O |
35 * | D3 | PF 3 | I/O |
36 * | D4 | PF 4 | I/O |
37 * | D5 | PF 5 | I/O |
38 * | D6 | PF 6 | I/O |
39 * | D7 | PF 7 | I/O |
40 * | RD | PD 3 | O |
41 * | WR | PD 2 | O |
42 * | MREQ | PD 4 | O |
43 * | RST | PD 5 | O |
44 * | BUSREQ | PD 7 | O |
45 * | BUSACK | PD 6 | I |
46 * |
47 * | Optional
48 * +------------------------------------+
49 * | STEP | PG 0 | O |
50 * | RUN | PG 1 | O |
51 * | WAIT | PG 2 | I |
52
53 */
54
55
56 #include "z80-if.h"
57 #include <util/atomic.h>
58 #include "debug.h"
59 #include "config.h"
60 #include "env.h"
61
62
63 //#define P_ZCLK PORTB
64 //#define ZCLK 5
65 //#define DDR_ZCLK DDRB
66 #define P_MREQ PORTD
67 #define MREQ 4
68 #define DDR_MREQ DDRD
69 #define P_RD PORTD
70 #define RD 3
71 #define P_WR PORTD
72 #define WR 2
73 #define P_BUSREQ PORTD
74 #define BUSREQ 7
75 #define DDR_BUSREQ DDRD
76 #define P_BUSACK PORTD
77 #define PIN_BUSACK PIND
78 #define BUSACK 6
79 #define DDR_BUSACK DDRD
80 #define P_RST PORTD
81 #define DDR_RST DDRD
82 #define RST 5
83
84
85 #define P_DB PORTF
86 #define PIN_DB PINF
87 #define DDR_DB DDRF
88
89 #define P_ADL PORTA
90 #define P_ADH PORTC
91 #define P_ADB PORTE
92 #define PIN_ADB PINE
93 #define DDR_ADL DDRA
94 #define DDR_ADH DDRC
95 #define DDR_ADB DDRE
96
97 #define ADB_WIDTH 3
98 #define ADB_SHIFT 2
99 //#define ADB_PORT PORTE
100
101
102 //#define Z80_O_ZCLK SBIT(P_ZCLK, 5)
103 #define Z80_O_MREQ SBIT(P_MREQ, 4)
104 #define Z80_O_RD SBIT(P_RD, 3)
105 #define Z80_O_WR SBIT(P_WR, 2)
106 #define Z80_O_BUSREQ SBIT(P_BUSREQ, 7)
107 //#define Z80_O_NMI SBIT(P_NMI, )
108 #define Z80_O_RST SBIT(P_RST, 5)
109 #define Z80_I_BUSACK SBIT(PIN_BUSACK, 6)
110 //#define Z80_I_HALT SBIT(P_HALT, )
111
112 /* Optional */
113 #define P_RUN PORTG
114 #define RUN 1
115 #define DDR_RUN DDRG
116 #define P_STEP PORTG
117 #define STEP 0
118 #define DDR_STEP DDRG
119 #define P_WAIT PORTG
120 #define WAIT 2
121 #define DDR_WAIT DDRG
122 /* All three signals are on the same Port (PortG) */
123 #define PORT_SS PORTG
124 #define DDR_SS DDRG
125 #define PIN_SS PING
126 #define Z80_O_RUN SBIT(PORT_SS, RUN)
127 #define Z80_O_STEP SBIT(PORT_SS, STEP)
128 #define Z80_I_WAIT SBIT(PORT_SS, WAIT)
129
130
131 #define BUS_TO 20
132
133
134 #define MASK(n) ((1<<(n))-1)
135 #define SMASK(w,s) (MASK(w) << (s))
136
137
138 static zstate_t zstate;
139 static volatile uint8_t timer; /* used for bus timeout */
140
141 /*---------------------------------------------------------*/
142 /* 10Hz timer interrupt generated by OC4A */
143 /*---------------------------------------------------------*/
144
145 ISR(TIMER5_COMPA_vect)
146 {
147
148 uint8_t i = timer;
149
150 if (i)
151 timer = i - 1;
152 }
153
154 /*--------------------------------------------------------------------------*/
155
156
157 static void z80_addrbus_set_in(void)
158 {
159 /* /MREQ, /RD, /WR: Input, no pullup */
160 DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
161 Z80_O_MREQ = 0;
162 Z80_O_RD = 0;
163 Z80_O_WR = 0;
164
165 P_ADL = 0;
166 DDR_ADL = 0;
167 P_ADH = 0;
168 DDR_ADH = 0;
169 PIN_ADB = P_ADB & (MASK(ADB_WIDTH) << ADB_SHIFT);
170 DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
171 }
172
173
174 static void z80_addrbus_set_out(void)
175 {
176 /* /MREQ, /RD, /WR: Output and high */
177 Z80_O_MREQ = 1;
178 Z80_O_RD = 1;
179 Z80_O_WR = 1;
180 DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
181
182 DDR_ADL = 0xff;
183 DDR_ADH = 0xff;
184 DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
185 }
186
187
188 static void z80_dbus_set_in(void)
189 {
190 DDR_DB = 0;
191 P_DB = 0;
192 }
193
194
195 static void z80_dbus_set_out(void)
196 {
197 DDR_DB = 0xff;
198 }
199
200
201 static void z80_reset_pulse(void)
202 {
203 Z80_O_RST = 0;
204 _delay_us(10);
205 Z80_O_RST = 1;
206 }
207
208
209 void z80_setup_bus(void)
210 {
211 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
212
213 /* /ZRESET: Output and low */
214 Z80_O_RST = 0;
215 DDR_RST |= _BV(RST);
216
217 /* /BUSREQ: Output and high */
218 Z80_O_BUSREQ = 1;
219 DDR_BUSREQ |= _BV(BUSREQ);
220
221 /* /BUSACK: Input, no pullup */
222 DDR_BUSACK &= ~_BV(BUSACK);
223 P_BUSACK &= ~_BV(BUSACK);
224
225 z80_addrbus_set_in();
226 z80_dbus_set_in();
227
228 if (getenv_yesno(PSTR(ENV_SINGLESTEP))) {
229 /* /RUN & /STEP: output, /WAIT: input */
230
231 PORT_SS = (PORT_SS & ~_BV(RUN)) | _BV(STEP);
232 DDR_SS = (DDR_SS & ~_BV(WAIT)) | _BV(RUN) | _BV(STEP);
233 }
234
235 zstate = RESET;
236 }
237
238 /* Timer 5 */
239 PRR1 &= ~_BV(PRTIM5);
240 OCR5A = F_CPU / 1024 / 10 - 1; /* Timer: 10Hz interval (OC4A) */
241 TCCR5B = (0b01<<WGM52)|(0b101<<CS40); /* CTC Mode, Prescaler 1024 */
242 TIMSK5 = _BV(OCIE5A); /* Enable oca interrupt */
243
244 }
245
246
247 zstate_t z80_bus_state(void)
248 {
249 return zstate;
250 }
251
252
253 static void z80_busreq_hpulse(void)
254 {
255 z80_dbus_set_in();
256 z80_addrbus_set_in();
257
258 #if 0
259 ATOMIC_BLOCK(ATOMIC_FORCEON) {
260 Z80_O_BUSREQ = 1;
261 Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
262 Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
263 }
264 #endif
265
266 ATOMIC_BLOCK(ATOMIC_FORCEON) {
267 Z80_O_BUSREQ = 1;
268
269 do {
270 if (Z80_I_BUSACK == 1) {
271 Z80_O_BUSREQ = 0;
272 break;
273 }
274 } while (1);
275 }
276
277
278 if (zstate & ZST_ACQUIRED) {
279 timer = BUS_TO;
280 while (Z80_I_BUSACK == 1 && timer)
281 ;
282 if (Z80_I_BUSACK == 0)
283 z80_addrbus_set_out();
284 }
285 }
286
287
288 /*
289
290 + | | | | |
291 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
292 + | | | | |
293 + | 0 | 1 | 2 | 3 |
294 Event + | | | | |
295 ----------------+---------------+---------------+---------------+---------------+
296 | | | | |
297 Reset | 0 | 0 | 0 | 0 |
298 | | | | |
299 | | | | |
300 Request | 1 | | 3 | |
301 | | | | |
302 | | | | |
303 Release | | 0 | | 2 |
304 | | | | |
305 | | | | |
306 Run | 2 | 3 | | |
307 | | | | |
308 | | | | |
309 Restart | | | 2 | 3 |
310 | | | | |
311 | | | | |
312 M_Cycle | | | | 3 |
313 | | | | |
314 | | | | |
315 */
316
317 zstate_t z80_bus_cmd(bus_cmd_t cmd)
318 {
319 switch (cmd) {
320
321 case Reset:
322 z80_dbus_set_in();
323 z80_addrbus_set_in();
324 Z80_O_RST = 0;
325 Z80_O_BUSREQ = 1;
326 zstate = RESET;
327 break;
328
329 case Request:
330 switch (zstate) {
331 case RESET:
332 Z80_O_BUSREQ = 0;
333 Z80_O_RST = 1;
334 timer = BUS_TO;
335 while (Z80_I_BUSACK == 1 && timer)
336 ;
337 if (Z80_I_BUSACK == 0) {
338 z80_addrbus_set_out();
339 zstate = RESET_AQRD;
340 } else {
341 Z80_O_RST = 0;
342 Z80_O_BUSREQ = 1;
343 }
344 break;
345
346 case RUNNING:
347 Z80_O_BUSREQ = 0;
348 timer = BUS_TO;
349 while (Z80_I_BUSACK == 1 && timer)
350 ;
351 if (Z80_I_BUSACK == 0) {
352 z80_addrbus_set_out();
353 zstate = RUNNING_AQRD;
354 } else {
355 Z80_O_BUSREQ = 1;
356 }
357 break;
358
359 default:
360 break;
361 }
362 break;
363
364 case Release:
365 switch (zstate) {
366 case RESET_AQRD:
367 z80_dbus_set_in();
368 z80_addrbus_set_in();
369 Z80_O_RST = 0;
370 Z80_O_BUSREQ = 1;
371 zstate = RESET;
372 break;
373 case RUNNING_AQRD:
374 z80_dbus_set_in();
375 z80_addrbus_set_in();
376 Z80_O_BUSREQ = 1;
377 zstate = RUNNING;
378 break;
379 default:
380 break;
381 }
382 break;
383
384 case Run:
385 switch (zstate) {
386 case RESET:
387 Z80_O_RST = 1;
388 zstate = RUNNING;
389 break;
390
391 case RESET_AQRD:
392 z80_dbus_set_in();
393 z80_addrbus_set_in();
394 z80_reset_pulse();
395 z80_addrbus_set_out();
396 zstate = RUNNING_AQRD;
397 break;
398 default:
399 break;
400 }
401 break;
402
403 case Restart:
404 switch (zstate) {
405 case RUNNING:
406 case RUNNING_AQRD:
407 z80_reset_pulse();
408 break;
409 default:
410 break;
411 }
412 break;
413
414 case M_Cycle:
415 switch (zstate) {
416 case RUNNING_AQRD:
417 z80_busreq_hpulse(); /* TODO: */
418 break;
419 default:
420 break;
421 }
422 }
423 return zstate;
424 }
425
426
427 /*--------------------------------------------------------------------------*/
428
429 static
430 //inline __attribute__ ((always_inline))
431 void z80_setaddress(uint32_t addr)
432 {
433 P_ADL = addr;
434 P_ADH = (addr & 0xff00) >> 8;
435 PIN_ADB = (((addr >> 16) << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT;
436 }
437
438 void z80_write(uint32_t addr, uint8_t data)
439 {
440 z80_setaddress(addr);
441 Z80_O_MREQ = 0;
442 z80_dbus_set_out();
443 P_DB = data;
444 P_DB = data;
445 Z80_O_WR = 0;
446 Z80_O_WR = 0;
447 Z80_O_WR = 1;
448 Z80_O_MREQ = 1;
449 }
450
451 uint8_t z80_read(uint32_t addr)
452 {
453 uint8_t data;
454
455 z80_setaddress(addr);
456 Z80_O_MREQ = 0;
457 z80_dbus_set_in();
458 Z80_O_RD = 0;
459 Z80_O_RD = 0;
460 Z80_O_RD = 0;
461 data = PIN_DB;
462 Z80_O_RD = 1;
463 Z80_O_MREQ = 1;
464
465 return data;
466 }
467
468
469 void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
470 {
471 z80_dbus_set_out();
472 Z80_O_MREQ = 0;
473 P_DB = data;
474 while(length--) {
475 z80_setaddress(addr++);
476 Z80_O_WR = 0;
477 Z80_O_WR = 0;
478 Z80_O_WR = 1;
479 }
480 Z80_O_MREQ = 1;
481 }
482
483 void z80_write_block_P(const FLASH uint8_t *src, uint32_t dest, uint32_t length)
484 {
485 uint8_t data;
486
487 z80_dbus_set_out();
488 Z80_O_MREQ = 0;
489 while(length--) {
490 z80_setaddress(dest++);
491 data = *src++;
492 P_DB = data;
493 P_DB = data;
494 Z80_O_WR = 0;
495 Z80_O_WR = 0;
496 Z80_O_WR = 1;
497 }
498 Z80_O_MREQ = 1;
499 }
500
501 void z80_write_block(const uint8_t *src, uint32_t dest, uint32_t length)
502 {
503 uint8_t data;
504
505 z80_dbus_set_out();
506 Z80_O_MREQ = 0;
507 while(length--) {
508 z80_setaddress(dest++);
509 data = *src++;
510 P_DB = data;
511 P_DB = data;
512 Z80_O_WR = 0;
513 Z80_O_WR = 0;
514 Z80_O_WR = 1;
515 }
516 Z80_O_MREQ = 1;
517 }
518
519 void z80_read_block (uint8_t *dest, uint32_t src, size_t length)
520 {
521 uint8_t data;
522
523 Z80_O_MREQ = 0;
524 z80_dbus_set_in();
525 while(length--) {
526 z80_setaddress(src++);
527 Z80_O_RD = 0;
528 Z80_O_RD = 0;
529 Z80_O_RD = 0;
530 data = PIN_DB;
531 Z80_O_RD = 1;
532 *dest++ = data;
533 }
534 Z80_O_MREQ = 1;
535 }
536
537
538 /*
539 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
540 017A' rx.in_idx: ds 1 ;
541 017B' rx.out_idx: ds 1 ;
542 017C' rx.buf: ds rx.buf_len ;
543 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
544
545 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
546 018D' tx.in_idx: ds 1 ;
547 018E' tx.out_idx: ds 1 ;
548 018F' tx.buf: ds tx.buf_len ;
549 019E' tx.buf_end equ $-1 ; last byte
550 */
551
552
553 typedef struct __attribute__((packed)) {
554 uint8_t mask;
555 uint8_t in_idx;
556 uint8_t out_idx;
557 uint8_t buf[];
558 } zfifo_t;
559
560
561
562 #define FIFO_BUFSIZE_MASK -3
563 #define FIFO_INDEX_IN -2
564 #define FIFO_INDEX_OUT -1
565
566
567 static struct {
568 uint32_t base;
569 uint8_t idx_out,
570 idx_in,
571 mask;
572 } fifo_dsc[NUM_FIFOS];
573
574
575 void z80_memfifo_init(const fifo_t f, uint32_t addr)
576 {
577 fifo_dsc[f].base = addr;
578
579 DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, addr);
580
581 if (addr != 0) {
582 z80_bus_cmd(Request);
583 fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK);
584 fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN);
585 fifo_dsc[f].idx_out = z80_read(addr + FIFO_INDEX_OUT);
586 z80_bus_cmd(Release);
587 }
588 }
589
590
591 int z80_memfifo_is_empty(const fifo_t f)
592 {
593 int rc = 1;
594
595 if (fifo_dsc[f].base != 0) {
596
597 uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
598 uint8_t idx;
599
600 z80_bus_cmd(Request);
601 idx = z80_read(adr);
602 z80_bus_cmd(Release);
603 rc = idx == fifo_dsc[f].idx_out;
604 }
605
606 return rc;
607 }
608
609 int z80_memfifo_is_full(const fifo_t f)
610 {
611 int rc = 0;
612
613 if (fifo_dsc[f].base != 0) {
614 z80_bus_cmd(Request);
615 rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
616 == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
617 z80_bus_cmd(Release);
618 }
619 return rc;
620 }
621
622
623 uint8_t z80_memfifo_getc_wait(const fifo_t f)
624 {
625 uint8_t rc, idx;
626
627 while (z80_memfifo_is_empty(f))
628 ;
629
630 z80_bus_cmd(Request);
631 idx = fifo_dsc[f].idx_out;
632 rc = z80_read(fifo_dsc[f].base+idx);
633 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
634 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
635 z80_bus_cmd(Release);
636
637 return rc;
638 }
639
640 int z80_memfifo_getc(const fifo_t f)
641 {
642 int rc = -1;
643
644 if (fifo_dsc[f].base != 0) {
645 uint8_t idx = fifo_dsc[f].idx_out;
646 z80_bus_cmd(Request);
647 if (idx != z80_read(fifo_dsc[f].base + FIFO_INDEX_IN)) {
648 rc = z80_read(fifo_dsc[f].base+idx);
649 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
650 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
651 }
652 z80_bus_cmd(Release);
653 }
654
655 return rc;
656 }
657
658
659 void z80_memfifo_putc(fifo_t f, uint8_t val)
660 {
661 int idx;
662
663 while (z80_memfifo_is_full(f))
664 ;
665
666 z80_bus_cmd(Request);
667 idx = fifo_dsc[f].idx_in;
668 z80_write(fifo_dsc[f].base+idx, val);
669 fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
670 z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
671 z80_bus_cmd(Release);
672 }