diff options
Diffstat (limited to 'avr/z180-stamp-avr.c')
-rw-r--r-- | avr/z180-stamp-avr.c | 591 |
1 files changed, 591 insertions, 0 deletions
diff --git a/avr/z180-stamp-avr.c b/avr/z180-stamp-avr.c new file mode 100644 index 0000000..e6edb33 --- /dev/null +++ b/avr/z180-stamp-avr.c @@ -0,0 +1,591 @@ +/* + */ + + +#include <avr/io.h> +//#include <avr/power.h> +//#include <avr/pgmspace.h> +#include <avr/interrupt.h> +//#include <util/atomic.h> +//#include <avr/sleep.h> +//#include <string.h> + +#include <stdio.h> + + +#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; +} |