~ubuntu-branches/ubuntu/raring/mame/raring-proposed

« back to all changes in this revision

Viewing changes to mess/src/emu/machine/i8255.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**********************************************************************
2
 
 
3
 
    Intel 8255(A) Programmable Peripheral Interface emulation
4
 
 
5
 
    Copyright MESS Team.
6
 
    Visit http://mamedev.org for licensing and usage restrictions.
7
 
 
8
 
**********************************************************************/
9
 
 
10
 
#include "i8255.h"
11
 
#include "machine/devhelpr.h"
12
 
 
13
 
 
14
 
 
15
 
//**************************************************************************
16
 
//  MACROS / CONSTANTS
17
 
//**************************************************************************
18
 
 
19
 
#define LOG 0
20
 
 
21
 
 
22
 
enum
23
 
{
24
 
        PORT_A = 0,
25
 
        PORT_B,
26
 
        PORT_C,
27
 
        CONTROL
28
 
};
29
 
 
30
 
 
31
 
enum
32
 
{
33
 
        GROUP_A = 0,
34
 
        GROUP_B
35
 
};
36
 
 
37
 
 
38
 
enum
39
 
{
40
 
        MODE_0 = 0,
41
 
        MODE_1,
42
 
        MODE_2
43
 
};
44
 
 
45
 
 
46
 
enum
47
 
{
48
 
        MODE_OUTPUT = 0,
49
 
        MODE_INPUT,
50
 
};
51
 
 
52
 
 
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
60
 
 
61
 
 
62
 
 
63
 
//**************************************************************************
64
 
//  DEVICE DEFINITIONS
65
 
//**************************************************************************
66
 
 
67
 
const device_type I8255 = &device_creator<i8255_device>;
68
 
const device_type I8255A = &device_creator<i8255_device>;
69
 
 
70
 
 
71
 
 
72
 
//**************************************************************************
73
 
//  INLINE HELPERS
74
 
//**************************************************************************
75
 
 
76
 
//-------------------------------------------------
77
 
//  check_interrupt -
78
 
//-------------------------------------------------
79
 
 
80
 
inline void i8255_device::check_interrupt(int port)
81
 
{
82
 
        switch (group_mode(port))
83
 
        {
84
 
        case MODE_1:
85
 
                switch (port_mode(port))
86
 
                {
87
 
                case MODE_INPUT:
88
 
                        set_intr(port, (m_inte[port] && m_ibf[port]));
89
 
                        break;
90
 
 
91
 
                case MODE_OUTPUT:
92
 
                        set_intr(port, (m_inte[port] && m_obf[port]));
93
 
                        break;
94
 
                }
95
 
                break;
96
 
 
97
 
        case MODE_2:
98
 
                set_intr(port, ((m_inte1 && m_obf[port]) || (m_inte2 && m_ibf[port])));
99
 
                break;
100
 
        }
101
 
}
102
 
 
103
 
 
104
 
//-------------------------------------------------
105
 
//  set_ibf -
106
 
//-------------------------------------------------
107
 
 
108
 
inline void i8255_device::set_ibf(int port, int state)
109
 
{
110
 
        if (LOG) logerror("I8255 '%s' Port %c IBF: %u\n", tag(), 'A' + port, state);
111
 
 
112
 
        m_ibf[port] = state;
113
 
 
114
 
        check_interrupt(port);
115
 
}
116
 
 
117
 
 
118
 
//-------------------------------------------------
119
 
//  set_obf -
120
 
//-------------------------------------------------
121
 
 
122
 
inline void i8255_device::set_obf(int port, int state)
123
 
{
124
 
        if (LOG) logerror("I8255 '%s' Port %c OBF: %u\n", tag(), 'A' + port, state);
125
 
 
126
 
        m_obf[port] = state;
127
 
 
128
 
        check_interrupt(port);
129
 
}
130
 
 
131
 
 
132
 
//-------------------------------------------------
133
 
//  set_inte -
134
 
