1 // license:BSD-3-Clause
2 // copyright-holders:Joakim Larsson Edstrom
3 /***************************************************************************
4 
5     Philips DUSCC - Dual Serial Communications Controller emulation
6 
7 ****************************************************************************
8 
9          Chan B                     Chan A  Chan B                     Chan A
10          =======   _____   _____  ========  =======   _____   _____  ========
11           IACKN  1|*    \_/     |48 VCC      IACKN  1|*    \_/     |48 VDD
12              A3  2|             |47 A4          A3  2|             |47 A4
13              A2  3|             |46 A5          A2  3|             |46 A5
14              A1  4|             |45 A6          A1  4|             |45 A6
15     RTxDAK/GPI1  5|             |44   RTxDAK/GPI1   5|             |44 RTxDAK/GP1
16            IRQN  6|             |43 X1/CLK    IRQN  6|             |43 X1/CLK
17            RDYN  7|             |42 X2      RESETN  7|             |42 X2
18      RTS/SYNOUT  8|             |41    RTS/SYNOUT   8|             |41 RTS/SYNOUT
19            TRxC  9|             |40 TRxC      TRxC  9|             |40 TRxC
20            RTxC 10|             |39 RTxC      RTxC 10|             |39 RTxC
21        DCD/SYNI 11|             |38     DCD/SYNI   11|             |38 DCD/SYNI
22             RxD 12|             |37 RxD        RxD 12|             |37 RxD
23             TxD 13|  SCN26562   |36 TxD        TxD 13|  SCN68562   |36 TxD
24      TxDAK/GPI2 14|  SCN26C562  |35   TxDAK/GPI2   14|  SCN68C562  |35 TxDAK/GPI2
25     RTxDRQ/GPO1 15|             |34   RTxDRQ/GPO1  15|             |34 RTxDRQ/GPO1
26  TxDRQ/RTS/GPO2 16|             |33 TxDRQ/RTS/GPO2 16|             |33 TxDRQ/RTS/GPO2
27          CTS/LC 17|             |32 CTS/LC  CTS/LC 17|             |32 CTS/LC
28              D7 18|             |31 D0          D7 18|             |31 D0
29              D6 19|             |30 D1          D6 19|             |30 D1
30              D5 20|             |29 D2          D5 20|             |29 D2
31              D4 21|             |28 D3          D4 21|             |28 D3
32             RDN 22|             |27 EOPN    DTACKN 22|             |27 DONEN
33          RESETN 23|             |26 WRN       DTCN 23|             |26 R/WN
34             GND 24|_____________|25 CEN        CND 24|_____________|25 CSN
35                     Intel Bus                          Motorola Bus
36 
37 ***************************************************************************/
38 
39 #ifndef MAME_MACHINE_SCNXX562_H
40 #define MAME_MACHINE_SCNXX562_H
41 
42 #pragma once
43 
44 #include "machine/z80daisy.h"
45 #include "diserial.h"
46 
47 
48 //**************************************************************************
49 //  TYPE DEFINITIONS
50 //**************************************************************************
51 
52 // ======================> duscc_channel
53 
54 class duscc_device;
55 
56 class duscc_channel : public device_t, public device_serial_interface
57 {
58 	friend class duscc_device;
59 
60 public:
61 	duscc_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
62 
63 	// read register handlers
64 	uint8_t do_dusccreg_cmr1_r();
65 	uint8_t do_dusccreg_cmr2_r();
66 	uint8_t do_dusccreg_s1r_r();
67 	uint8_t do_dusccreg_s2r_r();
68 	uint8_t do_dusccreg_tpr_r();
69 	uint8_t do_dusccreg_ttr_r();
70 	uint8_t do_dusccreg_rpr_r();
71 	uint8_t do_dusccreg_rtr_r();
72 	uint8_t do_dusccreg_ctprh_r();
73 	uint8_t do_dusccreg_ctprl_r();
74 	uint8_t do_dusccreg_ctcr_r();
75 	uint8_t do_dusccreg_omr_r();
76 	uint8_t do_dusccreg_cth_r();
77 	uint8_t do_dusccreg_ctl_r();
78 	uint8_t do_dusccreg_pcr_r();
79 	uint8_t do_dusccreg_ccr_r();
80 	uint8_t do_dusccreg_rxfifo_r();
81 	uint8_t do_dusccreg_rsr_r();
82 	uint8_t do_dusccreg_trsr_r();
83 	uint8_t do_dusccreg_ictsr_r();
84 	uint8_t do_dusccreg_gsr_r();
85 	uint8_t do_dusccreg_ier_r();
86 	uint8_t do_dusccreg_cid_r();
87 	uint8_t do_dusccreg_ivr_ivrm_r();
88 	uint8_t do_dusccreg_icr_r();
89 	uint8_t do_dusccreg_mrr_r();
90 	uint8_t do_dusccreg_ier1_r();
91 	uint8_t do_dusccreg_ier2_r();
92 	uint8_t do_dusccreg_ier3_r();
93 	uint8_t do_dusccreg_trcr_r();
94 	uint8_t do_dusccreg_rflr_r();
95 	uint8_t do_dusccreg_ftlr_r();
96 	uint8_t do_dusccreg_trmsr_r();
97 	uint8_t do_dusccreg_telr_r();
98 
99 	// write register handlers
100 	void do_dusccreg_cmr1_w(uint8_t data);
101 	void do_dusccreg_cmr2_w(uint8_t data);
102 	void do_dusccreg_s1r_w(uint8_t data);
103 	void do_dusccreg_s2r_w(uint8_t data);
104 	void do_dusccreg_tpr_w(uint8_t data);
105 	void do_dusccreg_ttr_w(uint8_t data);
106 	void do_dusccreg_rpr_w(uint8_t data);
107 	void do_dusccreg_rtr_w(uint8_t data);
108 	void do_dusccreg_ctprh_w(uint8_t data);
109 	void do_dusccreg_ctprl_w(uint8_t data);
110 	void do_dusccreg_ctcr_w(uint8_t data);
111 	void do_dusccreg_omr_w(uint8_t data);
112 	void do_dusccreg_pcr_w(uint8_t data);
113 	void do_dusccreg_ccr_w(uint8_t data);
114 	void do_dusccreg_txfifo_w(uint8_t data);
115 	void do_dusccreg_rsr_w(uint8_t data);
116 	void do_dusccreg_trsr_w(uint8_t data);
117 	void do_dusccreg_ictsr_w(uint8_t data);
118 	void do_dusccreg_gsr_w(uint8_t data);
119 	void do_dusccreg_ier_w(uint8_t data);
120 	//  void do_dusccreg_rea_w(uint8_t data); // Short cutted non complex feature
121 	void do_dusccreg_ivr_w(uint8_t data);
122 	void do_dusccreg_icr_w(uint8_t data);
123 	void do_dusccreg_sea_rea_w(uint8_t data); // Short cutted non complex feature
124 	void do_dusccreg_mrr_w(uint8_t data);
125 	void do_dusccreg_ier1_w(uint8_t data);
126 	void do_dusccreg_ier2_w(uint8_t data);
127 	void do_dusccreg_ier3_w(uint8_t data);
128 	void do_dusccreg_trcr_w(uint8_t data);
129 	void do_dusccreg_ftlr_w(uint8_t data);
130 	void do_dusccreg_trmsr_w(uint8_t data);
131 
132 	uint8_t read(offs_t &offset);
133 	void write(uint8_t data, offs_t &offset);
134 
135 	//  uint8_t data_read();
136 	//  void data_write(uint8_t data);
137 
138 	void receive_data(uint8_t data);
139 	void m_tx_fifo_rp_step();
140 	void m_rx_fifo_rp_step();
141 	uint8_t m_rx_fifo_rp_data();
142 
143 	void write_rx(int state);
144 	void cts_w(int state);
145 	void dcd_w(int state);
146 	void ri_w(int state);
147 	void rxc_w(int state);
148 	void txc_w(int state);
149 	void sync_w(int state);
150 
151 protected:
152 	// device-level overrides
153 	virtual void device_start() override;
154 	virtual void device_reset() override;
155 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
156 
157 	// device_serial_interface overrides
158 	virtual void tra_callback() override;
159 	virtual void tra_complete() override;
160 	virtual void rcv_callback() override;
161 	virtual void rcv_complete() override;
162 
163 	int m_rxc;
164 	int m_txc;
165 	int m_tra;
166 	int m_rcv;
167 
168 	// Register state
169 	uint8_t m_cmr1;
170 	uint8_t m_cmr2;
171 	uint8_t m_s1r;
172 	uint8_t m_s2r;
173 	uint8_t m_tpr;
174 	uint8_t m_ttr;
175 	uint8_t m_rpr;
176 	uint8_t m_rtr;
177 	//  uint8_t m_ctprh;
178 	//  uint8_t m_ctprl;
179 	unsigned int m_ctpr;
180 	uint8_t m_ctcr;
181 	uint8_t m_omr;
182 	//  uint8_t m_cth;
183 	//  uint8_t m_ctl;
184 	unsigned int m_ct;
185 	uint8_t m_pcr;
186 	uint8_t m_ccr;
187 	uint8_t m_txfifo[4];
188 	uint8_t m_rxfifo[4];
189 	uint8_t m_rsr;
190 	uint8_t m_trsr;
191 	uint8_t m_ictsr;
192 	//  uint8_t m_gsr; // moved to the device since it is global
193 	uint8_t m_ier;
194 	//  uint8_t m_rea;
195 	uint8_t m_cid;
196 	//uint8_t m_ivr;
197 	//uint8_t m_icr;
198 	//  uint8_t m_sea;
199 	//uint8_t m_ivrm;
200 	uint8_t m_mrr;
201 	uint8_t m_ier1;
202 	uint8_t m_ier2;
203 	uint8_t m_ier3;
204 	uint8_t m_trcr;
205 	uint8_t m_rflr;
206 	uint8_t m_ftlr;
207 	uint8_t m_trmsr;
208 	uint8_t m_telr;
209 
210 	enum // Needs to be 0-3 in unmodified prio level
211 	{
212 		INT_RXREADY     = 0,
213 		INT_TXREADY     = 1,
214 		INT_RXTXSTAT    = 2,
215 		INT_EXTCTSTAT   = 3
216 	};
217 
218 	enum
219 	{
220 		REG_CCR_RESET_TX    = 0x00,
221 		REG_CCR_ENABLE_TX   = 0x02,
222 		REG_CCR_DISABLE_TX  = 0x03,
223 		REG_CCR_RESET_RX    = 0x40,
224 		REG_CCR_ENABLE_RX   = 0x42,
225 		REG_CCR_DISABLE_RX  = 0x43,
226 		REG_CCR_START_TIMER = 0x80,
227 		REG_CCR_STOP_TIMER  = 0x81,
228 		REG_CCR_PRST_FFFF   = 0x82,
229 		REG_CCR_PRST_CTPR   = 0x83,
230 	};
231 
232 	enum
233 	{
234 		REG_CMR1_PARITY         = 0x20,
235 		REG_CMR1_PMMODE_MASK    = 0x18,
236 		REG_CMR1_PMMODE_NONE    = 0x00,
237 		REG_CMR1_PMMODE_RES     = 0x01,
238 		REG_CMR1_PMMODE_PARITY  = 0x10,
239 		REG_CMR1_PMMODE_FORCED  = 0x11,
240 		REG_CMR1_CPMODE_MASK    = 0x07,
241 		REG_CMR1_CPMODE_ASYNC   = 0x07
242 	};
243 
244 	enum
245 	{
246 		REG_CMR2_DTI_MASK = 0x38,
247 		REG_CMR2_DTI_NODMA = 0x38
248 	};
249 
250 	enum
251 	{
252 		REG_RPR_DATA_BITS_MASK  = 0x03,
253 		REG_RPR_DATA_BITS_5BIT  = 0x00,
254 		REG_RPR_DATA_BITS_6BIT  = 0x01,
255 		REG_RPR_DATA_BITS_7BIT  = 0x02,
256 		REG_RPR_DATA_BITS_8BIT  = 0x03,
257 		REG_RPR_DCD             = 0x04,
258 		REG_RPR_STRIP_PARITY    = 0x08,
259 		REG_RPR_RTS             = 0x10
260 	};
261 
262 	enum
263 	{
264 		REG_TPR_DATA_BITS_MASK  = 0x03,
265 		REG_TPR_DATA_BITS_5BIT  = 0x00,
266 		REG_TPR_DATA_BITS_6BIT  = 0x01,
267 		REG_TPR_DATA_BITS_7BIT  = 0x02,
268 		REG_TPR_DATA_BITS_8BIT  = 0x03,
269 		REG_TPR_CTS             = 0x04,
270 		REG_TPR_RTS             = 0x08,
271 		REG_TPR_STOP_BITS_MASK  = 0xf0
272 	};
273 
274 	enum
275 	{
276 		REG_TTR_EXT             = 0x80,
277 		REG_TTR_TXCLK_MASK      = 0x70,
278 		REG_TTR_TXCLK_1XEXT     = 0x00,
279 		REG_TTR_TXCLK_16XEXT    = 0x10,
280 		REG_TTR_TXCLK_DPLL      = 0x20,
281 		REG_TTR_TXCLK_BRG       = 0x30,
282 		REG_TTR_TXCLK_2X_OTHER  = 0x40,
283 		REG_TTR_TXCLK_32X_OTHER = 0x50,
284 		REG_TTR_TXCLK_2X_OWN    = 0x60,
285 		REG_TTR_TXCLK_32X_OWN   = 0x70,
286 		REG_TTR_BRG_RATE_MASK   = 0x0f,
287 	};
288 
289 	enum
290 	{
291 		REG_RTR_EXT             = 0x80,
292 		REG_RTR_RXCLK_MASK      = 0x70,
293 		REG_RTR_RXCLK_1XEXT     = 0x00,
294 		REG_RTR_RXCLK_16XEXT    = 0x10,
295 		REG_RTR_RXCLK_BRG       = 0x20,
296 		REG_RTR_RXCLK_CT        = 0x30,
297 		REG_RTR_RXCLK_DPLL_64X_X1   = 0x40,
298 		REG_RTR_RXCLK_DPLL_32X_EXT  = 0x50,
299 		REG_RTR_RXCLK_DPLL_32X_BRG  = 0x60,
300 		REG_RTR_RXCLK_DPLL_32X_CT   = 0x70,
301 		REG_RTR_BRG_RATE_MASK       = 0x0f,
302 	};
303 
304 	enum
305 	{
306 		REG_PCR_X2_IDC              = 0x80,
307 		REG_PCR_GP02_RTS            = 0x40,
308 		REG_PCR_SYNOUT_RTS          = 0x20,
309 		REG_PCR_RTXC_MASK           = 0x18,
310 		REG_PCR_RTXC_INPUT          = 0x00,
311 		REG_PCR_RTXC_CNTR_OUT       = 0x08,
312 		REG_PCR_RTXC_TXCLK_OUT      = 0x10,
313 		REG_PCR_RTXC_RXCLK_OUT      = 0x18,
314 		REG_PCR_TRXC_MASK           = 0x07,
315 		REG_PCR_TRXC_INPUT          = 0x00,
316 		REG_PCR_TRXC_CRYST_OUT      = 0x01,
317 		REG_PCR_TRXC_DPLL_OUT       = 0x02,
318 		REG_PCR_TRXC_CNTR_OUT       = 0x03,
319 		REG_PCR_TRXC_TXBRG_OUT      = 0x04,
320 		REG_PCR_TRXC_RXBRG_OUT      = 0x05,
321 		REG_PCR_TRXC_TXCLK_OUT      = 0x06,
322 		REG_PCR_TRXC_RXCLK_OUT      = 0x07,
323 	};
324 
325 	enum
326 	{
327 		REG_OMR_TXRCL_MASK          = 0xe0,
328 		REG_OMR_TXRCL_8BIT          = 0xe0,
329 		REG_OMR_TXRDY_ACTIVATED     = 0x10,
330 		REG_OMR_RXRDY_ACTIVATED     = 0x08,
331 		REG_OMR_GP02                = 0x04,
332 		REG_OMR_GP01                = 0x02,
333 		REG_OMR_RTS                 = 0x01,
334 	};
335 
336 	enum
337 	{
338 		REG_RSR_CHAR_COMPARE        = 0x80,
339 		REG_RSR_OVERRUN_ERROR       = 0x20,
340 		REG_RSR_FRAMING_ERROR       = 0x02,
341 		REG_RSR_PARITY_ERROR        = 0x01,
342 	};
343 
344 	enum
345 	{
346 		REG_GSR_CHAN_A_RXREADY      = 0x01,
347 		REG_GSR_CHAN_B_RXREADY      = 0x10,
348 		REG_GSR_CHAN_A_TXREADY      = 0x02,
349 		REG_GSR_CHAN_B_TXREADY      = 0x20,
350 		REG_GSR_XXREADY_MASK        = 0x33
351 	};
352 
353 	enum
354 	{
355 		REG_ICTSR_ZERO_DET          = 0x40,
356 		REG_ICTSR_DELTA_CTS         = 0x10,
357 		REG_ICTSR_DCD               = 0x08,
358 		REG_ICTSR_CTS               = 0x04,
359 	};
360 
361 	enum
362 	{
363 		REG_IER_DCD_CTS             = 0x80,
364 		REG_IER_TXRDY               = 0x40,
365 		REG_IER_TRSR73              = 0x20,
366 		REG_IER_RXRDY               = 0x10,
367 		REG_IER_RSR76               = 0x08,
368 		REG_IER_RSR54               = 0x04,
369 		REG_IER_RSR32               = 0x02,
370 		REG_IER_RSR10               = 0x01,
371 	};
372 
373 	// Register offsets, stripped from channel bit 0x20 but including A7 bit
374 	enum
375 	{
376 		REG_CMR1    = 0x00,
377 		REG_CMR2    = 0x01,
378 		REG_S1R     = 0x02,
379 		REG_S2R     = 0x03,
380 		REG_TPR     = 0x04,
381 		REG_TTR     = 0x05,
382 		REG_RPR     = 0x06,
383 		REG_RTR     = 0x07,
384 		REG_CTPRH   = 0x08,
385 		REG_CTPRL   = 0x09,
386 		REG_CTCR    = 0x0a,
387 		REG_OMR     = 0x0b,
388 		REG_CTH     = 0x0c,
389 		REG_CTL     = 0x0d,
390 		REG_PCR     = 0x0e,
391 		REG_CCR     = 0x0f,
392 		REG_TXFIFO_0= 0x10,
393 		REG_TXFIFO_1= 0x11,
394 		REG_TXFIFO_2= 0x12,
395 		REG_TXFIFO_3= 0x13,
396 		REG_RXFIFO_0= 0x14,
397 		REG_RXFIFO_1= 0x15,
398 		REG_RXFIFO_2= 0x16,
399 		REG_RXFIFO_3= 0x17,
400 		REG_RSR     = 0x18,
401 		REG_TRSR    = 0x19,
402 		REG_ICTSR   = 0x1a,
403 		REG_GSR     = 0x1b,
404 		REG_IER     = 0x1c,
405 		REG_REA     = 0x1d,
406 		REG_CID     = 0x1d,
407 		REG_IVR     = 0x1e,
408 		REG_ICR     = 0x1f,
409 		REG_SEA     = 0x1d,
410 		REG_IVRM    = 0x1e,
411 		REG_MRR     = 0x1f,
412 		REG_IER1    = 0x42,
413 		REG_IER2    = 0x43,
414 		REG_IER3    = 0x45,
415 		REG_TRCR    = 0x47,
416 		REG_RFLR    = 0x4e,
417 		REG_FTLR    = 0x5c,
418 		REG_TRMSR   = 0x5e,
419 		REG_TELR    = 0x5f,
420 	};
421 
422 	// Timers
423 	emu_timer *duscc_timer;
424 	emu_timer *rtxc_timer;
425 	emu_timer *trxc_timer;
426 
427 	uint8_t m_rtxc;
428 	uint8_t m_trxc;
429 
430 
431 	enum
432 	{
433 		REG_CTCR_ZERO_DET_INT   = 0x80,
434 		REG_CTCR_ZERO_DET_CTL   = 0x40,
435 		REG_CTCR_TIM_OC         = 0x20,
436 	};
437 
438 	enum
439 	{
440 		TIMER_ID,
441 		TIMER_ID_RTXC,
442 		TIMER_ID_TRXC
443 	};
444 
445 	uint16_t m_brg_rx_rate;
446 	uint16_t m_brg_tx_rate;
447 	uint16_t m_brg_const;
448 
449 	// TODO: Implement the 14.4K, 56K and 64K bauds available on the CDUSCC
get_baudrate(unsigned int br)450 	static unsigned int get_baudrate(unsigned int br)
451 	{
452 		switch (br)
453 		{
454 		case 0x00: return   50; break;
455 		case 0x01: return   75; break;
456 		case 0x02: return   110; break;
457 		case 0x03: return   134; break;
458 		case 0x04: return   150; break;
459 		case 0x05: return   200; break;
460 		case 0x06: return   300; break;
461 		case 0x07: return   600; break;
462 		case 0x08: return   1050; break;
463 		case 0x09: return   1200; break;
464 		case 0x0a: return   2000; break;
465 		case 0x0b: return   2400; break;
466 		case 0x0c: return   4800; break;
467 		case 0x0d: return   9600; break;
468 		case 0x0e: return   19200; break;
469 		case 0x0f: return   38400; break;
470 		};
471 		return 0;
472 	}
473 
474 	void update_serial();
475 	void set_dtr(int state);
476 	void set_rts(int state);
477 
478 	int get_tx_clock_mode();
479 	int get_rx_clock_mode();
480 	stop_bits_t get_stop_bits();
481 	int get_rx_word_length();
482 	int get_tx_word_length();
483 
484 	/* FIFOs and rx/tx status */
485 	/* Receiver */
486 	uint8_t m_rx_data_fifo[16];   // data FIFO
487 	uint8_t m_rx_error_fifo[16];  // error FIFO
488 	int m_rx_fifo_rp;           // FIFO read pointer
489 	int m_rx_fifo_wp;           // FIFO write pointer
490 	int m_rx_fifo_sz;           // FIFO size
491 	uint8_t m_rx_error;           // current error
492 
493 	/* Transmitter */
494 	uint8_t m_tx_data_fifo[16];   // data FIFO
495 	uint8_t m_tx_error_fifo[16];  // error FIFO
496 	int m_tx_fifo_rp;           // FIFO read pointer
497 	int m_tx_fifo_wp;           // FIFO write pointer
498 	int m_tx_fifo_sz;           // FIFO size
499 	uint8_t m_tx_error;           // current error
500 
501 	int m_rx_clock;     // receive clock pulse count
502 	int m_rx_first;     // first character received
503 	int m_rx_break;     // receive break condition
504 
505 	int m_rxd;
506 	int m_ri;       // ring indicator latch
507 	int m_cts;      // clear to send latch
508 	int m_dcd;      // data carrier detect latch
509 
510 	// transmitter state
511 	uint8_t m_tx_data;    // transmit data register
512 	int m_tx_clock;     // transmit clock pulse count
513 
514 	int m_dtr;      // data terminal ready
515 	int m_rts;      // request to send
516 
517 	// synchronous state
518 	uint16_t m_sync;      // sync character
519 
520 	int m_rcv_mode;
521 	int m_index;
522 	duscc_device *m_uart;
523 
524 	// CDUSCC specifics
525 	int m_a7;       // Access additional registers
526 };
527 
528 
529 // ======================> duscc_device
530 
531 class duscc_device : public device_t, public device_z80daisy_interface
532 {
533 	friend class duscc_channel;
534 
535 public:
536 	// construction/destruction
537 	duscc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
538 
out_txda_callback()539 	auto out_txda_callback() { return m_out_txda_cb.bind(); }
out_dtra_callback()540 	auto out_dtra_callback() { return m_out_dtra_cb.bind(); }
out_rtsa_callback()541 	auto out_rtsa_callback() { return m_out_rtsa_cb.bind(); }
out_synca_callback()542 	auto out_synca_callback() { return m_out_synca_cb.bind(); }
out_rtxca_callback()543 	auto out_rtxca_callback() { return m_out_rtxca_cb.bind(); }
out_trxca_callback()544 	auto out_trxca_callback() { return m_out_trxca_cb.bind(); }
545 
out_txdb_callback()546 	auto out_txdb_callback() { return m_out_txdb_cb.bind(); }
out_dtrb_callback()547 	auto out_dtrb_callback() { return m_out_dtrb_cb.bind(); }
out_rtsb_callback()548 	auto out_rtsb_callback() { return m_out_rtsb_cb.bind(); }
out_syncb_callback()549 	auto out_syncb_callback() { return m_out_syncb_cb.bind(); }
out_rtxcb_callback()550 	auto out_rtxcb_callback() { return m_out_rtxcb_cb.bind(); }
out_trxcb_callback()551 	auto out_trxcb_callback() { return m_out_trxcb_cb.bind(); }
out_int_callback()552 	auto out_int_callback() { return m_out_int_cb.bind(); }
553 
configure_channels(int rxa,int txa,int rxb,int txb)554 	void configure_channels(int rxa, int txa, int rxb, int txb)
555 	{
556 #if 0 // TODO: Fix this, need a way to set external rx/tx clocks for the channels
557 		m_chanA->m_rxc = rxa;
558 		m_chanA->m_txc = txa;
559 		m_chanB->m_rxc = rxb;
560 		m_chanB->m_txc = txb;
561 #endif
562 	}
563 
564 	uint8_t read(offs_t offset);
565 	void write(offs_t offset, uint8_t data);
566 
567 	// interrupt acknowledge
568 	uint8_t iack();
569 
570 	// device_z80daisy_interface overrides
571 	virtual int z80daisy_irq_state() override;
572 	virtual int z80daisy_irq_ack() override;
573 	virtual void z80daisy_irq_reti() override;
574 
rxa_w(int state)575 	void rxa_w(int state) { m_chanA->write_rx(state); }
rxb_w(int state)576 	void rxb_w(int state) { m_chanB->write_rx(state); }
ctsa_w(int state)577 	void ctsa_w(int state) { m_chanA->cts_w(state); }
ctsb_w(int state)578 	void ctsb_w(int state) { m_chanB->cts_w(state); }
dcda_w(int state)579 	void dcda_w(int state) { m_chanA->dcd_w(state); }
dcdb_w(int state)580 	void dcdb_w(int state) { m_chanB->dcd_w(state); }
ria_w(int state)581 	void ria_w(int state) { m_chanA->ri_w(state); }
rib_w(int state)582 	void rib_w(int state) { m_chanB->ri_w(state); }
583 #if 0
584 	void rxca_w(int state) { m_chanA->rxc_w(state); }
585 	void rxcb_w(int state) { m_chanB->rxc_w(state); }
586 	void txca_w(int state) { m_chanA->txc_w(state); }
587 	void txcb_w(int state) { m_chanB->txc_w(state); }
588 	void rxtxcb_w(int state) { m_chanB->rxc_w(state); m_chanB->txc_w(state); }
589 #endif
synca_w(int state)590 	void synca_w(int state) { m_chanA->sync_w(state); }
syncb_w(int state)591 	void syncb_w(int state) { m_chanB->sync_w(state); }
592 
593 protected:
594 	duscc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant);
595 
596 	// device-level overrides
597 	virtual void device_start() override;
598 	virtual void device_reset() override;
599 	virtual void device_add_mconfig(machine_config &config) override;
600 
601 	// internal interrupt management
602 	void check_interrupts();
603 	void reset_interrupts();
604 	uint8_t modify_vector(uint8_t vect, int i, uint8_t src);
605 	void trigger_interrupt(int index, int state);
get_channel_index(duscc_channel * ch)606 	int get_channel_index(duscc_channel *ch) const { return (ch == m_chanA) ? 0 : 1; }
607 
608 	// Variants in the DUSCC family
609 	enum
610 	{
611 		TYPE_DUSCC       = 0x001,
612 		TYPE_DUSCC26562  = 0x002,
613 		TYPE_DUSCC26C562 = 0x004,
614 		TYPE_DUSCC68562  = 0x008,
615 		TYPE_DUSCC68C562 = 0x010,
616 
617 		SET_NMOS   = TYPE_DUSCC26562 | TYPE_DUSCC68562,
618 		SET_CMOS   = TYPE_DUSCC26C562 | TYPE_DUSCC68C562
619 	};
620 
621 	enum
622 	{
623 		CHANNEL_A = 0,
624 		CHANNEL_B
625 	};
626 
627 	required_device<duscc_channel> m_chanA;
628 	required_device<duscc_channel> m_chanB;
629 
630 	// internal state
631 #if 0
632 	int m_rxca;
633 	int m_txca;
634 	int m_rxcb;
635 	int m_txcb;
636 #endif
637 
638 	devcb_write_line    m_out_txda_cb;
639 	devcb_write_line    m_out_dtra_cb;
640 	devcb_write_line    m_out_rtsa_cb;
641 	devcb_write_line    m_out_synca_cb;
642 	devcb_write_line    m_out_rtxca_cb;
643 	devcb_write_line    m_out_trxca_cb;
644 
645 	devcb_write_line    m_out_txdb_cb;
646 	devcb_write_line    m_out_dtrb_cb;
647 	devcb_write_line    m_out_rtsb_cb;
648 	devcb_write_line    m_out_syncb_cb;
649 	devcb_write_line    m_out_rtxcb_cb;
650 	devcb_write_line    m_out_trxcb_cb;
651 
652 	devcb_write_line    m_out_int_cb;
653 
654 	int m_int_state[8]; // interrupt state
655 
656 	int m_variant;
657 	uint8_t m_gsr;
658 	uint8_t m_ivr;
659 	uint8_t m_ivrm;
660 	uint8_t m_icr;
661 
662 	enum
663 	{
664 		REG_ICR_CHB             = 0x01,
665 		REG_ICR_CHA             = 0x02,
666 		REG_ICR_VEC_MOD         = 0x04,
667 		REG_ICR_V2V4_MOD        = 0x08,
668 		REG_ICR_VEC_MODE_MASK   = 0x30,
669 		REG_ICR_VEC_MODE_NONE   = 0x30,
670 		REG_ICR_PRIO_MASK       = 0xC0,
671 		REG_ICR_PRIO_AHI        = 0x00,
672 		REG_ICR_PRIO_BHI        = 0x40,
673 		REG_ICR_PRIO_AINT       = 0x80,
674 		REG_ICR_PRIO_BINT       = 0xC0,
675 	};
676 };
677 
678 // device type definition
DECLARE_DEVICE_TYPE(DUSCC,duscc_device)679 DECLARE_DEVICE_TYPE(DUSCC,         duscc_device)
680 DECLARE_DEVICE_TYPE(DUSCC_CHANNEL, duscc_channel)
681 DECLARE_DEVICE_TYPE(DUSCC26562,    duscc26562_device)
682 DECLARE_DEVICE_TYPE(DUSCC26C562,   duscc26c562_device)
683 DECLARE_DEVICE_TYPE(DUSCC68562,    duscc68562_device)
684 DECLARE_DEVICE_TYPE(DUSCC68C562,   duscc68c562_device)
685 
686 class duscc26562_device : public duscc_device
687 {
688 public :
689 	duscc26562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
690 };
691 
692 class duscc26c562_device : public duscc_device
693 {
694 public :
695 	duscc26c562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
696 };
697 
698 class duscc68562_device : public duscc_device
699 {
700 public :
701 	duscc68562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
702 };
703 
704 class duscc68c562_device : public duscc_device
705 {
706 public :
707 	duscc68c562_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
708 };
709 
710 #endif // MAME_MACHINE_SCNXX562_H
711