diff options
Diffstat (limited to 'trunk/src/emu/machine/ins8154.c')
-rw-r--r-- | trunk/src/emu/machine/ins8154.c | 271 |
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; + } +} |