1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
RST interrupt vector buffer
The hardware circuit emulated by this device, which is generally
made of various TTL gates and buffers, combines three independent
interrupt request lines into a single level trigger and also
generates a 8080-compatible RST opcode vector when the CPU
acknowledges the interrupt, reflecting the current state of all
three inputs.
The positive version of this device treats all of its inputs and
outputs as active high, in accordance with 8080 convention and
some actual practice. An active-low IRQ would need to be supplied
for a Z80, which may be used with this type of circuit in IM 0,
though the negative polarity of the Z80 IRQ is not currently
accounted for by MAME.
Table of interrupt vectors for positive version:
Active Vector Instruction Address of
inputs fetched executed service routine
------- ------- ----------- ---------------
1 only CF RST 1 0008
2 only D7 RST 2 0010
4 only E7 RST 4 0020
1 and 2 DF RST 3 0018
1 and 4 EF RST 5 0028
2 and 4 F7 RST 6 0030
1, 2, 4 FF RST 7 0038
An alternate version of this device buffers the logical negative
of the request lines. This variant is primarily associated with
Z80-based sound systems. Here the inputs, asserted singly, will
produce a RST 18H, RST 28H or RST 30H interrupt (using Zilog
rather than Intel syntax). When multiple request lines are active
at once, the result is equivalent to the logical AND of the
corresponding base vectors.
This type of circuit features no built-in edge triggers or
prioritization. Since its inputs are not latched, a spurious
interrupt may occur if one or more lines are asserted just long
enough for the CPU to accept the interrupt, but deasserted before
the CPU's interrupt acknowledge cycle completes. In the positive
version, the vector placed on the bus (C7) is a RST 0 instruction,
which (after the return address is pushed onto the stack) will
transfer control to 0000 as if the CPU had just been reset. The
negative version provides a more useful vector (RST 7/RST 38H)
for spurious interrupts, but will still generate RST 0 if all
three inputs are active at once, though this situation cannot
occur if the buffer only admits two request lines (as is
generally the case with this version).
**********************************************************************/
#include "emu.h"
#include "machine/rstbuf.h"
// device type definition
DEFINE_DEVICE_TYPE(RST_POS_BUFFER, rst_pos_buffer_device, "rst_pos_buffer", "RST Interrupt Buffer (positive modification)")
DEFINE_DEVICE_TYPE(RST_NEG_BUFFER, rst_neg_buffer_device, "rst_neg_buffer", "RST Interrupt Buffer (negative modification)")
//**************************************************************************
// RST INTERRUPT BUFFER DEVICE
//**************************************************************************
//-------------------------------------------------
// rst_buffer_device - constructor
//-------------------------------------------------
rst_buffer_device::rst_buffer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock)
: device_t(mconfig, type, tag, owner, clock)
, m_int_cb(*this)
, m_input_buffer(0)
{
}
//-------------------------------------------------
// rst_pos_buffer_device - constructor
//-------------------------------------------------
rst_pos_buffer_device::rst_pos_buffer_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock)
: rst_buffer_device(mconfig, RST_POS_BUFFER, tag, owner, clock)
{
}
//-------------------------------------------------
// rst_neg_buffer_device - constructor
//-------------------------------------------------
rst_neg_buffer_device::rst_neg_buffer_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock)
: rst_buffer_device(mconfig, RST_NEG_BUFFER, tag, owner, clock)
{
}
//-------------------------------------------------
// device_resolve_objects - resolve objects that
// may be needed for other devices to set
// initial conditions at start time
//-------------------------------------------------
void rst_buffer_device::device_resolve_objects()
{
m_int_cb.resolve_safe();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void rst_buffer_device::device_start()
{
// save input state
save_item(NAME(m_input_buffer));
}
//-------------------------------------------------
// sync_set_input - synchronize asserted input
//-------------------------------------------------
TIMER_CALLBACK_MEMBER(rst_buffer_device::sync_set_input)
{
if (m_input_buffer == 0)
{
// assert interrupt when one line becomes active
m_input_buffer = param;
m_int_cb(1);
}
else
m_input_buffer |= param;
}
//-------------------------------------------------
// sync_clear_input - synchronize cleared input
//-------------------------------------------------
TIMER_CALLBACK_MEMBER(rst_buffer_device::sync_clear_input)
{
if (m_input_buffer == param)
{
// deassert interrupt when no more lines are active
m_input_buffer = 0;
m_int_cb(0);
}
else
m_input_buffer &= ~param;
}
//-------------------------------------------------
// sync_input - helper to synchronize input lines
//-------------------------------------------------
void rst_buffer_device::sync_input(bool state, u8 mask)
{
if (state)
machine().scheduler().synchronize(timer_expired_delegate(FUNC(rst_pos_buffer_device::sync_set_input), this), mask);
else
machine().scheduler().synchronize(timer_expired_delegate(FUNC(rst_pos_buffer_device::sync_clear_input), this), mask);
}
//-------------------------------------------------
// inta_cb - provide vector when interrupt is
// acknowledged by CPU
//-------------------------------------------------
IRQ_CALLBACK_MEMBER(rst_buffer_device::inta_cb)
{
return get_vector();
}
|