summaryrefslogtreecommitdiff
path: root/avr/z80-if.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/z80-if.c')
-rw-r--r--avr/z80-if.c563
1 files changed, 563 insertions, 0 deletions
diff --git a/avr/z80-if.c b/avr/z80-if.c
new file mode 100644
index 0000000..955a61a
--- /dev/null
+++ b/avr/z80-if.c
@@ -0,0 +1,563 @@
+/**
+ *
+ * Pin assignments
+ *
+ * | Z180-Sig | AVR-Port | Dir | Special Function |
+ * +------------+---------------+-------+-----------------------+
+ * | A0 | PA 0 | O | |
+ * | A1 | PA 1 | O | |
+ * | A2 | PA 2 | O | |
+ * | A3 | PA 3 | O | |
+ * | A4 | PA 4 | O | |
+ * | A5 | PA 5 | O | |
+ * | A6 | PA 6 | O | |
+ * | A7 | PA 7 | O | |
+ * | A8 | PC 0 | O | |
+ * | A9 | PC 1 | O | |
+ * | A10 | PC 2 | O | |
+ * | A11 | PC 3 | O | |
+ * | A12 | PC 4 | O | |
+ * | A13 | PC 5 | O | |
+ * | A14 | PC 6 | O | |
+ * | A15 | PC 7 | O | |
+ * | A16 | PE 2 | O | |
+ * | A17 | PE 3 | O | |
+ * | A18 | PE 4 | O | |
+ * | D0 | PF 0 | I/O | |
+ * | D1 | PF 1 | I/O | |
+ * | D2 | PF 2 | I/O | |
+ * | D3 | PF 3 | I/O | |
+ * | D4 | PF 4 | I/O | |
+ * | D5 | PF 5 | I/O | |
+ * | D6 | PF 6 | I/O | |
+ * | D7 | PF 7 | I/O | |
+ * | RD | PD 3 | O | |
+ * | WR | PD 2 | O | |
+ * | MREQ | PD 4 | O | |
+ * | RST | PD 5 | O | |
+ * | BUSREQ | PD 7 | O | |
+ * | BUSACK | PD 6 | I | |
+ * | IOCS1 | PE 5 | I | |
+ * |* HALT | P | | |
+ * |* NMI | P | | |
+ * | | P | | |
+ * | | P | | af1 USART1_TX |
+ * | | P | | af1 USART1_RX |
+ * | | P |JTDI | remap SPI1_NSS' |
+ * | | P |JTDO | remap SPI1_SCK' |
+ * | | P |JTRST | remap SPI1_MISO' |
+ * | | P | | remap SPI1_MOSI' |
+ * | | P | | af1 OSC32 |
+ * | | P | | af1 OSC32 |
+
+
+ */
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include <stdio.h>
+#include "debug.h"
+#include "z80-if.h"
+
+
+/* Number of array elements */
+#define NELEMS(x) (sizeof x/sizeof *x)
+
+
+#define CONCAT(x,y) x ## y
+#define EVALUATOR(x,y) CONCAT(x,y)
+
+#define GPIO_(X) CONCAT(GPIO, X)
+
+struct bits {
+ uint8_t b0:1;
+ uint8_t b1:1;
+ uint8_t b2:1;
+ uint8_t b3:1;
+ uint8_t b4:1;
+ uint8_t b5:1;
+ uint8_t b6:1;
+ uint8_t b7:1;
+} __attribute__((__packed__));
+
+#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
+
+
+
+#define P_MREQ PORTD
+#define MREQ 4
+#define DDR_MREQ DDRD
+#define P_RD PORTD
+#define RD 3
+#define P_WR PORTD
+#define WR 2
+#define P_BUSREQ PORTD
+#define BUSREQ 7
+#define DDR_BUSREQ DDRD
+#define P_BUSACK PORTD
+#define BUSACK 6
+#define DDR_BUSACK DDRD
+//#define P_HALT PORTA
+//#define HALT 12
+#define P_IOCS1 PORTE
+#define IOCS1 5
+#define DDR_IOCS1 DDRE
+//#define P_NMI PORTB
+//#define NMI 7
+#define P_RST PORTD
+#define DDR_RST DDRD
+#define RST 5
+
+
+#define P_DB PORTF
+#define PIN_DB PINF
+#define DDR_DB DDRF
+
+#define P_ADL PORTA
+#define P_ADH PORTC
+#define P_ADB PORTE
+#define PIN_ADB PINE
+#define DDR_ADL DDRE
+#define DDR_ADH DDRE
+#define DDR_ADB DDRE
+
+#define ADB_WIDTH 3
+#define ADB_SHIFT 2
+//#define ADB_PORT PORTE
+
+
+
+#define ADp1_OFS 0
+#define ADp1_WIDTH 8
+#define ADp1_SHIFT 1
+#define ADp1_PORT GPIOA
+
+#define ADp2_OFS ADp1_WIDTH
+#define ADp2_WIDTH 8
+#define ADp2_SHIFT 0
+#define ADp2_PORT GPIOC
+
+#define ADp3_OFS (ADp2_OFS+ADp2_WIDTH)
+#define ADp3_WIDTH 3
+#define ADp3_SHIFT 10
+#define ADp3_PORT GPIOC
+
+#define ADunbuff1_WIDTH 1
+#define ADunbuff1_SHIFT 8
+#define ADunbuff1_PORT GPIOA
+
+#define ADunbuff2_WIDTH 2
+#define ADunbuff2_SHIFT 6
+#define ADunbuff2_PORT GPIOC
+
+#define ADunbuff3_WIDTH 3
+#define ADunbuff3_SHIFT 10
+#define ADunbuff3_PORT GPIOC
+
+#define DB_OFS 0
+#define DB_WIDTH 8
+#define DB_SHIFT 8
+#define DB_PORT GPIOB
+
+
+#define Z80_O_MREQ SBIT(P_MREQ, 4)
+#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_O_NMI SBIT(P_NMI, )
+#define Z80_O_RST SBIT(P_RST, 5)
+#define Z80_I_BUSACK SBIT(P_BUSACK, 6)
+//#define Z80_I_HALT SBIT(P_HALT, )
+
+void z80_busreq(level_t level)
+{
+ Z80_O_BUSREQ = level;
+}
+
+void z80_reset(level_t level)
+{
+ Z80_O_RST = level;
+}
+
+
+void z80_reset_pulse(void)
+{
+ Z80_O_RST = 0;
+ _delay_us(10);
+ Z80_O_RST = 1;
+}
+
+#if 0
+int z80_stat_halt(void)
+{
+ return Z80_I_HALT;
+}
+#endif
+
+
+#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;
+
+
+/*--------------------------------------------------------------------------*/
+
+
+
+/*
+ * A0..A6, A8..A13 are buffered. No need to disable.
+ * A7, A14..A18: set to input.
+ */
+
+static void z80_setup_adrbus_tristate(void)
+{
+ P_ADL = 0;
+ DDR_ADL = 0;
+ P_ADH = 0;
+ DDR_ADH = 0;
+ PIN_ADB = P_ADB & MASK(ADB_WIDTH) << ADB_SHIFT;
+ DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
+}
+
+
+static void z80_setup_adrbus_active(void)
+{
+ DDR_ADL = 0xff;
+ DDR_ADH = 0xff;
+ DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
+}
+
+
+
+static void z80_setup_dbus_in(void)
+{
+ DDR_DB = 0;
+ P_DB = 0;
+}
+
+static void z80_setup_dbus_out(void)
+{
+ DDR_DB = 0xff;
+}
+
+static
+void z80_setaddress(uint32_t addr)
+{
+ addr_t x; x.l = addr;
+
+ P_ADL = x.b[0];
+ P_ADH = x.b[1];
+ PIN_ADB = ((x.b[2] << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT ;
+}
+
+void z80_setup_bus(void)
+{
+ Z80_O_RST = 0;
+ DDR_RST |= _BV(RST);
+
+ Z80_O_BUSREQ = 1;
+ DDR_BUSREQ |= _BV(BUSREQ);
+
+// Z80_O_NMI = 1;
+// DDR_NMI |= _BV(NMI);
+
+ Z80_O_MREQ = 1;
+ Z80_O_RD = 1;
+ Z80_O_WR = 1;
+ DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
+
+ DDR_BUSACK &= ~_BV(BUSACK);
+ P_BUSACK &= ~_BV(BUSACK);
+
+ DDR_IOCS1 &= ~_BV(IOCS1);
+ P_IOCS1 &= ~_BV(IOCS1);
+
+ //Z80_O_BUSREQ = 0;
+ //while(Z80_I_BUSACK == 1);
+
+ z80_setup_adrbus_tristate();
+ z80_setup_dbus_in();
+}
+
+void z80_request_bus(void)
+{
+ Z80_O_BUSREQ = 0;
+ while(Z80_I_BUSACK == 1);
+ z80_setup_adrbus_active();
+}
+
+void z80_release_bus(void)
+{
+ z80_setup_dbus_in();
+ z80_setup_adrbus_tristate();
+ Z80_O_BUSREQ = 1;
+ while(Z80_I_BUSACK == 0);
+}
+
+void z80_write(uint32_t addr, uint8_t data)
+{
+ z80_setaddress(addr);
+ Z80_O_MREQ = 0;
+ P_DB = data;
+ z80_setup_dbus_out();
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ Z80_O_MREQ = 1;
+}
+
+uint8_t z80_read(uint32_t addr)
+{
+ uint8_t data;
+
+ z80_setaddress(addr);
+ Z80_O_MREQ = 0;
+ z80_setup_dbus_in();
+ Z80_O_RD = 0;
+ Z80_O_RD = 0;
+ data = PIN_DB;
+ Z80_O_RD = 1;
+ Z80_O_MREQ = 1;
+
+ return data;
+}
+
+
+void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
+{
+ z80_setup_dbus_out();
+ Z80_O_MREQ = 0;
+ while(length--) {
+ z80_setaddress(addr++);
+ P_DB = data;
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ }
+ Z80_O_MREQ = 1;
+}
+
+void z80_write_block(uint8_t *src, uint32_t dest, uint32_t length)
+{
+ uint8_t data;
+
+ z80_setup_dbus_out();
+ Z80_O_MREQ = 0;
+ while(length--) {
+ z80_setaddress(dest++);
+ data = *src++;
+ P_DB = data;
+ Z80_O_WR = 0;
+ Z80_O_WR = 1;
+ }
+ Z80_O_MREQ = 1;
+}
+
+/*
+ 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
+ 017A' rx.in_idx: ds 1 ;
+ 017B' rx.out_idx: ds 1 ;
+ 017C' rx.buf: ds rx.buf_len ;
+ 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
+
+ 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
+ 018D' tx.in_idx: ds 1 ;
+ 018E' tx.out_idx: ds 1 ;
+ 018F' tx.buf: ds tx.buf_len ;
+ 019E' tx.buf_end equ $-1 ; last byte
+*/
+
+
+typedef struct __attribute__((packed)) {
+ uint8_t mask;
+ uint8_t in_idx;
+ uint8_t out_idx;
+ uint8_t buf[];
+} zfifo_t;
+
+
+
+#define FIFO_BUFSIZE_MASK -3
+#define FIFO_INDEX_IN -2
+#define FIFO_INDEX_OUT -1
+
+
+static struct {
+ uint32_t base;
+ uint8_t idx_out,
+ idx_in,
+ mask;
+ } fifo_dsc[NUM_FIFOS];
+
+
+void z80_memfifo_init(const fifo_t f, uint32_t adr)
+{
+
+DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
+
+ fifo_dsc[f].base = adr;
+
+ z80_request_bus();
+
+ fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
+ fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
+ fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
+
+ z80_release_bus();
+}
+
+
+int z80_memfifo_is_empty(const fifo_t f)
+{
+ int rc = 1;
+
+ if (fifo_dsc[f].base != 0) {
+
+ uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
+ uint8_t idx;
+
+ z80_request_bus();
+ idx = z80_read(adr);
+ z80_release_bus();
+ rc = idx == fifo_dsc[f].idx_out;
+ }
+
+ return rc;
+}
+
+int z80_memfifo_is_full(const fifo_t f)
+{
+ int rc = 1;
+
+ if (fifo_dsc[f].base != 0) {
+ z80_request_bus();
+ rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
+ == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
+ z80_release_bus();
+ }
+ return rc;
+}
+
+uint8_t z80_memfifo_getc(const fifo_t f)
+{
+ uint8_t rc, idx;
+
+ while (z80_memfifo_is_empty(f))
+ ;
+
+ z80_request_bus();
+ idx = fifo_dsc[f].idx_out;
+ rc = z80_read(fifo_dsc[f].base+idx);
+ fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
+ z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
+ z80_release_bus();
+
+ return rc;
+}
+
+
+void z80_memfifo_putc(fifo_t f, uint8_t val)
+{
+ int idx;
+
+ while (z80_memfifo_is_full(f))
+ ;
+
+ z80_request_bus();
+ idx = fifo_dsc[f].idx_in;
+ z80_write(fifo_dsc[f].base+idx, val);
+ fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
+ z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
+ z80_release_bus();
+}
+
+/*--------------------------------------------------------------------------*/
+
+static struct {
+ uint32_t base;
+ //uint8_t idx_out, idx_in;
+ uint16_t count;
+ uint8_t buf[256];
+ } msg_fifo;
+
+/*--------------------------------------------------------------------------*/
+
+#if 0
+
+static void tim1_setup(void)
+{
+ RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
+ RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
+
+ TIM1_CR1 = 0;
+
+ TIM1_SMCR = 0
+ /* | TIM_SMCR_ETP */
+ /* | TIM_SMCR_ETF_CK_INT_N_2 */
+ | TIM_SMCR_TS_ETRF
+ | TIM_SMCR_SMS_OFF
+ ;
+
+ TIM1_DIER = TIM_DIER_TDE;
+
+
+ TIM1_CCMR1 = 0
+ | TIM_CCMR1_OC1M_FORCE_LOW
+ | TIM_CCMR1_CC1S_OUT;
+
+ TIM1_SMCR |= TIM_SMCR_SMS_TM;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+void z80_setup_msg_fifo(void)
+{
+// gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
+// GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
+
+//...
+
+// msg_fifo.count = NELEMS(msg_fifo.buf);
+ msg_fifo.count = 0;
+ msg_fifo.base = 0;
+
+}
+
+
+void z80_init_msg_fifo(uint32_t addr)
+{
+
+DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
+
+ z80_request_bus();
+ z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
+ z80_release_bus();
+ msg_fifo.base = addr;
+}
+
+
+int z80_msg_fifo_getc(void)
+{
+ int c = -1;
+
+ if (msg_fifo.count != (NELEMS(msg_fifo.buf) /*- DMA1_CNDTR4 */ )) {
+ c = msg_fifo.buf[msg_fifo.count];
+ if (++msg_fifo.count == NELEMS(msg_fifo.buf))
+ msg_fifo.count = 0;
+
+ if (msg_fifo.base != 0) {
+ z80_request_bus();
+ z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
+ z80_release_bus();
+ }
+ }
+
+ return c;
+}