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