Previous 199869 Revisions Next

r32116 Sunday 14th September, 2014 at 22:09:11 UTC by Carl
(mess) sb16: Add Soundblaster 16 low level emulation [Carl, Malice, O. Galibert]
---
The diagnose program mostly works but I'm sure there are still many more bugs, it definitely isn't near as usable as the hle (at least yet).
[src/emu/bus]bus.mak
[src/emu/bus/isa]isa_cards.c isa_cards.h sb16.c* sb16.h*

trunk/src/emu/bus/isa/isa_cards.c
r32115r32116
9393   SLOT_INTERFACE("dms3d2kp", ISA16_DMS3D2KPRO)
9494   SLOT_INTERFACE("gfxultra", ISA16_VGA_GFXULTRA)
9595   SLOT_INTERFACE("gfxultrap", ISA16_SVGA_GFXULTRAPRO)
96   SLOT_INTERFACE("3c505", ISA16_3C505)
9697   SLOT_INTERFACE("mach64", ISA16_SVGA_MACH64)
98   SLOT_INTERFACE("sb16_lle", ISA16_SB16)
9799SLOT_INTERFACE_END
trunk/src/emu/bus/isa/isa_cards.h
r32115r32116
4747#include "ssi2001.h"
4848#include "stereo_fx.h"
4949#include "dectalk.h"
50#include "sb16.h"
5051
5152// network
5253#include "3c503.h"
5354#include "ne1000.h"
5455#include "ne2000.h"
56#include "3c505.h"
5557
5658// communication ports
5759#include "lpt.h"
trunk/src/emu/bus/isa/sb16.c
r0r32116
1// License: BSD-3-Clause
2
3// Soundblaster 16 - LLE
4//
5// The mcu does host communication and control of the dma-dac unit
6// TODO: UART is connected to MIDI port, mixer, adc
7
8#include "sb16.h"
9
10const device_type ISA16_SB16 = &device_creator<sb16_lle_device>;
11
12READ8_MEMBER( sb16_lle_device::dsp_data_r )
13{
14   if(!space.debugger_access())
15      m_data_in = false;
16
17   return m_in_byte;
18}
19
20WRITE8_MEMBER( sb16_lle_device::dsp_data_w )
21{
22   m_data_out = true;
23   m_out_byte = data;
24}
25
26READ8_MEMBER( sb16_lle_device::dac_ctrl_r )
27{
28   return 0;
29}
30
31WRITE8_MEMBER( sb16_lle_device::dac_ctrl_w )
32{
33   /* port 0x05
34    * bit0 -
35    * bit1 - ?
36    * bit2 -
37    * bit3 -
38    * bit4 -
39    * bit5 - ?
40    * bit6 - clear irq line?
41    * bit7 -
42   */
43   if(data & 0x40)
44   {
45      m_cpu->set_input_line(MCS51_INT0_LINE, CLEAR_LINE);
46      m_cpu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE);
47   }
48}
49
50READ8_MEMBER( sb16_lle_device::adc_data_r )
51{
52   return 0;
53}
54
55WRITE8_MEMBER( sb16_lle_device::dac_data_w )
56{
57   m_dacl->write_unsigned8(data);
58   m_dacr->write_unsigned8(data);
59}
60
61READ8_MEMBER( sb16_lle_device::p1_r )
62{
63   UINT8 ret = 0;
64   ret |= m_data_out << 0;
65   ret |= m_data_in << 1;
66   return ret;
67}
68
69WRITE8_MEMBER( sb16_lle_device::p1_w )
70{
71   /* port P1
72    * bit0 - output byte ready
73    * bit1 - input byte ready
74    * bit2 - irq mask?
75    * bit3 -
76    * bit4 - ?
77    * bit5 - DRQ?
78    * bit6 - MIDI?
79    * bit7 - ?
80   */
81}
82
83READ8_MEMBER( sb16_lle_device::p2_r )
84{
85   return 0;
86}
87
88WRITE8_MEMBER( sb16_lle_device::p2_w )
89{
90   /* port P2
91    * bit0 -
92    * bit1 -
93    * bit2 -
94    * bit3 -
95    * bit4 - clock running?
96    * bit5 - ?
97    * bit6 - ?
98    * bit7 - ?
99   */
100}
101
102void sb16_lle_device::control_timer(bool start)
103{
104   if(start && m_freq)
105   {
106      double rate = (46615120.0/1024/256) * m_freq;
107      m_timer->adjust(attotime::from_hz(rate), 0, attotime::from_hz(rate));
108   }
109   else
110      m_timer->adjust(attotime::never);
111}
112
113WRITE8_MEMBER( sb16_lle_device::rate_w )
114{
115   m_freq = data;
116   if(!(m_ctrl8 & 2) || !(m_ctrl16 & 2))
117      control_timer(true);
118}
119
120READ8_MEMBER( sb16_lle_device::dma8_r )
121{
122   return m_dac_fifo[0].b[0];
123}
124
125WRITE8_MEMBER( sb16_lle_device::dma8_w )
126{
127   m_adc_fifo[0].b[0] = data;
128   m_isa->drq1_w(0);
129}
130
131READ8_MEMBER( sb16_lle_device::dma_stat_r )
132{
133   /* port 0x06
134    * bit0 - 8 bit complete
135    * bit1 - 16 bit complete
136    * bit2 -
137    * bit3 -
138    * bit4 -
139    * bit5 -
140    * bit6 -
141    * bit7 -
142   */
143   UINT8 ret = (m_dma16_done << 1) | m_dma8_done;
144   return ret;
145}
146
147READ8_MEMBER( sb16_lle_device::ctrl8_r )
148{
149   return m_ctrl8;
150}
151
152WRITE8_MEMBER( sb16_lle_device::ctrl8_w )
153{
154   /* port 0x08
155    * bit0 - ?
156    * bit1 - stop transfer
157    * bit2 - load counter
158    * bit3 -
159    * bit4 -
160    * bit5 -
161    * bit6 - ?
162    * bit7 - toggle for 8bit irq
163   */
164   if(data & 4)
165   {
166      m_dma8_cnt = m_dma8_len;
167      m_dma8_done = false;
168   }
169   if(!(data & 2) || !(m_ctrl16 & 2))
170      control_timer(true);
171   if(data & 2)
172   {
173      m_isa->drq1_w(0);
174      if(m_ctrl16 & 2)
175         control_timer(false);
176   }
177   else
178      m_isa->drq1_w(1);
179
180   if(data & 0x80)
181   {
182      m_irq8 = true;
183      m_isa->irq5_w(ASSERT_LINE);
184   }
185   m_ctrl8 = data;
186}
187
188READ8_MEMBER( sb16_lle_device::ctrl16_r )
189{
190   return m_ctrl16;
191}
192
193WRITE8_MEMBER( sb16_lle_device::ctrl16_w )
194{
195   /* port 0x10
196    * bit0 -
197    * bit1 - stop transfer
198    * bit2 - load counter
199    * bit3 -
200    * bit4 -
201    * bit5 -
202    * bit6 -
203    * bit7 - toggle for 16bit irq
204   */
205   if(data & 4)
206   {
207      m_dma16_cnt = m_dma16_len;
208      m_dma16_done = false;
209   }
210   if(!(data & 2) || !(m_ctrl8 & 2))
211      control_timer(true);
212   if(data & 2)
213   {
214      m_isa->drq5_w(0);
215      if(m_ctrl8 & 2)
216         control_timer(false);
217   }
218   else
219      m_isa->drq5_w(1);
220
221   if(data & 0x80)
222   {
223      m_irq16 = true;
224      m_isa->irq5_w(ASSERT_LINE);
225   }
226   m_ctrl16 = data;
227}
228
229READ8_MEMBER( sb16_lle_device::dac_fifo_ctrl_r )
230{
231   return m_dac_fifo_ctrl;
232}
233
234WRITE8_MEMBER( sb16_lle_device::dac_fifo_ctrl_w )
235{
236   /* port 0x0E
237    * bit0 - reset fifo
238    * bit1 - ?
239    * bit2 - disable fifo
240    * bit3 -
241    * bit4 -
242    * bit5 -
243    * bit6 -
244    * bit7 -
245   */
246   if(((m_dac_fifo_ctrl & 1) && !(data & 1)) || (data & 4))
247   {
248      m_dac_fifo_head = 1;
249      m_dac_fifo_tail = 0;
250      m_dac_r = false;
251      m_dac_h = false;
252   }
253   m_dac_fifo_ctrl = data;
254}
255
256READ8_MEMBER( sb16_lle_device::adc_fifo_ctrl_r )
257{
258   return m_adc_fifo_ctrl;
259}
260
261WRITE8_MEMBER( sb16_lle_device::adc_fifo_ctrl_w )
262{
263   /* port 0x16
264    * bit0 - reset fifo
265    * bit1 - ?
266    * bit2 - disable fifo
267    * bit3 -
268    * bit4 -
269    * bit5 -
270    * bit6 -
271    * bit7 -
272   */
273   if(((m_adc_fifo_ctrl & 1) && !(data & 1)) || (data & 4))
274   {
275      m_adc_fifo_head = 1;
276      m_adc_fifo_tail = 0;
277      m_adc_r = false;
278      m_adc_h = false;
279   }
280   m_adc_fifo_ctrl = data;
281}
282
283READ8_MEMBER( sb16_lle_device::mode_r )
284{
285   return m_mode;
286}
287
288WRITE8_MEMBER( sb16_lle_device::mode_w )
289{
290   /* port 0x04
291    * bit0 - 1 -- dac 16, adc 8; 0 -- adc 16, dac 8
292    * bit1 - int every sample
293    * bit2 - int dma complete
294    * bit3 -
295    * bit4 - 8 bit signed
296    * bit5 - 16 bit signed
297    * bit6 - 8 bit mono
298    * bit7 - 16 bit mono
299   */
300   m_mode = data;
301}
302
303READ8_MEMBER( sb16_lle_device::dma8_ready_r )
304{
305   /* port 0x0F
306    * bit0 -
307    * bit1 -
308    * bit2 -
309    * bit3 -
310    * bit4 -
311    * bit5 -
312    * bit6 - byte ready in fifo
313    * bit7 -
314   */
315   return ((m_dac_fifo_tail - m_dac_fifo_head) != 1) << 6;
316}
317
318READ8_MEMBER( sb16_lle_device::adc_data_ready_r )
319{
320   /* port 0x17
321    * bit0 -
322    * bit1 -
323    * bit2 -
324    * bit3 -
325    * bit4 -
326    * bit5 -
327    * bit6 -
328    * bit7 - sample ready from adc
329   */
330   return (m_mode & 1) ? 0x80 : 0;
331}
332
333READ8_MEMBER( sb16_lle_device::dma8_cnt_lo_r )
334{
335   return m_dma8_cnt & 0xff;
336}
337
338READ8_MEMBER( sb16_lle_device::dma8_cnt_hi_r )
339{
340   return m_dma8_cnt >> 8;
341}
342
343WRITE8_MEMBER( sb16_lle_device::dma8_len_lo_w )
344{
345   m_dma8_len = (m_dma8_len & 0xff00) | data;
346}
347
348WRITE8_MEMBER( sb16_lle_device::dma8_len_hi_w )
349{
350   m_dma8_len = (m_dma8_len & 0xff) | (data << 8);
351}
352
353WRITE8_MEMBER( sb16_lle_device::dma16_len_lo_w )
354{
355   m_dma16_len = (m_dma16_len & 0xff00) | data;
356}
357
358WRITE8_MEMBER( sb16_lle_device::dma16_len_hi_w )
359{
360   m_dma16_len = (m_dma16_len & 0xff) | (data << 8);
361}
362
363ROM_START( sb16 )
364   ROM_REGION( 0x2000, "sb16_cpu", 0 )
365   ROM_LOAD("ct1741_v413[80c52].bin", 0x0000, 0x2000, CRC(5181892f) SHA1(5b42f1c34c4e9c8dbbdcffa0a36c178ca4f1aa77))
366
367   ROM_REGION(0x40, "xor_table", 0)
368   ROM_LOAD("ct1741_v413_xor.bin", 0x00, 0x40, CRC(5243d15a) SHA1(c7637c92828843f47e6e2f956af639b07aee4571))
369ROM_END
370
371static ADDRESS_MAP_START(sb16_io, AS_IO, 8, sb16_lle_device)
372   AM_RANGE(0x0000, 0x0000) AM_MIRROR(0xff00) AM_READWRITE(dsp_data_r, dsp_data_w)
373//   AM_RANGE(0x0001, 0x0001) // MIDI related?
374//   AM_RANGE(0x0002, 0x0002)
375   AM_RANGE(0x0004, 0x0004) AM_MIRROR(0xff00) AM_READWRITE(mode_r, mode_w)
376   AM_RANGE(0x0005, 0x0005) AM_MIRROR(0xff00) AM_READWRITE(dac_ctrl_r, dac_ctrl_w)
377   AM_RANGE(0x0006, 0x0006) AM_MIRROR(0xff00) AM_READ(dma_stat_r)
378//   AM_RANGE(0x0007, 0x0007) // unknown
379   AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff00) AM_READWRITE(ctrl8_r, ctrl8_w)
380   AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xff00) AM_WRITE(rate_w)
381   AM_RANGE(0x000A, 0x000A) AM_MIRROR(0xff00) AM_READ(dma8_cnt_lo_r)
382   AM_RANGE(0x000B, 0x000B) AM_MIRROR(0xff00) AM_WRITE(dma8_len_lo_w)
383   AM_RANGE(0x000C, 0x000C) AM_MIRROR(0xff00) AM_WRITE(dma8_len_hi_w)
384   AM_RANGE(0x000D, 0x000D) AM_MIRROR(0xff00) AM_READ(dma8_cnt_hi_r)
385   AM_RANGE(0x000E, 0x000E) AM_MIRROR(0xff00) AM_READWRITE(dac_fifo_ctrl_r, dac_fifo_ctrl_w)
386   AM_RANGE(0x000F, 0x000F) AM_MIRROR(0xff00) AM_READ(dma8_ready_r)
387   AM_RANGE(0x0010, 0x0010) AM_MIRROR(0xff00) AM_READWRITE(ctrl16_r, ctrl16_w)
388   AM_RANGE(0x0013, 0x0013) AM_MIRROR(0xff00) AM_WRITE(dma16_len_lo_w)
389   AM_RANGE(0x0014, 0x0014) AM_MIRROR(0xff00) AM_WRITE(dma16_len_hi_w)
390   AM_RANGE(0x0016, 0x0016) AM_MIRROR(0xff00) AM_READWRITE(adc_fifo_ctrl_r, adc_fifo_ctrl_w)
391   AM_RANGE(0x0017, 0x0017) AM_MIRROR(0xff00) AM_READ(adc_data_ready_r)
392   AM_RANGE(0x0019, 0x0019) AM_MIRROR(0xff00) AM_WRITE(dac_data_w)
393   AM_RANGE(0x001B, 0x001B) AM_MIRROR(0xff00) AM_READ(adc_data_r)
394   AM_RANGE(0x001D, 0x001D) AM_MIRROR(0xff00) AM_WRITE(dma8_w)
395   AM_RANGE(0x001F, 0x001F) AM_MIRROR(0xff00) AM_READ(dma8_r)
396//   AM_RANGE(0x0080, 0x0080) // ASP comms
397//   AM_RANGE(0x0081, 0x0081)
398//   AM_RANGE(0x0082, 0x0082)
399   AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_READWRITE(p1_r, p1_w)
400   AM_RANGE(MCS51_PORT_P2, MCS51_PORT_P2) AM_READWRITE(p2_r, p2_w)
401ADDRESS_MAP_END
402
403static MACHINE_CONFIG_FRAGMENT( sb16 )
404   MCFG_CPU_ADD("sb16_cpu", I80C52, XTAL_24MHz)
405   MCFG_CPU_IO_MAP(sb16_io)
406
407   MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
408   MCFG_SOUND_ADD("ymf262", YMF262, XTAL_14_31818MHz)
409   MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
410   MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
411   MCFG_SOUND_ROUTE(2, "lspeaker", 1.00)
412   MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
413
414   MCFG_SOUND_ADD("dacl", DAC, 0)
415   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
416   MCFG_SOUND_ADD("dacr", DAC, 0)
417   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
418
419   MCFG_PC_JOY_ADD("pc_joy")
420MACHINE_CONFIG_END
421
422const rom_entry *sb16_lle_device::device_rom_region() const
423{
424   return ROM_NAME( sb16 );
425}
426
427machine_config_constructor sb16_lle_device::device_mconfig_additions() const
428{
429   return MACHINE_CONFIG_NAME( sb16 );
430}
431
432READ8_MEMBER( sb16_lle_device::host_data_r )
433{
434   m_data_out = false;
435   return m_out_byte;
436}
437
438WRITE8_MEMBER( sb16_lle_device::host_cmd_w )
439{
440   m_data_in = true;
441   m_in_byte = data;
442}
443
444UINT8 sb16_lle_device::dack_r(int line)
445{
446   UINT8 ret = m_adc_fifo[m_adc_fifo_tail].b[m_adc_h + (m_adc_r * 2)];
447
448   if(m_ctrl8 & 2)
449      return 0;
450
451   if(!(m_mode & 1))
452   {
453      m_adc_h = !m_adc_h;
454      if(m_adc_h)
455         return ret;
456   }
457   if((!(m_mode & 0x40) && !(m_mode & 1)) || (!(m_mode & 0x80) && !(m_mode & 1)))
458   {
459      m_adc_r = !m_adc_r;
460      if(m_adc_r)
461         return ret;
462   }
463
464   m_dma8_cnt--;
465   if(!m_dma8_cnt)
466   {
467      m_dma8_done = true;
468      if(m_mode & 4)
469         m_cpu->set_input_line(MCS51_INT1_LINE, ASSERT_LINE);
470      m_isa->drq1_w(0);
471      return ret;
472   }
473
474   ++m_adc_fifo_tail %= 16;
475
476   if(m_adc_fifo_ctrl & 4)
477   {
478      m_isa->drq1_w(0);
479      return ret;
480   }
481
482   if(m_adc_fifo_head == ((m_adc_fifo_tail + 1) % 16))
483      m_isa->drq1_w(0);
484   return ret;
485}
486
487void sb16_lle_device::dack_w(int line, UINT8 data)
488{
489   if(m_ctrl8 & 2)
490      return;
491
492   m_dac_fifo[m_dac_fifo_head].b[m_dac_h + (m_dac_r * 2)] = data;
493
494   if(m_mode & 1)
495   {
496      m_dac_h = !m_dac_h;
497      if(m_dac_h)
498         return;
499   }
500   if((!(m_mode & 0x40) && !(m_mode & 1)) || (!(m_mode & 0x80) && (m_mode & 1)))
501   {
502      m_dac_r = !m_dac_r;
503      if(m_dac_r)
504         return;
505   }
506
507   m_dma8_cnt--;
508   if(!m_dma8_cnt)
509   {
510      m_dma8_done = true;
511      if(m_mode & 4)
512         m_cpu->set_input_line(MCS51_INT1_LINE, ASSERT_LINE);
513      m_isa->drq1_w(0);
514      return;
515   }
516
517   ++m_dac_fifo_head %= 16;
518
519   if(m_dac_fifo_ctrl & 4)
520   {
521      m_isa->drq1_w(0);
522      return;
523   }
524
525   if(m_dac_fifo_head == m_dac_fifo_tail)
526      m_isa->drq1_w(0);
527}
528
529UINT16 sb16_lle_device::dack16_r(int line)
530{
531   UINT16 ret = m_adc_fifo[m_adc_fifo_tail].h[m_adc_r];
532
533   if(m_ctrl16 & 2)
534      return 0;
535
536   if(!(m_mode & 0x80))
537   {
538      m_adc_r = !m_adc_r;
539      if(m_adc_r)
540         return ret;
541   }
542   m_dma16_cnt--;
543   if(!m_dma16_cnt)
544   {
545      m_dma16_done = true;
546      if(m_mode & 4)
547         m_cpu->set_input_line(MCS51_INT1_LINE, ASSERT_LINE);
548      m_isa->drq5_w(0);
549      return ret;
550   }
551   ++m_adc_fifo_tail %= 16;
552
553   if(m_adc_fifo_ctrl & 4)
554   {
555      m_isa->drq5_w(0);
556      return ret;
557   }
558
559   if(m_adc_fifo_head == ((m_adc_fifo_tail + 1) % 16))
560      m_isa->drq5_w(0);
561   return ret;
562}
563
564void sb16_lle_device::dack16_w(int line, UINT16 data)
565{
566   if(m_ctrl16 & 2)
567      return;
568
569   m_dac_fifo[m_dac_fifo_head].h[m_dac_r] = data;
570
571   if(!(m_mode & 0x80))
572   {
573      m_dac_r = !m_dac_r;
574      if(m_dac_r)
575         return;
576   }
577   m_dma16_cnt--;
578   if(!m_dma16_cnt)
579   {
580      m_dma16_done = true;
581      if(m_mode & 4)
582         m_cpu->set_input_line(MCS51_INT1_LINE, ASSERT_LINE);
583      m_isa->drq5_w(0);
584      return;
585   }
586   ++m_dac_fifo_head %= 16;
587
588   if(m_dac_fifo_ctrl & 4)
589   {
590      m_isa->drq5_w(0);
591      return;
592   }
593
594   if(m_dac_fifo_head == m_dac_fifo_tail)
595      m_isa->drq5_w(0);
596}
597
598WRITE8_MEMBER( sb16_lle_device::dsp_reset_w )
599{
600   if(data & 1)
601   {
602      device_reset();
603      m_cpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
604   }
605}
606
607READ8_MEMBER( sb16_lle_device::dsp_wbuf_status_r )
608{
609   if(offset)
610      return 0xff;
611   return m_data_in << 7;
612}
613
614READ8_MEMBER( sb16_lle_device::dsp_rbuf_status_r )
615{
616   if(offset)
617   {
618      m_irq16 = false;
619      m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
620      return 0xff;
621   }
622   m_irq8 = false;
623   m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
624   return m_data_out << 7;
625}
626
627WRITE8_MEMBER( sb16_lle_device::invalid_w )
628{
629   logerror("sb16: invalid port write\n");
630}
631
632READ8_MEMBER( sb16_lle_device::invalid_r )
633{
634   logerror("sb16: invalid port read\n");
635   return 0xff;
636}
637
638// just using the old dummy mpu401 for now
639READ8_MEMBER( sb16_lle_device::mpu401_r )
640{
641   UINT8 res;
642
643   m_irq_midi = false;
644   m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
645   if(offset == 0) // data
646   {
647      res = m_mpu_byte;
648      m_mpu_byte = 0xff;
649   }
650   else // status
651   {
652      res = ((m_mpu_byte != 0xff)?0:0x80) | 0x3f; // bit 7 queue empty (DSR), bit 6 DRR (Data Receive Ready?)
653   }
654
655   return res;
656}
657
658WRITE8_MEMBER( sb16_lle_device::mpu401_w )
659{
660   if(offset == 0) // data
661   {
662      logerror("SB MPU401:%02x %02x\n",offset,data);
663   }
664   else // command
665   {
666      logerror("SB MPU401:%02x %02x\n",offset,data);
667
668      switch(data)
669      {
670         case 0xff: // reset
671            m_isa->irq5_w(ASSERT_LINE);
672            m_irq_midi = true;
673            m_mpu_byte = 0xfe;
674            break;
675      }
676   }
677
678}
679
680sb16_lle_device::sb16_lle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
681   device_t(mconfig, ISA16_SB16, "SoundBlaster 16 Audio Adapter LLE", tag, owner, clock, "sb16", __FILE__),
682   device_isa16_card_interface(mconfig, *this),
683   m_dacl(*this, "dacl"),
684   m_dacr(*this, "dacr"),
685   m_joy(*this, "pc_joy"),
686   m_cpu(*this, "sb16_cpu")
687{
688}
689
690void sb16_lle_device::device_start()
691{
692   address_space &space = m_cpu->space(AS_PROGRAM);
693   UINT8 *rom = memregion("sb16_cpu")->base();
694   UINT8 *xor_table = memregion("xor_table")->base();
695
696   for(int i = 0; i < 0x2000; i++)
697      rom[i] = rom[i] ^ xor_table[i & 0x3f];
698
699
700   ymf262_device *ymf262 = subdevice<ymf262_device>("ymf262");
701   set_isa_device();
702
703   m_isa->install_device(0x0200, 0x0207, 0, 0, read8_delegate(FUNC(pc_joy_device::joy_port_r), subdevice<pc_joy_device>("pc_joy")), write8_delegate(FUNC(pc_joy_device::joy_port_w), subdevice<pc_joy_device>("pc_joy")));
704   m_isa->install_device(0x0226, 0x0227, 0, 0, read8_delegate(FUNC(sb16_lle_device::invalid_r), this), write8_delegate(FUNC(sb16_lle_device::dsp_reset_w), this));
705   m_isa->install_device(0x022a, 0x022b, 0, 0, read8_delegate(FUNC(sb16_lle_device::host_data_r), this), write8_delegate(FUNC(sb16_lle_device::invalid_w), this) );
706   m_isa->install_device(0x022c, 0x022d, 0, 0, read8_delegate(FUNC(sb16_lle_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb16_lle_device::host_cmd_w), this) );
707   m_isa->install_device(0x022e, 0x022f, 0, 0, read8_delegate(FUNC(sb16_lle_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb16_lle_device::invalid_w), this) );
708   m_isa->install_device(0x0330, 0x0331, 0, 0, read8_delegate(FUNC(sb16_lle_device::mpu401_r), this), write8_delegate(FUNC(sb16_lle_device::mpu401_w), this));
709   m_isa->install_device(0x0388, 0x0389, 0, 0, read8_delegate(FUNC(ymf262_device::read), ymf262), write8_delegate(FUNC(ymf262_device::write), ymf262));
710   m_isa->install_device(0x0220, 0x0223, 0, 0, read8_delegate(FUNC(ymf262_device::read), ymf262), write8_delegate(FUNC(ymf262_device::write), ymf262));
711   m_isa->install_device(0x0228, 0x0229, 0, 0, read8_delegate(FUNC(ymf262_device::read), ymf262), write8_delegate(FUNC(ymf262_device::write), ymf262));
712   m_isa->set_dma_channel(1, this, FALSE);
713   m_isa->set_dma_channel(5, this, FALSE);
714   m_timer = timer_alloc();
715}
716
717
718void sb16_lle_device::device_reset()
719{
720   m_isa->drq1_w(0);
721   m_isa->drq5_w(0);
722   m_isa->irq5_w(0);
723   m_data_out = false;
724   m_data_in = false;
725   m_freq = 0;
726   m_mode = 0;
727   m_dma8_len = m_dma16_len = 0;
728   m_dma8_cnt = m_dma16_cnt = 0;
729   m_ctrl8 = m_ctrl16 = 0;
730   m_dac_fifo_ctrl = m_adc_fifo_ctrl = 0;
731   m_adc_fifo_head = m_dac_fifo_head = 1;
732   m_adc_fifo_tail = m_dac_fifo_tail = 0;
733   m_dac_r = m_adc_r = false;
734   m_dac_h = m_adc_h = false;
735   m_irq8 = m_irq16 = m_irq_midi = false;
736   m_dma8_done = m_dma16_done = false;
737}
738
739void sb16_lle_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
740{
741   UINT16 dacl = 0, dacr = 0, adcl = 0, adcr = 0;
742   if(m_mode & 2)
743   {
744      // it might be possible to run the adc though dma simultaneously but the rom doesn't appear to permit it
745      if(!(m_ctrl8 & 2))
746         m_cpu->set_input_line(MCS51_INT0_LINE, ASSERT_LINE);
747      return;
748   }
749   if(m_mode & 1)
750   {
751      switch(m_mode & 0xa0) // dac 16
752      {
753         case 0x00: // unsigned stereo
754            dacl = (m_dac_fifo[m_dac_fifo_tail].h[0] - 0x8000);
755            dacr = (m_dac_fifo[m_dac_fifo_tail].h[1] - 0x8000);
756            break;
757         case 0x20: // signed stereo
758            dacl = m_dac_fifo[m_dac_fifo_tail].h[0];
759            dacr = m_dac_fifo[m_dac_fifo_tail].h[1];
760            break;
761         case 0x80: // unsigned mono
762            dacl = (m_dac_fifo[m_dac_fifo_tail].h[0] - 0x8000);
763            dacr = (m_dac_fifo[m_dac_fifo_tail].h[0] - 0x8000);
764            break;
765         case 0xa0: // signed mono
766            dacl = m_dac_fifo[m_dac_fifo_tail].h[0];
767            dacr = m_dac_fifo[m_dac_fifo_tail].h[0];
768            break;
769      }
770      switch(m_mode & 0x50) // adc 8; placeholder
771      {
772         case 0x00: // unsigned stereo
773            adcl = 0;
774            adcr = 0;
775            break;
776         case 0x10: // signed stereo
777            adcl = 0;
778            adcr = 0;
779            break;
780         case 0x40: // unsigned mono
781            adcl = 0;
782            adcr = 0;
783            break;
784         case 0x50: // signed mono
785            adcl = 0;
786            adcr = 0;
787            break;
788      }
789   }
790   else
791   {
792      switch(m_mode & 0x50) // dac 8
793      {
794         case 0x00: // unsigned stereo
795            dacl = (m_dac_fifo[m_dac_fifo_tail].b[0] - 0x80) << 8;
796            dacr = (m_dac_fifo[m_dac_fifo_tail].b[2] - 0x80) << 8;
797            break;
798         case 0x10: // signed stereo
799            dacl = m_dac_fifo[m_dac_fifo_tail].b[0] << 8;
800            dacr = m_dac_fifo[m_dac_fifo_tail].b[2] << 8;
801            break;
802         case 0x40: // unsigned mono
803            dacl = (m_dac_fifo[m_dac_fifo_tail].b[0] - 0x80) << 8;
804            dacr = (m_dac_fifo[m_dac_fifo_tail].b[0] - 0x80) << 8;
805            break;
806         case 0x50: // signed mono
807            dacl = m_dac_fifo[m_dac_fifo_tail].b[0] << 8;
808            dacr = m_dac_fifo[m_dac_fifo_tail].b[0] << 8;
809            break;
810      }
811      switch(m_mode & 0xa0) // adc 16; placeholder
812      {
813         case 0x00: // unsigned stereo
814            adcl = 0;
815            adcr = 0;
816            break;
817         case 0x20: // signed stereo
818            adcl = 0;
819            adcr = 0;
820            break;
821         case 0x80: // unsigned mono
822            adcl = 0;
823            adcr = 0;
824            break;
825         case 0xa0: // signed mono
826            adcl = 0;
827            adcr = 0;
828            break;
829      }
830   }
831   m_dacr->write(dacr);
832   m_dacl->write(dacl);
833
834   if(!(m_ctrl8 & 2))
835      m_isa->drq1_w(1);
836
837   if(!(m_ctrl16 & 2))
838      m_isa->drq5_w(1);
839
840   if((!(m_ctrl8 & 2) && !(m_mode & 1)) || (!(m_ctrl16 & 2) && (m_mode & 1)))
841      ++m_dac_fifo_tail %= 16;
842
843   if((!(m_ctrl8 & 2) && (m_mode & 1)) || (!(m_ctrl16 & 2) && !(m_mode & 1)))
844   {
845      m_adc_fifo[m_adc_fifo_head].h[0] = adcl;
846      m_adc_fifo[m_adc_fifo_head].h[1] = adcr;
847      ++m_adc_fifo_head %= 16;
848   }
849}
Property changes on: trunk/src/emu/bus/isa/sb16.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/bus/isa/sb16.h
r0r32116
1#ifndef __SB16__
2#define __SB16__
3
4#include "emu.h"
5#include "isa.h"
6#include "sound/dac.h"
7#include "bus/pc_joy/pc_joy.h"
8#include "cpu/mcs51/mcs51.h"
9#include "sound/262intf.h"
10
11//*********************************************************************
12//   TYPE DEFINITIONS
13//*********************************************************************
14
15// ====================> sb16_device
16
17class sb16_lle_device : public device_t,
18               public device_isa16_card_interface
19{
20public:
21   // construction/destruction
22   sb16_lle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
23
24   // optional information overrides
25   virtual const rom_entry *device_rom_region() const;
26   virtual machine_config_constructor device_mconfig_additions() const;
27
28   required_device<dac_device> m_dacl;
29   required_device<dac_device> m_dacr;
30   required_device<pc_joy_device> m_joy;
31   required_device<cpu_device> m_cpu;
32
33   READ8_MEMBER( mpu401_r );
34   WRITE8_MEMBER( mpu401_w );
35
36   // mcu ports
37   DECLARE_READ8_MEMBER( dsp_data_r );
38   DECLARE_WRITE8_MEMBER( dsp_data_w );
39   DECLARE_READ8_MEMBER( p1_r );
40   DECLARE_WRITE8_MEMBER( p1_w );
41   DECLARE_READ8_MEMBER( p2_r );
42   DECLARE_WRITE8_MEMBER( p2_w );
43   DECLARE_WRITE8_MEMBER( rate_w );
44   DECLARE_READ8_MEMBER( dma8_r );
45   DECLARE_WRITE8_MEMBER( dma8_w );
46   DECLARE_READ8_MEMBER( ctrl8_r );
47   DECLARE_WRITE8_MEMBER( ctrl8_w );
48   DECLARE_READ8_MEMBER( ctrl16_r );
49   DECLARE_WRITE8_MEMBER( ctrl16_w );
50   DECLARE_READ8_MEMBER( dac_ctrl_r );
51   DECLARE_WRITE8_MEMBER( dac_ctrl_w );
52   DECLARE_READ8_MEMBER( dac_fifo_ctrl_r );
53   DECLARE_WRITE8_MEMBER( dac_fifo_ctrl_w );
54   DECLARE_READ8_MEMBER( adc_fifo_ctrl_r );
55   DECLARE_WRITE8_MEMBER( adc_fifo_ctrl_w );
56   DECLARE_READ8_MEMBER( dma_stat_r );
57   DECLARE_WRITE8_MEMBER( dac_data_w );
58   DECLARE_READ8_MEMBER( adc_data_r );
59   DECLARE_READ8_MEMBER( dma8_ready_r );
60   DECLARE_READ8_MEMBER( adc_data_ready_r );
61   DECLARE_READ8_MEMBER( dma8_cnt_lo_r );
62   DECLARE_READ8_MEMBER( dma8_cnt_hi_r );
63   DECLARE_WRITE8_MEMBER( dma8_len_lo_w );
64   DECLARE_WRITE8_MEMBER( dma8_len_hi_w );
65   DECLARE_WRITE8_MEMBER( dma16_len_lo_w );
66   DECLARE_WRITE8_MEMBER( dma16_len_hi_w );
67   DECLARE_READ8_MEMBER( mode_r );
68   DECLARE_WRITE8_MEMBER( mode_w );
69
70   // host ports
71   DECLARE_READ8_MEMBER( host_data_r );
72   DECLARE_WRITE8_MEMBER( host_cmd_w );
73   DECLARE_WRITE8_MEMBER( dsp_reset_w );
74   DECLARE_READ8_MEMBER( dsp_wbuf_status_r );
75   DECLARE_READ8_MEMBER( dsp_rbuf_status_r );
76   DECLARE_READ8_MEMBER( invalid_r );
77   DECLARE_WRITE8_MEMBER( invalid_w );
78
79protected:
80   // device-level overrides
81   virtual void device_start();
82   virtual void device_reset();
83
84   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
85   UINT8 dack_r(int line);
86   void dack_w(int line, UINT8 data);
87   UINT16 dack16_r(int line);
88   void dack16_w(int line, UINT16 data);
89private:
90   void control_timer(bool start);
91
92   // internal state
93   bool m_data_in;
94   UINT8 m_in_byte;
95   bool m_data_out;
96   UINT8 m_out_byte;
97
98   UINT8 m_freq, m_mode, m_dac_fifo_ctrl, m_adc_fifo_ctrl, m_ctrl8, m_ctrl16, m_bps, m_mpu_byte;
99   UINT16 m_dma8_len, m_dma16_len, m_dma8_cnt, m_dma16_cnt;
100   typedef union {
101      UINT32 w;
102      UINT16 h[2];
103      UINT8  b[4];
104   } samples;
105   samples m_adc_fifo[16], m_dac_fifo[16];
106   int m_adc_fifo_head, m_adc_fifo_tail, m_dac_fifo_head, m_dac_fifo_tail;
107   bool m_adc_r, m_dac_r, m_adc_h, m_dac_h, m_irq8, m_irq16, m_irq_midi;
108   bool m_dma8_done, m_dma16_done;
109
110   emu_timer *m_timer;
111};
112
113// device type definition
114
115extern const device_type ISA16_SB16;
116
117#endif
Property changes on: trunk/src/emu/bus/isa/sb16.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/bus/bus.mak
r32115r32116
380380BUSOBJS += $(BUSOBJ)/isa/finalchs.o
381381BUSOBJS += $(BUSOBJ)/isa/gblaster.o
382382BUSOBJS += $(BUSOBJ)/isa/gus.o
383BUSOBJS += $(BUSOBJ)/isa/sb16.o
383384BUSOBJS += $(BUSOBJ)/isa/hdc.o
384385BUSOBJS += $(BUSOBJ)/isa/ibm_mfc.o
385386BUSOBJS += $(BUSOBJ)/isa/mpu401.o
r32115r32116
407408BUSOBJS += $(BUSOBJ)/isa/3c503.o
408409BUSOBJS += $(BUSOBJ)/isa/ne1000.o
409410BUSOBJS += $(BUSOBJ)/isa/ne2000.o
411BUSOBJS += $(BUSOBJ)/isa/3c505.o
410412BUSOBJS += $(BUSOBJ)/isa/lpt.o
411413BUSOBJS += $(BUSOBJ)/isa/p1_fdc.o
412414BUSOBJS += $(BUSOBJ)/isa/p1_hdc.o
r32115r32116
415417BUSOBJS += $(BUSOBJ)/isa/mc1502_rom.o
416418BUSOBJS += $(BUSOBJ)/isa/xsu_cards.o
417419BUSOBJS += $(BUSOBJ)/isa/sc499.o
418BUSOBJS += $(BUSOBJ)/isa/3c505.o
419420BUSOBJS += $(BUSOBJ)/isa/aga.o
420421BUSOBJS += $(BUSOBJ)/isa/svga_trident.o
421422endif

Previous 199869 Revisions Next


© 1997-2024 The MAME Team