//-------------------------------------------------
135
 
 
136
 
inline void i8255_device::set_inte(int port, int state)
137
 
{
138
 
        if (LOG) logerror("I8255 '%s' Port %c INTE: %u\n", tag(), 'A' + port, state);
139
 
 
140
 
        m_inte[port] = state;
141
 
 
142
 
        check_interrupt(port);
143
 
}
144
 
 
145
 
 
146
 
//-------------------------------------------------
147
 
//  set_inte1 -
148
 
//-------------------------------------------------
149
 
 
150
 
inline void i8255_device::set_inte1(int state)
151
 
{
152
 
        if (LOG) logerror("I8255 '%s' Port A INTE1: %u\n", tag(), state);
153
 
 
154
 
        m_inte1 = state;
155
 
 
156
 
        check_interrupt(PORT_A);
157
 
}
158
 
 
159
 
 
160
 
//-------------------------------------------------
161
 
//  set_inte2 -
162
 
//-------------------------------------------------
163
 
 
164
 
inline void i8255_device::set_inte2(int state)
165
 
{
166
 
        if (LOG) logerror("I8255 '%s' Port A INTE2: %u\n", tag(), state);
167
 
 
168
 
        m_inte2 = state;
169
 
 
170
 
        check_interrupt(PORT_A);
171
 
}
172
 
 
173
 
 
174
 
//-------------------------------------------------
175
 
//  set_intr -
176
 
//-------------------------------------------------
177
 
 
178
 
inline void i8255_device::set_intr(int port, int state)
179
 
{
180
 
        if (LOG) logerror("I8255 '%s' Port %c INTR: %u\n", tag(), 'A' + port, state);
181
 
 
182
 
        m_intr[port] = state;
183
 
 
184
 
        output_pc();
185
 
}
186
 
 
187
 
 
188
 
//-------------------------------------------------
189
 
//  group_mode -
190
 
//-------------------------------------------------
191
 
 
192
 
inline int i8255_device::group_mode(int group)
193
 
{
194
 
        int mode = 0;
195
 
 
196
 
        switch (group)
197
 
        {
198
 
        case GROUP_A:
199
 
                switch ((m_control & CONTROL_GROUP_A_MODE_MASK) >> 5)
200
 
                {
201
 
                case 0: mode = MODE_0; break;
202
 
                case 1: mode = MODE_1; break;
203
 
                case 2: case 3: mode = MODE_2; break;
204
 
                }
205
 
                break;
206
 
 
207
 
        case GROUP_B:
208
 
                mode = m_control & CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0;
209
 
                break;
210
 
        }
211
 
 
212
 
        return mode;
213
 
}
214
 
 
215
 
 
216
 
//-------------------------------------------------
217
 
//  port_mode -
218
 
//-------------------------------------------------
219
 
 
220
 
inline int i8255_device::port_mode(int port)
221
 
{
222
 
        int mode = 0;
223
 
 
224
 
        switch (port)
225
 
        {
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;
228
 
        }
229
 
 
230
 
        return mode;
231
 
}
232
 
 
233
 
 
234
 
//-------------------------------------------------
235
 
//  port_c_lower_mode -
236
 
//-------------------------------------------------
237
 
 
238
 
inline int i8255_device::port_c_lower_mode()
239
 
{
240
 
        return m_control & CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT;
241
 
}
242
 
 
243
 
 
244
 
//-------------------------------------------------
245
 
//  port_c_upper_mode -
246
 
//-------------------------------------------------
247
 
 
248
 
inline int i8255_device::port_c_upper_mode()
249
 
{
250
 
        return m_control & CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT;
251
 
}
252
 
 
253
 
 
254
 
 
255
 
//**************************************************************************
256
 
//  LIVE DEVICE
257
 
//**************************************************************************
258
 
 
259
 
//-------------------------------------------------
260
 
//  i8255_device - constructor
261
 
//-------------------------------------------------
262
 
 
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)
265
 
