*
* Pin assignments
*
- * | Z180-Sig | AVR-Port | Dir | Special Function |
+ * | Z180-Sig | AVR-Port | Dir | Special Function |
* +------------+---------------+-------+-----------------------+
* | A0 | PA 0 | O | |
* | A1 | PA 1 | O | |
#include <avr/io.h>
#include <util/delay.h>
+#include <util/atomic.h>
#include <stdio.h>
#include "debug.h"
#include "z80-if.h"
#define BUSREQ 7
#define DDR_BUSREQ DDRD
#define P_BUSACK PORTD
+#define PIN_BUSACK PIND
#define BUSACK 6
#define DDR_BUSACK DDRD
//#define P_HALT PORTA
#define P_ADH PORTC
#define P_ADB PORTE
#define PIN_ADB PINE
-#define DDR_ADL DDRE
-#define DDR_ADH DDRE
+#define DDR_ADL DDRA
+#define DDR_ADH DDRC
#define DDR_ADB DDRE
#define ADB_WIDTH 3
//#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_BUSACK SBIT(PIN_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))
uint16_t w[2];
uint8_t b[4];
} addr_t;
-
-/*--------------------------------------------------------------------------*/
+static zstate_t zstate;
+/*--------------------------------------------------------------------------*/
-/*
- * A0..A6, A8..A13 are buffered. No need to disable.
- * A7, A14..A18: set to input.
- */
-
-static void z80_setup_adrbus_tristate(void)
+
+static void z80_setup_addrbus_tristate(void)
{
+ /* /MREQ, /RD, /WR: Input, no pullup */
+ DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
+ Z80_O_MREQ = 0;
+ Z80_O_RD = 0;
+ Z80_O_WR = 0;
+
P_ADL = 0;
DDR_ADL = 0;
P_ADH = 0;
DDR_ADH = 0;
- PIN_ADB = P_ADB & MASK(ADB_WIDTH) << ADB_SHIFT;
+ 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)
+static void z80_setup_addrbus_active(void)
{
+ /* /MREQ, /RD, /WR: Output and high */
+ Z80_O_MREQ = 1;
+ Z80_O_RD = 1;
+ Z80_O_WR = 1;
+ DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
+
DDR_ADL = 0xff;
DDR_ADH = 0xff;
DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
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)
{
+ /* /ZRESET: Output and low */
Z80_O_RST = 0;
DDR_RST |= _BV(RST);
+ /* /BUSREQ: Output and high */
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);
-
+ /* /BUSACK: Input, no pullup */
DDR_BUSACK &= ~_BV(BUSACK);
P_BUSACK &= ~_BV(BUSACK);
+ /* /IOCS1: Input, no pullup */
DDR_IOCS1 &= ~_BV(IOCS1);
P_IOCS1 &= ~_BV(IOCS1);
- //Z80_O_BUSREQ = 0;
- //while(Z80_I_BUSACK == 1);
+ z80_setup_addrbus_tristate();
+ z80_setup_dbus_in();
- z80_setup_adrbus_tristate();
+ zstate = RESET;
+// Stat &= ~S_Z180_RUNNING;
+}
+
+/*--------------------------------------------------------------------------*/
+#if 0
+ switch (zstate) {
+ case RESET:
+ break;
+ case RESET_AQRD:
+ break;
+ case RUN:
+ break;
+ case RUN_AQRD:
+ break;
+ }
+#endif
+/*--------------------------------------------------------------------------*/
+
+#if 0
+void z80_busreq(level_t level)
+{
+ Z80_O_BUSREQ = level;
+}
+
+int z80_stat_reset(void)
+{
+// return Z80_O_RESET;
+}
+
+int z80_stat_halt(void)
+{
+ return Z80_I_HALT;
+}
+#endif
+
+
+zstate_t z80_runstate(void)
+{
+ return zstate;
+}
+
+void z80_reset(void)
+{
+#if DEBUG
+ zstate_t old = zstate;
+#endif
z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_RST = 0;
+ Z80_O_BUSREQ = 1;
+ zstate = RESET;
+
+ debug("z80_reset: state: %02x --> %02x\n", old, zstate);
+}
+
+void z80_reset_pulse(void)
+{
+#if DEBUG
+ zstate_t old = zstate;
+#endif
+ switch (zstate) {
+ case RESET:
+ case RESET_AQRD:
+ break;
+
+ case RUN:
+ case RUN_AQRD:
+ Z80_O_RST = 0;
+ _delay_us(10);
+ Z80_O_RST = 1;
+ break;
+ }
+
+ debug("z80_reset_pulse: state: %02x --> %02x\n", old, zstate);
}
void z80_request_bus(void)
{
- Z80_O_BUSREQ = 0;
- while(Z80_I_BUSACK == 1);
- z80_setup_adrbus_active();
+#if DEBUG
+ zstate_t old = zstate;
+#endif
+
+ switch (zstate) {
+ case RESET:
+ Z80_O_BUSREQ = 0;
+ Z80_O_RST = 1;
+ while(Z80_I_BUSACK == 1)
+ ;
+ z80_setup_addrbus_active();
+ zstate = RESET_AQRD;
+ break;
+
+ case RESET_AQRD:
+ break;
+
+ case RUN:
+ Z80_O_BUSREQ = 0;
+ while(Z80_I_BUSACK == 1);
+ z80_setup_addrbus_active();
+ zstate = RUN_AQRD;
+ break;
+
+ case RUN_AQRD:
+ break;
+ }
+ debug("z80_request_bus: state: %02x --> %02x\n", old, zstate);
}
void z80_release_bus(void)
+{
+#if DEBUG
+ zstate_t old = zstate;
+#endif
+ switch (zstate) {
+ case RESET:
+ break;
+ case RESET_AQRD:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_RST = 0;
+ Z80_O_BUSREQ = 1;
+ zstate = RESET;
+ break;
+ case RUN:
+ break;
+ case RUN_AQRD:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_BUSREQ = 1;
+ zstate = RUN;
+ break;
+ }
+
+ debug("z80_release_bus: state: %02x --> %02x\n", old, zstate);
+}
+
+/*
+ * Do nothing, if we have the bus allready
+ *
+ * return previous state
+ */
+zstate_t z80_request_bus_save(void)
+{
+ zstate_t state;
+
+ state = z80_runstate();
+ if (!(state & ZST_ACQUIRED))
+ z80_request_bus();
+
+ return state;
+}
+
+/*
+ * Do nothing, if we had the bus before
+ */
+void z80_release_bus_save(zstate_t prev)
+{
+ if (!(prev & ZST_ACQUIRED))
+ z80_release_bus();
+}
+
+void z80_run(void)
+{
+#if DEBUG
+ zstate_t old = zstate;
+#endif
+ switch (zstate) {
+ case RESET:
+ Z80_O_RST = 1;
+ zstate = RUN;
+ break;
+
+ case RESET_AQRD:
+ z80_setup_dbus_in();
+ z80_setup_addrbus_tristate();
+ Z80_O_RST = 0;
+ _delay_us(10);
+ Z80_O_RST = 1;
+ z80_setup_addrbus_active();
+ zstate = RUN_AQRD;
+ break;
+
+ case RUN:
+ break;
+ case RUN_AQRD:
+ break;
+ }
+
+ debug("z80_run: state: %02x --> %02x\n", old, zstate);
+}
+
+void z80_busreq_hpulse(void)
{
z80_setup_dbus_in();
- z80_setup_adrbus_tristate();
- Z80_O_BUSREQ = 1;
- while(Z80_I_BUSACK == 0);
+ z80_setup_addrbus_tristate();
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ Z80_O_BUSREQ = 1;
+ Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
+ Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
+ }
+
+ if (zstate & ZST_ACQUIRED) {
+ while(Z80_I_BUSACK == 1)
+ ;
+ z80_setup_addrbus_active();
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static
+//inline __attribute__ ((always_inline))
+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_write(uint32_t addr, uint8_t data)
{
z80_setaddress(addr);
Z80_O_MREQ = 0;
- P_DB = data;
z80_setup_dbus_out();
+ P_DB = data;
+ P_DB = data;
+ Z80_O_WR = 0;
Z80_O_WR = 0;
Z80_O_WR = 1;
Z80_O_MREQ = 1;
z80_setup_dbus_in();
Z80_O_RD = 0;
Z80_O_RD = 0;
+ Z80_O_RD = 0;
data = PIN_DB;
Z80_O_RD = 1;
Z80_O_MREQ = 1;
while(length--) {
z80_setaddress(addr++);
P_DB = data;
+ P_DB = data;
+ Z80_O_WR = 0;
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)
+void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
{
uint8_t data;
z80_setaddress(dest++);
data = *src++;
P_DB = data;
+ P_DB = data;
+ Z80_O_WR = 0;
Z80_O_WR = 0;
Z80_O_WR = 1;
}
}
/*--------------------------------------------------------------------------*/
+/*
+ TODO: Rewrite msg_fifo routines for AVR
+*/
static struct {
uint32_t base;
{
int c = -1;
+#if 0
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))
z80_release_bus();
}
}
+#endif
return c;
}