--- /dev/null
+/* 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;
+}
+