avr: initial commit
[z80.git] / avr / io.c
diff --git a/avr/io.c b/avr/io.c
new file mode 100644 (file)
index 0000000..9106872
--- /dev/null
+++ b/avr/io.c
@@ -0,0 +1,101 @@
+/* I/O request code */
+
+#include <stdio.h>
+
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+
+#include "i2c.h"
+#include "bus.h"
+
+#include "monitor.h"
+#include "uart.h"
+#include "cpm.h"
+
+#define UNDEF_RD(ADDR, REG)    0xFF; printf_P(PSTR("<IORD %04x %s>"),ADDR,REG);
+#define UNDEF_WR(ADDR, REG)    printf_P(PSTR("<IOWR %04x %s>"), ADDR, REG);
+
+void io_init(void)
+{
+       /* nothing */
+}
+
+/* Z80 doing an I/O read */
+void io_read(void)
+{
+       uint8_t data;
+       uint8_t addr = i2c_read(I2C_ALOW);
+
+       /* select register to read from */
+       switch(addr) {
+               /* 0x00-0x07: return Slot ID */
+               case 0x00: data = slots[0]; break;
+               case 0x01: data = slots[1]; break;
+               case 0x02: data = slots[2]; break;
+               case 0x03: data = slots[3]; break;
+               case 0x04: data = slots[4]; break;
+               case 0x05: data = slots[5]; break;
+               case 0x06: data = slots[6]; break;
+               case 0x07: data = slots[7]; break;
+
+               /* 0x08-0x0F: SYSTEM */
+               case 0x0f: data = cpm_disk_read(); break;       /* ROMDISK */
+
+               /* 0x10-0x17: SERIAL PORT */
+               case 0x10:                                      /* DATA   */
+                       data = uart_rx_state() ? uart_getc(NULL) : 0xFF;
+                       break;
+               case 0x11: data = uart_rx_state(); break;       /* RXFILL */
+               case 0x12: data = UART_RXBUFSIZE;  break;       /* RXSIZE */
+               case 0x13: data = uart_tx_state(); break;       /* TXFILL */
+               case 0x14: data = UART_TXBUFSIZE;  break;       /* TXSIZE */
+               case 0x15: data = UNDEF_RD(addr, "UART_SET"); break;
+               case 0x16: data = UNDEF_RD(addr, "UART_IRQ"); break;
+
+               /* undefined address: return 0xFF */
+               default: data = 0xFF;
+       }
+
+//     printf_P(PSTR("<IORD @ %02xh = %02xh>"), addr, data);
+
+       i2c_write(I2C_DATA, data);      /* write data on bus */
+       bus_nowait();                   /* let Z80 read data */
+       bus_lock();                     /* lock bus */
+       while(!(MEMPIN & (1 << RD)));   /* wait until /RD goes high */
+       i2c_write(I2C_DATA, 0xFF);      /* remove data from bus */
+       bus_unlock();                   /* release bus */
+
+       bus_wait();     /* enable autowait for next cycle */
+       return;
+}
+
+/* Z80 doing an I/O write */
+void io_write(void)
+{
+       uint8_t addr = i2c_read(I2C_ALOW);
+       uint8_t data = i2c_read(I2C_DATA);
+
+       /* select register to write to */
+       switch(addr) {
+               /* 0x08-0x0F: SYSTEM */
+               case 0x0f: cpm_disk_write(data); break;         /* ROMDISK */
+
+               /* 0x10-0x17: SERIAL PORT */
+               case 0x10: uart_putc(data, NULL); break;        /* DATA */
+               case 0x15: UNDEF_WR(addr, "UART_SET"); break;
+               case 0x16: UNDEF_WR(addr, "UART_IRQ"); break;
+
+               /* invalid address: ignore request */
+               default: break;
+       }
+
+//     printf_P(PSTR("<IOWR @ %04x = %02x>"), addr, data);
+
+       /* release /WAIT and wait until /WR goes high */
+       bus_nowait();
+       while(!(MEMPIN & (1 << WR)));
+
+       bus_wait();     /* enable autowait for next cycle */
+       return;
+}
+