/* */ #include //#include //#include #include //#include //#include //#include #include #include "debug.h" #include "serial.h" #include "z80-if.h" #define const const __flash #include "../z180/hdrom.h" #undef const #define FLASH __flash //#define FLASH #define ESCCHAR ('^'-0x40) #define S_10MS_TO (1<<0) volatile int_fast8_t timeout_1s; //volatile uint_least8_t Stat; #define Stat GPIOR0 unsigned int to_counter; /****************************************************************/ #define P_ADL PORTA #define P_ADH PORTC #define P_ADB PORTE #define PIN_ADB PINE #define ADB_WIDTH 3 #define ADB_SHIFT 2 //#define ADB_PORT GPIOE #define MASK(n) ((1<<(n))-1) #define SMASK(w,s) (MASK(w) << (s)) typedef union { uint32_t l; uint16_t w[2]; uint8_t b[4]; } addr_t; /*--------------------------------------------------------------------------*/ /*---------------------------------------------------------*/ /* 1000Hz timer interrupt generated by OC1A */ /*---------------------------------------------------------*/ ISR(TIMER1_COMPA_vect) { static int_fast8_t tick_10ms; // static int_fast16_t count_ms; int_fast8_t i; i = tick_10ms + 1; if (i == 10) { i = 0; Stat |= S_10MS_TO; /* Drive timer procedure of low level disk I/O module */ //disk_timerproc(); } tick_10ms = i; #if 0 count_ms++; if (count_ms == 1000) { count_ms = 0; i = timeout_1s; if (i) timeout_1s = i - 1; } #endif } /*--------------------------------------------------------------------------*/ static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc) { uint8_t rval; int_fast8_t errors = 0; DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length); while (length--) { if ((rval = z80_read(addr)) != wval) { if (errors == 0) { DBG_P(1, "\nSRAM: Address W R\n" \ " ------------------\n"); } errors++; if (errors > 20) { DBG_P(1, " ...\n"); break; } DBG_P(1, " 0x%.5lx 0x%.2x 0x%.2x\n", addr, wval, rval); } addr++; wval += inc; } DBG_P(1, "Done.\n"); return addr; } static void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc) { printf("SRAM: Write 0x%.5lx byte... ", length); while (length--) { z80_write(addr, startval); ++addr; startval += inc; } printf("Done.\n"); } #if 0 void z80_sram_fill_string(uint32_t addr, int length, const char *text) { char c; const char *p = text; while (length--) { z80_write(addr++, c = *p++); if (c == 0) p = text; } } uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text) { char c; const char *p = text; while (length--) { c = *p++; if (z80_read(addr) != c) break; ++addr; if (c == 0) p = text; } return addr; } const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!"; const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!"; #endif uint8_t z80_get_byte(uint32_t adr) { uint8_t data; z80_request_bus(); data = z80_read(adr), z80_release_bus(); return data; } /*--------------------------------------------------------------------------*/ static void do_10ms(void) { if (to_counter) to_counter--; } /*--------------------------------------------------------------------------*/ struct msg_item { uint8_t fct; uint8_t sub_min, sub_max; void (*func)(uint8_t, int, uint8_t *); }; uint32_t msg_to_addr(uint8_t *msg) { union { uint32_t as32; uint8_t as8[4]; } addr; addr.as8[0] = msg[0]; addr.as8[1] = msg[1]; addr.as8[2] = msg[2]; addr.as8[3] = 0; return addr.as32; } void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg) { (void)subf; (void)len; z80_init_msg_fifo(msg_to_addr(msg)); } void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg) { (void)len; z80_memfifo_init(subf - 1, msg_to_addr(msg)); } void do_msg_char_out(uint8_t subf, int len, uint8_t * msg) { (void)subf; while (len--) putchar(*msg++); } const FLASH struct msg_item z80_messages[] = { { 0, /* fct nr. */ 0, 0, /* sub fct nr. from, to */ do_msg_ini_msgfifo}, { 0, 1, 2, do_msg_ini_memfifo}, { 1, 1, 1, do_msg_char_out}, { 0xff, /* end mark */ 0, 0, 0}, }; void do_message(int len, uint8_t *msg) { uint8_t fct, sub_fct; int_fast8_t i = 0; if (len >= 2) { fct = *msg++; sub_fct = *msg++; len -= 2; while (fct != z80_messages[i].fct) ++i; if (z80_messages[i].fct == 0xff) { DBG_P(1, "do_message: Unknown function: %i, %i\n", fct, sub_fct); return; /* TODO: unknown message # */ } while (fct == z80_messages[i].fct) { if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max ) break; ++i; } if (z80_messages[i].fct != fct) { DBG_P(1, "do_message: Unknown sub function: %i, %i\n", fct, sub_fct); return; /* TODO: unknown message sub# */ } (z80_messages[i].func)(sub_fct, len, msg); } else { /* TODO: error */ DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len); } } #define CTRBUF_LEN 256 void check_msg_fifo(void) { int ch; static int_fast8_t state; static int msglen,idx; static uint8_t buffer[CTRBUF_LEN]; while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) { switch (state) { case 0: /* wait for start of message */ if (ch == 0x81) { msglen = 0; idx = 0; state = 1; } break; case 1: /* get msg len */ if (ch > 0 && ch <= CTRBUF_LEN) { msglen = ch; state = 2; } else state = 0; break; case 2: /* get message */ buffer[idx++] = ch; if (idx == msglen) state = 3; break; } } if (state == 3) { do_message(msglen, buffer); state = 0; } } /*--------------------------------------------------------------------------*/ void dump_mem(const __flash uint8_t *addr, uint32_t len) { DBG_P(1, "hdrom dump:"); while (len) { DBG_P(1, "\n %.5x:", addr); for (unsigned i = 0; i<16; i++) DBG_P(1, " %.2x", *addr++); len -= len > 16 ? 16 : len; } DBG_P(1, "\n"); } /*--------------------------------------------------------------------------*/ void z80_load_mem(void) { unsigned sec = 0; uint32_t sec_base = hdrom_start; DBG_P(1, "Loading z80 memory... \n"); while (sec < hdrom_sections) { DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n", hdrom_address[sec], hdrom_address[sec]+hdrom_length_of_sections[sec] - 1, hdrom_length_of_sections[sec]); z80_write_block((const __flash unsigned char *) &hdrom[sec_base], /* src */ hdrom_address[sec], /* dest */ hdrom_length_of_sections[sec]); /* len */ sec_base+=hdrom_length_of_sections[sec]; sec++; } } /*--------------------------------------------------------------------------*/ void z80_dump_mem(uint32_t addr, uint32_t len) { DBG_P(1, "Memory dump:"); while (len) { DBG_P(1, "\n %.5lx:", addr); for (unsigned i = 0; i<16; i++) DBG_P(1, " %.2x", z80_read(addr++)); len -= len > 16 ? 16 : len; } DBG_P(1, "\n"); } /*--------------------------------------------------------------------------*/ void setup_rtc(void) { /* TODO: */ } void setup_avr(void) { /* WD */ /* CPU */ /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */ MCUCR = _BV(JTD); MCUCR = _BV(JTD); /* disable unused periphels */ PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC); PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) | _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1); /* disable analog comparator */ ACSR = _BV(ACD); /* Ports */ /* Clock */ CLKPR = _BV(CLKPCE); CLKPR = 0; /* Timer */ OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A) TCCR1B = 0b00001010; TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt } const __flash uint8_t iniprog[] = { 0xAF, // xor a 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh 0x3E, 0x30, // ld a,030h 0xED, 0x39, 0x32 //out0 (dcntl),a ;0 mem, max i/0 wait states }; const __flash uint8_t sertest[] = { 0xAF, // xor a 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh 0x3E, 0x30, // ld a,030h 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states 0x3E, 0x80, // ld a,M_MPBT ;no MP, PS=10, DR=16, SS=0 0xED, 0x39, 0x03, // out0 (cntlb1),a 0x3E, 0x64, // ld a,M_RE + M_TE + M_MOD2 ; 0xED, 0x39, 0x01, // out0 (cntla1),a 0x3E, 0x00, // ld a,0 0xED, 0x39, 0x05, // out0 (stat1),a ;Enable rx interrupts 0xED, 0x38, 0x05, //l0:in0 a,(stat1) 0xE6, 0x80, // and 80h 0x28, 0xF9, // jr z,l0 0xED, 0x00, 0x09, // in0 b,(rdr1) 0xED, 0x38, 0x05, //l1:in0 a,(stat1) 0xE6, 0x02, // and 02h 0x28, 0xF9, // jr z,l1 0xED, 0x01, 0x07, // out0 (tdr1),b 0x18, 0xEA, // jr l0 }; const __flash uint8_t test1[] = { 0xAF, // xor a 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh 0x3E, 0x30, // ld a,030h 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states 0x21, 0x1E, 0x00, // ld hl,dmclrt ;load DMA registers 0x06, 0x08, // ld b,dmct_e-dmclrt 0x0E, 0x20, // ld c,sar0l 0xED, 0x93, // otimr 0x3E, 0xC3, // ld a,0c3h ;dst +1, src +1, burst 0xED, 0x39, 0x31, // out0 (dmode),a ; 0x3E, 0x62, // ld a,062h ;enable dma0, 0xED, 0x39, 0x30, //cl_1: out0 (dstat),a ;copy 64k 0x18, 0xFB, // jr cl_1 ; 0x00, 0x00, //dmclrt: dw 0 ;src (inc) 0x00, // db 0 ;src 0x00, 0x00, // dw 0 ;dst (inc), 0x00, // db 0 ;dst 0x00, 0x00, // dw 0 ;count (64k) }; int main(void) { int_fast8_t state = 0; int ch; setup_avr(); serial_setup(); setup_rtc(); sei(); printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n")); DBG_P(1, "z80_setup_bus... "); z80_setup_msg_fifo(); z80_setup_bus(); DBG_P(1, "done.\n"); DBG_P(1, "Get bus... "); /* Now done via S_Z180_RUNNING z80_busreq(LOW); z80_reset(HIGH); */ z80_request_bus(); DBG_P(1, "got it!\n"); // z80_sram_fill(0, (uint32_t)512 * 1024, 0x00, 3); // z80_sram_cmp(0, (uint32_t)512 * 1024, 0x00, 3); // z80_dump_mem(0, 0x400); z80_memset(0, 0x76, 0x80000); // z80_memset(0, 0x00, 0x80000); // z80_write_block(test1, 0, sizeof(test1)); // z80_dump_mem(0, 0x100); // z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0); z80_load_mem(); // z80_write(0, 0x76); // z80_dump_mem(0, 0x200); /* Now done via S_Z180_RUNNING z80_reset(LOW); */ z80_release_bus(); DBG_P(1, "Bus released!\n"); z80_reset(HIGH); DBG_P(1, "Reset released!\n"); to_counter = 200; while (1) { if (Stat & S_10MS_TO) { Stat &= ~S_10MS_TO; do_10ms(); } if ((ch = serial_getc()) >= 0) { switch (state) { case 0: if (ch == ESCCHAR) { state = 1; /* TODO: Timer starten */ } else { // z80_memfifo_putc(fifo_out, ch); serial_putc(ch); if (ch == '\r') serial_putc('\n'); } break; case 1: switch (ch) { case 'r': z80_reset_pulse(); break; case 'b': z80_request_bus(); z80_dump_mem(0, 0x2d20); z80_release_bus(); break; case 'e': z80_request_bus(); z80_dump_mem(0x80000-0x4000, 0x800); z80_dump_mem(0x80000-0x200, 0x200); z80_release_bus(); break; case ESCCHAR: default: // z80_memfifo_putc(fifo_out, ch); serial_putc(ch); if (ch == '\r') serial_putc('\n'); } state = 0; break; } } // check_msg_fifo(); } return 0; }