{
266
 
        m_intr[PORT_A] = m_intr[PORT_B] = 0;
267
 
}
268
 
 
269
 
 
270
 
//-------------------------------------------------
271
 
//  device_config_complete - perform any
272
 
//  operations now that the configuration is
273
 
//  complete
274
 
//-------------------------------------------------
275
 
 
276
 
void i8255_device::device_config_complete()
277
 
{
278
 
        // inherit a copy of the static data
279
 
        const i8255_interface *intf = reinterpret_cast<const i8255_interface *>(static_config());
280
 
        if (intf != NULL)
281
 
                *static_cast<i8255_interface *>(this) = *intf;
282
 
 
283
 
        // or initialize to defaults if none provided
284
 
        else
285
 
        {
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));
292
 
        }
293
 
}
294
 
 
295
 
 
296
 
//-------------------------------------------------
297
 
//  device_start - device-specific startup
298
 
//-------------------------------------------------
299
 
 
300
 
void i8255_device::device_start()
301
 
{
302
 
        // resolve callbacks
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);
309
 
 
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));
320
 
}
321
 
 
322
 
 
323
 
//-------------------------------------------------
324
 
//  device_reset - device-specific reset
325
 
//-------------------------------------------------
326
 
 
327
 
void i8255_device::device_reset()
328
 
{
329
 
        set_mode(0x9b);
330
 
}
331
 
 
332
 
 
333
 
//-------------------------------------------------
334
 
//  read_mode0 -
335
 
//-------------------------------------------------
336
 
 
337
 
UINT8 i8255_device::read_mode0(int port)
338
 
{
339
 
        UINT8 data = 0;
340
 
 
341
 
        if (port_mode(port) == MODE_OUTPUT)
342
 
        {
343
 
                // read data from output latch
344
 
                data = m_output[port];
345
 
        }
346
 
        else
347
 
        {
348
 
                // read data from port
349
 
                data = m_in_port_func[port](0);
350
 
        }
351
 
 
352
 
        return data;
353
 
}
354
 
 
355
 
 
356
 
//-------------------------------------------------
357
 
//  read_mode1 -
358
 
//-------------------------------------------------
359
 
 
360
 
UINT8 i8255_device::read_mode1(int port)
361
 
{
362
 
        UINT8 data = 0;
363
 
 
364
 
        if (port_mode(port) == MODE_OUTPUT)
365
 
        {
366
 
                // read data from output latch
367
 
                data = m_output[port];
368
 
        }
369
 
        else
370
 
        {
371
 
                // read data from input latch
372
 
                data = m_input[port];
373
 
 
374
 
                // clear input buffer full flag
375
 
                set_ibf(port, 0);
376
 
 
377
 
                // clear interrupt
378
 
                set_intr(port, 0);
379
 
 
380
 
                // clear input latch
381
 
                m_input[port] = 0;
382
 
        }
383
 
 
384
 
        return data;
385
 
}
386
 
 
387
 
 
388
 
//-------------------------------------------------
389
 
//  read_mode2 -
390
 
//-------------------------------------------------
391
 
 
392
 
UINT8 i8255_device::read_mode2()
393
 
{
394
 
        UINT8 data = 0;
395
 
 
396
 
        // read data from input latch
397
 
        data = m_input[PORT_A];
398
 
 
399
 
        // clear input buffer full flag
400
 
        set_ibf(PORT_A, 0);
401
 
 
402
 
        // clear interrupt
403
 
        set_intr(PORT_A, 0);
404
 
 
405
 
        // clear input latch
406
 
        m_input[PORT_A] = 0;
407
 
 
408
 
        return data;
409
 
}
410
 
 
411
 
 
412
 
//-------------------------------------------------
413
 
//  read_pc -
414
 
//-------------------------------------------------
415
 
 
416
 
UINT8 i8255_device::read_pc()
417
 
