1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles, Nathan Woods
3 /**********************************************************************
4 
5     Motorola 6821 PIA interface and emulation
6 
7 **********************************************************************/
8 
9 #include "emu.h"
10 #include "6821pia.h"
11 
12 //**************************************************************************
13 //  MACROS
14 //**************************************************************************
15 
16 #define LOG_GENERAL 0x01
17 #define LOG_SETUP   0x02
18 #define LOG_CA1     0x08
19 
20 //#define VERBOSE (LOG_SETUP | LOG_GENERAL | LOG_CA1)
21 //#define LOG_OUTPUT_STREAM std::cout
22 
23 #include "logmacro.h"
24 #define LOGSETUP(...) LOGMASKED(LOG_SETUP,   __VA_ARGS__)
25 #define LOGCA1(...)   LOGMASKED(LOG_CA1,     __VA_ARGS__)
26 
27 #define PIA_IRQ1                (0x80)
28 #define PIA_IRQ2                (0x40)
29 
30 
31 //**************************************************************************
32 //  LIVE DEVICE
33 //**************************************************************************
34 
35 // device type definition
36 DEFINE_DEVICE_TYPE(PIA6821, pia6821_device, "pia6821", "6821 PIA")
37 
38 
39 //-------------------------------------------------
40 //  pia6821_device - constructor
41 //-------------------------------------------------
42 
pia6821_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)43 pia6821_device::pia6821_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
44 	: device_t(mconfig, PIA6821, tag, owner, clock),
45 		m_in_a_handler(*this),
46 		m_in_b_handler(*this),
47 		m_in_ca1_handler(*this),
48 		m_in_cb1_handler(*this),
49 		m_in_ca2_handler(*this),
50 		m_out_a_handler(*this),
51 		m_out_b_handler(*this),
52 		m_ca2_handler(*this),
53 		m_cb2_handler(*this),
54 		m_irqa_handler(*this),
55 		m_irqb_handler(*this), m_in_a(0),
56 		m_in_ca1(0), m_in_ca2(0), m_out_a(0), m_a_input_overrides_output_mask(0), m_out_ca2(0), m_ddr_a(0),
57 		m_ctl_a(0), m_irq_a1(0), m_irq_a2(0),
58 		m_irq_a_state(0), m_in_b(0),
59 		m_in_cb1(0), m_in_cb2(0), m_out_b(0), m_out_cb2(0), m_last_out_cb2_z(0), m_ddr_b(0),
60 		m_ctl_b(0), m_irq_b1(0), m_irq_b2(0),
61 		m_irq_b_state(0), m_in_a_pushed(false), m_out_a_needs_pulled(false), m_in_ca1_pushed(false),
62 		m_in_ca2_pushed(false), m_out_ca2_needs_pulled(false), m_in_b_pushed(false), m_out_b_needs_pulled(false),
63 		m_in_cb1_pushed(false), m_in_cb2_pushed(false), m_out_cb2_needs_pulled(false), m_logged_port_a_not_connected(false),
64 		m_logged_port_b_not_connected(false), m_logged_ca1_not_connected(false), m_logged_ca2_not_connected(false),
65 		m_logged_cb1_not_connected(false), m_logged_cb2_not_connected(false)
66 {
67 }
68 
69 
70 //-------------------------------------------------
71 //  device_start - device-specific startup
72 //-------------------------------------------------
73 
device_start()74 void pia6821_device::device_start()
75 {
76 	// resolve callbacks
77 	m_in_a_handler.resolve();
78 	m_in_b_handler.resolve();
79 	m_in_ca1_handler.resolve();
80 	m_in_cb1_handler.resolve();
81 	m_in_ca2_handler.resolve();
82 	m_out_a_handler.resolve();
83 	m_out_b_handler.resolve();
84 	m_ca2_handler.resolve();
85 	m_cb2_handler.resolve();
86 	m_irqa_handler.resolve_safe();
87 	m_irqb_handler.resolve_safe();
88 
89 	save_item(NAME(m_in_a));
90 	save_item(NAME(m_in_ca1));
91 	save_item(NAME(m_in_ca2));
92 	save_item(NAME(m_out_a));
93 	save_item(NAME(m_out_ca2));
94 	save_item(NAME(m_ddr_a));
95 	save_item(NAME(m_ctl_a));
96 	save_item(NAME(m_irq_a1));
97 	save_item(NAME(m_irq_a2));
98 	save_item(NAME(m_irq_a_state));
99 	save_item(NAME(m_in_b));
100 	save_item(NAME(m_in_cb1));
101 	save_item(NAME(m_in_cb2));
102 	save_item(NAME(m_out_b));
103 	save_item(NAME(m_out_cb2));
104 	save_item(NAME(m_last_out_cb2_z));
105 	save_item(NAME(m_ddr_b));
106 	save_item(NAME(m_ctl_b));
107 	save_item(NAME(m_irq_b1));
108 	save_item(NAME(m_irq_b2));
109 	save_item(NAME(m_irq_b_state));
110 	save_item(NAME(m_in_a_pushed));
111 	save_item(NAME(m_out_a_needs_pulled));
112 	save_item(NAME(m_in_ca1_pushed));
113 	save_item(NAME(m_in_ca2_pushed));
114 	save_item(NAME(m_out_ca2_needs_pulled));
115 	save_item(NAME(m_in_b_pushed));
116 	save_item(NAME(m_out_b_needs_pulled));
117 	save_item(NAME(m_in_cb1_pushed));
118 	save_item(NAME(m_in_cb2_pushed));
119 	save_item(NAME(m_out_cb2_needs_pulled));
120 }
121 
122 
123 //-------------------------------------------------
124 //  device_reset - device-specific reset
125 //-------------------------------------------------
126 
device_reset()127 void pia6821_device::device_reset()
128 {
129 	//
130 	// set default read values.
131 	//
132 	// ports A,CA1,CA2 default to 1
133 	// ports B,CB1,CB2 are three-state and undefined (set to 0)
134 	//
135 	m_in_a = 0xff;
136 	m_in_ca1 = true;
137 	m_in_ca2 = true;
138 	m_out_a = 0;
139 	m_out_ca2 = 0;
140 	m_ddr_a = 0;
141 	m_ctl_a = 0;
142 	m_irq_a1 = 0;
143 	m_irq_a2 = 0;
144 	m_irq_a_state = 0;
145 	m_in_b = 0;
146 	m_in_cb1 = 0;
147 	m_in_cb2 = 0;
148 	m_out_b = 0;
149 	m_out_cb2 = 0;
150 	m_last_out_cb2_z = 0;
151 	m_ddr_b = 0;
152 	m_ctl_b = 0;
153 	m_irq_b1 = 0;
154 	m_irq_b2 = 0;
155 	m_irq_b_state = 0;
156 	m_in_a_pushed = false;
157 	m_out_a_needs_pulled = false;
158 	m_in_ca1_pushed = false;
159 	m_in_ca2_pushed = false;
160 	m_out_ca2_needs_pulled = false;
161 	m_in_b_pushed = false;
162 	m_out_b_needs_pulled = false;
163 	m_in_cb1_pushed = false;
164 	m_in_cb2_pushed = false;
165 	m_out_cb2_needs_pulled = false;
166 	m_logged_port_a_not_connected = false;
167 	m_logged_port_b_not_connected = false;
168 	m_logged_ca1_not_connected = false;
169 	m_logged_ca2_not_connected = false;
170 	m_logged_cb1_not_connected = false;
171 	m_logged_cb2_not_connected = false;
172 
173 
174 	// clear the IRQs
175 	m_irqa_handler(false);
176 	m_irqb_handler(false);
177 }
178 
179 
180 //-------------------------------------------------
181 //  update_interrupts
182 //-------------------------------------------------
183 
update_interrupts()184 void pia6821_device::update_interrupts()
185 {
186 	// start with IRQ A
187 	int new_state = (m_irq_a1 && irq1_enabled(m_ctl_a)) || (m_irq_a2 && irq2_enabled(m_ctl_a));
188 
189 	if (new_state != m_irq_a_state)
190 	{
191 		m_irq_a_state = new_state;
192 		m_irqa_handler(m_irq_a_state);
193 	}
194 
195 	// then do IRQ B
196 	new_state = (m_irq_b1 && irq1_enabled(m_ctl_b)) || (m_irq_b2 && irq2_enabled(m_ctl_b));
197 
198 	if (new_state != m_irq_b_state)
199 	{
200 		m_irq_b_state = new_state;
201 		m_irqb_handler(m_irq_b_state);
202 	}
203 }
204 
205 
206 //-------------------------------------------------
207 //  get_in_a_value
208 //-------------------------------------------------
209 
get_in_a_value()210 uint8_t pia6821_device::get_in_a_value()
211 {
212 	uint8_t port_a_data = 0;
213 	uint8_t ret;
214 
215 	// update the input
216 	if (!m_in_a_handler.isnull())
217 	{
218 		port_a_data = m_in_a_handler(0);
219 	}
220 	else
221 	{
222 		if (m_in_a_pushed)
223 		{
224 			port_a_data = m_in_a;
225 		}
226 		else
227 		{
228 			// assume pins are disconnected and simulate the internal pullups.
229 			port_a_data = 0xff;
230 
231 			if (!m_logged_port_a_not_connected && (m_ddr_a != 0xff) &&
232 				!machine().side_effects_disabled())
233 			{
234 				logerror("Warning! No port A read handler. Assuming pins 0x%02X not connected\n", m_ddr_a ^ 0xff);
235 				m_logged_port_a_not_connected = true;
236 			}
237 		}
238 	}
239 
240 	// For port A, when the port is in output mode other devices can drive the
241 	// pins too. If the device pulls the voltage on the lines enough,a read of
242 	// the output register will show the external device value on the driven pins.
243 	ret = (~m_ddr_a & port_a_data)  // input pins
244 		| (m_ddr_a & m_out_a & ~m_a_input_overrides_output_mask)  // normal output pins
245 		| (m_ddr_a & port_a_data & m_a_input_overrides_output_mask);  // overridden output pins
246 
247 	return ret;
248 }
249 
250 
251 //-------------------------------------------------
252 //  get_in_b_value
253 //-------------------------------------------------
254 
get_in_b_value()255 uint8_t pia6821_device::get_in_b_value()
256 {
257 	uint8_t ret;
258 
259 	if (m_ddr_b == 0xff)
260 	{
261 		// all output, just return buffer
262 		ret = m_out_b;
263 	}
264 	else
265 	{
266 		uint8_t port_b_data;
267 
268 		// update the input
269 		if (!m_in_b_handler.isnull())
270 		{
271 			port_b_data = m_in_b_handler(0);
272 		}
273 		else
274 		{
275 			if (m_in_b_pushed)
276 			{
277 				port_b_data = m_in_b;
278 			}
279 			else
280 			{
281 				if (!m_logged_port_b_not_connected && (m_ddr_b != 0xff)
282 					&& !machine().side_effects_disabled())
283 				{
284 					logerror("Error! No port B read handler. Three-state pins 0x%02X are undefined\n", m_ddr_b ^ 0xff);
285 					m_logged_port_b_not_connected = true;
286 				}
287 
288 				// undefined -- need to return something
289 				port_b_data = 0x00;
290 			}
291 		}
292 
293 		// the DDR determines if the pin or the output buffer is read
294 		ret = (m_out_b & m_ddr_b) | (port_b_data & ~m_ddr_b);
295 	}
296 
297 	return ret;
298 }
299 
300 
301 //-------------------------------------------------
302 //  get_out_a_value
303 //-------------------------------------------------
304 
get_out_a_value()305 uint8_t pia6821_device::get_out_a_value()
306 {
307 	uint8_t ret;
308 
309 	if (m_ddr_a == 0xff)
310 	{
311 		// all output
312 		ret = m_out_a;
313 	}
314 	else
315 	{
316 		// input pins don't change
317 		ret = (m_out_a & m_ddr_a) | (get_in_a_value() & ~m_ddr_a);
318 	}
319 
320 	return ret;
321 }
322 
323 
324 //-------------------------------------------------
325 //  get_out_b_value
326 //-------------------------------------------------
327 
get_out_b_value()328 uint8_t pia6821_device::get_out_b_value()
329 {
330 	// input pins are high-impedance - we just send them as zeros for backwards compatibility
331 	return m_out_b & m_ddr_b;
332 }
333 
334 
335 //-------------------------------------------------
336 //  set_out_ca2
337 //-------------------------------------------------
338 
set_out_ca2(int data)339 void pia6821_device::set_out_ca2(int data)
340 {
341 	if (data != m_out_ca2)
342 	{
343 		m_out_ca2 = data;
344 
345 		// send to output function
346 		if (!m_ca2_handler.isnull())
347 		{
348 			m_ca2_handler(m_out_ca2);
349 		}
350 		else
351 		{
352 			if (m_out_ca2_needs_pulled)
353 				logerror("Warning! No port CA2 write handler. Previous value has been lost!\n");
354 
355 			m_out_ca2_needs_pulled = true;
356 		}
357 	}
358 }
359 
360 
361 //-------------------------------------------------
362 //  set_out_cb2
363 //-------------------------------------------------
364 
set_out_cb2(int data)365 void pia6821_device::set_out_cb2(int data)
366 {
367 	int z = cb2_output_z();
368 
369 	if ((data != m_out_cb2) || (z != m_last_out_cb2_z))
370 	{
371 		m_out_cb2 = data;
372 		m_last_out_cb2_z = z;
373 
374 		// send to output function
375 		if (!m_cb2_handler.isnull())
376 		{
377 			m_cb2_handler(m_out_cb2);
378 		}
379 		else
380 		{
381 			if (m_out_cb2_needs_pulled)
382 				logerror("Warning! No port CB2 write handler. Previous value has been lost!\n");
383 
384 			m_out_cb2_needs_pulled = true;
385 		}
386 	}
387 }
388 
389 
390 //-------------------------------------------------
391 //  port_a_r
392 //-------------------------------------------------
393 
port_a_r()394 uint8_t pia6821_device::port_a_r()
395 {
396 	uint8_t ret = get_in_a_value();
397 
398 	if (!machine().side_effects_disabled())
399 	{
400 		// IRQ flags implicitly cleared by a read
401 		m_irq_a1 = false;
402 		m_irq_a2 = false;
403 		update_interrupts();
404 
405 		// CA2 is configured as output and in read strobe mode
406 		if (c2_output(m_ctl_a) && c2_strobe_mode(m_ctl_a))
407 		{
408 			// this will cause a transition low
409 			set_out_ca2(false);
410 
411 			// if the CA2 strobe is cleared by the E, reset it right away
412 			if (strobe_e_reset(m_ctl_a))
413 				set_out_ca2(true);
414 		}
415 
416 		LOG("PIA port A read = %02X\n", ret);
417 	}
418 
419 	return ret;
420 }
421 
422 
423 //-------------------------------------------------
424 //  ddr_a_r
425 //-------------------------------------------------
426 
ddr_a_r()427 uint8_t pia6821_device::ddr_a_r()
428 {
429 	const uint8_t ret = m_ddr_a;
430 
431 	LOG("PIA DDR A read = %02X\n", ret);
432 
433 	return ret;
434 }
435 
436 
437 //-------------------------------------------------
438 //  port_b_r
439 //-------------------------------------------------
440 
port_b_r()441 uint8_t pia6821_device::port_b_r()
442 {
443 	const uint8_t ret = get_in_b_value();
444 
445 	if (!machine().side_effects_disabled())
446 	{
447 		// This read will implicitly clear the IRQ B1 flag.  If CB2 is
448 		// in write-strobe mode with CB1 restore, and a CB1 active
449 		// transition set the flag, clearing it will cause CB2 to go
450 		// high again.  Note that this is different from what happens
451 		// with port A.
452 		if (m_irq_b1 && c2_strobe_mode(m_ctl_b) && strobe_c1_reset(m_ctl_b))
453 			set_out_cb2(true);
454 
455 		// IRQ flags implicitly cleared by a read
456 		m_irq_b1 = false;
457 		m_irq_b2 = false;
458 		update_interrupts();
459 
460 		LOG("PIA port B read = %02X\n", ret);
461 	}
462 
463 	return ret;
464 }
465 
466 
467 //-------------------------------------------------
468 //  ddr_b_r
469 //-------------------------------------------------
470 
ddr_b_r()471 uint8_t pia6821_device::ddr_b_r()
472 {
473 	const uint8_t ret = m_ddr_b;
474 
475 	LOG("PIA DDR B read = %02X\n", ret);
476 
477 	return ret;
478 }
479 
480 
481 //-------------------------------------------------
482 //  control_a_r
483 //-------------------------------------------------
484 
control_a_r()485 uint8_t pia6821_device::control_a_r()
486 {
487 	uint8_t ret;
488 
489 	if (!machine().side_effects_disabled())
490 	{
491 		// update CA1 & CA2 if callback exists, these in turn may update IRQ's
492 		if (!m_in_ca1_handler.isnull())
493 		{
494 			ca1_w(m_in_ca1_handler());
495 		}
496 		else if(!m_logged_ca1_not_connected && (!m_in_ca1_pushed))
497 		{
498 			logerror("Warning! No CA1 read handler. Assuming pin not connected\n");
499 			m_logged_ca1_not_connected = true;
500 		}
501 
502 		if (!m_in_ca2_handler.isnull())
503 		{
504 			ca2_w(m_in_ca2_handler());
505 		}
506 		else if ( !m_logged_ca2_not_connected && c2_input(m_ctl_a) && !m_in_ca2_pushed)
507 		{
508 			logerror("Warning! No CA2 read handler. Assuming pin not connected\n");
509 			m_logged_ca2_not_connected = true;
510 		}
511 	}
512 
513 	// read control register
514 	ret = m_ctl_a;
515 
516 	// set the IRQ flags if we have pending IRQs
517 	if (m_irq_a1)
518 		ret |= PIA_IRQ1;
519 
520 	if (m_irq_a2 && c2_input(m_ctl_a))
521 		ret |= PIA_IRQ2;
522 
523 	LOG("PIA control A read = %02X\n", ret);
524 
525 	return ret;
526 }
527 
528 
529 //-------------------------------------------------
530 //  control_b_r
531 //-------------------------------------------------
532 
control_b_r()533 uint8_t pia6821_device::control_b_r()
534 {
535 	uint8_t ret;
536 
537 	if (!machine().side_effects_disabled())
538 	{
539 		// update CB1 & CB2 if callback exists, these in turn may update IRQ's
540 		if(!m_in_cb1_handler.isnull())
541 		{
542 			cb1_w(m_in_cb1_handler());
543 		}
544 		else if(!m_logged_cb1_not_connected && !m_in_cb1_pushed)
545 		{
546 			logerror("Error! no CB1 read handler. Three-state pin is undefined\n");
547 			m_logged_cb1_not_connected = true;
548 		}
549 
550 		if(!m_logged_cb2_not_connected && c2_input(m_ctl_b) && !m_in_cb2_pushed)
551 		{
552 			logerror("Error! Three-state pin is undefined\n");
553 			m_logged_cb2_not_connected = true;
554 		}
555 	}
556 
557 	// read control register
558 	ret = m_ctl_b;
559 
560 	// set the IRQ flags if we have pending IRQs
561 	if (m_irq_b1)
562 		ret |= PIA_IRQ1;
563 
564 	if (m_irq_b2 && c2_input(m_ctl_b))
565 		ret |= PIA_IRQ2;
566 
567 	LOG("PIA control B read = %02X\n", ret);
568 
569 	return ret;
570 }
571 
572 
573 //-------------------------------------------------
574 //  read
575 //-------------------------------------------------
576 
read(offs_t offset)577 uint8_t pia6821_device::read(offs_t offset)
578 {
579 	uint8_t ret;
580 
581 	switch (offset & 0x03)
582 	{
583 	default: // impossible
584 	case 0x00:
585 		ret = output_selected(m_ctl_a) ? port_a_r() : ddr_a_r();
586 		break;
587 
588 	case 0x01:
589 		ret = control_a_r();
590 		break;
591 
592 	case 0x02:
593 		ret = output_selected(m_ctl_b) ? port_b_r() : ddr_b_r();
594 		break;
595 
596 	case 0x03:
597 		ret = control_b_r();
598 		break;
599 	}
600 
601 	return ret;
602 }
603 
604 
605 
606 //-------------------------------------------------
607 //  send_to_out_a_func
608 //-------------------------------------------------
609 
send_to_out_a_func(const char * message)610 void pia6821_device::send_to_out_a_func(const char* message)
611 {
612 	// input pins are pulled high
613 	const uint8_t data = get_out_a_value();
614 
615 	LOG("PIA %s = %02X DDRA=%02x\n", message, data, m_ddr_a);
616 
617 	if (!m_out_a_handler.isnull())
618 	{
619 		m_out_a_handler(offs_t(0), data);
620 	}
621 	else
622 	{
623 		if (m_out_a_needs_pulled)
624 			logerror("Warning! No port A write handler. Previous value has been lost!\n");
625 
626 		m_out_a_needs_pulled = true;
627 	}
628 }
629 
630 
631 //-------------------------------------------------
632 //  send_to_out_b_func
633 //-------------------------------------------------
634 
send_to_out_b_func(const char * message)635 void pia6821_device::send_to_out_b_func(const char* message)
636 {
637 	// input pins are high-impedance - we just send them as zeros for backwards compatibility
638 	const uint8_t data = get_out_b_value();
639 
640 	LOG("PIA %s = %02X DDRB=%02x\n", message, data, m_ddr_b);
641 
642 	if (!m_out_b_handler.isnull())
643 	{
644 		m_out_b_handler(offs_t(0), data);
645 	}
646 	else
647 	{
648 		if (m_out_b_needs_pulled)
649 			logerror("Warning! No port B write handler. Previous value has been lost!\n");
650 
651 		m_out_b_needs_pulled = true;
652 	}
653 }
654 
655 
656 //-------------------------------------------------
657 //  port_a_w
658 //-------------------------------------------------
659 
port_a_w(uint8_t data)660 void pia6821_device::port_a_w(uint8_t data)
661 {
662 	// buffer the output value
663 	m_out_a = data;
664 
665 	LOGSETUP("PIA ");
666 	send_to_out_a_func("port A write");
667 }
668 
669 
670 //-------------------------------------------------
671 //  ddr_a_w
672 //-------------------------------------------------
673 
ddr_a_w(uint8_t data)674 void pia6821_device::ddr_a_w(uint8_t data)
675 {
676 	LOGSETUP("PIA DDR A write = %02X (%s mode)\n", data, (0x00 == data) ? "input" : (0xff == data) ? "output" : "mixed");
677 
678 	if (m_ddr_a != data)
679 	{
680 		// DDR changed, call the callback again
681 		m_ddr_a = data;
682 		m_logged_port_a_not_connected = false;
683 		send_to_out_a_func("port A write due to DDR change");
684 	}
685 }
686 
687 
688 //-------------------------------------------------
689 //  port_b_w
690 //-------------------------------------------------
691 
port_b_w(uint8_t data)692 void pia6821_device::port_b_w(uint8_t data)
693 {
694 	// buffer the output value
695 	m_out_b = data;
696 
697 	send_to_out_b_func("port B write");
698 
699 	// CB2 in write strobe mode
700 	if (c2_strobe_mode(m_ctl_b))
701 	{
702 		// this will cause a transition low
703 		set_out_cb2(false);
704 
705 		// if the CB2 strobe is cleared by the E, reset it right away
706 		if (strobe_e_reset(m_ctl_b))
707 			set_out_cb2(true);
708 	}
709 }
710 
711 
712 //-------------------------------------------------
713 //  ddr_b_w
714 //-------------------------------------------------
715 
ddr_b_w(uint8_t data)716 void pia6821_device::ddr_b_w(uint8_t data)
717 {
718 	LOGSETUP("PIA DDR B write = %02X (%s mode)\n", data, (0x00 == data) ? "input" : (0xff == data) ? "output" : "mixed");
719 
720 	if (m_ddr_b != data)
721 	{
722 		// DDR changed, call the callback again
723 		m_ddr_b = data;
724 		m_logged_port_b_not_connected = false;
725 		send_to_out_b_func("port B write due to DDR change");
726 	}
727 }
728 
729 
730 //-------------------------------------------------
731 //  control_a_w
732 //-------------------------------------------------
733 
control_a_w(uint8_t data)734 void pia6821_device::control_a_w(uint8_t data)
735 {
736 	// bit 7 and 6 are read only
737 	data &= 0x3f;
738 
739 	LOGSETUP("PIA control A write = %02X\n", data);
740 	LOGSETUP(" - CA1 interrupts %s\n", (data & 0x01) ? "enabled" : "disabled");
741 	LOGSETUP(" - CA1 interrupts active on %s transition\n", (data & 0x02) ? "low-to-high" : "high-to-low");
742 	LOGSETUP(" - Port A %s register selected\n", (data & 0x04) ? "Data" : "DDR");
743 
744 	// update the control register
745 	m_ctl_a = data;
746 
747 	// CA2 is configured as output
748 	if (c2_output(m_ctl_a))
749 	{
750 		bool temp;
751 		if (c2_set_mode(m_ctl_a))
752 		{
753 			LOGSETUP(" - CA2 set/reset mode: ");
754 			temp = c2_set(m_ctl_a); // set/reset mode - bit value determines the new output
755 		}
756 		else
757 		{
758 			LOGSETUP(" - CA2 strobe mode: ");
759 			temp = true; // strobe mode - output is always high unless strobed
760 		}
761 
762 		LOGSETUP("%d\n", temp);
763 		set_out_ca2(temp);
764 	}
765 
766 	// update externals
767 	update_interrupts();
768 }
769 
770 
771 //-------------------------------------------------
772 //  control_b_w
773 //-------------------------------------------------
774 
control_b_w(uint8_t data)775 void pia6821_device::control_b_w(uint8_t data)
776 {
777 	// bit 7 and 6 are read only
778 	data &= 0x3f;
779 
780 	LOGSETUP("PIA control B write = %02X\n", data);
781 	LOGSETUP(" - CB1 interrupts %s\n", (data & 0x01) ? "enabled" : "disabled");
782 	LOGSETUP(" - CB1 interrupts active on %s transition\n", (data & 0x02) ? "low-to-high" : "high-to-low");
783 	LOGSETUP(" - Port B %s register selected\n", (data & 0x04) ? "Data" : "DDR");
784 
785 	// update the control register
786 	m_ctl_b = data;
787 
788 	bool temp;
789 	if (c2_set_mode(m_ctl_b))
790 	{
791 		LOGSETUP(" - CB2 set/reset mode: ");
792 		temp = c2_set(m_ctl_b); // set/reset mode - bit value determines the new output
793 	}
794 	else
795 	{
796 		LOGSETUP(" - CB2 strobe mode: ");
797 		temp = true; // strobe mode - output is always high unless strobed
798 	}
799 
800 	LOGSETUP("%d\n", temp);
801 	set_out_cb2(temp);
802 
803 	// update externals
804 	update_interrupts();
805 }
806 
807 
808 //-------------------------------------------------
809 //  write
810 //-------------------------------------------------
811 
write(offs_t offset,uint8_t data)812 void pia6821_device::write(offs_t offset, uint8_t data)
813 {
814 	switch (offset & 0x03)
815 	{
816 	default: // impossible
817 	case 0x00:
818 		if (output_selected(m_ctl_a))
819 			port_a_w(data);
820 		else
821 			ddr_a_w(data);
822 		break;
823 
824 	case 0x01:
825 		control_a_w( data);
826 		break;
827 
828 	case 0x02:
829 		if (output_selected(m_ctl_b))
830 			port_b_w(data);
831 		else
832 			ddr_b_w(data);
833 		break;
834 
835 	case 0x03:
836 		control_b_w(data);
837 		break;
838 	}
839 }
840 
841 
842 //-------------------------------------------------
843 //  set_a_input
844 //-------------------------------------------------
845 
set_a_input(uint8_t data)846 void pia6821_device::set_a_input(uint8_t data)
847 {
848 	if (!m_in_a_handler.isnull())
849 		throw emu_fatalerror("pia6821_device::set_a_input() called when m_in_a_handler set");
850 
851 	LOG("Set PIA input port A = %02X\n", data);
852 
853 	m_in_a = data;
854 	m_in_a_pushed = true;
855 }
856 
857 
858 //-------------------------------------------------
859 //  porta_w
860 //-------------------------------------------------
861 
porta_w(uint8_t data)862 void pia6821_device::porta_w(uint8_t data)
863 {
864 	set_a_input(data);
865 }
866 
867 
868 //-------------------------------------------------
869 //  write_porta_line
870 //-------------------------------------------------
871 
write_porta_line(int line,bool state)872 void pia6821_device::write_porta_line(int line, bool state)
873 {
874 	const uint8_t mask = 1 << line;
875 	if (state)
876 		set_a_input(m_in_a | mask);
877 	else
878 		set_a_input(m_in_a & ~mask);
879 }
880 
881 
882 //-------------------------------------------------
883 //  a_output
884 //-------------------------------------------------
885 
a_output()886 uint8_t pia6821_device::a_output()
887 {
888 	m_out_a_needs_pulled = false;
889 
890 	return get_out_a_value();
891 }
892 
893 
894 //-------------------------------------------------
895 //  ca1_w
896 //-------------------------------------------------
897 
WRITE_LINE_MEMBER(pia6821_device::ca1_w)898 WRITE_LINE_MEMBER( pia6821_device::ca1_w )
899 {
900 	LOGCA1("Set PIA input CA1 = %d\n", state);
901 
902 	// the new state has caused a transition
903 	if ((m_in_ca1 != state) && ((state && c1_low_to_high(m_ctl_a)) || (!state && c1_high_to_low(m_ctl_a))))
904 	{
905 		LOGCA1("CA1 triggering\n");
906 
907 		// mark the IRQ
908 		m_irq_a1 = true;
909 
910 		// update externals
911 		update_interrupts();
912 
913 		// CA2 is configured as output and in read strobe mode and cleared by a CA1 transition
914 		if (c2_output(m_ctl_a) && c2_strobe_mode(m_ctl_a) && strobe_c1_reset(m_ctl_a))
915 			set_out_ca2(true);
916 	}
917 
918 	// set the new value for CA1
919 	m_in_ca1 = state;
920 	m_in_ca1_pushed = true;
921 }
922 
923 
924 //-------------------------------------------------
925 //  ca2_w
926 //-------------------------------------------------
927 
WRITE_LINE_MEMBER(pia6821_device::ca2_w)928 WRITE_LINE_MEMBER( pia6821_device::ca2_w )
929 {
930 	LOG("Set PIA input CA2 = %d\n", state);
931 
932 	// if input mode and the new state has caused a transition
933 	if (c2_input(m_ctl_a) && (m_in_ca2 != state) && ((state && c2_low_to_high(m_ctl_a)) || (!state && c2_high_to_low(m_ctl_a))))
934 	{
935 		LOG("CA2 triggering\n");
936 
937 		// mark the IRQ
938 		m_irq_a2 = true;
939 
940 		// update externals
941 		update_interrupts();
942 	}
943 
944 	// set the new value for CA2
945 	m_in_ca2 = state;
946 	m_in_ca2_pushed = true;
947 }
948 
949 
950 //-------------------------------------------------
951 //  ca2_output
952 //-------------------------------------------------
953 
ca2_output()954 bool pia6821_device::ca2_output()
955 {
956 	m_out_ca2_needs_pulled = false;
957 
958 	return m_out_ca2;
959 }
960 
961 
962 //-------------------------------------------------
963 //  ca2_output_z - version of ca2_output which
964 //  takes account of internal pullup resistor
965 //-------------------------------------------------
966 
ca2_output_z()967 bool pia6821_device::ca2_output_z()
968 {
969 	m_out_ca2_needs_pulled = false;
970 
971 	// If it's an output, output the bit, if it's an input, it's pulled up
972 	return m_out_ca2 | c2_input(m_ctl_a);
973 }
974 
975 
976 //-------------------------------------------------
977 //  portb_w
978 //-------------------------------------------------
979 
portb_w(uint8_t data)980 void pia6821_device::portb_w(uint8_t data)
981 {
982 	if (!m_in_b_handler.isnull())
983 		throw emu_fatalerror("pia6821_device::portb_w() called when in_b_func implemented");
984 
985 	LOG("Set PIA input port B = %02X\n", data);
986 
987 	m_in_b = data;
988 	m_in_b_pushed = true;
989 }
990 
991 
992 //-------------------------------------------------
993 //  write_portb_line
994 //-------------------------------------------------
995 
write_portb_line(int line,bool state)996 void pia6821_device::write_portb_line(int line, bool state)
997 {
998 	const uint8_t mask = 1 << line;
999 
1000 	if (state)
1001 		portb_w(m_in_b | mask);
1002 	else
1003 		portb_w(m_in_b & ~mask);
1004 }
1005 
1006 
1007 //-------------------------------------------------
1008 //  b_output
1009 //-------------------------------------------------
1010 
b_output()1011 uint8_t pia6821_device::b_output()
1012 {
1013 	m_out_b_needs_pulled = false;
1014 
1015 	return get_out_b_value();
1016 }
1017 
1018 
1019 //-------------------------------------------------
1020 //  cb1_w
1021 //-------------------------------------------------
1022 
WRITE_LINE_MEMBER(pia6821_device::cb1_w)1023 WRITE_LINE_MEMBER( pia6821_device::cb1_w )
1024 {
1025 	LOG("Set PIA input CB1 = %d\n", state);
1026 
1027 	// the new state has caused a transition
1028 	if ((m_in_cb1 != state) && ((state && c1_low_to_high(m_ctl_b)) || (!state && c1_high_to_low(m_ctl_b))))
1029 	{
1030 		LOG("CB1 triggering\n");
1031 
1032 		// mark the IRQ
1033 		m_irq_b1 = 1;
1034 
1035 		// update externals
1036 		update_interrupts();
1037 
1038 		// If CB2 is configured as a write-strobe output which is reset by a CB1
1039 		// transition, this reset will only happen when a read from port B implicitly
1040 		// clears the IRQ B1 flag.  So we handle the CB2 reset there.  Note that this
1041 		// is different from what happens with port A.
1042 	}
1043 
1044 	// set the new value for CB1
1045 	m_in_cb1 = state;
1046 	m_in_cb1_pushed = true;
1047 }
1048 
1049 
1050 //-------------------------------------------------
1051 //  cb2_w
1052 //-------------------------------------------------
1053 
WRITE_LINE_MEMBER(pia6821_device::cb2_w)1054 WRITE_LINE_MEMBER( pia6821_device::cb2_w )
1055 {
1056 	LOG("Set PIA input CB2 = %d\n", state);
1057 
1058 	// if input mode and the new state has caused a transition
1059 	if (c2_input(m_ctl_b) &&
1060 		(m_in_cb2 != state) &&
1061 		((state && c2_low_to_high(m_ctl_b)) || (!state && c2_high_to_low(m_ctl_b))))
1062 	{
1063 		LOG("CB2 triggering\n");
1064 
1065 		// mark the IRQ
1066 		m_irq_b2 = 1;
1067 
1068 		// update externals
1069 		update_interrupts();
1070 	}
1071 
1072 	// set the new value for CA2
1073 	m_in_cb2 = state;
1074 	m_in_cb2_pushed = true;
1075 }
1076 
1077 
1078 //-------------------------------------------------
1079 //  output_cb2
1080 //-------------------------------------------------
1081 
cb2_output()1082 bool pia6821_device::cb2_output()
1083 {
1084 	m_out_cb2_needs_pulled = false;
1085 
1086 	return m_out_cb2;
1087 }
1088 
1089 
1090 //-------------------------------------------------
1091 //  cb2_output_z
1092 //-------------------------------------------------
1093 
cb2_output_z()1094 bool pia6821_device::cb2_output_z()
1095 {
1096 	return !c2_output(m_ctl_b);
1097 }
1098 
1099 
1100 //-------------------------------------------------
1101 //  control byte wrappers
1102 //-------------------------------------------------
1103 
irq1_enabled(uint8_t c)1104 inline bool pia6821_device::irq1_enabled(uint8_t c)    { return  bool(BIT(c, 0)); }
c1_low_to_high(uint8_t c)1105 inline bool pia6821_device::c1_low_to_high(uint8_t c)  { return  bool(BIT(c, 1)); }
c1_high_to_low(uint8_t c)1106 inline bool pia6821_device::c1_high_to_low(uint8_t c)  { return !bool(BIT(c, 1)); }
output_selected(uint8_t c)1107 inline bool pia6821_device::output_selected(uint8_t c) { return  bool(BIT(c, 2)); }
irq2_enabled(uint8_t c)1108 inline bool pia6821_device::irq2_enabled(uint8_t c)    { return  bool(BIT(c, 3)); }
strobe_e_reset(uint8_t c)1109 inline bool pia6821_device::strobe_e_reset(uint8_t c)  { return  bool(BIT(c, 3)); }
strobe_c1_reset(uint8_t c)1110 inline bool pia6821_device::strobe_c1_reset(uint8_t c) { return !bool(BIT(c, 3)); }
c2_set(uint8_t c)1111 inline bool pia6821_device::c2_set(uint8_t c)          { return  bool(BIT(c, 3)); }
c2_low_to_high(uint8_t c)1112 inline bool pia6821_device::c2_low_to_high(uint8_t c)  { return  bool(BIT(c, 4)); }
c2_high_to_low(uint8_t c)1113 inline bool pia6821_device::c2_high_to_low(uint8_t c)  { return !bool(BIT(c, 4)); }
c2_set_mode(uint8_t c)1114 inline bool pia6821_device::c2_set_mode(uint8_t c)     { return  bool(BIT(c, 4)); }
c2_strobe_mode(uint8_t c)1115 inline bool pia6821_device::c2_strobe_mode(uint8_t c)  { return !bool(BIT(c, 4)); }
c2_output(uint8_t c)1116 inline bool pia6821_device::c2_output(uint8_t c)       { return  bool(BIT(c, 5)); }
c2_input(uint8_t c)1117 inline bool pia6821_device::c2_input(uint8_t c)        { return !bool(BIT(c, 5)); }
1118