]>
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 PIN_BUSREQ PIND
76 #define DDR_BUSREQ DDRD
77 #define P_BUSACK PORTD
78 #define PIN_BUSACK PIND
80 #define DDR_BUSACK DDRD
101 //#define ADB_PORT PORTE
104 //#define Z80_O_ZCLK SBIT(P_ZCLK, 5)
105 #define Z80_O_MREQ SBIT(P_MREQ, 4)
106 #define Z80_O_RD SBIT(P_RD, 3)
107 #define Z80_O_WR SBIT(P_WR, 2)
108 #define Z80_O_BUSREQ SBIT(P_BUSREQ, 7)
109 #define Z80_I_BUSREQ SBIT(PIN_BUSREQ, 7)
110 //#define Z80_O_NMI SBIT(P_NMI, )
111 #define Z80_O_RST SBIT(P_RST, 5)
112 #define Z80_I_RST SBIT(PIN_RST, 5)
113 #define Z80_I_BUSACK SBIT(PIN_BUSACK, 6)
114 //#define Z80_I_HALT SBIT(P_HALT, )
122 #define DDR_STEP DDRG
125 #define DDR_WAIT DDRG
126 /* All three signals are on the same Port (PortG) */
127 #define PORT_SS PORTG
130 #define Z80_O_RUN SBIT(PORT_SS, RUN)
131 #define Z80_O_STEP SBIT(PORT_SS, STEP)
132 #define Z80_I_WAIT SBIT(PORT_SS, WAIT)
138 #define MASK(n) ((1<<(n))-1)
139 #define SMASK(w,s) (MASK(w) << (s))
141 void z80_bus_request_or_exit(void)
143 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
))
144 cmd_error(CMD_RET_FAILURE
, EBUSTO
, NULL
);
147 static zstate_t zstate
;
148 static volatile uint8_t timer
; /* used for bus timeout */
151 static volatile uint16_t busack_cycles_ovl
;
153 static uint32_t busack_cycles
;
155 ISR(TIMER4_COMPB_vect
)
160 /*---------------------------------------------------------*/
161 /* 10Hz timer interrupt generated by OC5A */
162 /*---------------------------------------------------------*/
164 ISR(TIMER5_COMPA_vect
)
172 /*--------------------------------------------------------------------------*/
175 static void z80_addrbus_set_in(void)
177 /* /MREQ, /RD, /WR: Input, no pullup */
178 DDR_MREQ
&= ~(_BV(MREQ
) | _BV(RD
) | _BV(WR
));
187 PIN_ADB
= P_ADB
& (MASK(ADB_WIDTH
) << ADB_SHIFT
);
188 DDR_ADB
= DDR_ADB
& ~(MASK(ADB_WIDTH
) << ADB_SHIFT
);
192 static void z80_addrbus_set_out(void)
194 /* /MREQ, /RD, /WR: Output and high */
198 DDR_MREQ
|= _BV(MREQ
) | _BV(RD
) | _BV(WR
);
202 DDR_ADB
= DDR_ADB
| (MASK(ADB_WIDTH
) << ADB_SHIFT
);
206 static void z80_dbus_set_in(void)
213 static void z80_dbus_set_out(void)
218 static void z80_reset_active(void)
220 if (Stat
& S_RESET_POLARITY
)
226 static void z80_reset_inactive(void)
228 if (Stat
& S_RESET_POLARITY
)
234 static void z80_reset_pulse(void)
238 z80_reset_inactive();
242 void z80_setup_bus(void)
244 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
246 /* /ZRESET: Input, no pullup */
247 DDR_RST
&= ~_BV(RST
);
250 /* /BUSREQ: Output and high */
252 DDR_BUSREQ
|= _BV(BUSREQ
);
254 /* /BUSACK: Input, no pullup */
255 DDR_BUSACK
&= ~_BV(BUSACK
);
256 P_BUSACK
&= ~_BV(BUSACK
);
258 z80_addrbus_set_in();
261 if (getenv_yesno(PSTR(ENV_SINGLESTEP
))) {
262 /* /RUN & /STEP: output, /WAIT: input */
264 PORT_SS
= (PORT_SS
& ~_BV(RUN
)) | _BV(STEP
);
265 DDR_SS
= (DDR_SS
& ~_BV(WAIT
)) | _BV(RUN
) | _BV(STEP
);
269 Stat
|= S_RESET_POLARITY
;
271 Stat
&= ~S_RESET_POLARITY
;
279 PRR1
&= ~_BV(PRTIM5
);
280 OCR5A
= F_CPU
/ 1024 / 10 - 1; /* Timer: 10Hz interval (OC4A) */
281 TCCR5B
= (0b01<<WGM52
)|(0b101<<CS40
); /* CTC Mode, Prescaler 1024 */
282 TIMSK5
= _BV(OCIE5A
); /* Enable oca interrupt */
287 uint32_t z80_get_busreq_cycles(void)
289 return busack_cycles
;
292 zstate_t
z80_bus_state(void)
297 void z80_toggle_reset(void)
302 void z80_toggle_busreq(void)
308 static void z80_busreq_hpulse(void)
311 z80_addrbus_set_in();
314 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
316 Z80_O_BUSREQ
= 1; /* 2 AVR clock cycles */
317 Z80_O_BUSREQ
= 0; /* 2 AVR clock cycles */
322 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
326 if (Z80_I_BUSACK
== 1) {
334 if (zstate
& ZST_ACQUIRED
) {
336 while (Z80_I_BUSACK
== 1 && timer
)
338 if (Z80_I_BUSACK
== 0)
339 z80_addrbus_set_out();
347 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
351 ----------------+---------------+---------------+---------------+---------------+
353 Reset | 0 | 0 | 0 | 0 |
356 Request | 1 | | 3 | |
359 Release | | 0 | | 2 |
365 Restart | | | 2 | 3 |
373 zstate_t
z80_bus_cmd(bus_cmd_t cmd
)
379 z80_addrbus_set_in();
384 while (Z80_I_BUSACK
== 0 && timer
)
393 timer
= 255; //BUS_TO;
399 busack_cycles_ovl
= 0;
400 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
401 Z80_I_RST
= 1; /* Toggle RESET --> inactive */
403 TIFR4
= _BV(OCF4B
); /* Clear compare match flag */
404 // TIMSK4 &= ~_BV(OCIE4A); /* Disable Output Compare A interrupt */
406 TIMSK4
|= _BV(OCIE4B
); /* Enable compare match interrupt */
408 while (Z80_I_BUSACK
== 1 && timer
)
411 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
412 tcnt
= TCNT4
- OCR4B
;
413 ovl_cnt
= busack_cycles_ovl
;
415 TIMSK4
&= ~_BV(OCIE4B
); /* Disable compare match interrupt */
416 // TIMSK4 |= _BV(OCIE4A); /* Enable Output Compare A interrupt */
418 if (Z80_I_BUSACK
== 0) {
419 if ((ifr
& _BV(OCF4B
)) && !(tcnt
& (1<<15)))
421 busack_cycles
= tcnt
+ ((uint32_t) ovl_cnt
<< 16);
422 z80_addrbus_set_out();
424 // debug("### ovl: %u, ifr: %u, beg: %u, end: %u\n", ovl_cnt,
425 // (ifr & _BV(OCF4B)) != 0, OCR4B, tcnt);
435 while (Z80_I_BUSACK
== 1 && timer
)
437 if (Z80_I_BUSACK
== 0) {
438 z80_addrbus_set_out();
439 zstate
= RUNNING_AQRD
;
454 z80_addrbus_set_in();
459 while (Z80_I_BUSACK
== 0 && timer
)
465 z80_addrbus_set_in();
468 while (Z80_I_BUSACK
== 0 && timer
)
480 _delay_ms(20); /* TODO: */
481 z80_reset_inactive();
487 z80_addrbus_set_in();
489 z80_addrbus_set_out();
490 zstate
= RUNNING_AQRD
;
511 z80_busreq_hpulse(); /* TODO: */
520 /*--------------------------------------------------------------------------*/
522 #define DEBUG_FREQ 0 /* set to 1 to debug */
524 #define debug_cpu(fmt, args...) \
525 debug_cond(DEBUG_FREQ, fmt, ##args)
529 char * ulltoa (uint64_t val
, char *s
)
534 *p
++ = (val
% 10) + '0';
544 uint32_t z80_measure_phi(uint_fast8_t cycles
)
552 PRR1
&= ~_BV(PRTIM3
);
554 TCCR3B
= 0b000<<CS30
; /* stop counter */
560 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
561 EIFR
= _BV(INTF6
); /* Reset pending int */
562 while ((EIFR
& _BV(INTF6
)) == 0) /* Wait for falling edge */
565 TCCR3B
= 0b110<<CS30
; /* Count falling edges on T3 (==INT6) */
566 TIFR4
= _BV(OCF4B
); /* clear compare match flag */
568 while (ref_ovfl
< 60) {
569 if ((TIFR4
& _BV(OCF4B
)) != 0) {
573 if ((TIFR3
& _BV(TOV3
)) != 0) {
581 if (EIFR
& _BV(INTF6
)) {
582 TCCR3B
= 0b000<<CS30
; /* stop counter */
586 if ((TIFR4
& _BV(OCF4B
)) != 0) {
593 if ((TIFR3
& _BV(TOV3
)) != 0) {
598 uint32_t ref_cnt
= (ref_stop
- OCR4B
) + ((uint32_t)ref_ovfl
<< 16);
599 uint32_t x_cnt
= TCNT3
+ ((uint32_t) x_ovfl
<< 16);
600 uint64_t x_tmp
= (uint64_t) 100000 * (x_cnt
* cycles
);
606 debug_cpu("\nx_ovfl: %6u, TCNT3: %6u, cycles: %3u\n", x_ovfl
, TCNT3
, cycles
);
607 debug_cpu("ref_ovfl: %6u, ref_...: %6u\n", ref_ovfl
, ref_stop
-OCR4B
);
608 debug_cpu("x_cnt: %9lu, ref_cnt: %9lu\n", x_cnt
, ref_cnt
);
610 x_tmp
= (x_tmp
* getenv_ulong(PSTR(ENV_FMON
), 10, F_CPU
) + (ref_cnt
/ 2)) / ref_cnt
;
612 /* round to 5 decimal digits */
614 for ( ; sc
> 0 || x_tmp
>= 100000; sc
--) x_tmp
= (x_tmp
+ 5)/10;
616 for ( ; sc
< 0; sc
++) x_freq
*= 10;
621 /*--------------------------------------------------------------------------*/
624 //inline __attribute__ ((always_inline))
625 void z80_setaddress(uint32_t addr
)
628 P_ADH
= (addr
& 0xff00) >> 8;
629 PIN_ADB
= (((addr
>> 16) << ADB_SHIFT
) ^ P_ADB
) & MASK(ADB_WIDTH
) << ADB_SHIFT
;
632 int32_t z80_memsize_detect(void)
634 const uint8_t PATTERN_1
= 0x55;
635 const uint8_t PATTERN_2
= ~PATTERN_1
;
638 if (!(z80_bus_cmd(Request
) & ZST_ACQUIRED
))
641 uint8_t ram_0
= z80_read(0);
642 uint8_t ram_1
= z80_read(1);
644 z80_write(0, ram_0
^ 0xff);
646 if ((z80_read(0) ^ ram_0
) != 0xff) {
649 z80_write(0, PATTERN_1
);
650 for (addr
=1; addr
< CONFIG_SYS_RAMSIZE_MAX
; addr
<<= 1) {
651 uint8_t ram_i
= z80_read(addr
);
652 z80_write(addr
, PATTERN_2
);
653 if (z80_read(0) != PATTERN_1
|| z80_read(addr
) != PATTERN_2
)
655 z80_write(addr
, ram_i
);
660 z80_bus_cmd(Release
);
665 /*--------------------------------------------------------------------------*/
667 void z80_write(uint32_t addr
, uint8_t data
)
669 z80_setaddress(addr
);
680 uint8_t z80_read(uint32_t addr
)
684 z80_setaddress(addr
);
698 void z80_memset(uint32_t addr
, uint8_t data
, uint32_t length
)
704 z80_setaddress(addr
++);
712 void z80_write_block_P(const FLASH
uint8_t *src
, uint32_t dest
, uint32_t length
)
719 z80_setaddress(dest
++);
730 void z80_write_block(const uint8_t *src
, uint32_t dest
, uint32_t length
)
737 z80_setaddress(dest
++);
748 void z80_read_block (uint8_t *dest
, uint32_t src
, size_t length
)
755 z80_setaddress(src
++);
766 /*--------------------------------------------------------------------------*/
769 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
770 017A' rx.in_idx: ds 1 ;
771 017B' rx.out_idx: ds 1 ;
772 017C' rx.buf: ds rx.buf_len ;
773 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
775 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
776 018D' tx.in_idx: ds 1 ;
777 018E' tx.out_idx: ds 1 ;
778 018F' tx.buf: ds tx.buf_len ;
779 019E' tx.buf_end equ $-1 ; last byte
783 typedef struct __attribute__((packed
)) {
792 #define FIFO_BUFSIZE_MASK -3
793 #define FIFO_INDEX_IN -2
794 #define FIFO_INDEX_OUT -1
802 } fifo_dsc
[NUM_FIFOS
];
805 void z80_memfifo_init(const fifo_t f
, uint32_t addr
)
807 fifo_dsc
[f
].base
= addr
;
811 z80_bus_cmd(Request
);
812 fifo_dsc
[f
].mask
= z80_read(addr
+ FIFO_BUFSIZE_MASK
);
813 fifo_dsc
[f
].idx_in
= z80_read(addr
+ FIFO_INDEX_IN
);
814 fifo_dsc
[f
].idx_out
= z80_read(addr
+ FIFO_INDEX_OUT
);
815 z80_bus_cmd(Release
);
817 if (fifo_dsc
[f
].idx_in
!= 0 || fifo_dsc
[f
].idx_out
!= 0) {
818 DBG_P(1, "## z80_memfifo_init: %i, %lx, in: %.2x, out: %.2x, mask: %.2x\n",
819 f
, addr
, fifo_dsc
[f
].idx_in
, fifo_dsc
[f
].idx_out
, fifo_dsc
[f
].mask
);
825 int z80_memfifo_is_empty(const fifo_t f
)
829 if (fifo_dsc
[f
].base
!= 0) {
831 uint32_t adr
= fifo_dsc
[f
].base
+ FIFO_INDEX_IN
;
834 z80_bus_cmd(Request
);
836 z80_bus_cmd(Release
);
837 rc
= idx
== fifo_dsc
[f
].idx_out
;
843 int z80_memfifo_is_full(const fifo_t f
)
847 if (fifo_dsc
[f
].base
!= 0) {
848 z80_bus_cmd(Request
);
849 rc
= ((fifo_dsc
[f
].idx_in
+ 1) & fifo_dsc
[f
].mask
)
850 == z80_read(fifo_dsc
[f
].base
+FIFO_INDEX_OUT
);
851 z80_bus_cmd(Release
);
857 uint8_t z80_memfifo_getc_wait(const fifo_t f
)
861 while (z80_memfifo_is_empty(f
))
864 z80_bus_cmd(Request
);
865 idx
= fifo_dsc
[f
].idx_out
;
866 rc
= z80_read(fifo_dsc
[f
].base
+idx
);
867 fifo_dsc
[f
].idx_out
= ++idx
& fifo_dsc
[f
].mask
;
868 z80_write(fifo_dsc
[f
].base
+FIFO_INDEX_OUT
, fifo_dsc
[f
].idx_out
);
869 z80_bus_cmd(Release
);
874 int z80_memfifo_getc(const fifo_t f
)
878 if (fifo_dsc
[f
].base
!= 0) {
879 uint8_t idx
= fifo_dsc
[f
].idx_out
;
880 z80_bus_cmd(Request
);
881 if (idx
!= z80_read(fifo_dsc
[f
].base
+ FIFO_INDEX_IN
)) {
882 rc
= z80_read(fifo_dsc
[f
].base
+idx
);
883 fifo_dsc
[f
].idx_out
= ++idx
& fifo_dsc
[f
].mask
;
884 z80_write(fifo_dsc
[f
].base
+FIFO_INDEX_OUT
, fifo_dsc
[f
].idx_out
);
886 z80_bus_cmd(Release
);
893 void z80_memfifo_putc(fifo_t f
, uint8_t val
)
897 while (z80_memfifo_is_full(f
))
900 z80_bus_cmd(Request
);
901 idx
= fifo_dsc
[f
].idx_in
;
902 z80_write(fifo_dsc
[f
].base
+idx
, val
);
903 fifo_dsc
[f
].idx_in
= ++idx
& fifo_dsc
[f
].mask
;
904 z80_write(fifo_dsc
[f
].base
+FIFO_INDEX_IN
, fifo_dsc
[f
].idx_in
);
905 z80_bus_cmd(Release
);
908 /*--------------------------------------------------------------------------*/
910 void z80_load_mem(int_fast8_t verbosity
,
911 const FLASH
unsigned char data
[],
912 const FLASH
unsigned long *sections
,
913 const FLASH
unsigned long address
[],
914 const FLASH
unsigned long length_of_sections
[])
916 uint32_t sec_base
= 0;
919 printf_P(PSTR("Loading Z180 memory... \n"));
921 for (unsigned sec
= 0; sec
< *sections
; sec
++) {
923 printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"),
925 address
[sec
]+length_of_sections
[sec
] - 1,
926 length_of_sections
[sec
]);
929 z80_write_block_P((const FLASH
unsigned char *) &data
[sec_base
], /* src */
930 address
[sec
], /* dest */
931 length_of_sections
[sec
]); /* len */
932 sec_base
+= length_of_sections
[sec
];