{
418
 
        UINT8 data = 0;
419
 
        UINT8 mask = 0;
420
 
 
421
 
        // PC upper
422
 
        switch (group_mode(GROUP_A))
423
 
        {
424
 
        case MODE_0:
425
 
                if (port_c_upper_mode() == MODE_OUTPUT)
426
 
                {
427
 
                        // read data from output latch
428
 
                        data |= m_output[PORT_C] & 0xf0;
429
 
                }
430
 
                else
431
 
                {
432
 
                        // read data from port
433
 
                        mask |= 0xf0;
434
 
                }
435
 
                break;
436
 
 
437
 
        case MODE_1:
438
 
                data |= m_intr[PORT_A] ? 0x08 : 0x00;
439
 
 
440
 
                if (port_mode(PORT_A) == MODE_OUTPUT)
441
 
                {
442
 
                        data |= m_obf[PORT_A] ? 0x80 : 0x00;
443
 
                        data |= m_inte[PORT_A] ? 0x40 : 0x00;
444
 
                        mask |= 0x30;
445
 
                }
446
 
                else
447
 
                {
448
 
                        data |= m_ibf[PORT_A] ? 0x20 : 0x00;
449
 
                        data |= m_inte[PORT_A] ? 0x10 : 0x00;
450
 
                        mask |= 0xc0;
451
 
                }
452
 
                break;
453
 
 
454
 
        case MODE_2:
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;
460
 
                break;
461
 
        }
462
 
 
463
 
        // PC lower
464
 
        switch (group_mode(GROUP_B))
465
 
        {
466
 
        case MODE_0:
467
 
                if (port_c_lower_mode() == MODE_OUTPUT)
468
 
                {
469
 
                        // read data from output latch
470
 
                        data |= m_output[PORT_C] & 0x0f;
471
 
                }
472
 
                else
473
 
                {
474
 
                        // read data from port
475
 
                        mask |= 0x0f;
476
 
                }
477
 
                break;
478
 
 
479
 
        case MODE_1:
480
 
                data |= m_inte[PORT_B] ? 0x04 : 0x00;
481
 
                data |= m_intr[PORT_B] ? 0x01 : 0x00;
482
 
 
483
 
                if (port_mode(PORT_B) == MODE_OUTPUT)
484
 
                {
485
 
                        data |= m_obf[PORT_B] ? 0x02 : 0x00;
486
 
                }
487
 
                else
488
 
                {
489
 
                        data |= m_ibf[PORT_B] ? 0x02 : 0x00;
490
 
                }
491
 
        }
492
 
 
493
 
        if (mask)
494
 
        {
495
 
                // read data from port
496
 
                data |= m_in_port_func[PORT_C](0) & mask;
497
 
        }
498
 
 
499
 
        return data;
500
 
}
501
 
 
502
 
 
503
 
//-------------------------------------------------
504
 
//  write_mode0 -
505
 
//-------------------------------------------------
506
 
 
507
 
void i8255_device::write_mode0(int port, UINT8 data)
508
 
{
509
 
        if (port_mode(port) == MODE_OUTPUT)
510
 
        {
511
 
                // latch output data
512
 
                m_output[port] = data;
513
 
 
514
 
                // write data to port
515
 
                m_out_port_func[port](0, data);
516
 
        }
517
 
}
518
 
 
519
 
 
520
 
//-------------------------------------------------
521
 
//  write_mode1 -
522
 
//-------------------------------------------------
523
 
 
524
 
void i8255_device::write_mode1(int port, UINT8 data)
525
 
{
526
 
        if (port_mode(port) == MODE_OUTPUT)
527
 
        {
528
 
                // latch output data
529
 
                m_output[port] = data;
530
 
 
531
 
                // write data to port
532
 
                m_out_port_func[port](0, data);
533
 
 
534
 
                // set output buffer full flag
535
 
                set_obf(port, 0);
536
 
 
537
 
                // clear interrupt
538
 
                set_intr(port, 0);
539
 
        }
540
 
}
541
 
 
542
 
 
543
 
//-------------------------------------------------
544
 
//  write_mode2 -
545
 
