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