Previous 199869 Revisions Next

r20113 Monday 7th January, 2013 at 04:44:44 UTC by R. Belmont
n68681: preliminary working diserial-based I/O [R. Belmont]
[src/emu/machine]n68681.c n68681.h
[src/mess]mess.mak
[src/mess/drivers]esq5505.c
[src/mess/machine]esqpanel.c* esqpanel.h*

trunk/src/emu/machine/n68681.c
r20112r20113
2323   "MRA", "CSRA", "CRA", "THRA", "ACR", "IMR", "CRUR", "CTLR", "MRB", "CSRB", "CRB", "THRB", "IVR", "OPCR", "Set OP Bits", "Reset OP Bits"
2424};
2525
26static const int baud_rate_ACR_0[] = { 50, 110, 134, 200, 300, 600, 1200, 1050, 2400, 4800, 7200, 9600, 38400, 0, 0, 0 };
27static const int baud_rate_ACR_1[] = { 75, 110, 134, 150, 300, 600, 1200, 2000, 2400, 4800, 1800, 9600, 19200, 0, 0, 0 };
28
2629#define INT_INPUT_PORT_CHANGE      0x80
2730#define INT_DELTA_BREAK_B         0x40
2831#define INT_RXRDY_FFULLB         0x20
r20112r20113
4346
4447#define MODE_RX_INT_SELECT_BIT      0x40
4548
49#define CHANA_TAG   "cha"
50#define CHANB_TAG   "chb"
51
4652// device type definition
4753const device_type DUARTN68681 = &device_creator<duartn68681_device>;
54const device_type DUART68681CHANNEL = &device_creator<duart68681_channel>;
4855
56MACHINE_CONFIG_FRAGMENT( duart68681 )
57   MCFG_DUART68681_CHANNEL_ADD(CHANA_TAG)
58   MCFG_DUART68681_CHANNEL_ADD(CHANB_TAG)
59MACHINE_CONFIG_END
60
4961//**************************************************************************
5062//  LIVE DEVICE
5163//**************************************************************************
5264
5365duartn68681_device::duartn68681_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
5466   : device_t(mconfig, DUARTN68681, "DUART 68681 (new)", tag, owner, clock),
55   device_serial_interface(mconfig, *this)
67   m_chanA(*this, CHANA_TAG),
68   m_chanB(*this, CHANB_TAG)
5669{
5770}
5871
r20112r20113
6881   m_in_port_func.resolve(m_in_port_cb, *this);
6982   m_out_port_func.resolve(m_out_port_cb, *this);
7083
71   channel[0].tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(duartn68681_device::tx_timer_callback),this), NULL);
72   channel[1].tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(duartn68681_device::tx_timer_callback),this), NULL);
7384   duart_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(duartn68681_device::duart_timer_callback),this), NULL);
7485
7586   save_item(NAME(ACR));
r20112r20113
8091   save_item(NAME(CTR));
8192   save_item(NAME(IP_last_state));
8293   save_item(NAME(half_period));
83
84   save_item(NAME(channel[0].CR));
85   save_item(NAME(channel[0].CSR));
86   save_item(NAME(channel[0].MR1));
87   save_item(NAME(channel[0].MR2));
88   save_item(NAME(channel[0].MR_ptr));
89   save_item(NAME(channel[0].SR));
90   save_item(NAME(channel[0].baud_rate));
91   save_item(NAME(channel[0].rx_enabled));
92   save_item(NAME(channel[0].rx_fifo));
93   save_item(NAME(channel[0].rx_fifo_read_ptr));
94   save_item(NAME(channel[0].rx_fifo_write_ptr));
95   save_item(NAME(channel[0].rx_fifo_num));
96   save_item(NAME(channel[0].tx_enabled));
97   save_item(NAME(channel[0].tx_data));
98   save_item(NAME(channel[0].tx_ready));
99
100   save_item(NAME(channel[1].CR));
101   save_item(NAME(channel[1].CSR));
102   save_item(NAME(channel[1].MR1));
103   save_item(NAME(channel[1].MR2));
104   save_item(NAME(channel[1].MR_ptr));
105   save_item(NAME(channel[1].SR));
106   save_item(NAME(channel[1].baud_rate));
107   save_item(NAME(channel[1].rx_enabled));
108   save_item(NAME(channel[1].rx_fifo));
109   save_item(NAME(channel[1].rx_fifo_read_ptr));
110   save_item(NAME(channel[1].rx_fifo_write_ptr));
111   save_item(NAME(channel[1].rx_fifo_num));
112   save_item(NAME(channel[1].tx_enabled));
113   save_item(NAME(channel[1].tx_data));
114   save_item(NAME(channel[1].tx_ready));
11594}
11695
11796/*-------------------------------------------------
r20112r20113
12099
121100void duartn68681_device::device_reset()
122101{
123   emu_timer *save0, *save1;
124
125102   ACR = 0;  /* Interrupt Vector Register */
126103   IVR = 0x0f;  /* Interrupt Vector Register */
127104   IMR = 0;  /* Interrupt Mask Register */
r20112r20113
131108   CTR.d = 0;  /* Counter/Timer Preset Value */
132109   IP_last_state = 0;  /* last state of IP bits */
133110   // "reset clears internal registers (SRA, SRB, IMR, ISR, OPR, OPCR) puts OP0-7 in the high state, stops the counter/timer, and puts channels a/b in the inactive state"
134   save0 = channel[0].tx_timer;
135   save1 = channel[1].tx_timer;
136   memset(channel, 0, sizeof(channel));
137   channel[0].tx_timer = save0;
138   channel[1].tx_timer = save1;
139111
140112   m_out_port_func(0, OPR ^ 0xff);
141
142   // reset timers
143   channel[0].tx_timer->adjust(attotime::never);
144   channel[1].tx_timer->adjust(attotime::never, 1);
145113}
146114
147115//-------------------------------------------------
r20112r20113
171139   }
172140}
173141
142machine_config_constructor duartn68681_device::device_mconfig_additions() const
143{
144   return MACHINE_CONFIG_NAME( duart68681 );
145}
146
174147void duartn68681_device::update_interrupts()
175148{
176149   /* update SR state and update interrupt ISR state for the following bits:
r20112r20113
188161    ISR: bit 1: RxRDYA/FFULLA: this is handled here; depending on whether MSR1A bit 6 is 0 or 1, this bit holds the state of SRA bit 0 or bit 1 respectively
189162    ISR: bit 0: TxRDYA: this is handled here; it mirrors SRA bit 2
190163    */
191   UINT8 ch = 0;
192   //logerror("DEBUG: 68681 int check: upon func call, SRA is %02X, SRB is %02X, ISR is %02X\n", duart68681->channel[0].SR, duart68681->channel[1].SR, duart68681->ISR);
193   for (ch = 0; ch < 2; ch++)
194   {
195      //if ( duart68681->channel[ch].rx_enabled )
196      //{
197         if ( channel[ch].rx_fifo_num > 0 )
198         {
199            channel[ch].SR |= STATUS_RECEIVER_READY;
200         }
201         else
202         {
203            channel[ch].SR &= ~STATUS_RECEIVER_READY;
204         }
205         if ( channel[ch].rx_fifo_num == MC68681_RX_FIFO_SIZE )
206         {
207            channel[ch].SR |= STATUS_FIFO_FULL;
208         }
209         else
210         {
211            channel[ch].SR &= ~STATUS_FIFO_FULL;
212         }
213      //}
214      //else
215      //{
216      //duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY;
217      //duart68681->channel[ch].SR &= ~STATUS_FIFO_FULL;
218      //}
219      // Handle the TxEMT and TxRDY bits based on mode
220      switch( channel[ch].MR2&0xC0) // what mode are we in?
221         {
222         case 0x00: // normal mode
223            if ( channel[ch].tx_enabled )
224            {
225               channel[ch].SR |= STATUS_TRANSMITTER_EMPTY;
226            }
227            else
228            {
229               channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
230            }
231         break;
232         case 0x40: // automatic echo mode
233            channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
234            channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
235         break;
236         case 0x80: // local loopback mode
237            if ( channel[ch].tx_enabled )
238            {
239               channel[ch].SR |= STATUS_TRANSMITTER_EMPTY;
240            }
241            else
242            {
243               channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
244            }
245         break;
246         case 0xC0: // remote loopback mode
247            // write me, what the txrdy/txemt regs do for remote loopback mode is undocumented afaik, for now just clear both
248            channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
249            channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
250         break;
251         }
252      // now handle the ISR bits
253      if ( channel[ch].SR & STATUS_TRANSMITTER_READY )
254      {
255         if (ch == 0)
256            ISR |= INT_TXRDYA;
257         else
258            ISR |= INT_TXRDYB;
259      }
260      else
261      {
262         if (ch == 0)
263            ISR &= ~INT_TXRDYA;
264         else
265            ISR &= ~INT_TXRDYB;
266      }
267      //logerror("DEBUG: 68681 int check: before receiver test, SR%c is %02X, ISR is %02X\n", (ch+0x41), duart68681->channel[ch].SR, duart68681->ISR);
268      if ( channel[ch].MR1 & MODE_RX_INT_SELECT_BIT )
269      {
270         if ( channel[ch].SR & STATUS_FIFO_FULL )
271         {
272            ISR |= ((ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
273         }
274         else
275         {
276            ISR &= ((ch == 0) ? ~INT_RXRDY_FFULLA : ~INT_RXRDY_FFULLB);
277         }
278      }
279      else
280      {
281         if ( channel[ch].SR & STATUS_RECEIVER_READY )
282         {
283            ISR |= ((ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
284         }
285         else
286         {
287            ISR &= ((ch == 0) ? ~INT_RXRDY_FFULLA : ~INT_RXRDY_FFULLB);
288         }
289      }
290      //logerror("DEBUG: 68681 int check: after receiver test, SR%c is %02X, ISR is %02X\n", (ch+0x41), duart68681->channel[ch].SR, duart68681->ISR);
291   }
292164   if ( (ISR & IMR) != 0 )
293165   {
294166      LOG(( "68681: Interrupt line active (IMR & ISR = %02X)\n", (ISR & IMR) ));
r20112r20113
383255
384256};
385257
386void duartn68681_device::duart68681_write_MR(int ch, UINT8 data)
387{
388   if ( channel[ch].MR_ptr == 0 )
389   {
390      channel[ch].MR1 = data;
391      channel[ch].MR_ptr = 1;
392   }
393   else
394   {
395      channel[ch].MR2 = data;
396   }
397   update_interrupts();
398};
399
400void duartn68681_device::duart68681_write_CSR(int ch, UINT8 data, UINT8 inACR)
401{
402   static const int baud_rate_ACR_0[] = { 50, 110, 134, 200, 300, 600, 1200, 1050, 2400, 4800, 7200, 9600, 38400, 0, 0, 0 };
403   static const int baud_rate_ACR_1[] = { 75, 110, 134, 150, 300, 600, 1200, 2000, 2400, 4800, 1800, 9600, 19200, 0, 0, 0 };
404
405   channel[ch].CSR = data;
406
407   if ( BIT(inACR,7) == 0 )
408   {
409      channel[ch].baud_rate = baud_rate_ACR_0[data & 0x0f];
410
411      if (ch == 0)
412      {
413         if ((data & 0xf) == 0xe)
414         {
415            channel[ch].baud_rate = ip3clk/16;
416         }
417         else if ((data & 0xf) == 0xf)
418         {
419            channel[ch].baud_rate = ip3clk;
420         }
421      }
422      else if (ch == 1)
423      {
424         if ((data & 0xf) == 0xe)
425         {
426            channel[ch].baud_rate = ip5clk/16;
427         }
428         else if ((data & 0xf) == 0xf)
429         {
430            channel[ch].baud_rate = ip5clk;
431         }
432      }
433   }
434   else
435   {
436      channel[ch].baud_rate = baud_rate_ACR_1[data & 0x0f];
437   }
438   if ( channel[ch].baud_rate == 0 )
439   {
440      LOG(( "Unsupported transmitter clock: channel %d, clock select = %02x\n", ch, data ));
441   }
442};
443
444void duartn68681_device::duart68681_write_CR(int ch, UINT8 data)
445{
446   channel[ch].CR = data;
447
448   switch( (data >> 4) & 0x07 )
449   {
450      case 0: /* No command */
451         break;
452      case 1: /* Reset MR pointer. Causes the Channel A MR pointer to point to MR1 */
453         channel[ch].MR_ptr = 0;
454         break;
455      case 2: /* Reset channel A receiver (disable receiver and flush fifo) */
456         channel[ch].rx_enabled = 0;
457         channel[ch].SR &= ~STATUS_RECEIVER_READY;
458         channel[ch].SR &= ~STATUS_OVERRUN_ERROR; // is this correct?
459         channel[ch].rx_fifo_read_ptr = 0;
460         channel[ch].rx_fifo_write_ptr = 0;
461         channel[ch].rx_fifo_num = 0;
462         break;
463      case 3: /* Reset channel A transmitter */
464         channel[ch].tx_enabled = 0;
465         channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
466         if (ch == 0)
467            ISR &= ~INT_TXRDYA;
468         else
469            ISR &= ~INT_TXRDYB;
470         channel[ch].tx_timer->adjust(attotime::never, ch);
471            break;
472      case 4: /* Reset Error Status */
473         channel[ch].SR &= ~(STATUS_RECEIVED_BREAK | STATUS_FRAMING_ERROR | STATUS_PARITY_ERROR | STATUS_OVERRUN_ERROR);
474         break;
475      case 5: /* Reset Channel break change interrupt */
476         if ( ch == 0 )
477         {
478            ISR &= ~INT_DELTA_BREAK_A;
479         }
480         else
481         {
482            ISR &= ~INT_DELTA_BREAK_B;
483         }
484         break;
485      /* TODO: case 6 and case 7 are start break and stop break respectively, which start or stop holding the TxDA or TxDB line low (space) after whatever data is in the buffer finishes transmitting (following the stop bit?), or after two bit-times if no data is being transmitted  */
486      default:
487         LOG(( "68681: Unhandled command (%x) in CR%d\n", (data >> 4) & 0x07, ch ));
488         break;
489   }
490
491   if (BIT(data, 0)) {
492      channel[ch].rx_enabled = 1;
493   }
494   if (BIT(data, 1)) {
495      channel[ch].rx_enabled = 0;
496      channel[ch].SR &= ~STATUS_RECEIVER_READY;
497   }
498
499   if (BIT(data, 2)) {
500      channel[ch].tx_enabled = 1;
501      channel[ch].tx_ready = 1;
502      channel[ch].SR |= STATUS_TRANSMITTER_READY;
503      if (ch == 0)
504         ISR |= INT_TXRDYA;
505      else
506         ISR |= INT_TXRDYB;
507   }
508   if (BIT(data, 3)) {
509      channel[ch].tx_enabled = 0;
510      channel[ch].tx_ready = 0;
511      channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
512      if (ch == 0)
513         ISR &= ~INT_TXRDYA;
514      else
515         ISR &= ~INT_TXRDYB;
516   }
517
518    update_interrupts();
519};
520
521UINT8 duartn68681_device::duart68681_read_rx_fifo(int ch)
522{
523   UINT8 r;
524
525   if ( channel[ch].rx_fifo_num == 0 )
526   {
527      LOG(( "68681: rx fifo underflow\n" ));
528      return 0x0;
529   }
530
531   r = channel[ch].rx_fifo[channel[ch].rx_fifo_read_ptr++];
532   if ( channel[ch].rx_fifo_read_ptr == MC68681_RX_FIFO_SIZE )
533   {
534      channel[ch].rx_fifo_read_ptr = 0;
535   }
536
537   channel[ch].rx_fifo_num--;
538   update_interrupts();
539
540   return r;
541};
542
543TIMER_CALLBACK_MEMBER( duartn68681_device::tx_timer_callback )
544{
545   int ch = param & 1;
546
547   // send the byte unless we're in loopback mode;
548   // in loopback mode do NOT 'actually' send the byte: the TXn pin is held high when loopback mode is on.
549   if ((channel[ch].MR2&0xC0) != 0x80)
550   {
551      if (ch == 0)
552      {
553         m_out_a_tx_func(0, channel[0].tx_data);
554      }
555      else if (ch == 1)
556      {
557         m_out_b_tx_func(0, channel[1].tx_data);
558      }
559   }
560
561   // if local loopback is on, write the transmitted data as if a byte had been received
562   if ((channel[ch].MR2 & 0xC0) == 0x80)
563   {
564      if (channel[ch].rx_fifo_num >= MC68681_RX_FIFO_SIZE)
565      {
566         LOG(( "68681: FIFO overflow\n" ));
567         channel[ch].SR |= STATUS_OVERRUN_ERROR;
568      }
569      else
570      {
571         channel[ch].rx_fifo[channel[ch].rx_fifo_write_ptr++]
572               = channel[ch].tx_data;
573         if (channel[ch].rx_fifo_write_ptr == MC68681_RX_FIFO_SIZE)
574         {
575            channel[ch].rx_fifo_write_ptr = 0;
576         }
577         channel[ch].rx_fifo_num++;
578      }
579   }
580
581   channel[ch].tx_ready = 1;
582   channel[ch].SR |= STATUS_TRANSMITTER_READY;
583
584   if (ch == 0)
585      ISR |= INT_TXRDYA;
586   else
587      ISR |= INT_TXRDYB;
588
589   update_interrupts();
590   channel[ch].tx_timer->adjust(attotime::never, ch);
591};
592
593void duartn68681_device::duart68681_write_TX(int ch, UINT8 data)
594{
595   attotime period;
596
597   channel[ch].tx_data = data;
598
599   channel[ch].tx_ready = 0;
600   channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
601
602   if (ch == 0)
603      ISR &= ~INT_TXRDYA;
604   else
605      ISR &= ~INT_TXRDYB;
606
607   update_interrupts();
608
609   period = attotime::from_hz(channel[ch].baud_rate / 10 );
610   channel[ch].tx_timer->adjust(period, ch);
611};
612
613258READ8_MEMBER( duartn68681_device::read )
614259{
615260   UINT8 r = 0xff;
r20112r20113
621266   switch (offset)
622267   {
623268      case 0x00: /* MR1A/MR2A */
624         if ( channel[0].MR_ptr == 0 )
625         {
626            r = channel[0].MR1;
627            channel[0].MR_ptr = 1;
628         }
629         else
630         {
631            r = channel[0].MR2;
632         }
633         break;
634
635269      case 0x01: /* SRA */
636         r = channel[0].SR;
637         break;
638
639270      case 0x03: /* Rx Holding Register A */
640         r = duart68681_read_rx_fifo(0);
271         r = m_chanA->read_chan_reg(offset & 3);
641272         break;
642273
643274      case 0x04: /* IPCR */
r20112r20113
664295         break;
665296
666297      case 0x08: /* MR1B/MR2B */
667         if ( channel[1].MR_ptr == 0 )
668         {
669            r = channel[1].MR1;
670            channel[1].MR_ptr = 1;
671         }
672         else
673         {
674            r = channel[1].MR2;
675         }
676         break;
677
678298      case 0x09: /* SRB */
679         r = channel[1].SR;
680         break;
681
682299      case 0x0b: /* RHRB */
683         r = duart68681_read_rx_fifo(1);
300         r = m_chanB->read_chan_reg(offset & 3);
684301         break;
685302
686303      case 0x0d: /* IP */
r20112r20113
727344   switch(offset)
728345   {
729346      case 0x00: /* MRA */
730         duart68681_write_MR(0, data);
731         break;
732
733347      case 0x01: /* CSRA */
734         duart68681_write_CSR(0, data, ACR);
735         break;
736
737348      case 0x02: /* CRA */
738         duart68681_write_CR(0, data);
739         break;
740
741349      case 0x03: /* THRA */
742         duart68681_write_TX(0, data);
350         m_chanA->write_chan_reg(offset&3, data);
743351         break;
744352
745353      case 0x04: /* ACR */
r20112r20113
767375            }
768376         }
769377
770         duart68681_write_CSR(0, channel[0].CSR, data);
771         duart68681_write_CSR(1, channel[1].CSR, data);
772         update_interrupts(); // need to add ACR checking for IP delta ints
378         m_chanA->write_chan_reg(1, data);
379         m_chanB->write_chan_reg(1, data);
380         m_chanA->update_interrupts(); // need to add ACR checking for IP delta ints
381         m_chanB->update_interrupts();
382         update_interrupts();
773383         break;
774384      }
775385      case 0x05: /* IMR */
r20112r20113
786396         break;
787397
788398      case 0x08: /* MRB */
789         duart68681_write_MR(1, data);
790         break;
791
792399      case 0x09: /* CSRB */
793         duart68681_write_CSR(1, data, ACR);
794         break;
795
796400      case 0x0a: /* CRB */
797         duart68681_write_CR(1, data);
798         break;
799
800401      case 0x0b: /* THRB */
801         duart68681_write_TX(1, data);
402         m_chanB->write_chan_reg(offset&3, data);
802403         break;
803404
804405      case 0x0c: /* IVR */
r20112r20113
823424   }
824425}
825426
826void duartn68681_device::duart68681_rx_data(int ch, UINT8 data)
427duart68681_channel *duartn68681_device::get_channel(int chan)
827428{
828   if ( channel[ch].rx_enabled )
429   if (chan == 0)
829430   {
830      if ( channel[ch].rx_fifo_num >= MC68681_RX_FIFO_SIZE )
431      return m_chanA;
432   }
433
434   return m_chanB;
435}
436
437int duartn68681_device::calc_baud(int ch, UINT8 data)
438{
439   int baud_rate = 0;
440
441   if ( BIT(ACR, 7) == 0 )
442   {
443      baud_rate = baud_rate_ACR_0[data & 0x0f];
444
445      if (ch == 0)
831446      {
832         LOG(( "68681: FIFO overflow\n" ));
833         channel[ch].SR |= STATUS_OVERRUN_ERROR;
834         return;
447         if ((data & 0xf) == 0xe)
448         {
449            baud_rate = ip3clk/16;
450         }
451         else if ((data & 0xf) == 0xf)
452         {
453            baud_rate = ip3clk;
454         }
835455      }
836      channel[ch].rx_fifo[channel[ch].rx_fifo_write_ptr++] = data;
837      if ( channel[ch].rx_fifo_write_ptr == MC68681_RX_FIFO_SIZE )
456      else if (ch == 1)
838457      {
839         channel[ch].rx_fifo_write_ptr = 0;
458         if ((data & 0xf) == 0xe)
459         {
460            baud_rate = ip5clk/16;
461         }
462         else if ((data & 0xf) == 0xf)
463         {
464            baud_rate = ip5clk;
465         }
840466      }
841      channel[ch].rx_fifo_num++;
842      update_interrupts();
843467   }
468   else
469   {
470      baud_rate = baud_rate_ACR_1[data & 0x0f];
471   }
472
473   if ( baud_rate == 0 )
474   {
475      LOG(( "Unsupported transmitter clock: channel %d, clock select = %02x\n", ch, data ));
476   }
477
478   return baud_rate;
844479};
845480
481void duartn68681_device::clear_ISR_bits(int mask)
482{
483   ISR &= ~mask;
484}
485
486void duartn68681_device::set_ISR_bits(int mask)
487{
488   ISR |= mask;
489}
490
491// DUART channel class stuff
492
493duart68681_channel::duart68681_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
494   : device_t(mconfig, DUART68681CHANNEL, "DUART 68681 channel", tag, owner, clock),
495   device_serial_interface(mconfig, *this)
496{
497}
498
499void duart68681_channel::device_start()
500{
501   m_uart = downcast<duartn68681_device *>(owner());
502   m_ch = m_uart->get_ch(this);   // get our channel number
503
504   save_item(NAME(CR));
505   save_item(NAME(CSR));
506   save_item(NAME(MR1));
507   save_item(NAME(MR2));
508   save_item(NAME(MR_ptr));
509   save_item(NAME(SR));
510   save_item(NAME(rx_baud_rate));
511   save_item(NAME(tx_baud_rate));
512   save_item(NAME(rx_enabled));
513   save_item(NAME(rx_fifo));
514   save_item(NAME(rx_fifo_read_ptr));
515   save_item(NAME(rx_fifo_write_ptr));
516   save_item(NAME(rx_fifo_num));
517   save_item(NAME(tx_enabled));
518   save_item(NAME(tx_data));
519   save_item(NAME(tx_ready));
520}
521
522void duart68681_channel::device_reset()
523{
524   write_CR(0x10);   // reset MR
525   write_CR(0x20);   // reset Rx
526   write_CR(0x30); // reset Tx
527   write_CR(0x40); // reset errors
528
529   tx_baud_rate = rx_baud_rate = 0;
530}
531
846532// serial device virtual overrides
847void duartn68681_device::rcv_complete()
533void duart68681_channel::rcv_complete()
848534{
535   receive_register_extract();
536
537//   printf("ch %d rcv complete\n", m_ch);
538
539   if ( rx_enabled )
540   {
541      if ( rx_fifo_num >= MC68681_RX_FIFO_SIZE )
542      {
543         LOG(( "68681: FIFO overflow\n" ));
544         SR |= STATUS_OVERRUN_ERROR;
545         return;
546      }
547      rx_fifo[rx_fifo_write_ptr++] = get_received_char();
548      if ( rx_fifo_write_ptr == MC68681_RX_FIFO_SIZE )
549      {
550         rx_fifo_write_ptr = 0;
551      }
552      rx_fifo_num++;
553      update_interrupts();
554   }
849555}
850556
851void duartn68681_device::tra_complete()
557void duart68681_channel::tra_complete()
852558{
559//   printf("ch %d Tx complete\n", m_ch);
560   tx_ready = 1;
561   SR |= STATUS_TRANSMITTER_READY;
562
563   if (m_ch == 0)
564      m_uart->clear_ISR_bits(INT_TXRDYA);
565   else
566      m_uart->clear_ISR_bits(INT_TXRDYB);
567
568   update_interrupts();
853569}
854570
855void duartn68681_device::tra_callback()
571void duart68681_channel::tra_callback()
856572{
573   int bit = transmit_register_get_data_bit();
574//   printf("ch %d transmit %d\n", m_ch, bit);
575   if (m_ch == 0)
576   {
577      m_uart->m_out_a_tx_func(bit);
578   }
579   else
580   {
581      m_uart->m_out_b_tx_func(bit);
582   }   
857583}
858584
859void duartn68681_device::input_callback(UINT8 state)
585void duart68681_channel::input_callback(UINT8 state)
860586{
861587}
862588
589void duart68681_channel::update_interrupts()
590{
591   if ( rx_fifo_num > 0 )
592   {
593      SR |= STATUS_RECEIVER_READY;
594   }
595   else
596   {
597      SR &= ~STATUS_RECEIVER_READY;
598   }
599   if ( rx_fifo_num == MC68681_RX_FIFO_SIZE )
600   {
601      SR |= STATUS_FIFO_FULL;
602   }
603   else
604   {
605      SR &= ~STATUS_FIFO_FULL;
606   }
607
608   // Handle the TxEMT and TxRDY bits based on mode
609   switch(MR2&0xC0) // what mode are we in?
610      {
611      case 0x00: // normal mode
612         if ( tx_enabled )
613         {
614            SR |= STATUS_TRANSMITTER_EMPTY;
615         }
616         else
617         {
618            SR &= ~STATUS_TRANSMITTER_EMPTY;
619         }
620      break;
621      case 0x40: // automatic echo mode
622         SR &= ~STATUS_TRANSMITTER_EMPTY;
623         SR &= ~STATUS_TRANSMITTER_READY;
624      break;
625      case 0x80: // local loopback mode
626         if ( tx_enabled )
627         {
628            SR |= STATUS_TRANSMITTER_EMPTY;
629         }
630         else
631         {
632            SR &= ~STATUS_TRANSMITTER_EMPTY;
633         }
634      break;
635      case 0xC0: // remote loopback mode
636         // write me, what the txrdy/txemt regs do for remote loopback mode is undocumented afaik, for now just clear both
637         SR &= ~STATUS_TRANSMITTER_EMPTY;
638         SR &= ~STATUS_TRANSMITTER_READY;
639      break;
640      }
641   // now handle the ISR bits
642   if ( SR & STATUS_TRANSMITTER_READY )
643   {
644      if (m_ch == 0)
645         m_uart->set_ISR_bits(INT_TXRDYA);
646      else
647         m_uart->set_ISR_bits(INT_TXRDYB);
648   }
649   else
650   {
651      if (m_ch == 0)
652         m_uart->clear_ISR_bits(INT_TXRDYA);
653      else
654         m_uart->clear_ISR_bits(INT_TXRDYB);
655   }
656   //logerror("DEBUG: 68681 int check: before receiver test, SR%c is %02X, ISR is %02X\n", (ch+0x41), duart68681->channel[ch].SR, duart68681->ISR);
657   if ( MR1 & MODE_RX_INT_SELECT_BIT )
658   {
659      if ( SR & STATUS_FIFO_FULL )
660      {
661         m_uart->set_ISR_bits((m_ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
662      }
663      else
664      {
665         m_uart->clear_ISR_bits((m_ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
666      }
667   }
668   else
669   {
670      if ( SR & STATUS_RECEIVER_READY )
671      {
672         m_uart->set_ISR_bits((m_ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
673      }
674      else
675      {
676         m_uart->clear_ISR_bits((m_ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
677      }
678   }
679
680   m_uart->update_interrupts();
681
682   //logerror("DEBUG: 68681 int check: after receiver test, SR%c is %02X, ISR is %02X\n", (ch+0x41), duart68681->channel[ch].SR, duart68681->ISR);
683}
684
685UINT8 duart68681_channel::read_rx_fifo()
686{
687   UINT8 rv = 0;
688
689//   printf("read_rx_fifo: rx_fifo_num %d\n", rx_fifo_num);
690
691   if ( rx_fifo_num == 0 )
692   {
693      LOG(( "68681 channel: rx fifo underflow\n" ));
694      return 0x0;
695   }
696
697   rv = rx_fifo[rx_fifo_read_ptr++];
698   if ( rx_fifo_read_ptr == MC68681_RX_FIFO_SIZE )
699   {
700      rx_fifo_read_ptr = 0;
701   }
702
703   rx_fifo_num--;
704   update_interrupts();
705
706   return rv;
707};
708
709UINT8 duart68681_channel::read_chan_reg(int reg)
710{
711   UINT8 rv = 0xff;
712
713   switch (reg)
714   {
715      case 0:   // MR1/MR2
716         if ( MR_ptr == 0 )
717         {
718            rv = MR1;
719            MR_ptr = 1;
720         }
721         else
722         {
723            rv = MR2;
724         }
725         break;
726
727      case 1: // SRA
728         rv = SR;
729         break;
730
731      case 2: // CSRA: reading this is prohibited
732         break;
733
734      case 3:   // Rx holding register A
735         rv = read_rx_fifo();
736         break;
737   }
738
739   return rv;
740}
741
742void duart68681_channel::write_chan_reg(int reg, UINT8 data)
743{
744   switch (reg)
745   {
746   case 0x00: /* MRA */
747      write_MR(data);
748      break;
749
750   case 0x01: /* CSR */
751      CSR = data;
752      tx_baud_rate = m_uart->calc_baud(m_ch, data & 0xf);
753      rx_baud_rate = m_uart->calc_baud(m_ch, (data>>4) & 0xf);
754//      printf("ch %d Tx baud %d Rx baud %d\n", m_ch, tx_baud_rate, rx_baud_rate);
755      set_rcv_rate(rx_baud_rate);
756      set_tra_rate(tx_baud_rate);
757      break;
758
759   case 0x02: /* CR */
760      write_CR(data);
761      break;
762
763   case 0x03: /* THR */
764      write_TX(data);
765      break;
766   }
767}
768
769void duart68681_channel::write_MR(UINT8 data)
770{
771   if ( MR_ptr == 0 )
772   {
773      MR1 = data;
774      MR_ptr = 1;
775   }
776   else
777   {
778      MR2 = data;
779   }
780   recalc_framing();
781   update_interrupts();
782};
783
784void duart68681_channel::recalc_framing()
785{
786   int parity, stopbits;
787
788   switch ((MR2 >> 2) & 3)
789   {
790      case 0:
791      case 1:
792         stopbits = 1;
793         break;
794
795      case 2:   // "1.5 async, 2 sync"
796         stopbits = 2;
797         break;
798
799      case 3:
800         stopbits = 2;
801         break;
802   }
803
804   switch ((MR1>>3) & 3)
805   {
806      case 0:   // with parity
807         if (MR1 & 4)
808         {
809            parity = SERIAL_PARITY_ODD;
810         }
811         else
812         {
813            parity = SERIAL_PARITY_EVEN;
814         }
815         break;
816
817      case 1:   // force parity
818         if (MR1 & 4)
819         {
820            parity = SERIAL_PARITY_MARK;
821         }
822         else
823         {
824            parity = SERIAL_PARITY_SPACE;
825         }
826         break;
827
828      case 2:   // no parity
829         parity = SERIAL_PARITY_NONE;
830         break;
831
832      case 3:   // multidrop mode
833         fatalerror("68681: multidrop parity not supported\n");
834         break;
835   }
836
837//   printf("ch %d MR1 %02x MR2 %02x => %d bits / char, %d stop bits, parity %d\n", m_ch, MR1, MR2, (MR1 & 3)+5, stopbits, parity);
838
839   set_data_frame((MR1 & 3)+5, stopbits, parity);
840}
841
842void duart68681_channel::write_CR(UINT8 data)
843{
844   CR = data;
845
846   switch( (data >> 4) & 0x07 )
847   {
848      case 0: /* No command */
849         break;
850      case 1: /* Reset MR pointer. Causes the channel MR pointer to point to MR1 */
851         MR_ptr = 0;
852         break;
853      case 2: /* Reset channel receiver (disable receiver and flush fifo) */
854         rx_enabled = 0;
855         SR &= ~STATUS_RECEIVER_READY;
856         SR &= ~STATUS_OVERRUN_ERROR; // is this correct?
857         rx_fifo_read_ptr = 0;
858         rx_fifo_write_ptr = 0;
859         rx_fifo_num = 0;
860         receive_register_reset();
861         break;
862      case 3: /* Reset channel transmitter */
863         tx_enabled = 0;
864         SR &= ~STATUS_TRANSMITTER_READY;
865         if (m_ch == 0)
866            m_uart->clear_ISR_bits(INT_TXRDYA);
867         else
868            m_uart->clear_ISR_bits(INT_TXRDYB);
869         transmit_register_reset();
870            break;
871      case 4: /* Reset Error Status */
872         SR &= ~(STATUS_RECEIVED_BREAK | STATUS_FRAMING_ERROR | STATUS_PARITY_ERROR | STATUS_OVERRUN_ERROR);
873         break;
874      case 5: /* Reset Channel break change interrupt */
875         if ( m_ch == 0 )
876         {
877            m_uart->clear_ISR_bits(INT_DELTA_BREAK_A);
878         }
879         else
880         {
881            m_uart->clear_ISR_bits(INT_DELTA_BREAK_B);
882         }
883         break;
884      /* TODO: case 6 and case 7 are start break and stop break respectively, which start or stop holding the TxDA or TxDB line low (space) after whatever data is in the buffer finishes transmitting (following the stop bit?), or after two bit-times if no data is being transmitted  */
885      default:
886         LOG(( "68681: Unhandled command (%x) in CR%d\n", (data >> 4) & 0x07, m_ch ));
887         break;
888   }
889
890   if (BIT(data, 0)) {
891      rx_enabled = 1;
892   }
893   if (BIT(data, 1)) {
894      rx_enabled = 0;
895      SR &= ~STATUS_RECEIVER_READY;
896   }
897
898   if (BIT(data, 2)) {
899      tx_enabled = 1;
900      tx_ready = 1;
901      SR |= STATUS_TRANSMITTER_READY;
902      if (m_ch == 0)
903         m_uart->set_ISR_bits(INT_TXRDYA);
904      else
905         m_uart->set_ISR_bits(INT_TXRDYB);
906   }
907   if (BIT(data, 3)) {
908      tx_enabled = 0;
909      tx_ready = 0;
910      SR &= ~STATUS_TRANSMITTER_READY;
911      if (m_ch == 0)
912         m_uart->clear_ISR_bits(INT_TXRDYA);
913      else
914         m_uart->clear_ISR_bits(INT_TXRDYB);
915   }
916
917    update_interrupts();
918};
919
920void duart68681_channel::write_TX(UINT8 data)
921{
922   tx_data = data;
923
924/*   if (!tx_ready)
925   {
926       printf("Write %02x to TX when TX not ready!\n", data);
927   }*/
928
929//   printf("ch %d Tx %02x\n", m_ch, data);
930
931   // send the byte unless we're in loopback mode;
932   // in loopback mode do NOT 'actually' send the byte: the TXn pin is held high when loopback mode is on.
933   if ((MR2&0xC0) != 0x80)
934   {
935      tx_ready = 0;
936      SR &= ~STATUS_TRANSMITTER_READY;
937
938      if (m_ch == 0)
939         m_uart->clear_ISR_bits(INT_TXRDYA);
940      else
941         m_uart->clear_ISR_bits(INT_TXRDYB);
942
943      // send tx_data
944      transmit_register_setup(tx_data);
945   }
946   // if local loopback is on, write the transmitted data as if a byte had been received
947   else if ((MR2 & 0xC0) == 0x80)
948   {
949      if (rx_fifo_num >= MC68681_RX_FIFO_SIZE)
950      {
951         LOG(( "68681: FIFO overflow\n" ));
952         SR |= STATUS_OVERRUN_ERROR;
953      }
954      else
955      {
956         rx_fifo[rx_fifo_write_ptr++]= tx_data;
957         if (rx_fifo_write_ptr == MC68681_RX_FIFO_SIZE)
958         {
959            rx_fifo_write_ptr = 0;
960         }
961         rx_fifo_num++;
962      }
963
964      tx_ready = 1;
965      SR |= STATUS_TRANSMITTER_READY;
966      if (m_ch == 0)
967         m_uart->set_ISR_bits(INT_TXRDYA);
968      else
969         m_uart->set_ISR_bits(INT_TXRDYB);
970   }
971
972   update_interrupts();
973};
974
trunk/src/emu/machine/n68681.h
r20112r20113
33
44#include "diserial.h"
55
6#define MCFG_DUARTN68681_ADD(_tag, _clock, _config) \
7   MCFG_DEVICE_ADD(_tag, DUARTN68681, _clock) \
8   MCFG_DEVICE_CONFIG(_config)
9
10#define MCFG_DUARTN68681_REPLACE(_tag, _clock, _config) \
11   MCFG_DEVICE_REPLACE(_tag, DUARTN68681, _clock) \
12   MCFG_DEVICE_CONFIG(_config)
13
14#define MCFG_DUART68681_CHANNEL_ADD(_tag) \
15   MCFG_DEVICE_ADD(_tag, DUART68681CHANNEL, 0) \
16
617// forward declaration
718class duartn68681_device;
819
920struct duartn68681_config
1021{
1122   devcb_write_line   m_out_irq_cb;
12   devcb_write8      m_out_a_tx_cb;
13   devcb_write8      m_out_b_tx_cb;
23   devcb_write_line   m_out_a_tx_cb;
24   devcb_write_line   m_out_b_tx_cb;
1425   devcb_read8         m_in_port_cb;
1526   devcb_write8      m_out_port_cb;
1627
r20112r20113
2031
2132#define MC68681_RX_FIFO_SIZE            3
2233
23struct DUART68681_CHANNEL
34// forward declaration
35class duartn68681_device;
36
37// n68681 channel class
38class duart68681_channel : public device_t, public device_serial_interface
2439{
40public:
41   duart68681_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
42
43   // device-level overrides
44   virtual void device_start();
45   virtual void device_reset();
46
47   // device_serial overrides
48   virtual void rcv_complete();   // Rx completed receiving byte
49   virtual void tra_complete();   // Tx completed sending byte
50   virtual void tra_callback();   // Tx send bit
51   void input_callback(UINT8 state);
52
53   UINT8 read_chan_reg(int reg);
54   void write_chan_reg(int reg, UINT8 data);
55   void update_interrupts();
56
57   UINT8 read_rx_fifo();
58
59private:
2560   /* Registers */
2661   UINT8 CR;  /* Command register */
2762   UINT8 CSR; /* Clock select register */
r20112r20113
3166   UINT8 SR;  /* Status register */
3267
3368   /* State */
34   int  baud_rate;
69   int tx_baud_rate, rx_baud_rate;
3570
3671   /* Receiver */
3772   UINT8 rx_enabled;
r20112r20113
4075   int   rx_fifo_write_ptr;
4176   int   rx_fifo_num;
4277
78   int   m_ch;
79
4380   /* Transmitter */
4481   UINT8 tx_enabled;
4582   UINT8 tx_data;
4683   UINT8 tx_ready;
47   emu_timer *tx_timer;
84
85   duartn68681_device *m_uart;
86
87   void write_MR(UINT8 data);
88   void write_CR(UINT8 data);
89   void write_TX(UINT8 data);
90   void recalc_framing();
4891};
4992
50class duartn68681_device : public device_t, public device_serial_interface, public duartn68681_config
93class duartn68681_device : public device_t, public duartn68681_config
5194{
95   friend class duart68681_channel;
96
5297public:
5398   duartn68681_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
5499
100   required_device<duart68681_channel> m_chanA;
101   required_device<duart68681_channel> m_chanB;
102
103   // API
55104   DECLARE_READ8_HANDLER(read);
56105   DECLARE_WRITE8_HANDLER(write);
106   UINT8 get_irq_vector() { return IVR; }
57107
58   void duart68681_rx_data(int ch, UINT8 data);
108   DECLARE_WRITE_LINE_MEMBER( rx_a_w ) { m_chanA->check_for_start((UINT8)state); }
109   DECLARE_WRITE_LINE_MEMBER( rx_b_w ) { m_chanB->check_for_start((UINT8)state); }
59110
60   TIMER_CALLBACK_MEMBER( tx_timer_callback );
61   TIMER_CALLBACK_MEMBER( duart_timer_callback );
62
63   UINT8 get_irq_vector() { return IVR; }
64
65111protected:
66112   // device-level overrides
67113   virtual void device_config_complete();
68114   virtual void device_start();
69115   virtual void device_reset();
116    virtual machine_config_constructor device_mconfig_additions() const;
70117
71   // device_serial overrides
72   virtual void rcv_complete();   // Rx complete
73   virtual void tra_complete();   // Tx complete
74   virtual void tra_callback();   // Tx bit ready
75   void input_callback(UINT8 state);
118private:
119   TIMER_CALLBACK_MEMBER( duart_timer_callback );
76120
77private:
78121   /* registers */
79122   UINT8 ACR;  /* Auxiliary Control Register */
80123   UINT8 IMR;  /* Interrupt Mask Register */
r20112r20113
91134   UINT8 half_period;
92135   emu_timer *duart_timer;
93136
94   /* UART channels */
95   DUART68681_CHANNEL channel[2];
96
97   void update_interrupts();
98137   double duart68681_get_ct_rate();
99138   UINT16 duart68681_get_ct_count();
100139   void duart68681_start_ct(int count);
101   void duart68681_write_MR(int ch, UINT8 data);
102   void duart68681_write_CSR(int ch, UINT8 data, UINT8 ACR);
103   void duart68681_write_CR(int ch, UINT8 data);
104   UINT8 duart68681_read_rx_fifo(int ch);
105   void duart68681_write_TX(int ch, UINT8 data);
140   int calc_baud(int ch, UINT8 data);
141   int get_ch(duart68681_channel *ch) { return (ch == m_chanA) ? 0 : 1; }
142   void clear_ISR_bits(int mask);
143   void set_ISR_bits(int mask);
144   void update_interrupts();
106145
146   duart68681_channel *get_channel(int chan);
147
107148   devcb_resolved_write_line   m_out_irq_func;
108    devcb_resolved_write8      m_out_a_tx_func;
109    devcb_resolved_write8      m_out_b_tx_func;
149    devcb_resolved_write_line   m_out_a_tx_func;
150    devcb_resolved_write_line   m_out_b_tx_func;
110151   devcb_resolved_read8      m_in_port_func;
111152    devcb_resolved_write8      m_out_port_func;
112
113153};
114154
115#define MCFG_DUARTN68681_ADD(_tag, _clock, _config) \
116   MCFG_DEVICE_ADD(_tag, DUARTN68681, _clock) \
117   MCFG_DEVICE_CONFIG(_config)
118
119155extern const device_type DUARTN68681;
156extern const device_type DUART68681CHANNEL;
120157
121158#endif //_N68681_H
122159
trunk/src/mess/drivers/esq5505.c
r20112r20113
108108#include "formats/esq16_dsk.h"
109109
110110#include "machine/esqvfd.h"
111#include "machine/esqpanel.h"
111112
112113#define GENERIC (0)
113114#define EPS     (1)
114115#define SQ1     (2)
115116
116117#define KEYBOARD_HACK (1)   // turn on to play the SQ-1, SD-1, and SD-1 32-voice: Z and X are program up/down, A/S/D/F/G/H/J/K/L and Q/W/E/R/T/Y/U play notes
117#define HACK_VIA_MIDI   (1)
118#define HACK_VIA_MIDI   (0)   // won't work right now
118119
119120#if KEYBOARD_HACK
120121#if HACK_VIA_MIDI
r20112r20113
132133        m_maincpu(*this, "maincpu"),
133134        m_duart(*this, "duart"),
134135        m_fdc(*this, "wd1772"),
135        m_epsvfd(*this, "epsvfd"),
136        m_sq1vfd(*this, "sq1vfd"),
137        m_vfd(*this, "vfd"),
136        m_epspanel(*this, "epspanel"),
137        m_sq1panel(*this, "sq1panel"),
138        m_panel(*this, "panel"),
138139        m_dmac(*this, "mc68450")
139140    { }
140141
141142    required_device<m68000_device> m_maincpu;
142143    required_device<duartn68681_device> m_duart;
143144    optional_device<wd1772_t> m_fdc;
144    optional_device<esq1x22_t> m_epsvfd;
145    optional_device<esq2x40_sq1_t> m_sq1vfd;
146    optional_device<esq2x40_t> m_vfd;
145    optional_device<esqpanel1x22_device> m_epspanel;
146    optional_device<esqpanel2x40_sq1_device> m_sq1panel;
147    optional_device<esqpanel2x40_device> m_panel;
147148    optional_device<hd63450_device> m_dmac;
148149
149150    virtual void machine_reset();
r20112r20113
156157    DECLARE_WRITE16_MEMBER(lower_w);
157158
158159   DECLARE_WRITE_LINE_MEMBER(duart_irq_handler);
159   DECLARE_WRITE8_MEMBER(duart_tx_a);
160   DECLARE_WRITE8_MEMBER(duart_tx_b);
160   DECLARE_WRITE_LINE_MEMBER(duart_tx_a);
161   DECLARE_WRITE_LINE_MEMBER(duart_tx_b);
161162   DECLARE_READ8_MEMBER(duart_input);
162163   DECLARE_WRITE8_MEMBER(duart_output);
163164
164165    int m_system_type;
165166    UINT8 m_duart_io;
166    bool  m_bCalibSecondByte;
167167
168168   DECLARE_FLOPPY_FORMATS( floppy_formats );
169169
r20112r20113
179179
180180   UINT16   *m_rom, *m_ram;
181181
182#if KEYBOARD_HACK
183   void send_through_panel(UINT8 data);
184#endif
185
182186public:
183187   DECLARE_DRIVER_INIT(eps);
184188   DECLARE_DRIVER_INIT(common);
r20112r20113
199203{
200204   m_rom = (UINT16 *)machine().root_device().memregion("osrom")->base();
201205   m_ram = (UINT16 *)machine().root_device().memshare("osram")->ptr();
202
203   m_bCalibSecondByte = false;
204206}
205207
206208READ16_MEMBER(esq5505_state::es5510_dsp_r)
r20112r20113
522524}
523525
524526// MIDI send, we don't care yet
525WRITE8_MEMBER(esq5505_state::duart_tx_a)
527WRITE_LINE_MEMBER(esq5505_state::duart_tx_a)
526528{
527529}
528530
529WRITE8_MEMBER(esq5505_state::duart_tx_b)
531WRITE_LINE_MEMBER(esq5505_state::duart_tx_b)
530532{
531/*   if (data >= 'A' && data <= 'z')
532   {
533      printf("ch 1: [%02x](%c) (PC=%x)\n", data, data, m_maincpu->pc());
534   }
535   else
536   {
537      printf("ch 1: [%02x] (PC=%x)\n", data, m_maincpu->pc());
538   }*/
539
533//   printf("Tx B: %d\n", state);
540534   switch (m_system_type)
541535   {
542536      case GENERIC:
543         m_vfd->write_char(data);
537         m_panel->rx_w(state);
544538         break;
545539
546540      case EPS:
547         m_epsvfd->write_char(data);
541         m_epspanel->rx_w(state);
548542         break;
549543
550544      case SQ1:
551         m_sq1vfd->write_char(data);
545         m_sq1panel->rx_w(state);
552546         break;
553547   }
554548
549#if 0
555550   if (m_bCalibSecondByte)
556551   {
557552      if (data == 0xfd)   // calibration request
r20112r20113
584579         }
585580      }
586581   }
582#endif
587583}
588584
589585static const duartn68681_config duart_config =
590586{
591587   DEVCB_DRIVER_LINE_MEMBER(esq5505_state, duart_irq_handler),
592   DEVCB_DRIVER_MEMBER(esq5505_state, duart_tx_a),
593   DEVCB_DRIVER_MEMBER(esq5505_state, duart_tx_b),
588   DEVCB_DRIVER_LINE_MEMBER(esq5505_state, duart_tx_a),
589   DEVCB_DRIVER_LINE_MEMBER(esq5505_state, duart_tx_b),
594590   DEVCB_DRIVER_MEMBER(esq5505_state, duart_input),
595591   DEVCB_DRIVER_MEMBER(esq5505_state, duart_output),
596592
r20112r20113
631627}
632628
633629#if KEYBOARD_HACK
630void esq5505_state::send_through_panel(UINT8 data)
631{
632   switch (m_system_type)
633   {
634      case GENERIC:
635         m_panel->xmit_char(data);
636         break;
637
638      case EPS:
639         m_epspanel->xmit_char(data);
640         break;
641
642      case SQ1:
643         m_sq1panel->xmit_char(data);
644         break;
645   }
646}
647
634648INPUT_CHANGED_MEMBER(esq5505_state::key_stroke)
635649{
636650    #if HACK_VIA_MIDI
r20112r20113
704718      if (oldval == 0 && newval == 1)
705719      {
706720         printf("key pressed %d\n", val&0x7f);
707         m_duart->duart68681_rx_data(1, val);
708         m_duart->duart68681_rx_data(1, 0x00);
721         send_through_panel(val);
722         send_through_panel(0x00);
709723      }
710724      else if (oldval == 1 && newval == 0)
711725      {
712726   //        printf("key off %x\n", (UINT8)(FPTR)param);
713         m_duart->duart68681_rx_data(1, val&0x7f);
714         m_duart->duart68681_rx_data(1, 0x00);
727         send_through_panel(val&0x7f);
728         send_through_panel(0x00);
715729      }
716730   }
717731    #endif
r20112r20113
737751    esq5505_read_adc
738752};
739753
754static const esqpanel_interface esqpanel_config =
755{
756   DEVCB_DEVICE_LINE_MEMBER("duart", duartn68681_device, rx_b_w)
757};
758
740759static MACHINE_CONFIG_START( vfx, esq5505_state )
741760   MCFG_CPU_ADD("maincpu", M68000, XTAL_10MHz)
742761   MCFG_CPU_PROGRAM_MAP(vfx_map)
743762
744    MCFG_ESQ2x40_ADD("vfd")
763    MCFG_ESQPANEL2x40_ADD("panel", esqpanel_config)
745764
746765   MCFG_DUARTN68681_ADD("duart", 4000000, duart_config)
747766
r20112r20113
756775   MCFG_CPU_MODIFY( "maincpu" )
757776   MCFG_CPU_PROGRAM_MAP(eps_map)
758777
759    MCFG_ESQ2x40_REMOVE("vfd")
760    MCFG_ESQ1x22_ADD("epsvfd")
778   MCFG_ESQPANEL_2x40_REMOVE("panel")
779    MCFG_ESQPANEL1x22_ADD("epspanel", esqpanel_config)
761780
762781    MCFG_WD1772x_ADD("wd1772", 8000000)
763782   MCFG_FLOPPY_DRIVE_ADD("wd1772:0", ensoniq_floppies, "35dd", 0, esq5505_state::floppy_formats)
r20112r20113
778797   MCFG_CPU_ADD("maincpu", M68000, XTAL_30_4761MHz / 2)
779798   MCFG_CPU_PROGRAM_MAP(vfxsd_map)
780799
781    MCFG_ESQ2x40_ADD("vfd")
800    MCFG_ESQPANEL2x40_ADD("panel", esqpanel_config)
782801
783802   MCFG_DUARTN68681_ADD("duart", 4000000, duart_config)
784803
r20112r20113
796815   MCFG_CPU_MODIFY( "maincpu" )
797816   MCFG_CPU_PROGRAM_MAP(sq1_map)
798817
799   MCFG_ESQ2x40_REMOVE("vfd")
800    MCFG_ESQ2x40_SQ1_ADD("sq1vfd")
818   MCFG_ESQPANEL_2x40_REMOVE("panel")
819    MCFG_ESQPANEL2x40_SQ1_ADD("sq1panel", esqpanel_config)
801820MACHINE_CONFIG_END
802821
803822static INPUT_PORTS_START( vfx )
trunk/src/mess/mess.mak
r20112r20113
11191119   $(MESS_DRIVERS)/esqkt.o     \
11201120   $(MESS_DRIVERS)/esqmr.o     \
11211121    $(MESS_MACHINE)/esqvfd.o    \
1122   $(MESS_MACHINE)/esqpanel.o   \
11221123
11231124$(MESSOBJ)/entex.a:            \
11241125   $(MESS_VIDEO)/advision.o   \
trunk/src/mess/machine/esqpanel.c
r0r20113
1/*
2   Ensoniq panel/display device
3*/
4#include "emu.h"
5#include "esqpanel.h"
6
7//**************************************************************************
8//  MACROS / CONSTANTS
9//**************************************************************************
10
11//**************************************************************************
12//  DEVICE DEFINITIONS
13//**************************************************************************
14
15const device_type ESQPANEL1x22 = &device_creator<esqpanel1x22_device>;
16const device_type ESQPANEL2x40 = &device_creator<esqpanel2x40_device>;
17const device_type ESQPANEL2x40_SQ1 = &device_creator<esqpanel2x40_sq1_device>;
18
19//**************************************************************************
20//  LIVE DEVICE
21//**************************************************************************
22
23//-------------------------------------------------
24//  esqpanel_device - constructor
25//-------------------------------------------------
26
27esqpanel_device::esqpanel_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
28   device_t(mconfig, type, name, tag, owner, clock),
29   device_serial_interface(mconfig, *this)
30{
31}
32
33void esqpanel_device::device_config_complete()
34{
35    m_shortname = "esqpanel";
36
37   // inherit a copy of the static data
38   const esqpanel_interface *intf = reinterpret_cast<const esqpanel_interface *>(static_config());
39   if (intf != NULL)
40   {
41      *static_cast<esqpanel_interface *>(this) = *intf;
42   }
43   // or initialize to defaults if none provided
44   else
45   {
46      memset(&m_out_tx_cb, 0, sizeof(m_out_tx_cb));
47   }
48}
49
50//-------------------------------------------------
51//  device_start - device-specific startup
52//-------------------------------------------------
53
54void esqpanel_device::device_start()
55{
56    m_out_tx_func.resolve(m_out_tx_cb, *this);
57}
58
59
60//-------------------------------------------------
61//  device_reset - device-specific reset
62//-------------------------------------------------
63
64void esqpanel_device::device_reset()
65{
66   // panel comms is at 62500 baud (double the MIDI rate), 8N2
67   set_rcv_rate(62500);
68   set_tra_rate(62500);
69   set_data_frame(8, 2, SERIAL_PARITY_NONE);
70
71   m_tx_busy = false;
72   m_xmit_read = m_xmit_write = 0;
73   m_bCalibSecondByte = false;
74}
75
76void esqpanel_device::rcv_complete()   // Rx completed receiving byte
77{   
78   receive_register_extract();
79   UINT8 data = get_received_char();
80
81//   if (data >= 0xe0) printf("Got %02x from motherboard (second %s)\n", data, m_bCalibSecondByte ? "yes" : "no");
82
83   send_to_display(data);
84
85   if (m_bCalibSecondByte)
86   {
87//      printf("second byte is %02x\n", data);
88      if (data == 0xfd)   // calibration request
89      {
90//         printf("let's send reply!\n");
91         xmit_char(0xff);   // this is the correct response for "calibration OK"
92      }
93      m_bCalibSecondByte = false;
94   }
95   else if (data == 0xfb)   // request calibration
96   {         
97      m_bCalibSecondByte = true;
98   }
99   else
100   {
101      // EPS wants a throwaway reply byte for each byte sent to the KPC
102      // VFX-SD and SD-1 definitely don't :)
103      if (m_eps_mode)
104      {
105         if (data == 0xe7)
106         {
107            xmit_char(0x00);   // actual value of response is never checked
108         }
109         else if (data == 0x71)
110         {
111            xmit_char(0x00);   // actual value of response is never checked
112         }
113         else
114         {
115            xmit_char(data);   // actual value of response is never checked
116         }
117      }
118   }
119}
120
121void esqpanel_device::tra_complete()   // Tx completed sending byte
122{
123//   printf("panel Tx complete\n");
124   // is there more waiting to send?
125   if (m_xmit_read != m_xmit_write)
126   {
127      transmit_register_setup(m_xmitring[m_xmit_read++]);
128      if (m_xmit_read >= XMIT_RING_SIZE)
129      {
130         m_xmit_read = 0;
131      }
132   }
133   else
134   {
135      m_tx_busy = false;
136   }
137}
138
139void esqpanel_device::tra_callback()   // Tx send bit
140{
141   int bit = transmit_register_get_data_bit();
142   m_out_tx_func(bit);
143}
144
145void esqpanel_device::input_callback(UINT8 state)
146{
147}
148
149void esqpanel_device::xmit_char(UINT8 data)
150{
151//   printf("Panel: xmit %02x\n", data);
152
153   // if tx is busy it'll pick this up automatically when it completes
154   if (!m_tx_busy)
155   {
156      m_tx_busy = true;
157      transmit_register_setup(data);
158   }
159   else
160   {
161      // tx is busy, it'll pick this up next time
162      m_xmitring[m_xmit_write++] = data;
163      if (m_xmit_write >= XMIT_RING_SIZE)
164      {
165         m_xmit_write = 0;
166      }
167   }
168}
169
170/* panel with 1x22 VFD display used in the EPS-16 and EPS-16 Plus */
171
172static MACHINE_CONFIG_FRAGMENT(esqpanel1x22)
173   MCFG_ESQ1x22_ADD("vfd")
174MACHINE_CONFIG_END
175
176machine_config_constructor esqpanel1x22_device::device_mconfig_additions() const
177{
178    return MACHINE_CONFIG_NAME( esqpanel1x22 );
179}
180
181esqpanel1x22_device::esqpanel1x22_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
182   esqpanel_device(mconfig, ESQPANEL1x22, "Ensoniq front panel with 1x22 VFD", tag, owner, clock),
183   m_vfd(*this, "vfd")
184{
185   m_eps_mode = true;
186}
187
188/* panel with 2x40 VFD display used in the ESQ-1, VFX-SD, SD-1, and others */
189
190static MACHINE_CONFIG_FRAGMENT(esqpanel2x40)
191   MCFG_ESQ2x40_ADD("vfd")
192MACHINE_CONFIG_END
193
194machine_config_constructor esqpanel2x40_device::device_mconfig_additions() const
195{
196    return MACHINE_CONFIG_NAME( esqpanel2x40 );
197}
198
199esqpanel2x40_device::esqpanel2x40_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
200   esqpanel_device(mconfig, ESQPANEL2x40, "Ensoniq front panel with 2x40 VFD", tag, owner, clock),
201   m_vfd(*this, "vfd")
202{
203   m_eps_mode = false;
204}
205
206/* panel with 2x16? LCD display used in the SQ and MR series, plus probably more */
207
208static MACHINE_CONFIG_FRAGMENT(esqpanel2x40_sq1)
209   MCFG_ESQ2x40_SQ1_ADD("vfd")
210MACHINE_CONFIG_END
211
212machine_config_constructor esqpanel2x40_sq1_device::device_mconfig_additions() const
213{
214    return MACHINE_CONFIG_NAME( esqpanel2x40_sq1 );
215}
216
217esqpanel2x40_sq1_device::esqpanel2x40_sq1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
218   esqpanel_device(mconfig, ESQPANEL2x40, "Ensoniq front panel with 2x16 LCD", tag, owner, clock),
219   m_vfd(*this, "vfd")
220{
221   m_eps_mode = false;
222}
223
trunk/src/mess/machine/esqpanel.h
r0r20113
1#pragma once
2
3#ifndef __ESQPANEL_H__
4#define __ESQPANEL_H__
5
6#include "emu.h"
7#include "machine/esqvfd.h"
8
9//**************************************************************************
10//  INTERFACE CONFIGURATION MACROS
11//**************************************************************************
12
13#define MCFG_ESQPANEL1x22_ADD(_tag, _config) \
14    MCFG_DEVICE_ADD(_tag, ESQPANEL1x22, 0) \
15    MCFG_DEVICE_CONFIG(_config)
16
17#define MCFG_ESQPANEL1x22_REPLACE(_tag, _config) \
18    MCFG_DEVICE_REPLACE(_tag, ESQPANEL1x22, 0) \
19    MCFG_DEVICE_CONFIG(_config)
20
21#define MCFG_ESQPANEL1x22_REMOVE(_tag) \
22    MCFG_DEVICE_REMOVE(_tag)
23
24#define MCFG_ESQPANEL2x40_ADD(_tag, _config) \
25    MCFG_DEVICE_ADD(_tag, ESQPANEL2x40, 0) \
26    MCFG_DEVICE_CONFIG(_config)
27
28#define MCFG_ESQPANEL2x40_REPLACE(_tag, _config) \
29    MCFG_DEVICE_REPLACE(_tag, ESQPANEL2x40, 0) \
30    MCFG_DEVICE_CONFIG(_config)
31
32#define MCFG_ESQPANEL_2x40_REMOVE(_tag) \
33    MCFG_DEVICE_REMOVE(_tag)
34
35#define MCFG_ESQPANEL2x40_SQ1_ADD(_tag, _config) \
36    MCFG_DEVICE_ADD(_tag, ESQPANEL2x40_SQ1, 0) \
37    MCFG_DEVICE_CONFIG(_config)
38
39#define MCFG_ESQPANEL2x40_SQ1_REPLACE(_tag, _config) \
40    MCFG_DEVICE_REPLACE(_tag, ESQPANEL2x40_SQ1, 0) \
41    MCFG_DEVICE_CONFIG(_config)
42
43#define MCFG_ESQPANEL2x40_SQ1_REMOVE(_tag) \
44    MCFG_DEVICE_REMOVE(_tag)
45
46//**************************************************************************
47//  TYPE DEFINITIONS
48//**************************************************************************
49
50struct esqpanel_interface
51{
52    devcb_write_line    m_out_tx_cb;
53};
54
55// ======================> esqpanel_device
56
57class esqpanel_device :  public device_t, public device_serial_interface, public esqpanel_interface
58{
59public:
60    // construction/destruction
61   esqpanel_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
62
63   DECLARE_WRITE_LINE_MEMBER( rx_w ) { check_for_start(state); }
64
65   virtual void send_to_display(UINT8 data) = 0;
66
67   void xmit_char(UINT8 data);
68
69protected:
70    // device-level overrides
71    virtual void device_start();
72    virtual void device_reset();
73    virtual void device_config_complete();
74
75   // serial overrides
76   virtual void rcv_complete();   // Rx completed receiving byte
77   virtual void tra_complete();   // Tx completed sending byte
78   virtual void tra_callback();   // Tx send bit
79   void input_callback(UINT8 state);
80
81   bool m_eps_mode;
82
83private:
84   static const int XMIT_RING_SIZE = 16;
85
86   bool  m_bCalibSecondByte;
87
88    devcb_resolved_write_line m_out_tx_func;
89   UINT8 m_xmitring[XMIT_RING_SIZE];
90   int m_xmit_read, m_xmit_write;
91   bool m_tx_busy;
92};
93
94class esqpanel1x22_device : public esqpanel_device {
95public:
96   esqpanel1x22_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
97
98   required_device<esq1x22_t> m_vfd;
99
100   virtual void send_to_display(UINT8 data) { m_vfd->write_char(data); }
101
102protected:
103    virtual machine_config_constructor device_mconfig_additions() const;
104
105private:
106};
107
108class esqpanel2x40_device : public esqpanel_device {
109public:
110   esqpanel2x40_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
111
112   required_device<esq2x40_t> m_vfd;
113
114   virtual void send_to_display(UINT8 data) { m_vfd->write_char(data); }
115
116protected:
117    virtual machine_config_constructor device_mconfig_additions() const;
118
119private:
120};
121
122class esqpanel2x40_sq1_device : public esqpanel_device {
123public:
124   esqpanel2x40_sq1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
125
126   required_device<esq2x40_sq1_t> m_vfd;
127
128   virtual void send_to_display(UINT8 data) { m_vfd->write_char(data); }
129
130protected:
131    virtual machine_config_constructor device_mconfig_additions() const;
132
133private:
134};
135
136extern const device_type ESQPANEL1x22;
137extern const device_type ESQPANEL2x40;
138extern const device_type ESQPANEL2x40_SQ1;
139
140#endif

Previous 199869 Revisions Next


© 1997-2024 The MAME Team