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