//-------------------------------------------------
546
 
 
547
 
void i8255_device::write_mode2(UINT8 data)
548
 
{
549
 
        // latch output data
550
 
        m_output[PORT_A] = data;
551
 
 
552
 
        // write data to port
553
 
        m_out_port_func[PORT_A](0, data);
554
 
 
555
 
        // set output buffer full flag
556
 
        set_obf(PORT_A, 0);
557
 
 
558
 
        // clear interrupt
559
 
        set_intr(PORT_A, 0);
560
 
}
561
 
 
562
 
 
563
 
//-------------------------------------------------
564
 
//  write_pc -
565
 
//-------------------------------------------------
566
 
 
567
 
void i8255_device::write_pc(UINT8 data)
568
 
{
569
 
        int changed = 0;
570
 
 
571
 
        if (group_mode(GROUP_A) == MODE_0)
572
 
        {
573
 
                // PC upper
574
 
                if (port_c_upper_mode() == MODE_OUTPUT)
575
 
                {
576
 
                        m_output[PORT_C] = (data & 0xf0) | (m_output[PORT_C] & 0x0f);
577
 
                        changed = 1;
578
 
                }
579
 
 
580
 
                // PC lower
581
 
                if (port_c_lower_mode() == MODE_OUTPUT)
582
 
                {
583
 
                        m_output[PORT_C] = (m_output[PORT_C] & 0xf0) | (data & 0x0f);
584
 
                        changed = 1;
585
 
                }
586
 
        }
587
 
 
588
 
        if (changed)
589
 
        {
590
 
                output_pc();
591
 
        }
592
 
}
593
 
 
594
 
 
595
 
//-------------------------------------------------
596
 
//  output_pc -
597
 
//-------------------------------------------------
598
 
 
599
 
void i8255_device::output_pc()
600
 
{
601
 
        UINT8 data = 0;
602
 
        UINT8 mask = 0;
603
 
 
604
 
        // PC upper
605
 
        switch (group_mode(GROUP_A))
606
 
        {
607
 
        case MODE_0:
608
 
                if (port_c_upper_mode() == MODE_OUTPUT)
609
 
                {
610
 
                        mask |= 0xf0;
611
 
                }
612
 
                else
613
 
                {
614
 
                        // TTL inputs float high
615
 
                        data |= 0xf0;
616
 
                }
617
 
                break;
618
 
 
619
 
        case MODE_1:
620
 
                data |= m_intr[PORT_A] ? 0x08 : 0x00;
621
 
 
622
 
                if (port_mode(PORT_A) == MODE_OUTPUT)
623
 
                {
624
 
                        data |= m_obf[PORT_A] ? 0x80 : 0x00;
625
 
                        mask |= 0x30;
626
 
                }
627
 
                else
628
 
                {
629
 
                        data |= m_ibf[PORT_A] ? 0x20 : 0x00;
630
 
                        mask |= 0xc0;
631
 
                }
632
 
                break;
633
 
 
634
 
        case MODE_2:
635
 
                data |= m_intr[PORT_A] ? 0x08 : 0x00;
636
 
                data |= m_ibf[PORT_A] ? 0x20 : 0x00;
637
 
                data |= m_obf[PORT_A] ? 0x80 : 0x00;
638
 
                break;
639
 
        }
640
 
 
641
 
        // PC lower
642
 
        switch (group_mode(GROUP_B))
643
 
        {
644
 
        case MODE_0:
645
 
                if (port_c_lower_mode() == MODE_OUTPUT)
646
 
                {
647
 
                        mask |= 0x0f;
648
 
                }
649
 
                else
650
 
                {
651
 
                        // TTL inputs float high
652
 
                        data |= 0x0f;
653
 
                }
654
 
                break;
655
 
 
656
 
        case MODE_1:
657
 
                data |= m_intr[PORT_B] ? 0x01 : 0x00;
658
 
 
659
 
                if (port_mode(PORT_B) == MODE_OUTPUT)
660
 
                {
661
 
                        data |= m_obf[PORT_B] ? 0x02 : 0x00;
662
 
                }
663
 
                else
664
 
                {
665
 
                        data |= m_ibf[PORT_B] ? 0x02 : 0x00;
666
 
                }
667
 
        }
668
 
 
669
 
        data |= m_output[PORT_C] & mask;
670
 
 
671
 
        m_out_port_func[PORT_C](0, data);
672
 
}
673
 
 
674
 
 
675
 
