summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/40105.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/40105.cpp')
-rw-r--r--src/devices/machine/40105.cpp143
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();
}
}