Previous 199869 Revisions Next

r20625 Thursday 31st January, 2013 at 05:47:51 UTC by R. Belmont
(MESS) SoundBlaster: MIDI Out support for single-byte, SB UART, and MPU-401 UART modes. [R. Belmont]
[src/mess/machine]isa_sblaster.c isa_sblaster.h
[src/osd/portmedia]pmmidi.c

trunk/src/osd/portmedia/pmmidi.c
r20624r20625
243243   #ifndef DISABLE_MIDI
244244   int bytes_needed = 0;
245245
246   // skip sysex data
247   if (dev->last_status == 0xf0)
248   {
249      if (data != 0xf7)
250      {
251         return;
252      }
253      else
254      {
255         dev->last_status = 0xf7;
256         return;
257      }
258   }
259
246260   if ((dev->xmit_cnt == 0) && (data & 0x80))
247261   {
248262      dev->last_status = data;
r20624r20625
258272      dev->xmit_in[dev->xmit_cnt++] = data;
259273   }
260274
275   if ((dev->xmit_cnt == 1) && (dev->xmit_in[0] == 0xf0))
276   {
277      dev->xmit_cnt = 0;
278      dev->last_status = 0xf0;
279      return;
280   }
281
261282   // are we there yet?
262283   switch ((dev->xmit_in[0]>>4) & 0xf)
263284   {
trunk/src/mess/machine/isa_sblaster.c
r20624r20625
4444   -1, -1, -1, -1,  1,  3, -1, -1, -1, -1, -1, -1, -1, -1,  2,  1, /* 0x */
4545      2, -1, -1, -1,  3, -1,  3,  3, -1, -1, -1,  -1,  1, -1, -1,  1, /* 1x */
4646   -1, -1, -1, -1,  3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 2x */
47   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 3x */
47    1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, /* 3x */
4848      2,  3,  3, -1, -1, -1, -1, -1,  3, -1, -1,  -1, -1, -1, -1, -1, /* 4x */
4949   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 5x */
5050   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 6x */
r20624r20625
7171   NULL
7272};
7373
74static SLOT_INTERFACE_START(midiout_slot)
75   SLOT_INTERFACE("midiout", MIDIOUT_PORT)
76SLOT_INTERFACE_END
77
78static const serial_port_interface midiout_intf =
79{
80   DEVCB_NULL   // midi out ports don't transmit inward
81};
82
7483static MACHINE_CONFIG_FRAGMENT( sblaster1_0_config )
7584   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
7685   MCFG_SOUND_ADD("ym3812", YM3812, ym3812_StdClock)
r20624r20625
9099   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
91100
92101   MCFG_PC_JOY_ADD("joy")
102   MCFG_SERIAL_PORT_ADD("mdout", midiout_intf, midiout_slot, "midiout", NULL)
93103MACHINE_CONFIG_END
94104
95105static MACHINE_CONFIG_FRAGMENT( sblaster1_5_config )
r20624r20625
106116   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
107117
108118   MCFG_PC_JOY_ADD("joy")
119   MCFG_SERIAL_PORT_ADD("mdout", midiout_intf, midiout_slot, "midiout", NULL)
109120MACHINE_CONFIG_END
110121
111122static MACHINE_CONFIG_FRAGMENT( sblaster_16_config )
r20624r20625
122133   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
123134
124135   MCFG_PC_JOY_ADD("joy")
136   MCFG_SERIAL_PORT_ADD("mdout", midiout_intf, midiout_slot, "midiout", NULL)
125137MACHINE_CONFIG_END
126138
127139static READ8_DEVICE_HANDLER( ym3812_16_r )
r20624r20625
225237   if(offset)
226238      return;
227239
228   if(data == 0 && m_dsp.reset_latch == 1)
240   // a reset while in UART MIDI mode simply restores the previous
241   // operating state (page 5-3 of the Creative manual).
242   if (!m_uart_midi)
229243   {
230      // reset routine
231      m_dsp.fifo_ptr = 0;
232      m_dsp.fifo_r_ptr = 0;
233      for(int i=0;i < 15; i++)
244      if(data == 0 && m_dsp.reset_latch == 1)
234245      {
235         m_dsp.fifo[i] = 0;
236         m_dsp.fifo_r[i] = 0;
246         // reset routine
247         m_dsp.fifo_ptr = 0;
248         m_dsp.fifo_r_ptr = 0;
249         for(int i=0;i < 15; i++)
250         {
251            m_dsp.fifo[i] = 0;
252            m_dsp.fifo_r[i] = 0;
253         }
254         queue_r(0xaa); // reset OK ID
237255      }
238      queue_r(0xaa); // reset OK ID
256
257      m_dsp.reset_latch = data;
258      drq_w(0);
259      m_dsp.dma_autoinit = 0;
260      irq_w(0, IRQ_ALL);
261      m_timer->adjust(attotime::never, 0);
262      m_dsp.d_rptr = 0;
263      m_dsp.d_wptr = 0;
264      m_dsp.dma_throttled = false;
265      m_dsp.dma_timer_started = false;
239266   }
240267
241   m_dsp.reset_latch = data;
242   drq_w(0);
243   m_dsp.dma_autoinit = 0;
244   irq_w(0, IRQ_ALL);
245   m_timer->adjust(attotime::never, 0);
246   m_dsp.d_rptr = 0;
247   m_dsp.d_wptr = 0;
248   m_dsp.dma_throttled = false;
249   m_dsp.dma_timer_started = false;
268   m_onebyte_midi = false;
269   m_uart_midi = false;
270   m_uart_irq = false;
271   m_mpu_midi = false;
272   m_tx_busy = false;
273   m_xmit_read = m_xmit_write = 0;
274   m_recv_read = m_recv_write = 0;
250275
251276   //printf("%02x\n",data);
252277}
r20624r20625
257282   if(offset)
258283      return 0xff;
259284
285   if (m_uart_midi)
286   {
287      UINT8 rv = m_recvring[m_recv_read];
288
289      // only advance the read pointer if the ring wasn't empty
290      if (m_recv_read != m_xmit_read)
291      {
292         m_recv_read++;
293      }
294
295      return rv;
296   }
297
260298   return dequeue_r();
261299}
262300
r20624r20625
282320//    printf("Clear IRQ5\n");
283321   irq_w(0, IRQ_DMA8);   // reading this port ACKs the card's IRQ, 8-bit dma only?
284322
323   // in UART MIDI mode, bit 7 indicates if a character is available
324   // to read.
325   if (m_uart_midi)
326   {
327      if (m_recv_read != m_recv_write)
328      {
329         return 0x80;
330      }
331
332      return 0x00;
333   }
334
285335   return m_dsp.rbuf_status;
286336}
287337
r20624r20625
363413            logerror("SB: ADC capture unimplemented\n");
364414            break;
365415
416         case 0x34:
417            m_uart_midi = true;
418            m_uart_irq = true;
419            break;
420
421         case 0x35:
422            m_uart_midi = true;
423            m_uart_irq = false;
424            break;
425
426         case 0x36:
427         case 0x37:   // Enter UART mode
428            printf("timestamp MIDI mode not supported, contact MESSDEV!\n");
429            break;
430
431         case 0x38:   // single-byte MIDI send
432            m_onebyte_midi = true;
433            break;
434
366435         case 0x40:  // set time constant
367436            m_dsp.frequency = (1000000 / (256 - m_dsp.fifo[1]));
368437            //printf("Set time constant: %02x -> %d\n", m_dsp.fifo[1], m_dsp.frequency);
r20624r20625
609678
610679WRITE8_MEMBER(sb_device::dsp_cmd_w)
611680{
612//  printf("%02x to DSP command @ %x\n", data, offset);
681//   printf("%02x to DSP command @ %x\n", data, offset);
613682
614683   if(offset)
615684      return;
616685
686   if (m_uart_midi || m_onebyte_midi)
687   {
688      xmit_char(data);
689      m_onebyte_midi = false;   // clear onebyte (if this is uart, that's harmless)
690      return;
691   }
692
617693   queue(data);
618694
619695   process_fifo(m_dsp.fifo[0]);
r20624r20625
698774   if(offset == 0) // data
699775   {
700776      logerror("SB MPU401:%02x %02x\n",offset,data);
777      if (m_mpu_midi)
778      {
779         xmit_char(data);
780      }
701781   }
702782   else // command
703783   {
r20624r20625
705785
706786      switch(data)
707787      {
788         case 0x3f: // enter MPU-401 UART mode
789            irq_w(1, IRQ_MPU);
790            m_head = m_tail = 0;
791            m_mpu_queue[m_head++] = 0xfe;
792            m_mpu_midi = true;
793            break;
794
708795         case 0xff: // reset
709796            irq_w(1, IRQ_MPU);
710797            m_head = m_tail = 0;
711798            m_mpu_queue[m_head++] = 0xfe;
799            m_mpu_midi = false;
712800            break;
713801      }
714802   }
r20624r20625
9881076
9891077sb_device::sb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name) :
9901078   device_t(mconfig, type, name, tag, owner, clock),
1079   device_serial_interface(mconfig, *this),
9911080   m_dacl(*this, "sbdacl"),
9921081   m_dacr(*this, "sbdacr"),
993   m_joy(*this, "joy")
1082   m_joy(*this, "joy"),
1083   m_mdout(*this, "mdout")
9941084{
9951085}
9961086
r20624r20625
11161206   m_dsp.irq_active = 0;
11171207   m_dsp.dma_no_irq = false;
11181208   mixer_reset();
1209
1210   // MIDI is 31250 baud, 8-N-1
1211   set_rcv_rate(31250);
1212   set_tra_rate(31250);
1213   set_data_frame(8, 1, SERIAL_PARITY_NONE);
11191214}
11201215
11211216UINT8 sb_device::dack_r(int line)
r20624r20625
14061501      }
14071502   }
14081503}
1504
1505void sb_device::rcv_complete()    // Rx completed receiving byte
1506{
1507   receive_register_extract();
1508   UINT8 data = get_received_char();
1509
1510   // in UART MIDI mode, we set the DMA8 IRQ on receiving a character
1511   if (m_uart_midi)
1512   {
1513      m_recvring[m_recv_write++] = data;
1514
1515      // if not polling mode, trigger the DMA8 IRQ
1516      if (m_uart_irq)
1517      {
1518         irq_w(1, IRQ_DMA8);
1519      }
1520   }
1521}
1522
1523void sb16_device::rcv_complete()    // Rx completed receiving byte
1524{
1525   receive_register_extract();
1526   UINT8 data = get_received_char();
1527
1528   // in UART MIDI mode, we set the DMA8 IRQ on receiving a character
1529   if (m_uart_midi)
1530   {
1531      m_recvring[m_recv_write++] = data;
1532      irq_w(1, IRQ_DMA8);
1533   }
1534
1535   // in MPU MIDI mode, do this instead
1536   if (m_mpu_midi)
1537   {
1538      m_mpu_queue[m_head++] = data;
1539      if (m_head >= 16)
1540      {
1541         m_head = 0;
1542      }
1543      irq_w(1, IRQ_MPU);
1544   }
1545}
1546
1547void sb_device::tra_complete()    // Tx completed sending byte
1548{
1549//  printf("Tx complete\n");
1550   // is there more waiting to send?
1551   if (m_xmit_read != m_xmit_write)
1552   {
1553      transmit_register_setup(m_xmitring[m_xmit_read++]);
1554      if (m_xmit_read >= MIDI_RING_SIZE)
1555      {
1556         m_xmit_read = 0;
1557      }
1558   }
1559   else
1560   {
1561      m_tx_busy = false;
1562   }
1563}
1564
1565void sb_device::tra_callback()    // Tx send bit
1566{
1567   int bit = transmit_register_get_data_bit();
1568    m_mdout->tx(bit);
1569}
1570
1571void sb_device::xmit_char(UINT8 data)
1572{
1573//   printf("SB: xmit %02x\n", data);
1574
1575   // if tx is busy it'll pick this up automatically when it completes
1576   if (!m_tx_busy)
1577   {
1578      m_tx_busy = true;
1579      transmit_register_setup(data);
1580   }
1581   else
1582   {
1583      // tx is busy, it'll pick this up next time
1584      m_xmitring[m_xmit_write++] = data;
1585      if (m_xmit_write >= MIDI_RING_SIZE)
1586      {
1587         m_xmit_write = 0;
1588      }
1589
1590      if (m_xmit_write == m_xmit_read)
1591      {
1592         printf("Overflow xmitring!\n");
1593      }
1594   }
1595}
1596
trunk/src/mess/machine/isa_sblaster.h
r20624r20625
77#include "machine/isa.h"
88#include "sound/dac.h"
99#include "machine/pc_joy.h"
10#include "machine/serial.h"
11#include "machine/midiinport.h"
12#include "machine/midioutport.h"
1013
1114#define SIXTEENBIT  0x01
1215#define STEREO      0x02
r20624r20625
8689   UINT8 bass[2];
8790};
8891
89// ======================> sb8_device (parent)
92// ======================> sb_device (parent)
9093
9194class sb_device :
92      public device_t
95      public device_t, public device_serial_interface
9396{
9497public:
9598      // construction/destruction
r20624r20625
97100
98101      required_device<dac_device> m_dacl;
99102      required_device<dac_device> m_dacr;
100   required_device<pc_joy_device> m_joy;
103      required_device<pc_joy_device> m_joy;
104      required_device<serial_port_device> m_mdout;
101105
102106      void process_fifo(UINT8 cmd);
103107      void queue(UINT8 data);
r20624r20625
125129      virtual void mixer_reset() {}
126130      void adpcm_decode(UINT8 sample, int size);
127131
132      // serial overrides
133      virtual void rcv_complete();    // Rx completed receiving byte
134      virtual void tra_complete();    // Tx completed sending byte
135      virtual void tra_callback();    // Tx send bit
136      void input_callback(UINT8 state) {}
137
138      static const int MIDI_RING_SIZE = 1024;
139
128140      struct sb8_dsp_state m_dsp;
129141      UINT8 m_dack_out;
142      void xmit_char(UINT8 data);
143      bool m_onebyte_midi, m_uart_midi, m_uart_irq, m_mpu_midi;
144      UINT8 m_recvring[MIDI_RING_SIZE];
145      UINT8 m_xmitring[MIDI_RING_SIZE];
146      int m_xmit_read, m_xmit_write;
147      int m_recv_read, m_recv_write;
148      bool m_tx_busy;
130149
131150      emu_timer *m_timer;
132151};
r20624r20625
198217      virtual void irq_w(int state, int source) { (state?m_dsp.irq_active|=source:m_dsp.irq_active&=~source); m_isa->irq5_w(m_dsp.irq_active);  }
199218      virtual void mixer_reset();
200219      void mixer_set();
220      virtual void rcv_complete();    // Rx completed receiving byte
201221private:
202222      UINT8 m_mpu_queue[16];
203223      UINT8 m_tail;

Previous 199869 Revisions Next


© 1997-2024 The MAME Team