]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/z80-if.c
Programmable Z180 clock, clock command
[z180-stamp.git] / avr / z80-if.c
index 392597e5945e9d5916feaa30259a4e64a1d719b8..c0f128e1a4870005d543becf1adf5a47b1c8776b 100644 (file)
@@ -84,7 +84,9 @@ struct bits {
 #define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
 
 
-
+#define P_ZCLK         PORTB
+#define ZCLK           7
+#define DDR_ZCLK       DDRB
 #define P_MREQ         PORTD
 #define MREQ           4
 #define DDR_MREQ       DDRD
@@ -128,6 +130,7 @@ struct bits {
 //#define ADB_PORT     PORTE
 
 
+#define Z80_O_ZCLK     SBIT(P_ZCLK, 7)
 #define        Z80_O_MREQ      SBIT(P_MREQ, 4)
 #define Z80_O_RD       SBIT(P_RD, 3)
 #define Z80_O_WR       SBIT(P_WR, 2)
@@ -154,8 +157,87 @@ static zstate_t zstate;
 
 /*--------------------------------------------------------------------------*/
 
+static
+void z80_setup_clock(void)
+{
+       /* ZCLK: Output and low */
+       DDR_ZCLK |= _BV(ZCLK);
+       Z80_O_ZCLK = 0;
+
+       DDRB  |= _BV(6);        /* Debug */
+       PORTB |= _BV(6);        /* Debug */
+
+       PRR0 &= ~_BV(PRTIM1);
+
+       /* Timer1: CTC: Toggle OC1C on compare match */
+       OCR1A =  0;
+       OCR1C =  0;
+       TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10);
+       TCCR1B = (0b01 << WGM12)  | (0b001 << CS10);
+}
+
+
+int z80_clock_set(unsigned long freq)
+{
+       unsigned long ocrval = F_CPU  / freq / 2;
+       uint8_t prescale = 0;
+
+       while (ocrval > (1L<<16)) {
+               prescale++;
+               if (prescale < 3)
+                       ocrval = ocrval / 8;
+               else
+                       ocrval = ocrval /  4;
+       }
+
+       if ((ocrval == 0) || (prescale > 4))
+               return -1;
+
+       ocrval -= 1;
+
+       PINB |= _BV(6);         /* Debug */
+
+       /* Stop Timer */
+       TCCR1B = (0b01 << WGM12)  | (0b000 << CS10);
+       TCNT1 = 0;
+
+       OCR1A =  ocrval;
+       OCR1CL =  ocrval;
+       TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10);
+       TCCR1B = (0b01 << WGM12)  | ((prescale+1) << CS10);
+
+       if (ocrval == 0) {
+//             TCCR1C |= _BV(FOC1C);
+               ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+                       TCNT1 = 0xFFFF;
+               }
+       }
+
+       PINB |= _BV(6);         /* Debug */
+
+       return 0;
+}
+
+uint32_t z80_clock_get(void)
+{
+       uint32_t count = (OCR1A + 1L) * 2;
+       uint8_t pre = (TCCR1B & 7) - 1;
+
+       while (pre) {
+               if (pre > 2)
+                       count *= 4;
+               else
+                       count *= 8;
+               pre--;
+
+       }
+
+       return F_CPU/count;
+}
+
+
 
-static void z80_setup_addrbus_tristate(void)
+static void z80_addrbus_set_tristate(void)
 {
        /* /MREQ, /RD, /WR: Input, no pullup */
        DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
@@ -171,8 +253,8 @@ static void z80_setup_addrbus_tristate(void)
        DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
 }
 
-       
-static void z80_setup_addrbus_active(void)
+
+static void z80_addrbus_set_active(void)
 {
        /* /MREQ, /RD, /WR: Output and high */
        Z80_O_MREQ = 1;
@@ -186,14 +268,14 @@ static void z80_setup_addrbus_active(void)
 }
 
 
-static void z80_setup_dbus_in(void)
+static void z80_dbus_set_in(void)
 {
        DDR_DB = 0;
        P_DB = 0;
 }
 
 
-static void z80_setup_dbus_out(void)
+static void z80_dbus_set_out(void)
 {
        DDR_DB = 0xff;
 }
@@ -209,6 +291,8 @@ static void z80_reset_pulse(void)
 
 void z80_setup_bus(void)
 {
+       z80_setup_clock();
+
        /* /ZRESET: Output and low */
        Z80_O_RST = 0;
        DDR_RST |= _BV(RST);
@@ -225,8 +309,8 @@ void z80_setup_bus(void)
        DDR_IOCS1 &= ~_BV(IOCS1);
        P_IOCS1 &= ~_BV(IOCS1);
 
-       z80_setup_addrbus_tristate();
-       z80_setup_dbus_in();
+       z80_addrbus_set_tristate();
+       z80_dbus_set_in();
 
        zstate = RESET;
 }
@@ -240,8 +324,8 @@ zstate_t z80_bus_state(void)
 
 static void z80_busreq_hpulse(void)
 {
-       z80_setup_dbus_in();
-       z80_setup_addrbus_tristate();
+       z80_dbus_set_in();
+       z80_addrbus_set_tristate();
 
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
                Z80_O_BUSREQ = 1;
@@ -252,7 +336,7 @@ static void z80_busreq_hpulse(void)
        if (zstate & ZST_ACQUIRED) {
                while(Z80_I_BUSACK == 1)
                        ;
-               z80_setup_addrbus_active();
+               z80_addrbus_set_active();
        }
 }
 
