summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/ins8154.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/ins8154.c')
-rw-r--r--trunk/src/emu/machine/ins8154.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/ins8154.c b/trunk/src/emu/machine/ins8154.c
new file mode 100644
index 00000000000..57e37387cf9
--- /dev/null
+++ b/trunk/src/emu/machine/ins8154.c
@@ -0,0 +1,271 @@
+/***************************************************************************
+
+ National Semiconductor INS8154
+
+ N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
+
+
+ TODO: Strobed modes
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ins8154.h"
+#include "devhelpr.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define VERBOSE 1
+
+/* Mode Definition Register */
+enum
+{
+ MDR_BASIC = 0x00,
+ MDR_STROBED_INPUT = 0x20,
+ MDR_STROBED_OUTPUT = 0x60,
+ MDR_STROBED_OUTPUT_3STATE = 0xe0
+};
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type INS8154 = &device_creator<ins8154_device>;
+
+//-------------------------------------------------
+// ins8154_device - constructor
+//-------------------------------------------------
+
+ins8154_device::ins8154_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, INS8154, "INS8154", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ins8154_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const ins8154_interface *intf = reinterpret_cast<const ins8154_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<ins8154_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_a_cb, 0, sizeof(m_in_a_cb));
+ memset(&m_in_b_cb, 0, sizeof(m_in_b_cb));
+ memset(&m_out_a_cb, 0, sizeof(m_out_a_cb));
+ memset(&m_out_b_cb, 0, sizeof(m_out_b_cb));
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ins8154_device::device_start()
+{
+ /* resolve callbacks */
+ m_in_a_func.resolve(m_in_a_cb, *this);
+ m_out_a_func.resolve(m_out_a_cb, *this);
+ m_in_b_func.resolve(m_in_b_cb, *this);
+ m_out_b_func.resolve(m_out_b_cb, *this);
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+
+ /* register for state saving */
+ save_item(NAME(m_in_a));
+ save_item(NAME(m_in_b));
+ save_item(NAME(m_out_a));
+ save_item(NAME(m_out_b));
+ save_item(NAME(m_mdr));
+ save_item(NAME(m_odra));
+ save_item(NAME(m_odrb));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ins8154_device::device_reset()
+{
+ m_in_a = 0;
+ m_in_b = 0;
+ m_out_a = 0;
+ m_out_b = 0;
+ m_mdr = 0;
+ m_odra = 0;
+ m_odrb = 0;
+}
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_r)
+{
+ UINT8 val = 0xff;
+
+ if (offset > 0x24)
+ {
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' Read from invalid offset %02x!\n", machine().describe_context(), tag(), offset);
+ }
+ return 0xff;
+ }
+
+ switch (offset)
+ {
+ case 0x20:
+ if(!m_in_a_func.isnull())
+ {
+ val = m_in_a_func(0);
+ }
+ m_in_a = val;
+ break;
+
+ case 0x21:
+ if(!m_in_b_func.isnull())
+ {
+ val = m_in_b_func(0);
+ }
+ m_in_b = val;
+ break;
+
+ default:
+ if (offset < 0x08)
+ {
+ if(!m_in_a_func.isnull())
+ {
+ val = (m_in_a_func(0) << (8 - offset)) & 0x80;
+ }
+ m_in_a = val;
+ }
+ else
+ {
+ if(!m_in_b_func.isnull())
+ {
+ val = (m_in_b_func(0) << (8 - (offset >> 4))) & 0x80;
+ }
+ m_in_b = val;
+ }
+ break;
+ }
+
+ return val;
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_porta_w)
+{
+ m_out_a = data;
+
+ /* Test if any pins are set as outputs */
+ if (m_odra)
+ {
+ m_out_a_func(0, (data & m_odra) | (m_odra ^ 0xff));
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_portb_w)
+{
+ m_out_b = data;
+
+ /* Test if any pins are set as outputs */
+ if (m_odrb)
+ {
+ m_out_b_func(0, (data & m_odrb) | (m_odrb ^ 0xff));
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_w)
+{
+ if (offset > 0x24)
+ {
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' Write %02x to invalid offset %02x!\n", machine().describe_context(), tag(), data, offset);
+ }
+ return;
+ }
+
+ switch (offset)
+ {
+ case 0x20:
+ ins8154_porta_w(0, data);
+ break;
+
+ case 0x21:
+ ins8154_portb_w(0, data);
+ break;
+
+ case 0x22:
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' ODRA set to %02x\n", machine().describe_context(), tag(), data);
+ }
+
+ m_odra = data;
+ break;
+
+ case 0x23:
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' ODRB set to %02x\n", machine().describe_context(), tag(), data);
+ }
+
+ m_odrb = data;
+ break;
+
+ case 0x24:
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' MDR set to %02x\n", machine().describe_context(), tag(), data);
+ }
+
+ m_mdr = data;
+ break;
+
+ default:
+ if (offset & 0x10)
+ {
+ /* Set bit */
+ if (offset < 0x08)
+ {
+ ins8154_porta_w(0, m_out_a |= offset & 0x07);
+ }
+ else
+ {
+ ins8154_portb_w(0, m_out_b |= (offset >> 4) & 0x07);
+ }
+ }
+ else
+ {
+ /* Clear bit */
+ if (offset < 0x08)
+ {
+ ins8154_porta_w(0, m_out_a & ~(offset & 0x07));
+ }
+ else
+ {
+ ins8154_portb_w(0, m_out_b & ~((offset >> 4) & 0x07));
+ }
+ }
+
+ break;
+ }
+}