diff options
Diffstat (limited to 'src/devices/machine/40105.cpp')
-rw-r--r-- | src/devices/machine/40105.cpp | 143 |
1 files changed, 105 insertions, 38 deletions
diff --git a/src/devices/machine/40105.cpp b/src/devices/machine/40105.cpp index 8dec8b78cec..63db529d3bd 100644 --- a/src/devices/machine/40105.cpp +++ b/src/devices/machine/40105.cpp @@ -2,7 +2,16 @@ // copyright-holders:Curt Coder /********************************************************************** - CMOS 40105 FIFO Register emulation + CD40105/HC40105 4-bit x 16-word FIFO Register + + Part of the 4000B series of CMOS TTL devices, the 40105 includes + an asynchronous master reset pin intended to be connected to the + system bus. + + Word size can be expanded from 4 bits to 8 bits by connecting two + 40105s in parallel, with external AND gates to combine the DIR and + DOR outputs. They can also be connected in series to extend the + FIFO capacity, with DOR -> SI and /SO <- DIR. **********************************************************************/ @@ -22,8 +31,8 @@ // DEVICE DEFINITIONS //************************************************************************** -const device_type CMOS_40105 = &device_creator<cmos_40105_device>; - +const device_type CD40105 = &device_creator<cmos_40105_device>; +const device_type HC40105 = &device_creator<cmos_40105_device>; //************************************************************************** @@ -34,10 +43,17 @@ const device_type CMOS_40105 = &device_creator<cmos_40105_device>; // cmos_40105_device - constructor //------------------------------------------------- -cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, CMOS_40105, "40105", tag, owner, clock, "40105", __FILE__), +cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, CD40105, "40105 FIFO", tag, owner, clock, "cd40105", __FILE__), m_write_dir(*this), - m_write_dor(*this), m_d(0), m_q(0), m_dir(0), m_dor(0), m_si(0), m_so(0) + m_write_dor(*this), + m_write_q(*this), + m_d(0), + m_q(0), + m_dir(false), + m_dor(false), + m_si(false), + m_so(false) { } @@ -51,6 +67,7 @@ void cmos_40105_device::device_start() // resolve callbacks m_write_dir.resolve_safe(); m_write_dor.resolve_safe(); + m_write_q.resolve_safe(); // state saving save_item(NAME(m_d)); @@ -68,36 +85,84 @@ void cmos_40105_device::device_start() void cmos_40105_device::device_reset() { - m_fifo = std::queue<uint8_t>(); - - m_dir = 1; - m_dor = 0; - m_si = 0; - - m_write_dir(m_dir); - m_write_dor(m_dor); + // invalidate data in queue + m_fifo = std::queue<u8>(); + + // reset control flip-flops + m_dir = true; + m_dor = false; + m_write_dir(1); + m_write_dor(0); } //------------------------------------------------- -// read - read Q +// read - read output buffer (Q0 to Q3) //------------------------------------------------- -uint8_t cmos_40105_device::read() +u8 cmos_40105_device::read() { return m_q; } //------------------------------------------------- -// write - write D +// write - write input buffer (D0 to D3) //------------------------------------------------- -void cmos_40105_device::write(uint8_t data) +void cmos_40105_device::write(u8 data) { m_d = data & 0x0f; } +WRITE8_MEMBER(cmos_40105_device::write) +{ + write(data); +} + + +//------------------------------------------------- +// load_input - load new data into FIFO +//------------------------------------------------- + +void cmos_40105_device::load_input() +{ + if (m_fifo.size() == 16) + { + logerror("Attempt to load data into full FIFO\n"); + return; + } + + m_fifo.push(m_d); + + // DIR remains low if FIFO is full, or else briefly pulses low + m_write_dir(0); + if (m_fifo.size() == 16) + m_dir = false; + else + m_write_dir(1); +} + + +//------------------------------------------------- +// output_ready - place new data at output +//------------------------------------------------- + +void cmos_40105_device::output_ready() +{ + if (m_fifo.size() == 0) + { + logerror("Attempt to output data from empty FIFO\n"); + return; + } + + m_q = m_fifo.front(); + m_write_q(m_q); + + m_dor = true; + m_write_dor(1); +} + //------------------------------------------------- // si_w - shift in write @@ -105,22 +170,16 @@ void cmos_40105_device::write(uint8_t data) WRITE_LINE_MEMBER( cmos_40105_device::si_w ) { + // load input on rising edge when ready if (m_dir && !m_si && state) { - m_fifo.push(m_d); - - if (m_fifo.size() == 16) - { - m_dir = 0; - m_write_dir(m_dir); - } - + load_input(); + } + else if (m_si && !state && m_fifo.size() > 0) + { + // data propagates through FIFO when SI goes low if (!m_dor) - { - m_dor = 1; - m_write_dor(m_dor); - } - + output_ready(); } m_si = state; @@ -133,18 +192,26 @@ WRITE_LINE_MEMBER( cmos_40105_device::si_w ) WRITE_LINE_MEMBER( cmos_40105_device::so_w ) { - if (m_dor && m_so && !m_so) + // shift out on falling edge when ready + if (m_dor && m_so && !state) { - m_dor = 0; - m_write_dor(m_dor); - - m_q = m_fifo.front(); m_fifo.pop(); + m_dor = false; + m_write_dor(0); + // DOR remains low if FIFO is now empty, or else briefly pulses low if (m_fifo.size() > 0) + output_ready(); + + if (!m_dir) { - m_dor = 1; - m_write_dor(m_dor); + // raise DIR since FIFO is no longer full + m_dir = true; + m_write_dir(1); + + // load new input immediately if SI is held high + if (m_si) + load_input(); } } |