@@ -291,8 +375,8 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd)
        switch (cmd) {
 
        case Reset:
-               z80_setup_dbus_in();
-               z80_setup_addrbus_tristate();
+               z80_dbus_set_in();
+               z80_addrbus_set_tristate();
                Z80_O_RST = 0;
                Z80_O_BUSREQ = 1;
                zstate = RESET;
@@ -305,7 +389,7 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd)
                        Z80_O_RST = 1;
                        while(Z80_I_BUSACK == 1)
                                ;
-                       z80_setup_addrbus_active();
+                       z80_addrbus_set_active();
                        zstate = RESET_AQRD;
                        break;
 
@@ -313,7 +397,7 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd)
                        Z80_O_BUSREQ = 0;
                        while(Z80_I_BUSACK == 1)
                                ;
-                       z80_setup_addrbus_active();
+                       z80_addrbus_set_active();
                        zstate = RUNNING_AQRD;
                        break;
 
@@ -325,15 +409,15 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd)
        case Release:
                switch (zstate) {
                case RESET_AQRD:
-                       z80_setup_dbus_in();
-                       z80_setup_addrbus_tristate();
+                       z80_dbus_set_in();
+                       z80_addrbus_set_tristate();
                        Z80_O_RST = 0;
                        Z80_O_BUSREQ = 1;
                        zstate = RESET;
                        break;
                case RUNNING_AQRD:
-                       z80_setup_dbus_in();
-                       z80_setup_addrbus_tristate();
+                       z80_dbus_set_in();
+                       z80_addrbus_set_tristate();
                        Z80_O_BUSREQ = 1;
                        zstate = RUNNING;
                        break;
@@ -350,10 +434,10 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd)
                        break;
 
                case RESET_AQRD:
-                       z80_setup_dbus_in();
-                       z80_setup_addrbus_tristate();
+                       z80_dbus_set_in();
+                       z80_addrbus_set_tristate();
                        z80_reset_pulse();
-                       z80_setup_addrbus_active();
+                       z80_addrbus_set_active();
                        zstate = RUNNING_AQRD;
                        break;
                default:
@@ -387,7 +471,7 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd)
 
 /*--------------------------------------------------------------------------*/
 
-static 
+static
 //inline __attribute__ ((always_inline))
 void z80_setaddress(uint32_t addr)
 {
@@ -402,7 +486,7 @@ void z80_write(uint32_t addr, uint8_t data)
 {
        z80_setaddress(addr);
        Z80_O_MREQ = 0;
-       z80_setup_dbus_out();
+       z80_dbus_set_out();
        P_DB = data;
        P_DB = data;
        Z80_O_WR = 0;
@@ -417,7 +501,7 @@ uint8_t z80_read(uint32_t addr)
 
        z80_setaddress(addr);
        Z80_O_MREQ = 0;
-       z80_setup_dbus_in();
+       z80_dbus_set_in();
        Z80_O_RD = 0;
        Z80_O_RD = 0;
        Z80_O_RD = 0;
@@ -431,7 +515,7 @@ uint8_t z80_read(uint32_t addr)
 
 void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
 {
-       z80_setup_dbus_out();
+       z80_dbus_set_out();
        Z80_O_MREQ = 0;
        while(length--) {
                z80_setaddress(addr++);
@@ -447,8 +531,8 @@ void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
 void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
 {
        uint8_t data;
-       
-       z80_setup_dbus_out();
+
+       z80_dbus_set_out();
        Z80_O_MREQ = 0;
        while(length--) {
                z80_setaddress(dest++);
@@ -468,7 +552,7 @@ void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
   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               ;
@@ -497,7 +581,7 @@ static struct {
                idx_in,
                mask;
        } fifo_dsc[NUM_FIFOS];
-       
+
 
 void z80_memfifo_init(const fifo_t f, uint32_t adr)
 {
@@ -537,7 +621,7 @@ int z80_memfifo_is_empty(const fifo_t f)
 int z80_memfifo_is_full(const fifo_t f)
 {
        int rc = 1;
-       
+
        if (fifo_dsc[f].base != 0) {
                z80_bus_cmd(Request);
                rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
@@ -550,7 +634,7 @@ int z80_memfifo_is_full(const fifo_t f)
 uint8_t z80_memfifo_getc(const fifo_t f)
 {
        uint8_t rc, idx;
-       
+
        while (z80_memfifo_is_empty(f))
                ;
 
@@ -560,7 +644,7 @@ uint8_t z80_memfifo_getc(const fifo_t f)
        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_bus_cmd(Release);
-       
+
        return rc;
 }
 
@@ -568,7 +652,7 @@ uint8_t z80_memfifo_getc(const fifo_t f)
 void z80_memfifo_putc(fifo_t f, uint8_t val)
 {
        int idx;
-       
+
        while (z80_memfifo_is_full(f))
                ;
 
@@ -653,7 +737,7 @@ DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
 int z80_msg_fifo_getc(void)
 {
        int c = -1;
-       
+
 #if 0
        if (msg_fifo.count != (NELEMS(msg_fifo.buf) /*- DMA1_CNDTR4 */ )) {
                c = msg_fifo.buf[msg_fifo.count];