diff options
author | 2017-09-25 19:29:14 -0400 | |
---|---|---|
committer | 2017-09-25 19:33:55 -0400 | |
commit | 2ad6b11191b86ef86e4f64caa59619fb5cfdc692 (patch) | |
tree | dc41d72b20721aae5af30e4166ee801312b2c99e | |
parent | 51dfc76af82e9462410fb3b94d5d24addbda6c7d (diff) |
i8212: Device overhaul (nw)
- Change the mode setting from a line write to an input callback. This is based on the observation that MD is nearly always tied to either Vcc or GND on actual hardware.
- Make the mode a scoped enumeration.
- Add strobed write handler for input mode. This allows the device to be hooked up in supstarf in place of generic_latch_8_device.
- Add interrupt acknowledge callback for future use.
- Add extensive introductory comments.
-rw-r--r-- | src/devices/machine/i8212.cpp | 129 | ||||
-rw-r--r-- | src/devices/machine/i8212.h | 41 | ||||
-rw-r--r-- | src/mame/drivers/supstarf.cpp | 18 |
3 files changed, 137 insertions, 51 deletions
diff --git a/src/devices/machine/i8212.cpp b/src/devices/machine/i8212.cpp index c08ee3ad6e0..4c7cd115c75 100644 --- a/src/devices/machine/i8212.cpp +++ b/src/devices/machine/i8212.cpp @@ -1,8 +1,40 @@ // license:BSD-3-Clause -// copyright-holders:Curt Coder +// copyright-holders:Curt Coder,AJR /********************************************************************** - Intel 8212 8-Bit Input/Output Port emulation + Intel 8212/3212 8-Bit Input/Output Port (Multi-Mode Latch Buffer) + + The Intel 8212 was one of the first in a line of bipolar Schottky + peripherals released early on for the 8080. Many of these were + assigned alternate part numbers in the 3200 series to identify + them with Intel's 3001/3002 bipolar bit-slice processing elements. + + The 8212's MD pin is typically tied to either GND or Vcc to fix + the chip in one of its two operating modes. In the input mode + (MD = L), data is latched on the falling edge of STB, and the + three-state outputs are enabled by a combination of two chip + select inputs of opposite polarities. In the output mode (MD = H), + data is latched on the falling edge of chip selection, and outputs + are always enabled. The service request flip-flop is clocked on + the falling edge of STB to produce the INT output, and is reset by + either chip selection or the active-low CLR input, the latter + also resetting the latched data to zero. + + The 8212 in output mode was often used with the 8080 to latch the + status word and with the 8085 to latch the lower address bits. + + RCA's CDP1852 is an almost pin-for-pin CMOS counterpart to the + 8212. The control lines of the CDP1852, however, work slightly + differently, especially in output mode. + + When TI second-sourced the 8080A, they cloned the 8212 as the + SN74S412 (and numbered their versions of the 8224, 8228 and 8338 + similarly). While simpler octal latches from the 7400 series such + as 74LS273, 74LS373 and 74LS374 became far more common and widely + used, even when a separate service request flip-flop needed to be + coupled, the Fairchild Advanced Schottky TTL (FAST) evolution of + the 7400 series had both inverting (74F432) and non-inverting + (74F412) versions of this device. **********************************************************************/ @@ -19,7 +51,7 @@ //************************************************************************** // device type definition -DEFINE_DEVICE_TYPE(I8212, i8212_device, "i8212", "Intel 8212 I/O") +DEFINE_DEVICE_TYPE(I8212, i8212_device, "i8212", "Intel 8212 I/O Port") //------------------------------------------------- // i8212_device - constructor @@ -30,8 +62,8 @@ i8212_device::i8212_device(const machine_config &mconfig, const char *tag, devic m_write_int(*this), m_read_di(*this), m_write_do(*this), - m_md(MODE_INPUT), - m_stb(0), m_data(0) + m_read_md(*this), + m_stb(1), m_data(0) { } @@ -46,23 +78,37 @@ void i8212_device::device_start() m_write_int.resolve_safe(); m_read_di.resolve_safe(0); m_write_do.resolve_safe(); + m_read_md.resolve_safe(0); // register for state saving - save_item(NAME(m_md)); save_item(NAME(m_stb)); save_item(NAME(m_data)); } //------------------------------------------------- +// get_mode - resolve device mode +//------------------------------------------------- + +i8212_device::mode i8212_device::get_mode() +{ + return m_read_md() ? mode::OUTPUT : mode::INPUT; +} + + +//------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void i8212_device::device_reset() { + // clear interrupt line + m_write_int(CLEAR_LINE); + + // clear latched data m_data = 0; - if (m_md == MODE_OUTPUT) + if (get_mode() == mode::OUTPUT) { // output data m_write_do((offs_t)0, m_data); @@ -74,13 +120,28 @@ void i8212_device::device_reset() // read - data latch read //------------------------------------------------- -READ8_MEMBER( i8212_device::read ) +READ8_MEMBER(i8212_device::read) +{ + if (!machine().side_effect_disabled()) + { + // clear interrupt line + m_write_int(CLEAR_LINE); + } + + return m_data; +} + + +//------------------------------------------------- +// inta_cb - data latch read (INTA triggered) +//------------------------------------------------- + +IRQ_CALLBACK_MEMBER(i8212_device::inta_cb) { // clear interrupt line m_write_int(CLEAR_LINE); - LOG("I8212 INT: %u\n", CLEAR_LINE); - + // read latched data as interrupt vector return m_data; } @@ -89,25 +150,37 @@ READ8_MEMBER( i8212_device::read ) // write - data latch write //------------------------------------------------- -WRITE8_MEMBER( i8212_device::write ) +WRITE8_MEMBER(i8212_device::write) { - // latch data - m_data = data; + // clear interrupt line + m_write_int(CLEAR_LINE); + + if (get_mode() == mode::OUTPUT) + { + // latch data + m_data = data; + LOG("I8212: Writing %02X into latch (output mode)\n", data); - // output data - m_write_do((offs_t)0, m_data); + // output data + m_write_do((offs_t)0, m_data); + } } //------------------------------------------------- -// md_w - mode write +// strobe - data input strobe //------------------------------------------------- -WRITE_LINE_MEMBER( i8212_device::md_w ) +WRITE8_MEMBER(i8212_device::strobe) { - LOG("I8212 Mode: %s\n", state ? "output" : "input"); + if (get_mode() == mode::INPUT) + { + m_data = data; + LOG("I8212: Writing %02X into latch (input mode)\n", data); + } - m_md = state; + // assert interrupt line + m_write_int(ASSERT_LINE); } @@ -115,22 +188,20 @@ WRITE_LINE_MEMBER( i8212_device::md_w ) // stb_w - data strobe write //------------------------------------------------- -WRITE_LINE_MEMBER( i8212_device::stb_w ) +WRITE_LINE_MEMBER(i8212_device::stb_w) { - LOG("I8212 STB: %u\n", state); - - if (m_md == MODE_INPUT) + // active on falling edge + if (m_stb && !state) { - if (m_stb && !state) + if (get_mode() == mode::INPUT) { // input data m_data = m_read_di(0); - - // assert interrupt line - m_write_int(ASSERT_LINE); - - LOG("I8212 INT: %u\n", ASSERT_LINE); + LOG("I8212: Reading %02X into latch (input mode)\n", m_data); } + + // assert interrupt line + m_write_int(ASSERT_LINE); } m_stb = state; diff --git a/src/devices/machine/i8212.h b/src/devices/machine/i8212.h index 30bbf4b2d6a..4f871420128 100644 --- a/src/devices/machine/i8212.h +++ b/src/devices/machine/i8212.h @@ -1,8 +1,8 @@ // license:BSD-3-Clause -// copyright-holders:Curt Coder +// copyright-holders:Curt Coder,AJR /********************************************************************** - Intel 8212 8-Bit Input/Output Port emulation + Intel 8212/3212 8-Bit Input/Output Port (Multi-Mode Latch Buffer) ********************************************************************** _____ _____ @@ -12,7 +12,7 @@ DO1 4 | | 21 DO8 DI2 5 | | 20 DI7 DO2 6 | 8212 | 19 DO7 - DI3 7 | | 18 DI6 + DI3 7 | 3212 | 18 DI6 DO3 8 | | 17 DO6 DI4 9 | | 16 DI5 DO4 10 | | 15 DO5 @@ -42,6 +42,9 @@ #define MCFG_I8212_DO_CALLBACK(_write) \ devcb = &i8212_device::set_do_wr_callback(*device, DEVCB_##_write); +#define MCFG_I8212_MD_CALLBACK(_read) \ + devcb = &i8212_device::set_md_rd_callback(*device, DEVCB_##_read); + ///************************************************************************* @@ -52,6 +55,12 @@ class i8212_device : public device_t { + enum class mode : u8 + { + INPUT, + OUTPUT + }; + public: // construction/destruction i8212_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -59,12 +68,19 @@ public: template <class Object> static devcb_base &set_int_wr_callback(device_t &device, Object &&cb) { return downcast<i8212_device &>(device).m_write_int.set_callback(std::forward<Object>(cb)); } template <class Object> static devcb_base &set_di_rd_callback(device_t &device, Object &&cb) { return downcast<i8212_device &>(device).m_read_di.set_callback(std::forward<Object>(cb)); } template <class Object> static devcb_base &set_do_wr_callback(device_t &device, Object &&cb) { return downcast<i8212_device &>(device).m_write_do.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_md_rd_callback(device_t &device, Object &&cb) { return downcast<i8212_device &>(device).m_read_md.set_callback(std::forward<Object>(cb)); } - DECLARE_READ8_MEMBER( read ); - DECLARE_WRITE8_MEMBER( write ); + // data read handlers + DECLARE_READ8_MEMBER(read); + IRQ_CALLBACK_MEMBER(inta_cb); - DECLARE_WRITE_LINE_MEMBER( md_w ); - DECLARE_WRITE_LINE_MEMBER( stb_w ); + // data write handlers + DECLARE_WRITE8_MEMBER(write); + DECLARE_WRITE8_MEMBER(strobe); + + // line write handlers + DECLARE_WRITE_LINE_MEMBER(md_w); + DECLARE_WRITE_LINE_MEMBER(stb_w); protected: // device-level overrides @@ -72,19 +88,16 @@ protected: virtual void device_reset() override; private: - enum - { - MODE_INPUT = 0, - MODE_OUTPUT - }; + // helpers + mode get_mode(); devcb_write_line m_write_int; devcb_read8 m_read_di; devcb_write8 m_write_do; + devcb_read_line m_read_md; - int m_md; // mode int m_stb; // strobe - uint8_t m_data; // data latch + uint8_t m_data; // data latch }; diff --git a/src/mame/drivers/supstarf.cpp b/src/mame/drivers/supstarf.cpp index d84a99bddde..1cdf084d30b 100644 --- a/src/mame/drivers/supstarf.cpp +++ b/src/mame/drivers/supstarf.cpp @@ -11,7 +11,7 @@ #include "emu.h" #include "cpu/i8085/i8085.h" #include "cpu/mcs48/mcs48.h" -#include "machine/gen_latch.h" +#include "machine/i8212.h" #include "sound/ay8910.h" #include "speaker.h" @@ -45,7 +45,7 @@ private: required_device<cpu_device> m_maincpu; required_device<cpu_device> m_soundcpu; required_device_array<ay8910_device, 2> m_psg; - required_device_array<generic_latch_8_device, 2> m_soundlatch; + required_device_array<i8212_device, 2> m_soundlatch; u8 m_port1_data; bool m_pcs[2]; @@ -54,7 +54,7 @@ private: static ADDRESS_MAP_START(main_map, AS_PROGRAM, 8, supstarf_state) AM_RANGE(0x0000, 0x3fff) AM_ROM - AM_RANGE(0x8000, 0x8000) AM_DEVREAD("soundlatch1", generic_latch_8_device, read) AM_DEVWRITE("soundlatch2", generic_latch_8_device, write) + AM_RANGE(0x8000, 0x8000) AM_DEVREAD("soundlatch1", i8212_device, read) AM_DEVWRITE("soundlatch2", i8212_device, strobe) AM_RANGE(0xc000, 0xc7ff) AM_RAM // 5517 (2Kx8) at IC11 ADDRESS_MAP_END @@ -102,7 +102,7 @@ WRITE8_MEMBER(supstarf_state::psg_latch_w) } if (m_latch_select) - m_soundlatch[0]->write(space, 0, data); + m_soundlatch[0]->strobe(space, 0, data); } WRITE8_MEMBER(supstarf_state::port1_w) @@ -177,11 +177,13 @@ static MACHINE_CONFIG_START(supstarf) MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(supstarf_state, port2_w)) MCFG_MCS48_PORT_T1_IN_CB(READLINE(supstarf_state, phase_detect_r)) - MCFG_GENERIC_LATCH_8_ADD("soundlatch1") - MCFG_GENERIC_LATCH_DATA_PENDING_CB(INPUTLINE("maincpu", I8085_RST55_LINE)) + MCFG_DEVICE_ADD("soundlatch1", I8212, 0) + MCFG_I8212_MD_CALLBACK(GND) + MCFG_I8212_INT_CALLBACK(INPUTLINE("maincpu", I8085_RST55_LINE)) - MCFG_GENERIC_LATCH_8_ADD("soundlatch2") - MCFG_GENERIC_LATCH_DATA_PENDING_CB(INPUTLINE("soundcpu", MCS48_INPUT_IRQ)) + MCFG_DEVICE_ADD("soundlatch2", I8212, 0) + MCFG_I8212_MD_CALLBACK(GND) + MCFG_I8212_INT_CALLBACK(INPUTLINE("soundcpu", MCS48_INPUT_IRQ)) //MCFG_DEVCB_CHAIN_OUTPUT(INPUTLINE("maincpu", I8085_READY_LINE)) MCFG_SPEAKER_STANDARD_MONO("mono") |