1 // license:BSD-3-Clause 2 // copyright-holders:Curt Coder 3 /*************************************************************************** 4 5 Zilog Z80 Parallel Input/Output Controller implementation 6 7 *************************************************************************** 8 _____ _____ 9 D2 1 |* \_/ | 40 D3 10 D7 2 | | 39 D4 11 D6 3 | | 38 D5 12 _CE 4 | | 37 _M1 13 C/_D 5 | | 36 _IORQ 14 B/_A 6 | | 35 RD 15 PA7 7 | | 34 PB7 16 PA6 8 | | 33 PB6 17 PA5 9 | | 32 PB5 18 PA4 10 | Z8420 | 31 PB4 19 GND 11 | | 30 PB3 20 PA3 12 | | 29 PB2 21 PA2 13 | | 28 PB1 22 PA1 14 | | 27 PB0 23 PA0 15 | | 26 +5V 24 _ASTB 16 | | 25 CLK 25 _BSTB 17 | | 24 IEI 26 ARDY 18 | | 23 _INT 27 D0 19 | | 22 IEO 28 D1 20 |_____________| 21 BRDY 29 30 ***************************************************************************/ 31 32 #ifndef MAME_MACHINE_Z80PIO_H 33 #define MAME_MACHINE_Z80PIO_H 34 35 #pragma once 36 37 #include "machine/z80daisy.h" 38 39 40 //************************************************************************** 41 // TYPE DEFINITIONS 42 //************************************************************************** 43 44 45 // ======================> z80pio_device 46 47 class z80pio_device : public device_t, 48 public device_z80daisy_interface 49 { 50 public: 51 enum 52 { 53 PORT_A = 0, 54 PORT_B, 55 PORT_COUNT 56 }; 57 58 // construction/destruction 59 z80pio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 60 out_int_callback()61 auto out_int_callback() { return m_out_int_cb.bind(); } in_pa_callback()62 auto in_pa_callback() { return m_in_pa_cb.bind(); } out_pa_callback()63 auto out_pa_callback() { return m_out_pa_cb.bind(); } out_ardy_callback()64 auto out_ardy_callback() { return m_out_ardy_cb.bind(); } in_pb_callback()65 auto in_pb_callback() { return m_in_pb_cb.bind(); } out_pb_callback()66 auto out_pb_callback() { return m_out_pb_cb.bind(); } out_brdy_callback()67 auto out_brdy_callback() { return m_out_brdy_cb.bind(); } 68 69 70 // I/O line access rdy(int which)71 int rdy(int which) { return m_port[which].rdy(); } strobe(int which,bool state)72 void strobe(int which, bool state) { m_port[which].strobe(state); } DECLARE_READ_LINE_MEMBER(rdy_a)73 DECLARE_READ_LINE_MEMBER( rdy_a ) { return rdy(PORT_A); } DECLARE_READ_LINE_MEMBER(rdy_b)74 DECLARE_READ_LINE_MEMBER( rdy_b ) { return rdy(PORT_B); } DECLARE_WRITE_LINE_MEMBER(strobe_a)75 DECLARE_WRITE_LINE_MEMBER( strobe_a ) { strobe(PORT_A, state); } DECLARE_WRITE_LINE_MEMBER(strobe_b)76 DECLARE_WRITE_LINE_MEMBER( strobe_b ) { strobe(PORT_B, state); } 77 78 // control register I/O 79 uint8_t control_read(); control_write(int offset,uint8_t data)80 void control_write(int offset, uint8_t data) { m_port[offset & 1].control_write(data); } control_a_write(uint8_t data)81 void control_a_write(uint8_t data) { control_write(PORT_A, data); } control_b_write(uint8_t data)82 void control_b_write(uint8_t data) { control_write(PORT_B, data); } 83 84 // data register I/O data_read(int offset)85 uint8_t data_read(int offset) { return m_port[offset & 1].data_read(); } data_write(int offset,uint8_t data)86 void data_write(int offset, uint8_t data) { m_port[offset & 1].data_write(data); } data_a_read()87 uint8_t data_a_read() { return data_read(PORT_A); } data_b_read()88 uint8_t data_b_read() { return data_read(PORT_B); } data_a_write(uint8_t data)89 void data_a_write(uint8_t data) { data_write(PORT_A, data); } data_b_write(uint8_t data)90 void data_b_write(uint8_t data) { data_write(PORT_B, data); } 91 92 // port I/O port_read(int offset)93 uint8_t port_read(int offset) { return m_port[offset & 1].read(); } port_write(int offset,uint8_t data)94 void port_write(int offset, uint8_t data) { m_port[offset & 1].write(data); } port_write(int offset,int bit,int state)95 void port_write(int offset, int bit, int state) { port_write(offset, (m_port[offset & 1].m_input & ~(1 << bit)) | (state << bit)); } port_a_read()96 uint8_t port_a_read() { return port_read(PORT_A); } port_b_read()97 uint8_t port_b_read() { return port_read(PORT_B); } port_a_write(uint8_t data)98 void port_a_write(uint8_t data) { port_write(PORT_A, data); } port_b_write(uint8_t data)99 void port_b_write(uint8_t data) { port_write(PORT_B, data); } DECLARE_WRITE_LINE_MEMBER(pa0_w)100 DECLARE_WRITE_LINE_MEMBER( pa0_w ) { port_write(PORT_A, 0, state); } DECLARE_WRITE_LINE_MEMBER(pa1_w)101 DECLARE_WRITE_LINE_MEMBER( pa1_w ) { port_write(PORT_A, 1, state); } DECLARE_WRITE_LINE_MEMBER(pa2_w)102 DECLARE_WRITE_LINE_MEMBER( pa2_w ) { port_write(PORT_A, 2, state); } DECLARE_WRITE_LINE_MEMBER(pa3_w)103 DECLARE_WRITE_LINE_MEMBER( pa3_w ) { port_write(PORT_A, 3, state); } DECLARE_WRITE_LINE_MEMBER(pa4_w)104 DECLARE_WRITE_LINE_MEMBER( pa4_w ) { port_write(PORT_A, 4, state); } DECLARE_WRITE_LINE_MEMBER(pa5_w)105 DECLARE_WRITE_LINE_MEMBER( pa5_w ) { port_write(PORT_A, 5, state); } DECLARE_WRITE_LINE_MEMBER(pa6_w)106 DECLARE_WRITE_LINE_MEMBER( pa6_w ) { port_write(PORT_A, 6, state); } DECLARE_WRITE_LINE_MEMBER(pa7_w)107 DECLARE_WRITE_LINE_MEMBER( pa7_w ) { port_write(PORT_A, 7, state); } DECLARE_WRITE_LINE_MEMBER(pb0_w)108 DECLARE_WRITE_LINE_MEMBER( pb0_w ) { port_write(PORT_B, 0, state); } DECLARE_WRITE_LINE_MEMBER(pb1_w)109 DECLARE_WRITE_LINE_MEMBER( pb1_w ) { port_write(PORT_B, 1, state); } DECLARE_WRITE_LINE_MEMBER(pb2_w)110 DECLARE_WRITE_LINE_MEMBER( pb2_w ) { port_write(PORT_B, 2, state); } DECLARE_WRITE_LINE_MEMBER(pb3_w)111 DECLARE_WRITE_LINE_MEMBER( pb3_w ) { port_write(PORT_B, 3, state); } DECLARE_WRITE_LINE_MEMBER(pb4_w)112 DECLARE_WRITE_LINE_MEMBER( pb4_w ) { port_write(PORT_B, 4, state); } DECLARE_WRITE_LINE_MEMBER(pb5_w)113 DECLARE_WRITE_LINE_MEMBER( pb5_w ) { port_write(PORT_B, 5, state); } DECLARE_WRITE_LINE_MEMBER(pb6_w)114 DECLARE_WRITE_LINE_MEMBER( pb6_w ) { port_write(PORT_B, 6, state); } DECLARE_WRITE_LINE_MEMBER(pb7_w)115 DECLARE_WRITE_LINE_MEMBER( pb7_w ) { port_write(PORT_B, 7, state); } 116 117 // standard read/write, with C/D in bit 1, B/A in bit 0 118 u8 read(offs_t offset); 119 void write(offs_t offset, u8 data); 120 121 // alternate read/write, with C/D in bit 0, B/A in bit 1 122 u8 read_alt(offs_t offset); 123 void write_alt(offs_t offset, u8 data); 124 125 private: 126 enum 127 { 128 MODE_OUTPUT = 0, 129 MODE_INPUT, 130 MODE_BIDIRECTIONAL, 131 MODE_BIT_CONTROL 132 }; 133 134 enum 135 { 136 ANY = 0, 137 IOR, 138 MASK 139 }; 140 141 enum 142 { 143 ICW_ENABLE_INT = 0x80, 144 ICW_AND_OR = 0x40, 145 ICW_AND = 0x40, 146 ICW_OR = 0x00, 147 ICW_HIGH_LOW = 0x20, 148 ICW_HIGH = 0x20, 149 ICW_LOW = 0x00, 150 ICW_MASK_FOLLOWS = 0x10 151 }; 152 153 // device-level overrides 154 virtual void device_start() override; 155 virtual void device_reset() override; 156 157 // device_z80daisy_interface overrides 158 virtual int z80daisy_irq_state() override; 159 virtual int z80daisy_irq_ack() override; 160 virtual void z80daisy_irq_reti() override; 161 162 // internal helpers 163 void check_interrupts(); 164 165 // a single PIO port 166 class pio_port 167 { 168 friend class z80pio_device; 169 170 public: 171 pio_port(); 172 173 void start(z80pio_device *device, int index); 174 void reset(); 175 176 void trigger_interrupt(); 177 rdy()178 int rdy() const { return m_rdy; } 179 void set_rdy(bool state); 180 void set_mode(int mode); 181 void strobe(bool state); 182 183 uint8_t read(); 184 void write(uint8_t data); 185 186 void control_write(uint8_t data); 187 188 uint8_t data_read(); 189 void data_write(uint8_t data); 190 191 private: check_interrupts()192 void check_interrupts() { m_device->check_interrupts(); } 193 194 z80pio_device * m_device; 195 int m_index; 196 197 int m_mode; // mode register 198 int m_next_control_word; // next control word 199 uint8_t m_input; // input latch 200 uint8_t m_output; // output latch 201 uint8_t m_ior; // input/output register 202 bool m_rdy; // ready 203 bool m_stb; // strobe 204 205 // interrupts 206 bool m_ie; // interrupt enabled 207 bool m_ip; // interrupt pending 208 bool m_ius; // interrupt under service 209 uint8_t m_icw; // interrupt control word 210 uint8_t m_vector; // interrupt vector 211 uint8_t m_mask; // interrupt mask 212 bool m_match; // logic equation match 213 }; 214 215 // internal state 216 pio_port m_port[2]; 217 devcb_write_line m_out_int_cb; 218 219 devcb_read8 m_in_pa_cb; 220 devcb_write8 m_out_pa_cb; 221 devcb_write_line m_out_ardy_cb; 222 223 devcb_read8 m_in_pb_cb; 224 devcb_write8 m_out_pb_cb; 225 devcb_write_line m_out_brdy_cb; 226 }; 227 228 229 // device type definition 230 DECLARE_DEVICE_TYPE(Z80PIO, z80pio_device) 231 232 #endif // MAME_MACHINE_Z80PIO_H 233