Previous 199869 Revisions Next

r31312 Friday 18th July, 2014 at 17:27:04 UTC by hap
removed old z80sio device
[src/emu/machine]machine.mak z80sio.c z80sio.h
[src/mame]mame.mak
[src/mess]mess.mak

trunk/src/mame/mame.mak
r31311r31312
550550MACHINES += Z80DART
551551MACHINES += Z80DMA
552552MACHINES += Z80PIO
553MACHINES += Z80SIO
554553MACHINES += Z80STI
555554MACHINES += Z8536
556555MACHINES += SECFLASH
trunk/src/emu/machine/z80sio.c
r31311r31312
1/***************************************************************************
2
3    !!! DEPRECATED DO NOT USE !!!
4
5    WILL BE DELETED WHEN src/mame/drivers/dlair.c USES z80dart.h
6
7    Z80 SIO (Z8440) implementation
8
9    Copyright Nicola Salmoria and the MAME Team.
10    Visit http://mamedev.org for licensing and usage restrictions.
11
12***************************************************************************/
13
14#include "emu.h"
15#include "z80sio.h"
16#include "cpu/z80/z80.h"
17#include "cpu/z80/z80daisy.h"
18
19
20// device type definition
21const device_type Z80SIO = &device_creator<z80sio_device>;
22
23
24//**************************************************************************
25//  DEBUGGING
26//**************************************************************************
27
28#define VERBOSE     0
29
30#define VPRINTF(x) do { if (VERBOSE) logerror x; } while (0)
31
32
33
34//**************************************************************************
35//  CONSTANTS
36//**************************************************************************
37
38// interrupt states
39const int INT_TRANSMIT      = 0x00;     // not confirmed
40const int INT_STATUS        = 0x01;
41const int INT_RECEIVE       = 0x02;
42const int INT_ERROR         = 0x03;
43
44const int INT_CHB_TRANSMIT  = 0 + INT_TRANSMIT;
45const int INT_CHB_STATUS    = 0 + INT_STATUS;
46const int INT_CHB_RECEIVE   = 0 + INT_RECEIVE;
47const int INT_CHB_ERROR     = 0 + INT_ERROR;
48const int INT_CHA_TRANSMIT  = 4 + INT_TRANSMIT;
49const int INT_CHA_STATUS    = 4 + INT_STATUS;
50const int INT_CHA_RECEIVE   = 4 + INT_RECEIVE;
51const int INT_CHA_ERROR     = 4 + INT_ERROR;
52
53// SIO write register 0
54//const int SIO_WR0_RESET_MASK                = 0xc0;     // D7-D6: Reset control
55//const int SIO_WR0_RESET_NULL                =   0x00;   //  00 = NULL code
56//const int SIO_WR0_RESET_RX_CRC              =   0x40;   //  01 = Reset Rx CRC checker
57//const int SIO_WR0_RESET_TX_CRC              =   0x80;   //  10 = Reset Tx CRC generator
58//const int SIO_WR0_RESET_TX_LATCH            =   0xc0;   //  11 = Reset Tx Underrun/EOM latch
59const int SIO_WR0_COMMAND_MASK              = 0x38;     // D5-D3: Command
60//const int SIO_WR0_COMMAND_NULL              =   0x00;   //  000 = NULL code
61//const int SIO_WR0_COMMAND_SET_ABORT         =   0x08;   //  001 = Set abort (SDLC)
62const int SIO_WR0_COMMAND_RES_STATUS_INT    =   0x10;   //  010 = reset ext/status interrupts
63const int SIO_WR0_COMMAND_CH_RESET          =   0x18;   //  011 = Channel reset
64const int SIO_WR0_COMMAND_ENA_RX_INT        =   0x20;   //  100 = Enable int on next Rx character
65const int SIO_WR0_COMMAND_RES_TX_INT        =   0x28;   //  101 = Reset Tx int pending
66const int SIO_WR0_COMMAND_RES_ERROR         =   0x30;   //  110 = Error reset
67//const int SIO_WR0_COMMAND_RETI              =   0x38;   //  111 = Return from int (CH-A only)
68//const int SIO_WR0_REGISTER_MASK             = 0x07;     // D2-D0: Register select (0-7)
69
70// SIO write register 1
71//const int SIO_WR1_READY_WAIT_ENA            = 0x80;     // D7 = READY/WAIT enable
72//const int SIO_WR1_READY_WAIT_FUNCTION       = 0x40;     // D6 = READY/WAIT function
73//const int SIO_WR1_READY_WAIT_ON_RT          = 0x20;     // D5 = READY/WAIT on R/T
74const int SIO_WR1_RXINT_MASK                = 0x18;     // D4-D3 = Rx int control
75//const int SIO_WR1_RXINT_DISABLE             =   0x00;   //  00 = Rx int disable
76const int SIO_WR1_RXINT_FIRST               =   0x08;   //  01 = Rx int on first character
77const int SIO_WR1_RXINT_ALL_PARITY          =   0x10;   //  10 = int on all Rx characters (parity affects vector)
78const int SIO_WR1_RXINT_ALL_NOPARITY        =   0x18;   //  11 = int on all Rx characters (parity ignored)
79//const int SIO_WR1_STATUS_AFFECTS_VECTOR     = 0x04;     // D2 = Status affects vector (CH-B only)
80const int SIO_WR1_TXINT_ENABLE              = 0x02;     // D1 = Tx int enable
81const int SIO_WR1_STATUSINT_ENABLE          = 0x01;     // D0 = Ext int enable
82
83// SIO write register 2 (CH-B only)
84//const int SIO_WR2_INT_VECTOR_MASK           = 0xff;     // D7-D0 = interrupt vector
85
86// SIO write register 3
87//const int SIO_WR3_RX_DATABITS_MASK          = 0xc0;     // D7-D6 = Rx Data bits
88//const int SIO_WR3_RX_DATABITS_5             =   0x00;   //  00 = Rx 5 bits/character
89//const int SIO_WR3_RX_DATABITS_7             =   0x40;   //  01 = Rx 7 bits/character
90//const int SIO_WR3_RX_DATABITS_6             =   0x80;   //  10 = Rx 6 bits/character
91//const int SIO_WR3_RX_DATABITS_8             =   0xc0;   //  11 = Rx 8 bits/character
92//const int SIO_WR3_AUTO_ENABLES              = 0x20;     // D5 = Auto enables
93//const int SIO_WR3_ENTER_HUNT_PHASE          = 0x10;     // D4 = Enter hunt phase
94//const int SIO_WR3_RX_CRC_ENABLE             = 0x08;     // D3 = Rx CRC enable
95//const int SIO_WR3_ADDR_SEARCH_MODE          = 0x04;     // D2 = Address search mode (SDLC)
96//const int SIO_WR3_SYNC_LOAD_INHIBIT         = 0x02;     // D1 = Sync character load inhibit
97const int SIO_WR3_RX_ENABLE                 = 0x01;     // D0 = Rx enable
98
99// SIO write register 4
100//const int SIO_WR4_CLOCK_MODE_MASK           = 0xc0;     // D7-D6 = Clock mode
101//const int SIO_WR4_CLOCK_MODE_x1             =   0x00;   //  00 = x1 clock mode
102//const int SIO_WR4_CLOCK_MODE_x16            =   0x40;   //  01 = x16 clock mode
103//const int SIO_WR4_CLOCK_MODE_x32            =   0x80;   //  10 = x32 clock mode
104//const int SIO_WR4_CLOCK_MODE_x64            =   0xc0;   //  11 = x64 clock mode
105//const int SIO_WR4_SYNC_MODE_MASK            = 0x30;     // D5-D4 = Sync mode
106//const int SIO_WR4_SYNC_MODE_8BIT            =   0x00;   //  00 = 8 bit sync character
107//const int SIO_WR4_SYNC_MODE_16BIT           =   0x10;   //  01 = 16 bit sync character
108//const int SIO_WR4_SYNC_MODE_SDLC            =   0x20;   //  10 = SDLC mode (01111110 flag)
109//const int SIO_WR4_SYNC_MODE_EXTERNAL        =   0x30;   //  11 = External sync mode
110//const int SIO_WR4_STOPBITS_MASK             = 0x0c;     // D3-D2 = Stop bits
111//const int SIO_WR4_STOPBITS_SYNC             =   0x00;   //  00 = Sync modes enable
112//const int SIO_WR4_STOPBITS_1                =   0x04;   //  01 = 1 stop bit/character
113//const int SIO_WR4_STOPBITS_15               =   0x08;   //  10 = 1.5 stop bits/character
114//const int SIO_WR4_STOPBITS_2                =   0x0c;   //  11 = 2 stop bits/character
115//const int SIO_WR4_PARITY_EVEN               = 0x02;     // D1 = Parity even/odd
116//const int SIO_WR4_PARITY_ENABLE             = 0x01;     // D0 = Parity enable
117
118// SIO write register 5
119const int SIO_WR5_DTR                       = 0x80;     // D7 = DTR
120//const int SIO_WR5_TX_DATABITS_MASK          = 0x60;     // D6-D5 = Tx Data bits
121//const int SIO_WR5_TX_DATABITS_5             =   0x00;   //  00 = Tx 5 bits/character
122//const int SIO_WR5_TX_DATABITS_7             =   0x20;   //  01 = Tx 7 bits/character
123//const int SIO_WR5_TX_DATABITS_6             =   0x40;   //  10 = Tx 6 bits/character
124//const int SIO_WR5_TX_DATABITS_8             =   0x60;   //  11 = Tx 8 bits/character
125//const int SIO_WR5_SEND_BREAK                = 0x10;     // D4 = Send break
126const int SIO_WR5_TX_ENABLE                 = 0x08;     // D3 = Tx Enable
127//const int SIO_WR5_CRC16_SDLC                = 0x04;     // D2 = CRC-16/SDLC
128const int SIO_WR5_RTS                       = 0x02;     // D1 = RTS
129//const int SIO_WR5_TX_CRC_ENABLE             = 0x01;     // D0 = Tx CRC enable
130
131// SIO write register 6
132//const int SIO_WR6_SYNC_7_0_MASK             = 0xff;     // D7-D0 = Sync bits 7-0
133
134// SIO write register 7
135//const int SIO_WR7_SYNC_15_8_MASK            = 0xff;     // D7-D0 = Sync bits 15-8
136
137// SIO read register 0
138//const int SIO_RR0_BREAK_ABORT               = 0x80;     // D7 = Break/abort
139//const int SIO_RR0_TX_UNDERRUN               = 0x40;     // D6 = Tx underrun/EOM
140const int SIO_RR0_CTS                       = 0x20;     // D5 = CTS
141//const int SIO_RR0_SYNC_HUNT                 = 0x10;     // D4 = Sync/hunt
142const int SIO_RR0_DCD                       = 0x08;     // D3 = DCD
143const int SIO_RR0_TX_BUFFER_EMPTY           = 0x04;     // D2 = Tx buffer empty
144const int SIO_RR0_INT_PENDING               = 0x02;     // D1 = int pending (CH-A only)
145const int SIO_RR0_RX_CHAR_AVAILABLE         = 0x01;     // D0 = Rx character available
146
147// SIO read register 1
148//const int SIO_RR1_END_OF_FRAME              = 0x80;     // D7 = End of frame (SDLC)
149//const int SIO_RR1_CRC_FRAMING_ERROR         = 0x40;     // D6 = CRC/Framing error
150//const int SIO_RR1_RX_OVERRUN_ERROR          = 0x20;     // D5 = Rx overrun error
151//const int SIO_RR1_PARITY_ERROR              = 0x10;     // D4 = Parity error
152//const int SIO_RR1_IFIELD_BITS_MASK          = 0x0e;     // D3-D1 = I field bits
153                                          //  100 = 0 in prev, 3 in 2nd prev
154                                          //  010 = 0 in prev, 4 in 2nd prev
155                                          //  110 = 0 in prev, 5 in 2nd prev
156                                          //  001 = 0 in prev, 6 in 2nd prev
157                                          //  101 = 0 in prev, 7 in 2nd prev
158                                          //  011 = 0 in prev, 8 in 2nd prev
159                                          //  111 = 1 in prev, 8 in 2nd prev
160                                          //  000 = 2 in prev, 8 in 2nd prev
161//const int SIO_RR1_ALL_SENT                  = 0x01;     // D0 = All sent
162
163// SIO read register 2 (CH-B only)
164//const int SIO_RR2_VECTOR_MASK               = 0xff;     // D7-D0 = Interrupt vector
165
166
167const UINT8 z80sio_device::k_int_priority[] =
168{
169   INT_CHA_RECEIVE,
170   INT_CHA_TRANSMIT,
171   INT_CHA_STATUS,
172   INT_CHA_ERROR,
173   INT_CHB_RECEIVE,
174   INT_CHB_TRANSMIT,
175   INT_CHB_STATUS,
176   INT_CHB_ERROR
177};
178
179
180
181/***************************************************************************
182    FUNCTION PROTOTYPES
183***************************************************************************/
184
185
186/*
187
188    Interrupt priorities:
189        Ch A receive
190        Ch A transmit
191        Ch A external/status
192        Ch B receive
193        Ch B transmit
194        Ch B external/status
195
196
197    Initial configuration (both channels):
198        005D:sio_reg_w(0,4) = 44
199                    01 = x16 clock mode
200                    00 = 8 bit sync character
201                    01 = 1 stop bit/character
202                    Parity odd
203                    Parity disabled
204
205        005D:sio_reg_w(0,3) = C1
206                    11 = Rx 8 bits/character
207                    No auto enables
208                    No enter hunt phase
209                    No Rx CRC enable
210                    No address search mode
211                    No sync character load inhibit
212                    Rx enable
213
214        005D:sio_reg_w(0,5) = 68
215                    DTR = 0
216                    11 = Tx 8 bits/character
217                    No send break
218                    Tx enable
219                    SDLC
220                    No RTS
221                    No CRC enable
222
223        005D:sio_reg_w(0,2) = 40
224                    Vector = 0x40
225
226        005D:sio_reg_w(0,1) = 1D
227                    No READY/WAIT
228                    No READY/WAIT function
229                    No READY/WAIT on R/T
230                    11 = int on all Rx characters (parity ignored)
231                    Status affects vector
232                    No Tx int enable
233                    Ext int enable
234
235*/
236
237
238//**************************************************************************
239//  INLINE FUNCTIONS
240//**************************************************************************
241
242//-------------------------------------------------
243//  update_interrupt_state - update the interrupt
244//  state to the external world
245//-------------------------------------------------
246
247inline void z80sio_device::update_interrupt_state()
248{
249   // if we have a callback, update it with the current state
250   if (!m_irq.isnull())
251      m_irq((z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE);
252}
253
254
255//-------------------------------------------------
256//  set_interrupt - set the given interrupt state
257//  on this channel and update the overall device
258//  state
259//-------------------------------------------------
260
261inline void z80sio_device::sio_channel::set_interrupt(int type)
262{
263   int inum = (this == &m_device->m_channel[0] ? 4 : 0) + type;
264   m_device->m_int_state[inum] = Z80_DAISY_INT;
265   m_device->update_interrupt_state();
266}
267
268
269//-------------------------------------------------
270//  clear_interrupt - clear the given interrupt
271//  state on this channel and update the overall
272//  device state
273//-------------------------------------------------
274
275inline void z80sio_device::sio_channel::clear_interrupt(int type)
276{
277   int inum = (this == &m_device->m_channel[0] ? 4 : 0) + type;
278   m_device->m_int_state[inum] &= ~Z80_DAISY_INT;
279   m_device->update_interrupt_state();
280}
281
282
283//-------------------------------------------------
284//  compute_time_per_character - compute the
285//  serial clocking period
286//-------------------------------------------------
287
288inline attotime z80sio_device::sio_channel::compute_time_per_character()
289{
290   // fix me -- should compute properly and include data, stop, parity bit
291   return attotime::from_hz(9600) * 10;
292}
293
294
295
296//**************************************************************************
297//  LIVE DEVICE
298//**************************************************************************
299
300//-------------------------------------------------
301//  z80sio_device - constructor
302//-------------------------------------------------
303
304z80sio_device::z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
305   : device_t(mconfig, Z80SIO, "Z80 SIO", tag, owner, clock, "z80sio", __FILE__),
306      device_z80daisy_interface(mconfig, *this),
307      m_irq(*this),
308      m_dtr_changed(*this),
309      m_rts_changed(*this),
310      m_break_changed(*this),
311      m_transmit(*this),
312      m_received_poll(*this)
313{
314   for (int i = 0; i < 8; i++)
315      m_int_state[i] = 0;
316}
317
318
319//-------------------------------------------------
320//  device_start - device-specific startup
321//-------------------------------------------------
322
323void z80sio_device::device_start()
324{
325   m_irq.resolve_safe();
326   m_dtr_changed.resolve_safe();
327   m_rts_changed.resolve_safe();
328   m_break_changed.resolve_safe();
329   m_transmit.resolve_safe();
330   m_received_poll.resolve_safe(0);
331
332   m_channel[0].start(this, 0);
333   m_channel[1].start(this, 1);
334}
335
336
337//-------------------------------------------------
338//  device_reset - device-specific reset
339//-------------------------------------------------
340
341void z80sio_device::device_reset()
342{
343   // loop over channels
344   for (int ch = 0; ch < 2; ch++)
345      m_channel[ch].reset();
346}
347
348
349
350//**************************************************************************
351//  DAISY CHAIN INTERFACE
352//**************************************************************************
353
354//-------------------------------------------------
355//  z80daisy_irq_state - return the overall IRQ
356//  state for this device
357//-------------------------------------------------
358
359int z80sio_device::z80daisy_irq_state()
360{
361   int state = 0;
362
363   VPRINTF(("sio IRQ state = B:%d%d%d%d A:%d%d%d%d\n",
364            m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
365            m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
366
367   // loop over all interrupt sources
368   for (int irqsource = 0; irqsource < 8; irqsource++)
369   {
370      int inum = k_int_priority[irqsource];
371
372      // if we're servicing a request, don't indicate more interrupts
373      if (m_int_state[inum] & Z80_DAISY_IEO)
374      {
375         state |= Z80_DAISY_IEO;
376         break;
377      }
378      state |= m_int_state[inum];
379   }
380
381   return state;
382}
383
384
385//-------------------------------------------------
386//  z80daisy_irq_ack - acknowledge an IRQ and
387//  return the appropriate vector
388//-------------------------------------------------
389
390int z80sio_device::z80daisy_irq_ack()
391{
392   // loop over all interrupt sources
393   for (int irqsource = 0; irqsource < 8; irqsource++)
394   {
395      int inum = k_int_priority[irqsource];
396
397      // find the first channel with an interrupt requested
398      if (m_int_state[inum] & Z80_DAISY_INT)
399      {
400         VPRINTF(("sio IRQAck %d\n", inum));
401
402         // clear interrupt, switch to the IEO state, and update the IRQs
403         m_int_state[inum] = Z80_DAISY_IEO;
404         update_interrupt_state();
405         return m_channel[1].m_regs[2] + inum * 2;
406      }
407   }
408
409   logerror("z80sio_irq_ack: failed to find an interrupt to ack!\n");
410   return m_channel[1].m_regs[2];
411}
412
413
414//-------------------------------------------------
415//  z80daisy_irq_reti - clear the interrupt
416//  pending state to allow other interrupts through
417//-------------------------------------------------
418
419void z80sio_device::z80daisy_irq_reti()
420{
421   // loop over all interrupt sources
422   for (int irqsource = 0; irqsource < 8; irqsource++)
423   {
424      int inum = k_int_priority[irqsource];
425
426      // find the first channel with an IEO pending
427      if (m_int_state[inum] & Z80_DAISY_IEO)
428      {
429         VPRINTF(("sio IRQReti %d\n", inum));
430
431         // clear the IEO state and update the IRQs
432         m_int_state[inum] &= ~Z80_DAISY_IEO;
433         update_interrupt_state();
434         return;
435      }
436   }
437
438   logerror("z80sio_irq_reti: failed to find an interrupt to clear IEO on!\n");
439}
440
441
442
443//**************************************************************************
444//  SIO CHANNEL
445//**************************************************************************
446
447//-------------------------------------------------
448//  sio_channel - constructor
449//-------------------------------------------------
450
451z80sio_device::sio_channel::sio_channel()
452   : m_device(NULL),
453      m_index(0),
454      m_inbuf(-1),
455      m_outbuf(-1),
456      m_int_on_next_rx(false),
457      m_receive_timer(NULL),
458      m_receive_inptr(0),
459      m_receive_outptr(0)
460{
461   memset(m_regs, 0, sizeof(m_regs));
462   memset(m_status, 0, sizeof(m_status));
463   memset(m_receive_buffer, 0, sizeof(m_receive_buffer));
464}
465
466
467//-------------------------------------------------
468//  start - channel-specific startup
469//-------------------------------------------------
470
471void z80sio_device::sio_channel::start(z80sio_device *device, int index)
472{
473   m_device = device;
474   m_index = index;
475   m_receive_timer = device->machine().scheduler().timer_alloc(FUNC(static_serial_callback), this);
476}
477
478
479//-------------------------------------------------
480//  reset - reset a single SIO channel
481//-------------------------------------------------
482
483void z80sio_device::sio_channel::reset()
484{
485   m_status[0] = SIO_RR0_TX_BUFFER_EMPTY;
486   m_status[1] = 0x00;
487   m_status[2] = 0x00;
488   m_int_on_next_rx = false;
489   m_outbuf = -1;
490
491   // reset interrupts
492   clear_interrupt(INT_TRANSMIT);
493   clear_interrupt(INT_STATUS);
494   clear_interrupt(INT_RECEIVE);
495   clear_interrupt(INT_ERROR);
496
497   // start the receive timer running
498   attotime tpc = compute_time_per_character();
499   m_receive_timer->adjust(tpc, 0, tpc);
500}
501
502
503//-------------------------------------------------
504//  control_write - write to a control register
505//-------------------------------------------------
506
507void z80sio_device::sio_channel::control_write(UINT8 data)
508{
509   int regnum = m_regs[0] & 7;
510
511   if (regnum != 0 || (regnum & 0xf8) != 0)
512      VPRINTF(("%s:sio_reg_w(%c,%d) = %02X\n", m_device->machine().describe_context(), 'A' + m_index, regnum, data));
513
514   // write a new value to the selected register
515   //UINT8 old = m_regs[regnum];
516   m_regs[regnum] = data;
517
518   // clear the register number for the next write
519   if (regnum != 0)
520      m_regs[0] &= ~7;
521
522   // switch off the register for live state changes
523   switch (regnum)
524   {
525      // SIO write register 0
526      case 0:
527         switch (data & SIO_WR0_COMMAND_MASK)
528         {
529            case SIO_WR0_COMMAND_CH_RESET:
530               VPRINTF(("%s:SIO reset channel %c\n", m_device->machine().describe_context(), 'A' + m_index));
531               reset();
532               break;
533
534            case SIO_WR0_COMMAND_RES_STATUS_INT:
535               clear_interrupt(INT_STATUS);
536               break;
537
538            case SIO_WR0_COMMAND_ENA_RX_INT:
539               m_int_on_next_rx = true;
540               m_device->update_interrupt_state();
541               break;
542
543            case SIO_WR0_COMMAND_RES_TX_INT:
544               clear_interrupt(INT_TRANSMIT);
545               break;
546
547            case SIO_WR0_COMMAND_RES_ERROR:
548               clear_interrupt(INT_ERROR);
549               break;
550         }
551         break;
552
553      // SIO write register 1
554      case 1:
555         m_device->update_interrupt_state();
556         break;
557
558      // SIO write register 5
559      case 5:
560      /*
561         if (((old ^ data) & SIO_WR5_DTR) && !m_device->m_dtr_changed.isnull())
562            m_device->m_dtr_changed(m_index, (data & SIO_WR5_DTR) != 0);
563         if (((old ^ data) & SIO_WR5_SEND_BREAK) && !m_device->m_break_changed.isnull())
564            m_device->m_break_changed(m_index, (data & SIO_WR5_SEND_BREAK) != 0);
565         if (((old ^ data) & SIO_WR5_RTS) && !m_device->m_rts_changed.isnull())
566            m_device->m_rts_changed(m_index, (data & SIO_WR5_RTS) != 0);
567            */
568         break;
569   }
570}
571
572
573//-------------------------------------------------
574//  control_read - read from a control register
575//-------------------------------------------------
576
577UINT8 z80sio_device::sio_channel::control_read()
578{
579   int regnum = m_regs[0] & 7;
580   UINT8 result = m_status[regnum];
581
582   // switch off the register for live state changes
583   switch (regnum)
584   {
585      // SIO read register 0
586      case 0:
587         result &= ~SIO_RR0_INT_PENDING;
588         if (m_device->z80daisy_irq_state() & Z80_DAISY_INT)
589            result |= SIO_RR0_INT_PENDING;
590         break;
591   }
592
593   VPRINTF(("%s:sio_reg_r(%c,%d) = %02x\n", m_device->machine().describe_context(), 'A' + m_index, regnum, m_status[regnum]));
594
595   return result;
596}
597
598
599//-------------------------------------------------
600//  data_write - write to a data register
601//-------------------------------------------------
602
603void z80sio_device::sio_channel::data_write(UINT8 data)
604{
605   VPRINTF(("%s:sio_data_w(%c) = %02X\n", m_device->machine().describe_context(), 'A' + m_index, data));
606
607   // if tx not enabled, just ignore it
608   if (!(m_regs[5] & SIO_WR5_TX_ENABLE))
609      return;
610
611   // update the status register
612   m_status[0] &= ~SIO_RR0_TX_BUFFER_EMPTY;
613
614   // reset the transmit interrupt
615   clear_interrupt(INT_TRANSMIT);
616
617   // stash the character
618   m_outbuf = data;
619}
620
621
622//-------------------------------------------------
623//  data_read - read from a data register
624//-------------------------------------------------
625
626UINT8 z80sio_device::sio_channel::data_read()
627{
628   // update the status register
629   m_status[0] &= ~SIO_RR0_RX_CHAR_AVAILABLE;
630
631   // reset the receive interrupt
632   clear_interrupt(INT_RECEIVE);
633
634   VPRINTF(("%s:sio_data_r(%c) = %02X\n", m_device->machine().describe_context(), 'A' + m_index, m_inbuf));
635
636   return m_inbuf;
637}
638
639
640//-------------------------------------------------
641//  dtr - return the state of the DTR line
642//-------------------------------------------------
643
644int z80sio_device::sio_channel::dtr()
645{
646   return ((m_regs[5] & SIO_WR5_DTR) != 0);
647}
648
649
650//-------------------------------------------------
651//  rts - return the state of the RTS line
652//-------------------------------------------------
653
654int z80sio_device::sio_channel::rts()
655{
656   return ((m_regs[5] & SIO_WR5_RTS) != 0);
657}
658
659
660//-------------------------------------------------
661//  set_cts - set the state of the CTS line
662//-------------------------------------------------
663
664void z80sio_device::sio_channel::set_cts(int state)
665{
666   m_device->machine().scheduler().synchronize(FUNC(static_change_input_line), (SIO_RR0_CTS << 1) + (state != 0), this);
667}
668
669
670//-------------------------------------------------
671//  set_dcd - set the state of the DCD line
672//-------------------------------------------------
673
674void z80sio_device::sio_channel::set_dcd(int state)
675{
676   m_device->machine().scheduler().synchronize(FUNC(static_change_input_line), (SIO_RR0_DCD << 1) + (state != 0), this);
677}
678
679
680//-------------------------------------------------
681//  receive_data - receive data on the input lines
682//-------------------------------------------------
683
684void z80sio_device::sio_channel::receive_data(int data)
685{
686   // put it on the queue
687   int newinptr = (m_receive_inptr + 1) % ARRAY_LENGTH(m_receive_buffer);
688   if (newinptr != m_receive_outptr)
689   {
690      m_receive_buffer[m_receive_inptr] = data;
691      m_receive_inptr = newinptr;
692   }
693   else
694      logerror("z80sio_receive_data: buffer overrun\n");
695}
696
697
698//-------------------------------------------------
699//  change_input_line - generically change the
700//  state of an input line; designed to be called
701//  from a timer callback
702//-------------------------------------------------
703
704void z80sio_device::sio_channel::change_input_line(int line, int state)
705{
706   VPRINTF(("sio_change_input_line(%c, %s) = %d\n", 'A' + m_index, (line == SIO_RR0_CTS) ? "CTS" : "DCD", state));
707
708   // remember the old value
709   UINT8 old = m_status[0];
710
711   // set the bit in the status register
712   m_status[0] &= ~line;
713   if (state)
714      m_status[0] |= line;
715
716   // if state change interrupts are enabled, signal
717   if (((old ^ m_status[0]) & line) && (m_regs[1] & SIO_WR1_STATUSINT_ENABLE))
718      set_interrupt(INT_STATUS);
719}
720
721
722//-------------------------------------------------
723//  serial_callback - callback to pump
724//  data through
725//-------------------------------------------------
726
727void z80sio_device::sio_channel::serial_callback()
728{
729   int data = -1;
730
731   // first perform any outstanding transmits
732   if (m_outbuf != -1)
733   {
734      VPRINTF(("serial_callback(%c): Transmitting %02x\n", 'A' + m_index, m_outbuf));
735
736      // actually transmit the character
737      if (!m_device->m_transmit.isnull())
738         m_device->m_transmit(m_index, m_outbuf, 0xffff);
739
740      // update the status register
741      m_status[0] |= SIO_RR0_TX_BUFFER_EMPTY;
742
743      // set the transmit buffer empty interrupt if enabled
744      if (m_regs[1] & SIO_WR1_TXINT_ENABLE)
745         set_interrupt(INT_TRANSMIT);
746
747      // reset the output buffer
748      m_outbuf = -1;
749   }
750
751   // ask the polling callback if there is data to receive
752   if (!m_device->m_received_poll.isnull())
753      data = INT16(m_device->m_received_poll(m_index, 0xffff));
754
755   // if we have buffered data, pull it
756   if (m_receive_inptr != m_receive_outptr)
757   {
758      data = m_receive_buffer[m_receive_outptr];
759      m_receive_outptr = (m_receive_outptr + 1) % ARRAY_LENGTH(m_receive_buffer);
760   }
761
762   // if we have data, receive it
763   if (data != -1)
764   {
765      VPRINTF(("serial_callback(%c): Receiving %02x\n", 'A' + m_index, data));
766
767      // if rx not enabled, just ignore it
768      if (!(m_regs[3] & SIO_WR3_RX_ENABLE))
769      {
770         VPRINTF(("  (ignored because receive is disabled)\n"));
771         return;
772      }
773
774      // stash the data and update the status
775      m_inbuf = data;
776      m_status[0] |= SIO_RR0_RX_CHAR_AVAILABLE;
777
778      // update our interrupt state
779      switch (m_regs[1] & SIO_WR1_RXINT_MASK)
780      {
781         case SIO_WR1_RXINT_FIRST:
782            if (!m_int_on_next_rx)
783               break;
784
785         case SIO_WR1_RXINT_ALL_NOPARITY:
786         case SIO_WR1_RXINT_ALL_PARITY:
787            set_interrupt(INT_RECEIVE);
788            break;
789      }
790      m_int_on_next_rx = false;
791   }
792}
793
794
795
796//**************************************************************************
797//  GLOBAL STUBS
798//**************************************************************************
799
800READ8_MEMBER( z80sio_device::read )
801{
802   switch (offset & 3)
803   {
804      case 0: return data_read(0);
805      case 1: return data_read(1);
806      case 2: return control_read(0);
807      case 3: return control_read(1);
808   }
809
810   return 0xff;
811}
812
813WRITE8_MEMBER( z80sio_device::write )
814{
815   switch (offset & 3)
816   {
817      case 0: data_write(0, data); break;
818      case 1: data_write(1, data); break;
819      case 2: control_write(0, data); break;
820      case 3: control_write(1, data); break;
821   }
822}
823
824READ8_MEMBER( z80sio_device::read_alt )
825{
826   switch (offset & 3)
827   {
828      case 0: return data_read(0);
829      case 1: return control_read(0);
830      case 2: return data_read(1);
831      case 3: return control_read(1);
832   }
833
834   return 0xff;
835}
836
837WRITE8_MEMBER( z80sio_device::write_alt )
838{
839   switch (offset & 3)
840   {
841      case 0: data_write(0, data); break;
842      case 1: control_write(0, data); break;
843      case 2: data_write(1, data); break;
844      case 3: control_write(1, data); break;
845   }
846}
trunk/src/emu/machine/z80sio.h
r31311r31312
1/***************************************************************************
2
3    !!! DEPRECATED DO NOT USE !!!
4
5    WILL BE DELETED WHEN src/mame/drivers/dlair.c USES z80dart.h
6   
7    Z80 SIO (Z8440) implementation
8
9    Copyright Nicola Salmoria and the MAME Team.
10    Visit http://mamedev.org for licensing and usage restrictions.
11
12***************************************************************************/
13
14#ifndef __Z80SIO_H__
15#define __Z80SIO_H__
16
17#include "cpu/z80/z80daisy.h"
18
19
20//**************************************************************************
21//  DEVICE CONFIGURATION MACROS
22//**************************************************************************
23
24#define MCFG_Z80SIO_INT_CALLBACK(_write) \
25   devcb = &z80sio_device::set_int_callback(*device, DEVCB_##_write);
26
27#define MCFG_Z80SIO_TRANSMIT_CALLBACK(_write) \
28   devcb = &z80sio_device::set_transmit_callback(*device, DEVCB_##_write);
29
30#define MCFG_Z80SIO_RECEIVE_CALLBACK(_read) \
31   devcb = &z80sio_device::set_receive_callback(*device, DEVCB_##_read);
32
33
34
35//**************************************************************************
36//  TYPE DEFINITIONS
37//**************************************************************************
38
39// ======================> z80sio_device
40
41class z80sio_device :   public device_t,
42                  public device_z80daisy_interface
43{
44public:
45   // construction/destruction
46   z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
47
48   template<class _Object> static devcb_base &set_int_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_irq.set_callback(object); }
49   template<class _Object> static devcb_base &set_transmit_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_transmit.set_callback(object); }
50   template<class _Object> static devcb_base &set_receive_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_received_poll.set_callback(object); }
51
52   // control register I/O
53   UINT8 control_read(int ch) { return m_channel[ch].control_read(); }
54   void control_write(int ch, UINT8 data) { m_channel[ch].control_write(data); }
55
56   // data register I/O
57   UINT8 data_read(int ch) { return m_channel[ch].data_read(); }
58   void data_write(int ch, UINT8 data) { m_channel[ch].data_write(data); }
59
60   // communication line I/O
61   int dtr(int ch) { return m_channel[ch].dtr(); }
62   int rts(int ch) { return m_channel[ch].rts(); }
63   void set_cts(int ch, int state) { m_channel[ch].set_cts(state); }
64   void set_dcd(int ch, int state) { m_channel[ch].set_dcd(state); }
65   void receive_data(int ch, int data) { m_channel[ch].receive_data(data); }
66
67   // standard read/write, with C/D in bit 1, B/A in bit 0
68   DECLARE_READ8_MEMBER( read );
69   DECLARE_WRITE8_MEMBER( write );
70
71   // alternate read/write, with C/D in bit 0, B/A in bit 1
72   DECLARE_READ8_MEMBER( read_alt );
73   DECLARE_WRITE8_MEMBER( write_alt );
74
75private:
76   // device-level overrides
77   virtual void device_start();
78   virtual void device_reset();
79
80   // device_z80daisy_interface overrides
81   virtual int z80daisy_irq_state();
82   virtual int z80daisy_irq_ack();
83   virtual void z80daisy_irq_reti();
84
85   // internal helpers
86   void update_interrupt_state();
87
88   // a single SIO channel
89   class sio_channel
90   {
91   public:
92      sio_channel();
93
94      void start(z80sio_device *device, int index);
95      void reset();
96
97      UINT8 control_read();
98      UINT8 data_read();
99      void control_write(UINT8 data);
100      void data_write(UINT8 data);
101
102      int dtr();
103      int rts();
104      void set_cts(int state);
105      void set_dcd(int state);
106      void receive_data(int data);
107
108   private:
109      void set_interrupt(int type);
110      void clear_interrupt(int type);
111      attotime compute_time_per_character();
112
113      static TIMER_CALLBACK( static_change_input_line ) { reinterpret_cast<sio_channel *>(ptr)->change_input_line(param >> 1, param & 1); }
114      void change_input_line(int line, int state);
115
116      static TIMER_CALLBACK( static_serial_callback ) { reinterpret_cast<sio_channel *>(ptr)->serial_callback(); }
117      void serial_callback();
118
119   public:
120      UINT8       m_regs[8];              // 8 writeable registers
121
122   private:
123      z80sio_device *m_device;            // pointer back to our device
124      int         m_index;                // our channel index
125      UINT8       m_status[4];            // 3 readable registers
126      int         m_inbuf;                // input buffer
127      int         m_outbuf;               // output buffer
128      bool        m_int_on_next_rx;       // interrupt on next rx?
129      emu_timer * m_receive_timer;        // timer to clock data in
130      UINT8       m_receive_buffer[16];   // buffer for incoming data
131      UINT8       m_receive_inptr;        // index of data coming in
132      UINT8       m_receive_outptr;       // index of data going out
133   };
134
135   // internal state
136   sio_channel                 m_channel[2];           // 2 channels
137   UINT8                       m_int_state[8];         // interrupt states
138
139   // callbacks
140   devcb_write_line m_irq;
141   devcb_write8 m_dtr_changed;
142   devcb_write8 m_rts_changed;
143   devcb_write8 m_break_changed;
144   devcb_write16 m_transmit;
145   devcb_read16 m_received_poll;
146
147   static const UINT8 k_int_priority[];
148};
149
150
151// device type definition
152extern const ATTR_DEPRECATED device_type Z80SIO;
153
154
155#endif
trunk/src/emu/machine/machine.mak
r31311r31312
17171717
17181718#-------------------------------------------------
17191719#
1720#@src/emu/machine/z80sio.h,MACHINES += Z80SIO
1721#-------------------------------------------------
1722
1723ifneq ($(filter Z80SIO,$(MACHINES)),)
1724MACHINEOBJS += $(MACHINEOBJ)/z80sio.o
1725endif
1726
1727#-------------------------------------------------
1728#
17291720#@src/emu/machine/z80sti.h,MACHINES += Z80STI
17301721#-------------------------------------------------
17311722
trunk/src/mess/mess.mak
r31311r31312
541541MACHINES += Z80DART
542542MACHINES += Z80DMA
543543MACHINES += Z80PIO
544MACHINES += Z80SIO
545544MACHINES += Z80STI
546545MACHINES += Z8536
547546#MACHINES += SECFLASH

Previous 199869 Revisions Next


© 1997-2024 The MAME Team