avr: initial commit
[z80.git] / avr / io.c
1 /* I/O request code */
2
3 #include <stdio.h>
4
5 #include <avr/pgmspace.h>
6 #include <avr/interrupt.h>
7
8 #include "i2c.h"
9 #include "bus.h"
10
11 #include "monitor.h"
12 #include "uart.h"
13 #include "cpm.h"
14
15 #define UNDEF_RD(ADDR, REG)     0xFF; printf_P(PSTR("<IORD %04x %s>"),ADDR,REG);
16 #define UNDEF_WR(ADDR, REG)     printf_P(PSTR("<IOWR %04x %s>"), ADDR, REG);
17
18 void io_init(void)
19 {
20         /* nothing */
21 }
22
23 /* Z80 doing an I/O read */
24 void io_read(void)
25 {
26         uint8_t data;
27         uint8_t addr = i2c_read(I2C_ALOW);
28
29         /* select register to read from */
30         switch(addr) {
31                 /* 0x00-0x07: return Slot ID */
32                 case 0x00: data = slots[0]; break;
33                 case 0x01: data = slots[1]; break;
34                 case 0x02: data = slots[2]; break;
35                 case 0x03: data = slots[3]; break;
36                 case 0x04: data = slots[4]; break;
37                 case 0x05: data = slots[5]; break;
38                 case 0x06: data = slots[6]; break;
39                 case 0x07: data = slots[7]; break;
40
41                 /* 0x08-0x0F: SYSTEM */
42                 case 0x0f: data = cpm_disk_read(); break;       /* ROMDISK */
43
44                 /* 0x10-0x17: SERIAL PORT */
45                 case 0x10:                                      /* DATA   */
46                         data = uart_rx_state() ? uart_getc(NULL) : 0xFF;
47                         break;
48                 case 0x11: data = uart_rx_state(); break;       /* RXFILL */
49                 case 0x12: data = UART_RXBUFSIZE;  break;       /* RXSIZE */
50                 case 0x13: data = uart_tx_state(); break;       /* TXFILL */
51                 case 0x14: data = UART_TXBUFSIZE;  break;       /* TXSIZE */
52                 case 0x15: data = UNDEF_RD(addr, "UART_SET"); break;
53                 case 0x16: data = UNDEF_RD(addr, "UART_IRQ"); break;
54
55                 /* undefined address: return 0xFF */
56                 default: data = 0xFF;
57         }
58
59 //      printf_P(PSTR("<IORD @ %02xh = %02xh>"), addr, data);
60
61         i2c_write(I2C_DATA, data);      /* write data on bus */
62         bus_nowait();                   /* let Z80 read data */
63         bus_lock();                     /* lock bus */
64         while(!(MEMPIN & (1 << RD)));   /* wait until /RD goes high */
65         i2c_write(I2C_DATA, 0xFF);      /* remove data from bus */
66         bus_unlock();                   /* release bus */
67
68         bus_wait();     /* enable autowait for next cycle */
69         return;
70 }
71
72 /* Z80 doing an I/O write */
73 void io_write(void)
74 {
75         uint8_t addr = i2c_read(I2C_ALOW);
76         uint8_t data = i2c_read(I2C_DATA);
77
78         /* select register to write to */
79         switch(addr) {
80                 /* 0x08-0x0F: SYSTEM */
81                 case 0x0f: cpm_disk_write(data); break;         /* ROMDISK */
82
83                 /* 0x10-0x17: SERIAL PORT */
84                 case 0x10: uart_putc(data, NULL); break;        /* DATA */
85                 case 0x15: UNDEF_WR(addr, "UART_SET"); break;
86                 case 0x16: UNDEF_WR(addr, "UART_IRQ"); break;
87
88                 /* invalid address: ignore request */
89                 default: break;
90         }
91
92 //      printf_P(PSTR("<IOWR @ %04x = %02x>"), addr, data);
93
94         /* release /WAIT and wait until /WR goes high */
95         bus_nowait();
96         while(!(MEMPIN & (1 << WR)));
97
98         bus_wait();     /* enable autowait for next cycle */
99         return;
100 }
101