summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/rstbuf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/rstbuf.cpp')
-rw-r--r--src/devices/machine/rstbuf.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/devices/machine/rstbuf.cpp b/src/devices/machine/rstbuf.cpp
new file mode 100644
index 00000000000..9e13d72743a
--- /dev/null
+++ b/src/devices/machine/rstbuf.cpp
@@ -0,0 +1,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, u32 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, u32 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, u32 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();
+}