]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/z80-if.c
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
4 * SPDX-License-Identifier: GPL-2.0
11 * | Z180-Sig | AVR-Port | Dir |
12 * +------------+---------------+-------+
44 * | BUSREQ | PD 7 | O |
45 * | BUSACK | PD 6 | I |
48 * +------------------------------------+
57 #include <util/atomic.h>
63 //#define P_ZCLK PORTB
65 //#define DDR_ZCLK DDRB
73 #define P_BUSREQ PORTD
75 #define DDR_BUSREQ DDRD
76 #define P_BUSACK PORTD
77 #define PIN_BUSACK PIND
79 #define DDR_BUSACK DDRD
99 //#define ADB_PORT PORTE
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, )
118 #define DDR_STEP DDRG
121 #define DDR_WAIT DDRG
122 /* All three signals are on the same Port (PortG) */
123 #define PORT_SS PORTG
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)
134 #define MASK(n) ((1<<(n))-1)
135 #define SMASK(w,s) (MASK(w) << (s))
138 static zstate_t zstate
;
139 static volatile uint8_t timer
; /* used for bus timeout */
141 /*---------------------------------------------------------*/
142 /* 10Hz timer interrupt generated by OC4A */
143 /*---------------------------------------------------------*/
145 ISR(TIMER5_COMPA_vect
)
154 /*--------------------------------------------------------------------------*/
157 static void z80_addrbus_set_in(void)
159 /* /MREQ, /RD, /WR: Input, no pullup */
160 DDR_MREQ
&= ~(_BV(MREQ
) | _BV(RD
) | _BV(WR
));
169 PIN_ADB
= P_ADB
& (MASK(ADB_WIDTH
) << ADB_SHIFT
);
170 DDR_ADB
= DDR_ADB
& ~(MASK(ADB_WIDTH
) << ADB_SHIFT
);
174 static void z80_addrbus_set_out(void)
176 /* /MREQ, /RD, /WR: Output and high */
180 DDR_MREQ
|= _BV(MREQ
) | _BV(RD
) | _BV(WR
);
184 DDR_ADB
= DDR_ADB
| (MASK(ADB_WIDTH
) << ADB_SHIFT
);
188 static void z80_dbus_set_in(void)
195 static void z80_dbus_set_out(void)
201 static void z80_reset_pulse(void)
209 void z80_setup_bus(void)
211 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
213 /* /ZRESET: Output and low */
217 /* /BUSREQ: Output and high */
219 DDR_BUSREQ
|= _BV(BUSREQ
);
221 /* /BUSACK: Input, no pullup */
222 DDR_BUSACK
&= ~_BV(BUSACK
);
223 P_BUSACK
&= ~_BV(BUSACK
);
225 z80_addrbus_set_in();
228 if (getenv_yesno(PSTR(ENV_SINGLESTEP
))) {
229 /* /RUN & /STEP: output, /WAIT: input */
231 PORT_SS
= (PORT_SS
& ~_BV(RUN
)) | _BV(STEP
);
232 DDR_SS
= (DDR_SS
& ~_BV(WAIT
)) | _BV(RUN
) | _BV(STEP
);
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 */
247 zstate_t
z80_bus_state(void)
253 static void z80_busreq_hpulse(void)
256 z80_addrbus_set_in();
259 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
261 Z80_O_BUSREQ
= 1; /* 2 AVR clock cycles */
262 Z80_O_BUSREQ
= 0; /* 2 AVR clock cycles */
267 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
271 if (Z80_I_BUSACK
== 1) {
279 if (zstate
& ZST_ACQUIRED
) {
281 while (Z80_I_BUSACK
== 1 && timer
)
283 if (Z80_I_BUSACK
== 0)
284 z80_addrbus_set_out();
292 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
296 ----------------+---------------+---------------+---------------+---------------+
298 Reset | 0 | 0 | 0 | 0 |
301 Request | 1 | | 3 | |
304 Release | | 0 | | 2 |
310 Restart | | | 2 | 3 |
318 zstate_t
z80_bus_cmd(bus_cmd_t cmd
)
324 z80_addrbus_set_in();
336 while (Z80_I_BUSACK
== 1 && timer
)
338 if (Z80_I_BUSACK
== 0) {
339 z80_addrbus_set_out();
350 while (Z80_I_BUSACK
== 1 && timer
)
352 if (Z80_I_BUSACK
== 0) {
353 z80_addrbus_set_out();
354 zstate
= RUNNING_AQRD
;
369 z80_addrbus_set_in();
376 z80_addrbus_set_in();
394 z80_addrbus_set_in();
396 z80_addrbus_set_out();
397 zstate
= RUNNING_AQRD
;
418 z80_busreq_hpulse(); /* TODO: */
428 /*--------------------------------------------------------------------------*/
431 //inline __attribute__ ((always_inline))
432 void z80_setaddress(uint32_t addr
)
435 P_ADH
= (addr
& 0xff00) >> 8;
436 PIN_ADB
= (((addr
>> 16) << ADB_SHIFT
) ^ P_ADB
) & MASK(ADB_WIDTH
) << ADB_SHIFT
;
439 void z80_write(uint32_t addr
, uint8_t data
)
441 z80_setaddress(addr
);
452 uint8_t z80_read(uint32_t addr
)
456 z80_setaddress(addr
);
470 void z80_memset(uint32_t addr
, uint8_t data
, uint32_t length
)
476 z80_setaddress(addr
++);
484 void z80_write_block_P(const FLASH
uint8_t *src
, uint32_t dest
, uint32_t length
)
491 z80_setaddress(dest
++);
502 void z80_write_block(const uint8_t *src
, uint32_t dest
, uint32_t length
)
509 z80_setaddress(dest
++);
520 void z80_read_block (uint8_t *dest
, uint32_t src
, size_t length
)
527 z80_setaddress(src
++);
540 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
541 017A' rx.in_idx: ds 1 ;
542 017B' rx.out_idx: ds 1 ;
543 017C' rx.buf: ds rx.buf_len ;
544 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
546 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
547 018D' tx.in_idx: ds 1 ;
548 018E' tx.out_idx: ds 1 ;
549 018F' tx.buf: ds tx.buf_len ;
550 019E' tx.buf_end equ $-1 ; last byte
554 typedef struct __attribute__((packed
)) {
563 #define FIFO_BUFSIZE_MASK -3
564 #define FIFO_INDEX_IN -2
565 #define FIFO_INDEX_OUT -1
573 } fifo_dsc
[NUM_FIFOS
];
576 void z80_memfifo_init(const fifo_t f
, uint32_t addr
)
578 fifo_dsc
[f
].base
= addr
;
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
);
588 if (fifo_dsc
[f
].idx_in
!= 0 || fifo_dsc
[f
].idx_out
!= 0) {
589 DBG_P(1, "## z80_memfifo_init: %i, %lx, in: %.2x, out: %.2x, mask: %.2x\n",
590 f
, addr
, fifo_dsc
[f
].idx_in
, fifo_dsc
[f
].idx_out
, fifo_dsc
[f
].mask
);
596 int z80_memfifo_is_empty(const fifo_t f
)
600 if (fifo_dsc
[f
].base
!= 0) {
602 uint32_t adr
= fifo_dsc
[f
].base
+ FIFO_INDEX_IN
;
605 z80_bus_cmd(Request
);
607 z80_bus_cmd(Release
);
608 rc
= idx
== fifo_dsc
[f
].idx_out
;
614 int z80_memfifo_is_full(const fifo_t f
)
618 if (fifo_dsc
[f
].base
!= 0) {
619 z80_bus_cmd(Request
);
620 rc
= ((fifo_dsc
[f
].idx_in
+ 1) & fifo_dsc
[f
].mask
)
621 == z80_read(fifo_dsc
[f
].base
+FIFO_INDEX_OUT
);
622 z80_bus_cmd(Release
);
628 uint8_t z80_memfifo_getc_wait(const fifo_t f
)
632 while (z80_memfifo_is_empty(f
))
635 z80_bus_cmd(Request
);
636 idx
= fifo_dsc
[f
].idx_out
;
637 rc
= z80_read(fifo_dsc
[f
].base
+idx
);
638 fifo_dsc
[f
].idx_out
= ++idx
& fifo_dsc
[f
].mask
;
639 z80_write(fifo_dsc
[f
].base
+FIFO_INDEX_OUT
, fifo_dsc
[f
].idx_out
);
640 z80_bus_cmd(Release
);
645 int z80_memfifo_getc(const fifo_t f
)
649 if (fifo_dsc
[f
].base
!= 0) {
650 uint8_t idx
= fifo_dsc
[f
].idx_out
;
651 z80_bus_cmd(Request
);
652 if (idx
!= z80_read(fifo_dsc
[f
].base
+ FIFO_INDEX_IN
)) {
653 rc
= z80_read(fifo_dsc
[f
].base
+idx
);
654 fifo_dsc
[f
].idx_out
= ++idx
& fifo_dsc
[f
].mask
;
655 z80_write(fifo_dsc
[f
].base
+FIFO_INDEX_OUT
, fifo_dsc
[f
].idx_out
);
657 z80_bus_cmd(Release
);
664 void z80_memfifo_putc(fifo_t f
, uint8_t val
)
668 while (z80_memfifo_is_full(f
))
671 z80_bus_cmd(Request
);
672 idx
= fifo_dsc
[f
].idx_in
;
673 z80_write(fifo_dsc
[f
].base
+idx
, val
);
674 fifo_dsc
[f
].idx_in
= ++idx
& fifo_dsc
[f
].mask
;
675 z80_write(fifo_dsc
[f
].base
+FIFO_INDEX_IN
, fifo_dsc
[f
].idx_in
);
676 z80_bus_cmd(Release
);