1
/**********************************************************************
3
Intel 8255(A) Programmable Peripheral Interface emulation
6
Visit http://mamedev.org for licensing and usage restrictions.
8
**********************************************************************/
11
#include "machine/devhelpr.h"
15
//**************************************************************************
17
//**************************************************************************
53
#define CONTROL_PORT_C_LOWER_INPUT 0x01
54
#define CONTROL_PORT_B_INPUT 0x02
55
#define CONTROL_GROUP_B_MODE_1 0x04
56
#define CONTROL_PORT_C_UPPER_INPUT 0x08
57
#define CONTROL_PORT_A_INPUT 0x10
58
#define CONTROL_GROUP_A_MODE_MASK 0x60
59
#define CONTROL_MODE_SET 0x80
63
//**************************************************************************
65
//**************************************************************************
67
const device_type I8255 = &device_creator<i8255_device>;
68
const device_type I8255A = &device_creator<i8255_device>;
72
//**************************************************************************
74
//**************************************************************************
76
//-------------------------------------------------
78
//-------------------------------------------------
80
inline void i8255_device::check_interrupt(int port)
82
switch (group_mode(port))
85
switch (port_mode(port))
88
set_intr(port, (m_inte[port] && m_ibf[port]));
92
set_intr(port, (m_inte[port] && m_obf[port]));
98
set_intr(port, ((m_inte1 && m_obf[port]) || (m_inte2 && m_ibf[port])));
104
//-------------------------------------------------
106
//-------------------------------------------------
108
inline void i8255_device::set_ibf(int port, int state)
110
if (LOG) logerror("I8255 '%s' Port %c IBF: %u\n", tag(), 'A' + port, state);
114
check_interrupt(port);
118
//-------------------------------------------------
120
//-------------------------------------------------
122
inline void i8255_device::set_obf(int port, int state)
124
if (LOG) logerror("I8255 '%s' Port %c OBF: %u\n", tag(), 'A' + port, state);
128
check_interrupt(port);
132
//-------------------------------------------------
134
//-------------------------------------------------
136
inline void i8255_device::set_inte(int port, int state)
138
if (LOG) logerror("I8255 '%s' Port %c INTE: %u\n", tag(), 'A' + port, state);
140
m_inte[port] = state;
142
check_interrupt(port);
146
//-------------------------------------------------
148
//-------------------------------------------------
150
inline void i8255_device::set_inte1(int state)
152
if (LOG) logerror("I8255 '%s' Port A INTE1: %u\n", tag(), state);
156
check_interrupt(PORT_A);
160
//-------------------------------------------------
162
//-------------------------------------------------
164
inline void i8255_device::set_inte2(int state)
166
if (LOG) logerror("I8255 '%s' Port A INTE2: %u\n", tag(), state);
170
check_interrupt(PORT_A);
174
//-------------------------------------------------
176
//-------------------------------------------------
178
inline void i8255_device::set_intr(int port, int state)
180
if (LOG) logerror("I8255 '%s' Port %c INTR: %u\n", tag(), 'A' + port, state);
182
m_intr[port] = state;
188
//-------------------------------------------------
190
//-------------------------------------------------
192
inline int i8255_device::group_mode(int group)
199
switch ((m_control & CONTROL_GROUP_A_MODE_MASK) >> 5)
201
case 0: mode = MODE_0; break;
202
case 1: mode = MODE_1; break;
203
case 2: case 3: mode = MODE_2; break;
208
mode = m_control & CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0;
216
//-------------------------------------------------
218
//-------------------------------------------------
220
inline int i8255_device::port_mode(int port)
226
case PORT_A: mode = m_control & CONTROL_PORT_A_INPUT ? MODE_INPUT : MODE_OUTPUT; break;
227
case PORT_B: mode = m_control & CONTROL_PORT_B_INPUT ? MODE_INPUT : MODE_OUTPUT; break;
234
//-------------------------------------------------
235
// port_c_lower_mode -
236
//-------------------------------------------------
238
inline int i8255_device::port_c_lower_mode()
240
return m_control & CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT;
244
//-------------------------------------------------
245
// port_c_upper_mode -
246
//-------------------------------------------------
248
inline int i8255_device::port_c_upper_mode()
250
return m_control & CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT;
255
//**************************************************************************
257
//**************************************************************************
259
//-------------------------------------------------
260
// i8255_device - constructor
261
//-------------------------------------------------
263
i8255_device::i8255_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
264
: device_t(mconfig, I8255, "I8255", tag, owner, clock)
266
m_intr[PORT_A] = m_intr[PORT_B] = 0;
270
//-------------------------------------------------
271
// device_config_complete - perform any
272
// operations now that the configuration is
274
//-------------------------------------------------
276
void i8255_device::device_config_complete()
278
// inherit a copy of the static data
279
const i8255_interface *intf = reinterpret_cast<const i8255_interface *>(static_config());
281
*static_cast<i8255_interface *>(this) = *intf;
283
// or initialize to defaults if none provided
286
memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb));
287
memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb));
288
memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb));
289
memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb));
290
memset(&m_in_pc_cb, 0, sizeof(m_in_pc_cb));
291
memset(&m_out_pc_cb, 0, sizeof(m_out_pc_cb));
296
//-------------------------------------------------
297
// device_start - device-specific startup
298
//-------------------------------------------------
300
void i8255_device::device_start()
303
m_in_port_func[PORT_A].resolve(m_in_pa_cb, *this);
304
m_out_port_func[PORT_A].resolve(m_out_pa_cb, *this);
305
m_in_port_func[PORT_B].resolve(m_in_pb_cb, *this);
306
m_out_port_func[PORT_B].resolve(m_out_pb_cb, *this);
307
m_in_port_func[PORT_C].resolve(m_in_pc_cb, *this);
308
m_out_port_func[PORT_C].resolve(m_out_pc_cb, *this);
310
// register for state saving
311
save_item(NAME(m_control));
312
save_item(NAME(m_output));
313
save_item(NAME(m_input));
314
save_item(NAME(m_ibf));
315
save_item(NAME(m_obf));
316
save_item(NAME(m_inte));
317
save_item(NAME(m_inte1));
318
save_item(NAME(m_inte2));
319
save_item(NAME(m_intr));
323
//-------------------------------------------------
324
// device_reset - device-specific reset
325
//-------------------------------------------------
327
void i8255_device::device_reset()
333
//-------------------------------------------------
335
//-------------------------------------------------
337
UINT8 i8255_device::read_mode0(int port)
341
if (port_mode(port) == MODE_OUTPUT)
343
// read data from output latch
344
data = m_output[port];
348
// read data from port
349
data = m_in_port_func[port](0);
356
//-------------------------------------------------
358
//-------------------------------------------------
360
UINT8 i8255_device::read_mode1(int port)
364
if (port_mode(port) == MODE_OUTPUT)
366
// read data from output latch
367
data = m_output[port];
371
// read data from input latch
372
data = m_input[port];
374
// clear input buffer full flag
388
//-------------------------------------------------
390
//-------------------------------------------------
392
UINT8 i8255_device::read_mode2()
396
// read data from input latch
397
data = m_input[PORT_A];
399
// clear input buffer full flag
412
//-------------------------------------------------
414
//-------------------------------------------------
416
UINT8 i8255_device::read_pc()
422
switch (group_mode(GROUP_A))
425
if (port_c_upper_mode() == MODE_OUTPUT)
427
// read data from output latch
428
data |= m_output[PORT_C] & 0xf0;
432
// read data from port
438
data |= m_intr[PORT_A] ? 0x08 : 0x00;
440
if (port_mode(PORT_A) == MODE_OUTPUT)
442
data |= m_obf[PORT_A] ? 0x80 : 0x00;
443
data |= m_inte[PORT_A] ? 0x40 : 0x00;
448
data |= m_ibf[PORT_A] ? 0x20 : 0x00;
449
data |= m_inte[PORT_A] ? 0x10 : 0x00;
455
data |= m_intr[PORT_A] ? 0x08 : 0x00;
456
data |= m_inte2 ? 0x10 : 0x00;
457
data |= m_ibf[PORT_A] ? 0x20 : 0x00;
458
data |= m_inte1 ? 0x40 : 0x00;
459
data |= m_obf[PORT_A] ? 0x80 : 0x00;
464
switch (group_mode(GROUP_B))
467
if (port_c_lower_mode() == MODE_OUTPUT)
469
// read data from output latch
470
data |= m_output[PORT_C] & 0x0f;
474
// read data from port
480
data |= m_inte[PORT_B] ? 0x04 : 0x00;
481
data |= m_intr[PORT_B] ? 0x01 : 0x00;
483
if (port_mode(PORT_B) == MODE_OUTPUT)
485
data |= m_obf[PORT_B] ? 0x02 : 0x00;
489
data |= m_ibf[PORT_B] ? 0x02 : 0x00;
495
// read data from port
496
data |= m_in_port_func[PORT_C](0) & mask;
503
//-------------------------------------------------
505
//-------------------------------------------------
507
void i8255_device::write_mode0(int port, UINT8 data)
509
if (port_mode(port) == MODE_OUTPUT)
512
m_output[port] = data;
514
// write data to port
515
m_out_port_func[port](0, data);
520
//-------------------------------------------------
522
//-------------------------------------------------
524
void i8255_device::write_mode1(int port, UINT8 data)
526
if (port_mode(port) == MODE_OUTPUT)
529
m_output[port] = data;
531
// write data to port
532
m_out_port_func[port](0, data);
534
// set output buffer full flag
543
//-------------------------------------------------
545
//-------------------------------------------------
547
void i8255_device::write_mode2(UINT8 data)
550
m_output[PORT_A] = data;
552
// write data to port
553
m_out_port_func[PORT_A](0, data);
555
// set output buffer full flag
563
//-------------------------------------------------
565
//-------------------------------------------------
567
void i8255_device::write_pc(UINT8 data)
571
if (group_mode(GROUP_A) == MODE_0)
574
if (port_c_upper_mode() == MODE_OUTPUT)
576
m_output[PORT_C] = (data & 0xf0) | (m_output[PORT_C] & 0x0f);
581
if (port_c_lower_mode() == MODE_OUTPUT)
583
m_output[PORT_C] = (m_output[PORT_C] & 0xf0) | (data & 0x0f);
595
//-------------------------------------------------
597
//-------------------------------------------------
599
void i8255_device::output_pc()
605
switch (group_mode(GROUP_A))
608
if (port_c_upper_mode() == MODE_OUTPUT)
614
// TTL inputs float high
620
data |= m_intr[PORT_A] ? 0x08 : 0x00;
622
if (port_mode(PORT_A) == MODE_OUTPUT)
624
data |= m_obf[PORT_A] ? 0x80 : 0x00;
629
data |= m_ibf[PORT_A] ? 0x20 : 0x00;
635
data |= m_intr[PORT_A] ? 0x08 : 0x00;
636
data |= m_ibf[PORT_A] ? 0x20 : 0x00;
637
data |= m_obf[PORT_A] ? 0x80 : 0x00;
642
switch (group_mode(GROUP_B))
645
if (port_c_lower_mode() == MODE_OUTPUT)
651
// TTL inputs float high
657
data |= m_intr[PORT_B] ? 0x01 : 0x00;
659
if (port_mode(PORT_B) == MODE_OUTPUT)
661
data |= m_obf[PORT_B] ? 0x02 : 0x00;
665
data |= m_ibf[PORT_B] ? 0x02 : 0x00;
669
data |= m_output[PORT_C] & mask;
671
m_out_port_func[PORT_C](0, data);
675
//-------------------------------------------------
677
//-------------------------------------------------
679
void i8255_device::set_mode(UINT8 data)
684
m_output[PORT_A] = 0;
692
if (port_mode(PORT_A) == MODE_OUTPUT)
694
m_out_port_func[PORT_A](0, m_output[PORT_A]);
698
// TTL inputs float high
699
m_out_port_func[PORT_A](0, 0xff);
704
logerror("I8255 '%s' Group A Mode: %u\n", tag(), group_mode(GROUP_A));
705
logerror("I8255 '%s' Port A Mode: %s\n", tag(), (port_mode(PORT_A) == MODE_OUTPUT) ? "output" : "input");
706
logerror("I8255 '%s' Port C Upper Mode: %s\n", tag(), (port_c_upper_mode() == MODE_OUTPUT) ? "output" : "input");
707
logerror("I8255 '%s' Group B Mode: %u\n", tag(), group_mode(GROUP_B));
708
logerror("I8255 '%s' Port B Mode: %s\n", tag(), (port_mode(PORT_B) == MODE_OUTPUT) ? "output" : "input");
709
logerror("I8255 '%s' Port C Lower Mode: %s\n", tag(), (port_c_lower_mode() == MODE_OUTPUT) ? "output" : "input");
713
m_output[PORT_B] = 0;
719
if (port_mode(PORT_B) == MODE_OUTPUT)
721
m_out_port_func[PORT_B](0, m_output[PORT_B]);
725
// TTL inputs float high
726
m_out_port_func[PORT_B](0, 0xff);
729
m_output[PORT_C] = 0;
736
//-------------------------------------------------
738
//-------------------------------------------------
740
void i8255_device::set_pc_bit(int bit, int state)
742
// set output latch bit
743
m_output[PORT_C] &= ~(1 << bit);
744
m_output[PORT_C] |= state << bit;
746
switch (group_mode(GROUP_A))
749
if (port_mode(PORT_A) == MODE_OUTPUT)
753
case 3: set_intr(PORT_A, state); break;
754
case 6: set_inte(PORT_A, state); break;
755
case 7: set_obf(PORT_A, state); break;
762
case 3: set_intr(PORT_A, state); break;
763
case 4: set_inte(PORT_A, state); break;
764
case 5: set_ibf(PORT_A, state); break;
772
case 3: set_intr(PORT_A, state); break;
773
case 4: set_inte2(state); break;
774
case 5: set_ibf(PORT_A, state); break;
775
case 6: set_inte1(state); break;
776
case 7: set_obf(PORT_A, state); break;
781
if (group_mode(GROUP_B) == MODE_1)
785
case 0: set_intr(PORT_B, state); break;
787
if (port_mode(PORT_B) == MODE_OUTPUT)
788
set_obf(PORT_B, state);
790
set_ibf(PORT_B, state);
792
case 2: set_inte(PORT_B, state); break;
800
//-------------------------------------------------
802
//-------------------------------------------------
804
READ8_MEMBER( i8255_device::read )
808
switch (offset & 0x03)
811
switch (group_mode(GROUP_A))
813
case MODE_0: data = read_mode0(PORT_A); break;
814
case MODE_1: data = read_mode1(PORT_A); break;
815
case MODE_2: data = read_mode2(); break;
817
if (LOG) logerror("I8255 '%s' Port A Read: %02x\n", tag(), data);
821
switch (group_mode(GROUP_B))
823
case MODE_0: data = read_mode0(PORT_B); break;
824
case MODE_1: data = read_mode1(PORT_B); break;
826
if (LOG) logerror("I8255 '%s' Port B Read: %02x\n", tag(), data);
831
if (LOG) logerror("I8255 '%s' Port C Read: %02x\n", tag(), data);
836
if (LOG) logerror("I8255 '%s' Mode Control Word Read: %02x\n", tag(), data);
844
//-------------------------------------------------
846
//-------------------------------------------------
848
WRITE8_MEMBER( i8255_device::write )
850
switch (offset & 0x03)
853
if (LOG) logerror("I8255 '%s' Port A Write: %02x\n", tag(), data);
855
switch (group_mode(GROUP_A))
857
case MODE_0: write_mode0(PORT_A, data); break;
858
case MODE_1: write_mode1(PORT_A, data); break;
859
case MODE_2: write_mode2(data); break;
864
if (LOG) logerror("I8255 '%s' Port B Write: %02x\n", tag(), data);
866
switch (group_mode(GROUP_B))
868
case MODE_0: write_mode0(PORT_B, data); break;
869
case MODE_1: write_mode1(PORT_B, data); break;
874
if (LOG) logerror("I8255 '%s' Port C Write: %02x\n", tag(), data);
880
if (data & CONTROL_MODE_SET)
882
if (LOG) logerror("I8255 '%s' Mode Control Word: %02x\n", tag(), data);
888
int bit = (data >> 1) & 0x07;
889
int state = BIT(data, 0);
891
if (LOG) logerror("I8255 '%s' %s Port C Bit %u\n", tag(), state ? "Set" : "Reset", bit);
893
set_pc_bit(bit, state);
900
//-------------------------------------------------
902
//-------------------------------------------------
904
READ8_MEMBER( i8255_device::pa_r )
910
//-------------------------------------------------
911
// pb_r - port A read
912
//-------------------------------------------------
914
UINT8 i8255_device::pa_r()
918
if (port_mode(PORT_A) == MODE_OUTPUT)
920
data = m_output[PORT_A];
927
//-------------------------------------------------
929
//-------------------------------------------------
931
READ8_MEMBER( i8255_device::pb_r )
937
//-------------------------------------------------
938
// pb_r - port B read
939
//-------------------------------------------------
941
UINT8 i8255_device::pb_r()
945
if (port_mode(PORT_B) == MODE_OUTPUT)
947
data = m_output[PORT_B];
954
//-------------------------------------------------
956
//-------------------------------------------------
958
WRITE_LINE_MEMBER( i8255_device::pc2_w )
960
if (group_mode(GROUP_B) == 1)
962
if (port_mode(PORT_B) == MODE_OUTPUT)
964
// port B acknowledge
965
if (!m_obf[PORT_B] && !state)
967
if (LOG) logerror("I8255 '%s' Port B Acknowledge\n", tag());
969
// clear output buffer flag
976
if (!m_ibf[PORT_B] && !state)
978
if (LOG) logerror("I8255 '%s' Port B Strobe\n", tag());
980
// read port into latch
981
m_input[PORT_B] = m_in_port_func[PORT_B](0);
983
// set input buffer flag
991
//-------------------------------------------------
993
//-------------------------------------------------
995
WRITE_LINE_MEMBER( i8255_device::pc4_w )
997
if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_INPUT)))
1000
if (!m_ibf[PORT_A] && !state)
1002
if (LOG) logerror("I8255 '%s' Port A Strobe\n", tag());
1004
// read port into latch
1005
m_input[PORT_A] = m_in_port_func[PORT_A](0);
1007
// set input buffer flag
1014
//-------------------------------------------------
1016
//-------------------------------------------------
1018
WRITE_LINE_MEMBER( i8255_device::pc6_w )
1020
if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_OUTPUT)))
1022
// port A acknowledge
1023
if (!m_obf[PORT_A] && !state)
1025
if (LOG) logerror("I8255 '%s' Port A Acknowledge\n", tag());
1027
// clear output buffer flag