//-------------------------------------------------
676
 
//  set_mode -
677
 
//-------------------------------------------------
678
 
 
679
 
void i8255_device::set_mode(UINT8 data)
680
 
{
681
 
        m_control = data;
682
 
 
683
 
        // group A
684
 
        m_output[PORT_A] = 0;
685
 
        m_input[PORT_A] = 0;
686
 
        m_ibf[PORT_A] = 0;
687
 
        m_obf[PORT_A] = 1;
688
 
        m_inte[PORT_A] = 0;
689
 
        m_inte1 = 0;
690
 
        m_inte2 = 0;
691
 
 
692
 
        if (port_mode(PORT_A) == MODE_OUTPUT)
693
 
        {
694
 
                m_out_port_func[PORT_A](0, m_output[PORT_A]);
695
 
        }
696
 
        else
697
 
        {
698
 
                // TTL inputs float high
699
 
                m_out_port_func[PORT_A](0, 0xff);
700
 
        }
701
 
 
702
 
        if (LOG)
703
 
        {
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");
710
 
        }
711
 
 
712
 
        // group B
713
 
        m_output[PORT_B] = 0;
714
 
        m_input[PORT_B] = 0;
715
 
        m_ibf[PORT_B] = 0;
716
 
        m_obf[PORT_B] = 1;
717
 
        m_inte[PORT_B] = 0;
718
 
 
719
 
        if (port_mode(PORT_B) == MODE_OUTPUT)
720
 
        {
721
 
                m_out_port_func[PORT_B](0, m_output[PORT_B]);
722
 
        }
723
 
        else
724
 
        {
725
 
                // TTL inputs float high
726
 
                m_out_port_func[PORT_B](0, 0xff);
727
 
        }
728
 
 
729
 
        m_output[PORT_C] = 0;
730
 
        m_input[PORT_C] = 0;
731
 
 
732
 
        output_pc();
733
 
}
734
 
 
735
 
 
736
 
//-------------------------------------------------
737
 
//  set_pc_bit -
738
 
//-------------------------------------------------
739
 
 
740
 
void i8255_device::set_pc_bit(int bit, int state)
741
 
{
742
 
        // set output latch bit
743
 
        m_output[PORT_C] &= ~(1 << bit);
744
 
        m_output[PORT_C] |= state << bit;
745
 
 
746
 
        switch (group_mode(GROUP_A))
747
 
        {
748
 
        case MODE_1:
749
 
                if (port_mode(PORT_A) == MODE_OUTPUT)
750
 
                {
751
 
                        switch (bit)
752
 
                        {
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;
756
 
                        }
757
 
                }
758
 
                else
759
 
                {
760
 
                        switch (bit)
761
 
                        {
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;
765
 
                        }
766
 
                }
767
 
                break;
768
 
 
769
 
        case MODE_2:
770
 
                switch (bit)
771
 
                {
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;
777
 
                }
778
 
                break;
779
 
        }
780
 
 
781
 
        if (group_mode(GROUP_B) == MODE_1)
782
 
        {
783
 
                switch (bit)
784
 
                {
785
 
                case 0: set_intr(PORT_B, state); break;
786
 
                case 1:
787
 
                        if (port_mode(PORT_B) == MODE_OUTPUT)
788
 
                                set_obf(PORT_B, state);
789
 
                        else
790
 
                                set_ibf(PORT_B, state);
791
 
                        break;
792
 
                case 2: set_inte(PORT_B, state); break;
793
 
                }
794
 
        }
795
 
 
796
 
        output_pc();
797
 
}
798
 
 
799
 
 
800
 
