1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     CD40105/HC40105 4-bit x 16-word FIFO Register
6 
7     Part of the 4000B series of CMOS logic devices, the 40105 includes
8     an asynchronous master reset pin intended to be connected to the
9     system bus.
10 
11     Word size can be expanded from 4 bits to 8 bits by connecting two
12     40105s in parallel, with external AND gates to combine the DIR and
13     DOR outputs. They can also be connected in series to extend the
14     FIFO capacity, with DOR -> SI and /SO <- DIR.
15 
16 **********************************************************************/
17 
18 #include "emu.h"
19 #include "40105.h"
20 
21 
22 
23 //**************************************************************************
24 //  MACROS / CONSTANTS
25 //**************************************************************************
26 
27 #define LOG 0
28 
29 
30 
31 //**************************************************************************
32 //  DEVICE DEFINITIONS
33 //**************************************************************************
34 
35 DEFINE_DEVICE_TYPE(CD40105, cmos_40105_device, "cd40105", "CD40105B FIFO Register")
36 
37 
38 //**************************************************************************
39 //  LIVE DEVICE
40 //**************************************************************************
41 
42 //-------------------------------------------------
43 //  cmos_40105_device - constructor
44 //-------------------------------------------------
45 
cmos_40105_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)46 cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
47 	: device_t(mconfig, CD40105, tag, owner, clock),
48 		m_write_dir(*this),
49 		m_write_dor(*this),
50 		m_write_q(*this),
51 		m_d(0),
52 		m_q(0),
53 		m_dir(false),
54 		m_dor(false),
55 		m_si(false),
56 		m_so(false)
57 {
58 }
59 
60 
61 //-------------------------------------------------
62 //  device_start - device-specific startup
63 //-------------------------------------------------
64 
device_start()65 void cmos_40105_device::device_start()
66 {
67 	// resolve callbacks
68 	m_write_dir.resolve_safe();
69 	m_write_dor.resolve_safe();
70 	m_write_q.resolve_safe();
71 
72 	// state saving
73 	save_item(NAME(m_d));
74 	save_item(NAME(m_q));
75 	save_item(NAME(m_dir));
76 	save_item(NAME(m_dor));
77 	save_item(NAME(m_si));
78 	save_item(NAME(m_so));
79 }
80 
81 
82 //-------------------------------------------------
83 //  device_reset - device-specific reset
84 //-------------------------------------------------
85 
device_reset()86 void cmos_40105_device::device_reset()
87 {
88 	// invalidate data in queue
89 	m_fifo = std::queue<u8>();
90 
91 	// reset control flip-flops
92 	m_dir = true;
93 	m_dor = false;
94 	m_write_dir(1);
95 	m_write_dor(0);
96 }
97 
98 
99 //-------------------------------------------------
100 //  read - read output buffer (Q0 to Q3)
101 //-------------------------------------------------
102 
read()103 u8 cmos_40105_device::read()
104 {
105 	return m_q;
106 }
107 
108 
109 //-------------------------------------------------
110 //  write - write input buffer (D0 to D3)
111 //-------------------------------------------------
112 
write(u8 data)113 void cmos_40105_device::write(u8 data)
114 {
115 	m_d = data & 0x0f;
116 }
117 
118 
119 //-------------------------------------------------
120 //  load_input - load new data into FIFO
121 //-------------------------------------------------
122 
load_input()123 void cmos_40105_device::load_input()
124 {
125 	if (m_fifo.size() == 16)
126 	{
127 		logerror("Attempt to load data into full FIFO\n");
128 		return;
129 	}
130 
131 	m_fifo.push(m_d);
132 
133 	// DIR remains low if FIFO is full, or else briefly pulses low
134 	m_write_dir(0);
135 	if (m_fifo.size() == 16)
136 		m_dir = false;
137 	else
138 		m_write_dir(1);
139 }
140 
141 
142 //-------------------------------------------------
143 //  output_ready - place new data at output
144 //-------------------------------------------------
145 
output_ready()146 void cmos_40105_device::output_ready()
147 {
148 	if (m_fifo.size() == 0)
149 	{
150 		logerror("Attempt to output data from empty FIFO\n");
151 		return;
152 	}
153 
154 	m_q = m_fifo.front();
155 	m_write_q(m_q);
156 
157 	m_dor = true;
158 	m_write_dor(1);
159 }
160 
161 
162 //-------------------------------------------------
163 //  si_w - shift in write
164 //-------------------------------------------------
165 
WRITE_LINE_MEMBER(cmos_40105_device::si_w)166 WRITE_LINE_MEMBER( cmos_40105_device::si_w )
167 {
168 	// load input on rising edge when ready
169 	if (m_dir && !m_si && state)
170 	{
171 		load_input();
172 	}
173 	else if (m_si && !state && m_fifo.size() > 0)
174 	{
175 		// data propagates through FIFO when SI goes low
176 		if (!m_dor)
177 			output_ready();
178 	}
179 
180 	m_si = state;
181 }
182 
183 
184 //-------------------------------------------------
185 //  so_w - shift out write
186 //-------------------------------------------------
187 
WRITE_LINE_MEMBER(cmos_40105_device::so_w)188 WRITE_LINE_MEMBER( cmos_40105_device::so_w )
189 {
190 	// shift out on falling edge when ready
191 	if (m_dor && m_so && !state)
192 	{
193 		m_fifo.pop();
194 		m_dor = false;
195 		m_write_dor(0);
196 
197 		// DOR remains low if FIFO is now empty, or else briefly pulses low
198 		if (m_fifo.size() > 0)
199 			output_ready();
200 
201 		if (!m_dir)
202 		{
203 			// raise DIR since FIFO is no longer full
204 			m_dir = true;
205 			m_write_dir(1);
206 
207 			// load new input immediately if SI is held high
208 			if (m_si)
209 				load_input();
210 		}
211 	}
212 
213 	m_so = state;
214 }
215 
216 
217 //-------------------------------------------------
218 //  dir_r - data in ready read
219 //-------------------------------------------------
220 
READ_LINE_MEMBER(cmos_40105_device::dir_r)221 READ_LINE_MEMBER( cmos_40105_device::dir_r )
222 {
223 	return m_dir;
224 }
225 
226 
227 //-------------------------------------------------
228 //  dor_r - data out ready read
229 //-------------------------------------------------
230 
READ_LINE_MEMBER(cmos_40105_device::dor_r)231 READ_LINE_MEMBER( cmos_40105_device::dor_r )
232 {
233 	return m_dor;
234 }
235