1 // license:BSD-3-Clause 2 // copyright-holders:Curt Coder 3 /********************************************************************** 4 5 Zilog Z8036/Z8536 Counter/Timer and Parallel I/O Unit 6 7 ********************************************************************** 8 _____ _____ 9 AD4 1 |* \_/ | 40 AD3 10 AD5 2 | | 39 AD2 11 AD6 3 | | 38 AD1 12 AD7 4 | | 37 AD0 13 _DS 5 | | 36 _CS0 14 R/_W 6 | | 35 CS1 15 GND 7 | | 34 _AS 16 PB0 8 | | 33 PA0 17 PB1 9 | | 32 PA1 18 PB2 10 | Z8036 | 31 PA2 19 PB3 11 | | 30 PA3 20 PB4 12 | | 29 PA4 21 PB5 13 | | 28 PA5 22 PB6 14 | | 27 PA6 23 PB7 15 | | 26 PA7 24 PCLK 16 | | 25 _INTACK 25 IEI 17 | | 24 _INT 26 IEO 18 | | 23 +5 V 27 PC0 19 | | 22 PC3 28 PC1 20 |_____________| 21 PC2 29 30 _____ _____ 31 D4 1 |* \_/ | 40 D3 32 D5 2 | | 39 D2 33 D6 3 | | 38 D1 34 D7 4 | | 37 D0 35 _RD 5 | | 36 _CE 36 _WR 6 | | 35 A1 37 GND 7 | | 34 A0 38 PB0 8 | | 33 PA0 39 PB1 9 | | 32 PA1 40 PB2 10 | Z8536 | 31 PA2 41 PB3 11 | | 30 PA3 42 PB4 12 | | 29 PA4 43 PB5 13 | | 28 PA5 44 PB6 14 | | 27 PA6 45 PB7 15 | | 26 PA7 46 PCLK 16 | | 25 _INTACK 47 IEI 17 | | 24 _INT 48 IEO 18 | | 23 +5 V 49 PC0 19 | | 22 PC3 50 PC1 20 |_____________| 21 PC2 51 52 **********************************************************************/ 53 54 #ifndef MAME_MACHINE_Z8536_H 55 #define MAME_MACHINE_Z8536_H 56 57 #pragma once 58 59 #include "machine/z80daisy.h" 60 61 62 //************************************************************************** 63 // TYPE DEFINITIONS 64 //************************************************************************** 65 66 // ======================> cio_base_device 67 68 class cio_base_device : public device_t 69 { 70 public: 71 irq_wr_cb()72 auto irq_wr_cb() { return m_write_irq.bind(); } pa_rd_cb()73 auto pa_rd_cb() { return m_read_pa.bind(); } pa_wr_cb()74 auto pa_wr_cb() { return m_write_pa.bind(); } pb_rd_cb()75 auto pb_rd_cb() { return m_read_pb.bind(); } pb_wr_cb()76 auto pb_wr_cb() { return m_write_pb.bind(); } pc_rd_cb()77 auto pc_rd_cb() { return m_read_pc.bind(); } pc_wr_cb()78 auto pc_wr_cb() { return m_write_pc.bind(); } 79 DECLARE_WRITE_LINE_MEMBER(pa0_w)80 DECLARE_WRITE_LINE_MEMBER( pa0_w ) { external_port_w(PORT_A, 0, state); } DECLARE_WRITE_LINE_MEMBER(pa1_w)81 DECLARE_WRITE_LINE_MEMBER( pa1_w ) { external_port_w(PORT_A, 1, state); } DECLARE_WRITE_LINE_MEMBER(pa2_w)82 DECLARE_WRITE_LINE_MEMBER( pa2_w ) { external_port_w(PORT_A, 2, state); } DECLARE_WRITE_LINE_MEMBER(pa3_w)83 DECLARE_WRITE_LINE_MEMBER( pa3_w ) { external_port_w(PORT_A, 3, state); } DECLARE_WRITE_LINE_MEMBER(pa4_w)84 DECLARE_WRITE_LINE_MEMBER( pa4_w ) { external_port_w(PORT_A, 4, state); } DECLARE_WRITE_LINE_MEMBER(pa5_w)85 DECLARE_WRITE_LINE_MEMBER( pa5_w ) { external_port_w(PORT_A, 5, state); } DECLARE_WRITE_LINE_MEMBER(pa6_w)86 DECLARE_WRITE_LINE_MEMBER( pa6_w ) { external_port_w(PORT_A, 6, state); } DECLARE_WRITE_LINE_MEMBER(pa7_w)87 DECLARE_WRITE_LINE_MEMBER( pa7_w ) { external_port_w(PORT_A, 7, state); } 88 DECLARE_WRITE_LINE_MEMBER(pb0_w)89 DECLARE_WRITE_LINE_MEMBER( pb0_w ) { external_port_w(PORT_B, 0, state); } DECLARE_WRITE_LINE_MEMBER(pb1_w)90 DECLARE_WRITE_LINE_MEMBER( pb1_w ) { external_port_w(PORT_B, 1, state); } DECLARE_WRITE_LINE_MEMBER(pb2_w)91 DECLARE_WRITE_LINE_MEMBER( pb2_w ) { external_port_w(PORT_B, 2, state); } DECLARE_WRITE_LINE_MEMBER(pb3_w)92 DECLARE_WRITE_LINE_MEMBER( pb3_w ) { external_port_w(PORT_B, 3, state); } DECLARE_WRITE_LINE_MEMBER(pb4_w)93 DECLARE_WRITE_LINE_MEMBER( pb4_w ) { external_port_w(PORT_B, 4, state); } DECLARE_WRITE_LINE_MEMBER(pb5_w)94 DECLARE_WRITE_LINE_MEMBER( pb5_w ) { external_port_w(PORT_B, 5, state); } DECLARE_WRITE_LINE_MEMBER(pb6_w)95 DECLARE_WRITE_LINE_MEMBER( pb6_w ) { external_port_w(PORT_B, 6, state); } DECLARE_WRITE_LINE_MEMBER(pb7_w)96 DECLARE_WRITE_LINE_MEMBER( pb7_w ) { external_port_w(PORT_B, 7, state); } 97 DECLARE_WRITE_LINE_MEMBER(pc0_w)98 DECLARE_WRITE_LINE_MEMBER( pc0_w ) { external_port_w(PORT_C, 0, state); } DECLARE_WRITE_LINE_MEMBER(pc1_w)99 DECLARE_WRITE_LINE_MEMBER( pc1_w ) { external_port_w(PORT_C, 1, state); } DECLARE_WRITE_LINE_MEMBER(pc2_w)100 DECLARE_WRITE_LINE_MEMBER( pc2_w ) { external_port_w(PORT_C, 2, state); } DECLARE_WRITE_LINE_MEMBER(pc3_w)101 DECLARE_WRITE_LINE_MEMBER( pc3_w ) { external_port_w(PORT_C, 3, state); } 102 103 int intack_r(); 104 105 protected: 106 // construction/destruction 107 cio_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); 108 109 // device-level overrides 110 virtual void device_start() override; 111 virtual void device_reset() override; 112 virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; 113 is_reset()114 bool is_reset() const { return (m_register[MASTER_INTERRUPT_CONTROL] & MICR_RESET) != 0; } 115 116 enum 117 { 118 TIMER_1 = 0, 119 TIMER_2, 120 TIMER_3 121 }; 122 123 // ports 124 enum 125 { 126 PORT_A = 0, 127 PORT_B, 128 PORT_C, 129 CONTROL 130 }; 131 132 133 // registers 134 enum 135 { 136 MASTER_INTERRUPT_CONTROL = 0x00, 137 MASTER_CONFIGURATION_CONTROL, 138 PORT_A_INTERRUPT_VECTOR, 139 PORT_B_INTERRUPT_VECTOR, 140 COUNTER_TIMER_INTERRUPT_VECTOR, 141 PORT_C_DATA_PATH_POLARITY, 142 PORT_C_DATA_DIRECTION, 143 PORT_C_SPECIAL_IO_CONTROL, 144 PORT_A_COMMAND_AND_STATUS, 145 PORT_B_COMMAND_AND_STATUS, 146 COUNTER_TIMER_1_COMMAND_AND_STATUS, 147 COUNTER_TIMER_2_COMMAND_AND_STATUS, 148 COUNTER_TIMER_3_COMMAND_AND_STATUS, 149 PORT_A_DATA, 150 PORT_B_DATA, 151 PORT_C_DATA, 152 COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE = 0x10, 153 COUNTER_TIMER_1_CURRENT_COUNT_LS_BYTE, 154 COUNTER_TIMER_2_CURRENT_COUNT_MS_BYTE, 155 COUNTER_TIMER_2_CURRENT_COUNT_LS_BYTE, 156 COUNTER_TIMER_3_CURRENT_COUNT_MS_BYTE, 157 COUNTER_TIMER_3_CURRENT_COUNT_LS_BYTE, 158 COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE, 159 COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE, 160 COUNTER_TIMER_2_TIME_CONSTANT_MS_BYTE, 161 COUNTER_TIMER_2_TIME_CONSTANT_LS_BYTE, 162 COUNTER_TIMER_3_TIME_CONSTANT_MS_BYTE, 163 COUNTER_TIMER_3_TIME_CONSTANT_LS_BYTE, 164 COUNTER_TIMER_1_MODE_SPECIFICATION, 165 COUNTER_TIMER_2_MODE_SPECIFICATION, 166 COUNTER_TIMER_3_MODE_SPECIFICATION, 167 CURRENT_VECTOR, 168 PORT_A_MODE_SPECIFICATION = 0x20, 169 PORT_A_HANDSHAKE_SPECIFICATION, 170 PORT_A_DATA_PATH_POLARITY, 171 PORT_A_DATA_DIRECTION, 172 PORT_A_SPECIAL_IO_CONTROL, 173 PORT_A_PATTERN_POLARITY, 174 PORT_A_PATTERN_TRANSITION, 175 PORT_A_PATTERN_MASK, 176 PORT_B_MODE_SPECIFICATION, 177 PORT_B_HANDSHAKE_SPECIFICATION, 178 PORT_B_DATA_PATH_POLARITY, 179 PORT_B_DATA_DIRECTION, 180 PORT_B_SPECIAL_IO_CONTROL, 181 PORT_B_PATTERN_POLARITY, 182 PORT_B_PATTERN_TRANSITION, 183 PORT_B_PATTERN_MASK 184 }; 185 186 187 // master interrupt control register 188 enum 189 { 190 MICR_RESET = 0x01, // reset 191 MICR_RJA = 0x02, // right justified address 192 MICR_CT_VIS = 0x04, // counter/timer vector includes status 193 MICR_PB_VIS = 0x08, // port B vector includes status 194 MICR_PA_VIS = 0x10, // port A vector includes status 195 MICR_NV = 0x20, // no vector 196 MICR_DLC = 0x40, // disable lower chain 197 MICR_MIE = 0x80 // master interrupt enable 198 }; 199 200 201 // master configuration control register 202 enum 203 { 204 MCCR_LC_MASK = 0x03, // counter/timer link controls 205 MCCR_PAE = 0x04, // port A enable 206 MCCR_PLC = 0x08, // port link control 207 MCCR_PCE_CT3E = 0x10, // port C and counter/timer 3 enable 208 MCCR_CT2E = 0x20, // counter/timer 2 enable 209 MCCR_CT1E = 0x40, // counter/timer 1 enable 210 MCCR_PBE = 0x80 // port B enable 211 }; 212 213 214 // port mode specification registers 215 enum 216 { 217 PMS_LPM = 0x01, // latch on pattern match 218 PMS_DTE = 0x01, // deskew timer enable 219 PMS_PMS_MASK = 0x06, // pattern mode specification 220 PMS_IMO = 0x08, // interrupt on match only 221 PMS_SB = 0x10, // single buffer 222 PMS_ITB = 0x20, // interrupt on two bytes 223 PMS_PTS_MASK = 0xc0 // port type select 224 }; 225 226 227 // port handshake specification registers 228 enum 229 { 230 PHS_DTS_MASK = 0x07, // deskew time specification 231 PHS_RWS_MASK = 0x38, // request/wait specification 232 PHS_HTS_MASK = 0xc0 // handshake type specification 233 }; 234 235 236 // port command and status registers 237 enum 238 { 239 PCS_IOE = 0x01, // interrupt on error 240 PCS_PMF = 0x02, // pattern match flag (read only) 241 PCS_IRF = 0x04, // input register full (read only) 242 PCS_ORE = 0x08, // output register empty (read only) 243 PCS_ERR = 0x10, // interrupt error (read only) 244 PCS_IP = 0x20, // interrupt pending 245 PCS_IE = 0x40, // interrupt enable 246 PCS_IUS = 0x80 // interrupt under service 247 }; 248 249 250 // counter/timer mode specification registers 251 enum 252 { 253 CTMS_DCS_MASK = 0x03, // output duty cycle 254 CTMS_REB = 0x04, // retrigger enable bit 255 CTMS_EDE = 0x08, // external gate enable 256 CTMS_ETE = 0x10, // external trigger enable 257 CTMS_ECE = 0x20, // external count enable 258 CTMS_EOE = 0x40, // external output enable 259 CTMS_CSC = 0x80 // continuous/single cycle 260 }; 261 262 263 // counter/timer command and status registers 264 enum 265 { 266 CTCS_CIP = 0x01, // count in progress (read only) 267 CTCS_TCB = 0x02, // trigger command bit (write only - read returns 0) 268 CTCS_GCB = 0x04, // gate command bit 269 CTCS_RCC = 0x08, // read counter control (read/set only - cleared by reading CCR LSB) 270 CTCS_ERR = 0x10, // interrupt error (read only) 271 CTCS_IP = 0x20, // interrupt pending 272 CTCS_IE = 0x40, // interrupt enable 273 CTCS_IUS = 0x80 // interrupt under service 274 }; 275 276 277 // interrupt control 278 enum 279 { 280 IC_NULL = 0, 281 IC_CLEAR_IP_IUS, 282 IC_SET_IUS, 283 IC_CLEAR_IUS, 284 IC_SET_IP, 285 IC_CLEAR_IP, 286 IC_SET_IE, 287 IC_CLEAR_IE 288 }; 289 290 291 // counter/timer link control 292 enum 293 { 294 LC_INDEPENDENT = 0, 295 LC_CT1_GATES_CT2, 296 LC_CT1_TRIGGERS_CT2, 297 LC_CT1_COUNTS_CT2 298 }; 299 300 301 // port type select 302 enum 303 { 304 PTS_BIT = 0, 305 PTS_INPUT, 306 PTS_OUTPUT, 307 PTS_BIDIRECTIONAL 308 }; 309 310 311 312 // pattern mode specification 313 enum 314 { 315 PMS_DISABLE = 0, 316 PMS_AND, 317 PMS_OR, 318 PMS_OR_PEV 319 }; 320 321 // handshake specification 322 enum 323 { 324 HTS_INTERLOCKED = 0, 325 HTS_STROBED, 326 HTS_PULSED, 327 HTS_3_WIRE 328 }; 329 330 331 // request/wait specification 332 enum 333 { 334 RWS_DISABLED = 0, 335 RWS_OUTPUT_WAIT, 336 RWS_INPUT_WAIT = 3, 337 RWS_SPECIAL_REQUEST, 338 RWS_OUTPUT_REQUEST, 339 RWS_INPUT_REQUEST = 7 340 }; 341 342 343 // pattern specification 344 enum 345 { 346 BIT_MASKED_OFF = 0, 347 ANY_TRANSITION, 348 ZERO = 4, 349 ONE, 350 ONE_TO_ZERO, 351 ZERO_TO_ONE 352 }; 353 354 355 // output duty cycle 356 enum 357 { 358 DCS_PULSE, 359 DCS_ONE_SHOT, 360 DCS_SQUARE_WAVE, 361 DCS_DO_NOT_USE 362 }; 363 364 void get_interrupt_vector(); 365 void check_interrupt(); 366 367 u8 read_register(offs_t offset); 368 u8 read_register(offs_t offset, u8 mask); 369 void write_register(offs_t offset, u8 data); 370 void write_register(offs_t offset, u8 data, u8 mask); 371 372 bool counter_enabled(device_timer_id id); 373 bool counter_external_output(device_timer_id id); 374 bool counter_external_count(device_timer_id id); 375 bool counter_external_trigger(device_timer_id id); 376 bool counter_external_gate(device_timer_id id); 377 bool counter_gated(device_timer_id id); 378 void count(device_timer_id id); 379 void trigger(device_timer_id id); 380 void gate(device_timer_id id, int state); 381 void match_pattern(int port); 382 void external_port_w(int port, int bit, int state); 383 384 private: 385 devcb_write_line m_write_irq; 386 387 devcb_read8 m_read_pa; 388 devcb_write8 m_write_pa; 389 390 devcb_read8 m_read_pb; 391 devcb_write8 m_write_pb; 392 393 devcb_read8 m_read_pc; 394 devcb_write8 m_write_pc; 395 396 // interrupt state 397 int m_irq; 398 399 // register state 400 u8 m_register[48]; 401 402 // input/output port state 403 u8 m_input[3]; 404 u8 m_output[3]; 405 u8 m_buffer[3]; 406 u8 m_match[3]; 407 408 // timers 409 emu_timer *m_timer; 410 u16 m_counter[3]; 411 }; 412 413 // ======================> z8036_device 414 415 class z8036_device : public cio_base_device 416 { 417 public: 418 // construction/destruction 419 z8036_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); 420 421 u8 read(offs_t offset); 422 void write(offs_t offset, u8 data); 423 }; 424 425 // ======================> z8536_device 426 427 class z8536_device : public cio_base_device, public device_z80daisy_interface 428 { 429 public: 430 // construction/destruction 431 z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); 432 433 u8 read(offs_t offset); 434 void write(offs_t offset, u8 data); 435 436 protected: 437 // device-level overrides 438 virtual void device_start() override; 439 virtual void device_reset() override; 440 441 // device_z80daisy_interface overrides 442 virtual int z80daisy_irq_state() override; 443 virtual int z80daisy_irq_ack() override; 444 virtual void z80daisy_irq_reti() override; 445 446 private: 447 // control state machine 448 bool m_state0; 449 u8 m_pointer; 450 }; 451 452 453 // device type definition 454 DECLARE_DEVICE_TYPE(Z8036, z8036_device) 455 DECLARE_DEVICE_TYPE(Z8536, z8536_device) 456 457 #endif // MAME_MACHINE_Z8536_H 458