//-------------------------------------------------
801
 
//  read -
802
 
//-------------------------------------------------
803
 
 
804
 
READ8_MEMBER( i8255_device::read )
805
 
{
806
 
        UINT8 data = 0;
807
 
 
808
 
        switch (offset & 0x03)
809
 
        {
810
 
        case PORT_A:
811
 
                switch (group_mode(GROUP_A))
812
 
                {
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;
816
 
                }
817
 
                if (LOG) logerror("I8255 '%s' Port A Read: %02x\n", tag(), data);
818
 
                break;
819
 
 
820
 
        case PORT_B:
821
 
                switch (group_mode(GROUP_B))
822
 
                {
823
 
                case MODE_0: data = read_mode0(PORT_B); break;
824
 
                case MODE_1: data = read_mode1(PORT_B); break;
825
 
                }
826
 
                if (LOG) logerror("I8255 '%s' Port B Read: %02x\n", tag(), data);
827
 
                break;
828
 
 
829
 
        case PORT_C:
830
 
                data = read_pc();
831
 
                if (LOG) logerror("I8255 '%s' Port C Read: %02x\n", tag(), data);
832
 
                break;
833
 
 
834
 
        case CONTROL:
835
 
                data = m_control;
836
 
                if (LOG) logerror("I8255 '%s' Mode Control Word Read: %02x\n", tag(), data);
837
 
                break;
838
 
        }
839
 
 
840
 
        return data;
841
 
}
842
 
 
843
 
 
844
 
//-------------------------------------------------
845
 
//  write -
846
 
//-------------------------------------------------
847
 
 
848
 
WRITE8_MEMBER( i8255_device::write )
849
 
{
850
 
        switch (offset & 0x03)
851
 
        {
852
 
        case PORT_A:
853
 
                if (LOG) logerror("I8255 '%s' Port A Write: %02x\n", tag(), data);
854
 
 
855
 
                switch (group_mode(GROUP_A))
856
 
                {
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;
860
 
                }
861
 
                break;
862
 
 
863
 
        case PORT_B:
864
 
                if (LOG) logerror("I8255 '%s' Port B Write: %02x\n", tag(), data);
865
 
 
866
 
                switch (group_mode(GROUP_B))
867
 
                {
868
 
                case MODE_0: write_mode0(PORT_B, data); break;
869
 
                case MODE_1: write_mode1(PORT_B, data); break;
870
 
                }
871
 
                break;
872
 
 
873
 
        case PORT_C:
874
 
                if (LOG) logerror("I8255 '%s' Port C Write: %02x\n", tag(), data);
875
 
 
876
 
                write_pc(data);
877
 
                break;
878
 
 
879
 
        case CONTROL:
880
 
                if (data & CONTROL_MODE_SET)
881
 
                {
882
 
                        if (LOG) logerror("I8255 '%s' Mode Control Word: %02x\n", tag(), data);
883
 
 
884
 
                        set_mode(data);
885
 
                }
886
 
                else
887
 
                {
888
 
                        int bit = (data >> 1) & 0x07;
889
 
                        int state = BIT(data, 0);
890
 
 
891
 
                        if (LOG) logerror("I8255 '%s' %s Port C Bit %u\n", tag(), state ? "Set" : "Reset", bit);
892
 
 
893
 
                        set_pc_bit(bit, state);
894
 
                }
895
 
                break;
896
 
        }
897
 
}
898
 
 
899
 
 
900
 
//-------------------------------------------------
901
 
//  pa_r -
902
 
//-------------------------------------------------
903
 
 
904
 
READ8_MEMBER( i8255_device::pa_r )
905
 
{
906
 
        return pa_r();
907
 
}
908
 
 
909
 
 
910
 
//-------------------------------------------------
911
 
//  pb_r - port A read
912
 
//-------------------------------------------------
913
 
 
914
 
UINT8 i8255_device::pa_r()
915
 
