1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     Motorola MC6852 Synchronous Serial Data Adapter emulation
6 
7 **********************************************************************/
8 
9 /*
10 
11     TODO:
12 
13     - FIFO flags
14     - receive
15     - transmit
16     - parity
17     - 1-sync-character mode
18     - 2-sync-character mode
19     - external sync mode
20     - interrupts
21 
22 */
23 
24 #include "emu.h"
25 #include "mc6852.h"
26 
27 //#define VERBOSE 1
28 #include "logmacro.h"
29 
30 
31 //**************************************************************************
32 //  DEVICE DEFINITIONS
33 //**************************************************************************
34 
35 DEFINE_DEVICE_TYPE(MC6852, mc6852_device, "mc6852", "Motorola MC6852 SSDA")
36 
37 
38 
39 //**************************************************************************
40 //  LIVE DEVICE
41 //**************************************************************************
42 
43 //-------------------------------------------------
44 //  mc6852_device - constructor
45 //-------------------------------------------------
46 
mc6852_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)47 mc6852_device::mc6852_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
48 	device_t(mconfig, MC6852, tag, owner, clock),
49 	device_serial_interface(mconfig, *this),
50 	m_write_tx_data(*this),
51 	m_write_irq(*this),
52 	m_write_sm_dtr(*this),
53 	m_write_tuf(*this),
54 	m_rx_clock(0),
55 	m_tx_clock(0),
56 	m_cts(1),
57 	m_dcd(1),
58 	m_sm_dtr(0),
59 	m_tuf(0),
60 	m_in_sync(0)
61 {
62 }
63 
64 
65 //-------------------------------------------------
66 //  device_start - device-specific startup
67 //-------------------------------------------------
68 
device_start()69 void mc6852_device::device_start()
70 {
71 	// resolve callbacks
72 	m_write_tx_data.resolve_safe();
73 	m_write_irq.resolve_safe();
74 	m_write_sm_dtr.resolve_safe();
75 	m_write_tuf.resolve_safe();
76 
77 	set_rcv_rate(m_rx_clock);
78 	set_tra_rate(m_tx_clock);
79 
80 	// register for state saving
81 	save_item(NAME(m_status));
82 	save_item(NAME(m_cr));
83 	save_item(NAME(m_scr));
84 	save_item(NAME(m_tdr));
85 	save_item(NAME(m_tsr));
86 	save_item(NAME(m_rdr));
87 	save_item(NAME(m_rsr));
88 	save_item(NAME(m_cts));
89 	save_item(NAME(m_dcd));
90 	save_item(NAME(m_sm_dtr));
91 	save_item(NAME(m_tuf));
92 	save_item(NAME(m_in_sync));
93 }
94 
95 
96 //-------------------------------------------------
97 //  device_reset - device-specific reset
98 //-------------------------------------------------
99 
device_reset()100 void mc6852_device::device_reset()
101 {
102 	m_rx_fifo = std::queue<uint8_t>();
103 	m_tx_fifo = std::queue<uint8_t>();
104 
105 	receive_register_reset();
106 	transmit_register_reset();
107 
108 	/* reset and inhibit receiver/transmitter sections */
109 	m_cr[0] |= (C1_TX_RS | C1_RX_RS);
110 	m_cr[1] &= ~(C2_EIE | C2_PC2 | C2_PC1);
111 	m_status |= S_TDRA;
112 
113 	/* set receiver shift register to all 1's */
114 	m_rsr = 0xff;
115 }
116 
117 
118 //-------------------------------------------------
119 //  tra_callback -
120 //-------------------------------------------------
121 
tra_callback()122 void mc6852_device::tra_callback()
123 {
124 	m_write_tx_data(transmit_register_get_data_bit());
125 }
126 
127 
128 //-------------------------------------------------
129 //  tra_complete -
130 //-------------------------------------------------
131 
tra_complete()132 void mc6852_device::tra_complete()
133 {
134 	// TODO
135 }
136 
137 //-------------------------------------------------
138 //  receive_byte -
139 //-------------------------------------------------
receive_byte(uint8_t data)140 void mc6852_device::receive_byte(uint8_t data)
141 {
142 	// Ignore if the receiver is in reset or sync is not enabled
143 	if (m_cr[0] & (C1_RX_RS | C1_CLEAR_SYNC))
144 		return;
145 
146 	// Handle sync detection
147 	if (!m_in_sync)
148 	{
149 		// TODO also handle two sync codes.
150 		if (data == m_scr)
151 		{
152 			m_in_sync = 1;
153 			// TODO handle the various SM responses
154 		}
155 		return;
156 	}
157 
158 	if ((m_cr[0] & C1_STRIP_SYNC) && (data == m_scr))
159 		return;
160 
161 	int size = m_rx_fifo.size();
162 
163 	if (size < 3)
164 	{
165 		m_rx_fifo.push(data);
166 		size++;
167 	}
168 	else
169 	{
170 		// Overrun.
171 		// TODO this should override the last data pushed
172 		m_status |= S_RX_OVRN;
173 	}
174 
175 	int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
176 
177 	if (size >= trigger)
178 	{
179 		m_status |= S_RDA;
180 	}
181 }
182 
183 //-------------------------------------------------
184 //  rcv_complete -
185 //-------------------------------------------------
186 
rcv_complete()187 void mc6852_device::rcv_complete()
188 {
189 	// TODO
190 }
191 
192 //-------------------------------------------------
193 //  read -
194 //-------------------------------------------------
195 
196 // TODO each RX fifo element needs an associated PE status flag, and reading
197 // the status register should return the PE for the last element of the fifo.
198 
199 // TODO RX overrun should be cleared by reading the status register followed
200 // by reading the RX fifo.
201 
read(offs_t offset)202 uint8_t mc6852_device::read(offs_t offset)
203 {
204 	uint8_t data = 0;
205 
206 	if (BIT(offset, 0))
207 	{
208 		int size = m_rx_fifo.size();
209 		if (size > 0)
210 		{
211 			data = m_rx_fifo.front();
212 			if (!machine().side_effects_disabled())
213 			{
214 				m_rx_fifo.pop();
215 				int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
216 				if (size <= trigger)
217 				{
218 					m_status &= ~S_RDA;
219 				}
220 			}
221 		}
222 	}
223 	else
224 	{
225 		data = m_status;
226 
227 		// TS reset inhibits the TDRA status bit (in the
228 		// one-sync-character and two-sync-character modes) The
229 		// m_status S_TDRA bit is allowed to reflect the actual fifo
230 		// availability, masking it here on a read of the status, so
231 		// that the TDRA status bit is simply unmasked here when the
232 		// TX is taken out of reset.
233 		if (m_cr[0] & C1_TX_RS)
234 		{
235 			data &= ~S_TDRA;
236 		}
237 
238 		if (!machine().side_effects_disabled())
239 		{
240 			// TODO this might not be quite right, the datasheet
241 			// states that the RX overrun flag is cleared by
242 			// reading the status, and the RX data fifo?
243 			m_status &= S_RX_OVRN;
244 		}
245 	}
246 
247 	return data;
248 }
249 
250 //-------------------------------------------------
251 //  tx_start -
252 //-------------------------------------------------
253 
254 // The corresponds in time to just before the first bit of the next word is
255 // transmitted by this device. At this time the TX shift register is loaded
256 // the TUF line may be asserted if there is a TX FIFO underflow.
get_tx_byte(int * tuf)257 uint8_t mc6852_device::get_tx_byte(int *tuf)
258 {
259 	if (m_cr[0] & C1_TX_RS)
260 	{
261 		// FIFO is not popped when the TX is reset, but may be loaded
262 		// so that it is pre-loaded when the reset is cleared.  But
263 		// will is send a sync code if that is enabled, of just ones?
264 		*tuf = 0;
265 		return 0xff;
266 	}
267 
268 	int size = m_tx_fifo.size();
269 
270 	if (size == 0)
271 	{
272 		// TX underflow
273 		if (m_cr[1] & C2_TX_SYNC)
274 		{
275 			m_status |= S_TUF;
276 			// TODO should the TUF callback be called, TUF is to
277 			// be pulsed.
278 			*tuf = 1;
279 			return m_scr;
280 		}
281 
282 		*tuf = 0;
283 		return 0xff;
284 	}
285 
286 	uint8_t data = m_tx_fifo.front();
287 	m_tx_fifo.pop();
288 	size--;
289 
290 	int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
291 	int available = 3 - size;
292 
293 	if (available >= trigger)
294 	{
295 		m_status |= S_TDRA;
296 	}
297 
298 	*tuf = 0;
299 	return data;
300 }
301 
302 
303 //-------------------------------------------------
304 //  write -
305 //-------------------------------------------------
306 
write(offs_t offset,uint8_t data)307 void mc6852_device::write(offs_t offset, uint8_t data)
308 {
309 	if (BIT(offset, 0))
310 	{
311 		switch (m_cr[0] & C1_AC_MASK)
312 		{
313 		case C1_AC_C2: {
314 			/* control 2 */
315 			LOG("MC6852 Control 2 %02x\n", data);
316 			m_cr[1] = data;
317 
318 			int data_bit_count = 0;
319 			parity_t parity = PARITY_NONE;
320 			stop_bits_t stop_bits = STOP_BITS_1;
321 
322 			switch (data & C2_WS_MASK)
323 			{
324 			case 0: data_bit_count = 6; parity = PARITY_EVEN; break;
325 			case 1: data_bit_count = 6; parity = PARITY_ODD; break;
326 			case 2: data_bit_count = 7; parity = PARITY_NONE; break;
327 			case 3: data_bit_count = 8; parity = PARITY_NONE; break;
328 			case 4: data_bit_count = 7; parity = PARITY_EVEN; break;
329 			case 5: data_bit_count = 7; parity = PARITY_ODD; break;
330 			case 6: data_bit_count = 8; parity = PARITY_EVEN; break;
331 			case 7: data_bit_count = 8; parity = PARITY_ODD; break;
332 			}
333 
334 			set_data_frame(1, data_bit_count, parity, stop_bits);
335 
336 			// The fifo trigger levels may have changed, so update
337 			// the status bits.
338 
339 			int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
340 
341 			if (m_rx_fifo.size() >= trigger)
342 				m_status |= S_RDA;
343 			else
344 				m_status &= ~S_RDA;
345 
346 			int tx_fifo_available = 3 - m_tx_fifo.size();
347 			if (tx_fifo_available >= trigger)
348 				m_status |= S_TDRA;
349 			else
350 				m_status &= ~S_TDRA;
351 
352 			break;
353 			}
354 
355 		case C1_AC_C3:
356 			/* control 3 */
357 			LOG("MC6852 Control 3 %02x\n", data);
358 			m_cr[2] = data;
359 			if (m_cr[2] & C3_CTUF)
360 			{
361 				m_cr[2] &= ~C3_CTUF;
362 				m_status &= ~S_TUF;
363 			}
364 			if (m_cr[2] & C3_CTS)
365 			{
366 				m_cr[2] &= ~C3_CTS;
367 				m_status &= ~S_CTS;
368 			}
369 			break;
370 
371 		case C1_AC_SYNC:
372 			/* sync code */
373 			LOG("MC6852 Sync Code %02x\n", data);
374 			m_scr = data;
375 			break;
376 
377 		case C1_AC_TX_FIFO: {
378 			/* transmit data FIFO */
379 			int available = 3 - m_tx_fifo.size();
380 			if (available > 0)
381 			{
382 				LOG("MC6852 Transmit FIFO %02x\n", data);
383 				m_tx_fifo.push(data);
384 				available--;
385 			}
386 			else
387 			{
388 				LOG("MC6852 Transmit FIFO OVERFLOW %02x\n", data);
389 			}
390 			int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
391 			if (available < trigger)
392 			{
393 				m_status &= ~S_TDRA;
394 			}
395 			break;
396 			}
397 		}
398 	}
399 	else
400 	{
401 		LOG("MC6852 Control 1 %02x\n", data);
402 
403 		/* receiver reset */
404 		if (data & C1_RX_RS)
405 		{
406 			/* When Rx Rs is set, it clears the receiver
407 			control logic, sync logic, error logic, Rx Data FIFO Control,
408 			Parity Error status bit, and DCD interrupt. The Receiver Shift
409 			Register is set to ones.
410 			*/
411 
412 			LOG("MC6852 Receiver Reset\n");
413 
414 			m_status &= ~(S_RX_OVRN | S_PE | S_DCD | S_RDA);
415 			m_rsr = 0xff;
416 			m_rx_fifo = std::queue<uint8_t>();
417 
418 			receive_register_reset();
419 		}
420 
421 		/* transmitter reset */
422 		if (data & C1_TX_RS)
423 		{
424 			// When Tx Rs is set, it clears the transmitter
425 			// control section, Transmitter Shift Register, Tx
426 			// Data FIFO Control (the Tx Data FIFO can be reloaded
427 			// after one E clock pulse), the Transmitter Underflow
428 			// status bit, and the CTS interrupt.
429 
430 			LOG("MC6852 Transmitter Reset\n");
431 
432 			m_status &= ~(S_TUF | S_CTS);
433 			m_status |= S_TDRA;
434 			m_tx_fifo = std::queue<uint8_t>();
435 
436 			transmit_register_reset();
437 		}
438 
439 		if (data & C1_STRIP_SYNC)
440 			LOG("MC6852 Strip Synchronization Characters\n");
441 
442 		if (data & C1_CLEAR_SYNC)
443 		{
444 			LOG("MC6852 Clear Synchronization\n");
445 			m_in_sync = 0;
446 		}
447 
448 		m_cr[0] = data;
449 	}
450 }
451