X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/blobdiff_plain/b30c4e8f1aef96f6fdc93da9f125545f5f74d06e..aea51b6c4c93c56715f50e64d424e1181c6d0242:/avr/z80-if.c diff --git a/avr/z80-if.c b/avr/z80-if.c index e36b369..5a4104d 100644 --- a/avr/z80-if.c +++ b/avr/z80-if.c @@ -72,6 +72,7 @@ #define WR 2 #define P_BUSREQ PORTD #define BUSREQ 7 +#define PIN_BUSREQ PIND #define DDR_BUSREQ DDRD #define P_BUSACK PORTD #define PIN_BUSACK PIND @@ -105,6 +106,7 @@ #define Z80_O_RD SBIT(P_RD, 3) #define Z80_O_WR SBIT(P_WR, 2) #define Z80_O_BUSREQ SBIT(P_BUSREQ, 7) +#define Z80_I_BUSREQ SBIT(PIN_BUSREQ, 7) //#define Z80_O_NMI SBIT(P_NMI, ) #define Z80_O_RST SBIT(P_RST, 5) #define Z80_I_RST SBIT(PIN_RST, 5) @@ -136,13 +138,27 @@ #define MASK(n) ((1<<(n))-1) #define SMASK(w,s) (MASK(w) << (s)) +void z80_bus_request_or_exit(void) +{ + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) + cmd_error(CMD_RET_FAILURE, EBUSTO, NULL); +} static zstate_t zstate; static volatile uint8_t timer; /* used for bus timeout */ -static bool reset_polarity; + + +static volatile uint16_t busack_cycles_ovl; + +static uint32_t busack_cycles; + +ISR(TIMER4_COMPB_vect) +{ + busack_cycles_ovl++; +} /*---------------------------------------------------------*/ -/* 10Hz timer interrupt generated by OC4A */ +/* 10Hz timer interrupt generated by OC5A */ /*---------------------------------------------------------*/ ISR(TIMER5_COMPA_vect) @@ -202,7 +218,7 @@ static void z80_dbus_set_out(void) static void z80_reset_active(void) { - if (reset_polarity) + if (Stat & S_RESET_POLARITY) Z80_O_RST = 1; else Z80_O_RST = 0; @@ -210,7 +226,7 @@ static void z80_reset_active(void) static void z80_reset_inactive(void) { - if (reset_polarity) + if (Stat & S_RESET_POLARITY) Z80_O_RST = 0; else Z80_O_RST = 1; @@ -250,7 +266,10 @@ void z80_setup_bus(void) DDR_SS = (DDR_SS & ~_BV(WAIT)) | _BV(RUN) | _BV(STEP); } - reset_polarity = Z80_I_RST; + if (Z80_I_RST) + Stat |= S_RESET_POLARITY; + else + Stat &= ~S_RESET_POLARITY; z80_reset_active(); DDR_RST |= _BV(RST); @@ -266,11 +285,26 @@ void z80_setup_bus(void) } +uint32_t z80_get_busreq_cycles(void) +{ + return busack_cycles; +} + zstate_t z80_bus_state(void) { return zstate; } +void z80_toggle_reset(void) +{ + Z80_I_RST = 1; +} + +void z80_toggle_busreq(void) +{ + Z80_I_BUSREQ = 1; +} + static void z80_busreq_hpulse(void) { @@ -345,7 +379,11 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) z80_dbus_set_in(); z80_addrbus_set_in(); z80_reset_active(); + _delay_us(10); Z80_O_BUSREQ = 1; + timer = BUS_TO; + while (Z80_I_BUSACK == 0 && timer) + ; zstate = RESET; break; @@ -353,13 +391,39 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) switch (zstate) { case RESET: Z80_O_BUSREQ = 0; - z80_reset_inactive(); - timer = BUS_TO; + timer = 255; //BUS_TO; + + uint16_t tcnt; + uint16_t ovl_cnt; + uint8_t ifr; + busack_cycles = 0; + busack_cycles_ovl = 0; + ATOMIC_BLOCK(ATOMIC_FORCEON) { + Z80_I_RST = 1; /* Toggle RESET --> inactive */ + OCR4B = TCNT4; + TIFR4 = _BV(OCF4B); /* Clear compare match flag */ +// TIMSK4 &= ~_BV(OCIE4A); /* Disable Output Compare A interrupt */ + } + TIMSK4 |= _BV(OCIE4B); /* Enable compare match interrupt */ + while (Z80_I_BUSACK == 1 && timer) ; + + ATOMIC_BLOCK(ATOMIC_FORCEON) { + tcnt = TCNT4 - OCR4B; + ovl_cnt = busack_cycles_ovl; + ifr = TIFR4; + TIMSK4 &= ~_BV(OCIE4B); /* Disable compare match interrupt */ +// TIMSK4 |= _BV(OCIE4A); /* Enable Output Compare A interrupt */ + } if (Z80_I_BUSACK == 0) { + if ((ifr & _BV(OCF4B)) && !(tcnt & (1<<15))) + ovl_cnt++; + busack_cycles = tcnt + ((uint32_t) ovl_cnt << 16); z80_addrbus_set_out(); zstate = RESET_AQRD; +// debug("### ovl: %u, ifr: %u, beg: %u, end: %u\n", ovl_cnt, +// (ifr & _BV(OCF4B)) != 0, OCR4B, tcnt); } else { z80_reset_active(); Z80_O_BUSREQ = 1; @@ -390,13 +454,20 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) z80_dbus_set_in(); z80_addrbus_set_in(); z80_reset_active(); + _delay_us(10); Z80_O_BUSREQ = 1; + timer = BUS_TO; + while (Z80_I_BUSACK == 0 && timer) + ; zstate = RESET; break; case RUNNING_AQRD: z80_dbus_set_in(); z80_addrbus_set_in(); Z80_O_BUSREQ = 1; + timer = BUS_TO; + while (Z80_I_BUSACK == 0 && timer) + ; zstate = RUNNING; break; default: @@ -407,6 +478,7 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) case Run: switch (zstate) { case RESET: + _delay_ms(20); /* TODO: */ z80_reset_inactive(); zstate = RUNNING; break; @@ -458,6 +530,41 @@ void z80_setaddress(uint32_t addr) PIN_ADB = (((addr >> 16) << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT; } +int32_t z80_memsize_detect(void) +{ + const uint8_t PATTERN_1 = 0x55; + const uint8_t PATTERN_2 = ~PATTERN_1; + uint32_t addr; + + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) + return -EBUSTO; + + uint8_t ram_0 = z80_read(0); + uint8_t ram_1 = z80_read(1); + + z80_write(0, ram_0 ^ 0xff); + z80_write(1, ram_1); + if ((z80_read(0) ^ ram_0) != 0xff) { + addr = 0; + } else { + z80_write(0, PATTERN_1); + for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) { + uint8_t ram_i = z80_read(addr); + z80_write(addr, PATTERN_2); + if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2) + break; + z80_write(addr, ram_i); + } + } + + z80_write(0, ram_0); + z80_bus_cmd(Release); + + return addr; +} + +/*--------------------------------------------------------------------------*/ + void z80_write(uint32_t addr, uint8_t data) { z80_setaddress(addr); @@ -557,6 +664,7 @@ void z80_read_block (uint8_t *dest, uint32_t src, size_t length) Z80_O_MREQ = 1; } +/*--------------------------------------------------------------------------*/ /* 0179' rx.bs_mask: ds 1 ; (buf_len - 1) @@ -697,3 +805,31 @@ void z80_memfifo_putc(fifo_t f, uint8_t val) z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in); z80_bus_cmd(Release); } + +/*--------------------------------------------------------------------------*/ + +void z80_load_mem(int_fast8_t verbosity, + const FLASH unsigned char data[], + const FLASH unsigned long *sections, + const FLASH unsigned long address[], + const FLASH unsigned long length_of_sections[]) +{ + uint32_t sec_base = 0; + + if (verbosity > 1) + printf_P(PSTR("Loading Z180 memory... \n")); + + for (unsigned sec = 0; sec < *sections; sec++) { + if (verbosity > 0) { + printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"), + address[sec], + address[sec]+length_of_sections[sec] - 1, + length_of_sections[sec]); + } + + z80_write_block_P((const FLASH unsigned char *) &data[sec_base], /* src */ + address[sec], /* dest */ + length_of_sections[sec]); /* len */ + sec_base += length_of_sections[sec]; + } +}