{
916
 
        UINT8 data = 0xff;
917
 
 
918
 
        if (port_mode(PORT_A) == MODE_OUTPUT)
919
 
        {
920
 
                data = m_output[PORT_A];
921
 
        }
922
 
 
923
 
        return data;
924
 
}
925
 
 
926
 
 
927
 
//-------------------------------------------------
928
 
//  pb_r -
929
 
//-------------------------------------------------
930
 
 
931
 
READ8_MEMBER( i8255_device::pb_r )
932
 
{
933
 
        return pb_r();
934
 
}
935
 
 
936
 
 
937
 
//-------------------------------------------------
938
 
//  pb_r - port B read
939
 
//-------------------------------------------------
940
 
 
941
 
UINT8 i8255_device::pb_r()
942
 
{
943
 
        UINT8 data = 0xff;
944
 
 
945
 
        if (port_mode(PORT_B) == MODE_OUTPUT)
946
 
        {
947
 
                data = m_output[PORT_B];
948
 
        }
949
 
 
950
 
        return data;
951
 
}
952
 
 
953
 
 
954
 
//-------------------------------------------------
955
 
//  pc2_w -
956
 
//-------------------------------------------------
957
 
 
958
 
WRITE_LINE_MEMBER( i8255_device::pc2_w )
959
 
{
960
 
        if (group_mode(GROUP_B) == 1)
961
 
        {
962
 
                if (port_mode(PORT_B) == MODE_OUTPUT)
963
 
                {
964
 
                        // port B acknowledge
965
 
                        if (!m_obf[PORT_B] && !state)
966
 
                        {
967
 
                                if (LOG) logerror("I8255 '%s' Port B Acknowledge\n", tag());
968
 
 
969
 
                                // clear output buffer flag
970
 
                                set_obf(PORT_B, 1);
971
 
                        }
972
 
                }
973
 
                else
974
 
                {
975
 
                        // port B strobe
976
 
                        if (!m_ibf[PORT_B] && !state)
977
 
                        {
978
 
                                if (LOG) logerror("I8255 '%s' Port B Strobe\n", tag());
979
 
 
980
 
                                // read port into latch
981
 
                                m_input[PORT_B] = m_in_port_func[PORT_B](0);
982
 
 
983
 
                                // set input buffer flag
984
 
                                set_ibf(PORT_B, 1);
985
 
                        }
986
 
                }
987
 
        }
988
 
}
989
 
 
990
 
 
991
 
//-------------------------------------------------
992
 
//  pc4_w -
993
 
//-------------------------------------------------
994
 
 
995
 
WRITE_LINE_MEMBER( i8255_device::pc4_w )
996
 
{
997
 
        if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_INPUT)))
998
 
        {
999
 
                // port A strobe
1000
 
                if (!m_ibf[PORT_A] && !state)
1001
 
                {
1002
 
                        if (LOG) logerror("I8255 '%s' Port A Strobe\n", tag());
1003
 
 
1004
 
                        // read port into latch
1005
 
                        m_input[PORT_A] = m_in_port_func[PORT_A](0);
1006
 
 
1007
 
                        // set input buffer flag
1008
 
                        set_ibf(PORT_A, 1);
1009
 
                }
1010
 
        }
1011
 
}
1012
 
 
1013
 
 
1014
 
//-------------------------------------------------
1015
 
//  pc6_w -
1016
 
//-------------------------------------------------
1017
 
 
1018
 
WRITE_LINE_MEMBER( i8255_device::pc6_w )
1019
 
{
1020
 
        if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_OUTPUT)))
1021
 
        {
1022
 
                // port A acknowledge
1023
 
                if (!m_obf[PORT_A] && !state)
1024
 
                {
1025
 
                        if (LOG) logerror("I8255 '%s' Port A Acknowledge\n", tag());
1026
 
 
1027
 
                        // clear output buffer flag
1028
 
                        set_obf(PORT_A, 1);
1029
 
                }
1030
 
        }
1031
 
}