diff options
Diffstat (limited to 'src/devices/machine/2812fifo.cpp')
-rw-r--r-- | src/devices/machine/2812fifo.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/src/devices/machine/2812fifo.cpp b/src/devices/machine/2812fifo.cpp new file mode 100644 index 00000000000..250be669639 --- /dev/null +++ b/src/devices/machine/2812fifo.cpp @@ -0,0 +1,235 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/************************************************************************** + + 2812 32*8 First-In First-Out Memory (AMD, Plessey, and others) + + These devices contain a file of 32 data registers and corresponding + control registers indicating when the data registers are valid. + Data ripples from the input register towards the output until it + reaches a register containing valid data. The first and last data + registers support serial operation. + + The half-full flag responds to the number of valid locations. It + favours glitch-free operation over precision. It's never asserted + when fewer than 13 registers are valid, and it's always asserted + when at least 16 registers are valid. + + TODO: + * Propagation delays + * Serial I/O + * Am2813 32*9 version without serial I/O + +**************************************************************************/ + +#include "emu.h" +#include "2812fifo.h" + +#include <algorithm> +#include <cassert> + + +DEFINE_DEVICE_TYPE(FIFO2812, fifo2812_device, "fifo2812", "2812 32*8 FIFO Memory"); + + +fifo2812_device::fifo2812_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, FIFO2812, tag, owner, clock), + m_q_cb(*this), + m_ir_cb(*this), + m_or_cb(*this), + m_flag_cb(*this), + m_control(0U), + m_count(0U), + m_d(0U), m_mr(1U), m_pl(0U), m_pd(0U), m_oe(1U) +{ + std::fill(std::begin(m_data), std::end(m_data), 0U); +} + + +WRITE_LINE_MEMBER(fifo2812_device::mr_w) +{ + if (bool(state) != bool(m_mr)) + { + m_mr = state ? 1U : 0U; + if (!m_mr) + device_reset(); + } +} + +WRITE_LINE_MEMBER(fifo2812_device::pl_w) +{ + if (bool(state) != bool(m_pl)) + { + m_pl = state ? 1U : 0U; + if (m_mr) + { + if (m_pl) + { + m_data[0] = m_d; + if (!BIT(m_control, 0)) + { + m_control |= u32(1) << 0; + m_ir_cb(1); + if (15U == ++m_count) + m_flag_cb(1); + } + } + else if (BIT(m_control, 0) && !BIT(m_control, 1)) + { + unsigned bit(1); + m_data[bit] = m_data[bit - 1]; + m_control |= u32(1) << bit; + m_control &= ~(u32(1) << (bit - 1)); + m_ir_cb(0); + for (++bit; ((LENGTH - 1) > bit) && !BIT(m_control, bit); ++bit) + { + m_data[bit] = m_data[bit - 1]; + m_control |= u32(1) << bit; + m_control &= ~(u32(1) << (bit - 1)); + } + if (!m_pd && ((LENGTH - 1) == bit) && !BIT(m_control, bit)) + { + if (m_data[bit] != m_data[bit - 1]) + { + m_data[bit] = m_data[bit - 1]; + if (m_oe) + m_q_cb(0U, m_data[bit], 0xffU); + } + m_control |= u32(1) << bit; + m_control &= ~(u32(1) << (bit - 1)); + m_or_cb(1); + } + } + } + } +} + +WRITE_LINE_MEMBER(fifo2812_device::pd_w) +{ + if (bool(state) != bool(m_pd)) + { + m_pd = state ? 1U : 0U; + if (m_mr) + { + if (m_pd) + { + if (BIT(m_control, LENGTH - 1)) + { + m_control &= ~(u32(1) << (LENGTH - 1)); + m_or_cb(0); + if (15U == m_count--) + m_flag_cb(0); + } + } + else if (BIT(m_control, LENGTH - 2)) + { + unsigned bit(LENGTH - 2); + if (m_data[bit + 1] != m_data[bit]) + { + m_data[bit + 1] = m_data[bit]; + if (m_oe) + m_q_cb(0U, m_data[bit + 1], 0xffU); + } + m_control |= u32(1) << (bit + 1); + m_control &= ~(u32(1) << bit); + m_or_cb(1); + for (--bit; (0U < bit) && BIT(m_control, bit); --bit) + { + m_data[bit + 1] = m_data[bit]; + m_control |= u32(1) << (bit + 1); + m_control &= ~(u32(1) << bit); + } + if (!m_pl && (0U == bit) && BIT(m_control, bit)) + { + m_data[bit + 1] = m_data[bit]; + m_control |= u32(1) << (bit + 1); + m_control &= ~(u32(1) << bit); + m_ir_cb(0); + } + } + } + } +} + +WRITE_LINE_MEMBER(fifo2812_device::oe_w) +{ + if (bool(state) != bool(m_oe)) + { + m_oe = state ? 1U : 0U; + if (m_oe) + m_q_cb(0U, m_data[LENGTH - 1], 0xffU); + else + m_q_cb(0U, 0xffU, 0x00U); + } +} + + +u8 fifo2812_device::read() +{ + if (machine().side_effects_disabled()) + { + return m_data[LENGTH - 1]; + } + else + { + assert(!m_pd); + pd_w(1); + u8 const data(m_data[LENGTH - 1]); + pd_w(0); + return data; + } +} + +void fifo2812_device::write(u8 data) +{ + assert(!m_pl); + d_w(data); + pl_w(1); + pl_w(0); +} + + +void fifo2812_device::device_resolve_objects() +{ + m_q_cb.resolve_safe(); + m_ir_cb.resolve_safe(); + m_or_cb.resolve_safe(); + m_flag_cb.resolve_safe(); + + m_d = 0U; + m_mr = 1U; + m_pl = 0U; + m_pd = 0U; + m_oe = 1U; +} + +void fifo2812_device::device_start() +{ + save_item(NAME(m_control)); + save_item(NAME(m_data)); + save_item(NAME(m_count)); + save_item(NAME(m_d)); + save_item(NAME(m_mr)); + save_item(NAME(m_pl)); + save_item(NAME(m_pd)); + save_item(NAME(m_oe)); +} + +void fifo2812_device::device_reset() +{ + u32 const prev_ir(BIT(m_control, 0)); + u32 const prev_or(BIT(m_control, LENGTH - 1)); + u8 const prev_q(m_data[LENGTH - 1]); + bool const prev_flag(15U <= m_count); + m_control = 0U; + std::fill(std::begin(m_data), std::end(m_data), 0U); + m_count = 0U; + if (m_oe && (0U != prev_q)) + m_q_cb(0U, 0U, 0xffU); + if (prev_ir) + m_ir_cb(0); + if (prev_or) + m_or_cb(0); + if (prev_flag) + m_flag_cb(0); +} |