summaryrefslogtreecommitdiff
path: root/avr/z180-stamp-avr.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/z180-stamp-avr.c')
-rw-r--r--avr/z180-stamp-avr.c591
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;
+}