Previous 15994 Revisions Next

r14399 Thursday 9th February, 2012 at 10:06:52 UTC by Barry Rodewald
Very preliminary ISA Gravis Ultrasound device. Warning: sound output is not
perfect. [Barry Rodewald]
[src/mess/drivers]at.c
[src/mess/includes]at.h
[src/mess/machine]isa_gus.c* isa_gus.h*

src/mess/machine/isa_gus.c
r0r14399
1/*
2 *  Gravis Ultrasound ISA card
3 *
4 *  Started: 28/01/2012
5 */
6
7
8#include "emu.h"
9#include "isa_gus.h"
10#include "sound/speaker.h"
11#include "machine/6850acia.h"
12
13//**************************************************************************
14//  GLOBAL VARIABLES
15//**************************************************************************
16
17// uncomment this to save wave RAM content to a file
18//#define SAVE_WAVE_RAM 1
19//#define LOG_SOUND 1
20
21static const UINT16 rate_table[33] =
22{
23   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24   44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400,
25   28063, 26843, 25725, 24696, 23746, 22866, 22050, 21289,
26   20580, 19916, 19293
27};
28
29static const UINT16 volume_ramp_table[4] =
30{
31   1, 8, 64, 512
32};
33
34const device_type GGF1 = &device_creator<gf1_device>;
35const device_type ISA16_GUS = &device_creator<isa16_gus_device>;
36
37#ifdef LOG_SOUND
38FILE* f;
39#endif
40
41/* only the Adlib timers are implemented in hardware */
42READ8_MEMBER( gf1_device::adlib_r )
43{
44   UINT8 retVal = 0xff;
45   switch(offset)
46   {
47      case 0:
48         return m_adlib_status;
49         break;
50   }
51   return retVal;
52}
53
54WRITE8_MEMBER( gf1_device::adlib_w )
55{
56   switch(offset)
57   {
58      case 0:
59         m_adlib_cmd = data;
60         break;
61      case 1:
62         switch(m_adlib_cmd)
63         {
64         case 0x04:
65            if(data & 0x80)
66            {
67               m_timer1_irq_func(0);
68               m_timer2_irq_func(0);
69               m_adlib_status &= ~0xe0;
70               logerror("GUS: Timer flags reset\n");
71            }
72            else
73            {
74               if((data & 0x01) && !(data & 0x40))
75               {
76                  m_adlib_timer1_enable = 1;
77                  m_timer1->adjust(attotime::zero,0,attotime::from_usec(80));
78               }
79               if((data & 0x02) && !(data & 0x20))
80               {
81                  m_adlib_timer2_enable = 1;
82                  m_timer2->adjust(attotime::zero,0,attotime::from_usec(320));
83               }
84               if(!(data & 0x01) && !(data & 0x40))
85               {
86                  m_adlib_timer1_enable = 0;
87                  m_timer1->adjust(attotime::zero,0,attotime::never);
88               }
89               if(!(data & 0x02) && !(data & 0x20))
90               {
91                  m_adlib_timer2_enable = 0;
92                  m_timer2->adjust(attotime::zero,0,attotime::never);
93               }
94               logerror("GUS: Timer enable - %02x\n",data);
95            }
96            m_adlib_timer_cmd = data;
97            break;
98         default:
99            logerror("GUS: Invalid Adlib register write %02x\n",m_adlib_cmd);
100         }
101         break;
102   }
103}
104
105void gf1_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
106{
107   int x;
108
109   switch(id)
110   {
111   case ADLIB_TIMER1:
112      if(m_adlib_timer1_enable != 0)
113      {
114         m_timer1_count++;
115         if(m_timer1_count == 0xff)
116         {
117            m_adlib_status |= 0xc0;
118            m_timer1_count = m_timer1_value;
119            if(m_timer_ctrl & 0x04)
120               m_timer1_irq_func(1);
121         }
122      }
123      break;
124   case ADLIB_TIMER2:
125      if(m_adlib_timer2_enable != 0)
126      {
127         m_timer2_count++;
128         if(m_timer2_count == 0xff)
129         {
130            m_adlib_status |= 0xa0;
131            m_timer2_count = m_timer2_value;
132            if(m_timer_ctrl & 0x08)
133               m_timer2_irq_func(1);
134         }
135      }
136      break;
137   case DMA_TIMER:
138      if(!(m_dma_dram_ctrl & 0x02))  // transfer direction (1=read from DRAM, 0=write to DRAM)
139         m_drq1(1);
140      break;
141   case VOL_RAMP_TIMER:
142      for(x=0;x<32;x++)
143      {
144         if(!(m_voice[x].vol_ramp_ctrl & 0x01))  // if ramping is enabled
145         {
146            m_voice[x].vol_count++;
147            if(m_voice[x].vol_count % volume_ramp_table[(m_voice[x].vol_ramp_rate & 0xc0)>>6] == 0)
148            {
149               // increase/decrease volume
150               if(m_voice[x].vol_ramp_ctrl & 0x40)
151               {
152                  //m_voice[x].current_vol = (m_voice[x].current_vol & 0xf000) | ((m_voice[x].current_vol & 0x0ff0) + ((m_voice[x].vol_ramp_rate & 0x0f)<<8));
153                  m_voice[x].current_vol -= ((m_voice[x].vol_ramp_rate & 0x3f) << 6);
154                  if(m_voice[x].current_vol <= (m_voice[x].vol_ramp_start << 8))  // end of ramp?
155                  {
156                     if(m_voice[x].vol_ramp_ctrl & 0x08)
157                     {
158                        if(m_voice[x].vol_ramp_ctrl & 0x10)
159                           m_voice[x].vol_ramp_ctrl &= ~0x40; // change direction and continue
160                        else
161                           m_voice[x].current_vol = (m_voice[x].vol_ramp_end << 8);
162                     }
163                     else
164                     {
165                        m_voice[x].vol_ramp_ctrl |= 0x01;  // stop volume ramp
166                        if(!(m_voice[x].vol_ramp_ctrl & 0x10))
167                           m_voice[x].current_vol = (m_voice[x].vol_ramp_end << 8);
168                     }
169                     if(m_voice[x].vol_ramp_ctrl & 0x20)
170                        set_irq(IRQ_VOLUME_RAMP,x);
171                  }
172               }
173               else
174               {
175                  //m_voice[x].current_vol = (m_voice[x].current_vol & 0xf000) | ((m_voice[x].current_vol & 0x0ff0) - ((m_voice[x].vol_ramp_rate & 0x0f)<<8));
176                  m_voice[x].current_vol += ((m_voice[x].vol_ramp_rate & 0x3f) << 6);
177                  if(m_voice[x].current_vol >= (m_voice[x].vol_ramp_end << 8))  // end of ramp?
178                  {
179                     if(m_voice[x].vol_ramp_ctrl & 0x08)
180                     {
181                        if(m_voice[x].vol_ramp_ctrl & 0x10)
182                           m_voice[x].vol_ramp_ctrl |= 0x40; // change direction and continue
183                        else
184                           m_voice[x].current_vol = (m_voice[x].vol_ramp_start << 8);
185                     }
186                     else
187                     {
188                        m_voice[x].vol_ramp_ctrl |= 0x01;  // stop volume ramp
189                        if(!(m_voice[x].vol_ramp_ctrl & 0x10))
190                           m_voice[x].current_vol = (m_voice[x].vol_ramp_start << 8);
191                     }
192                     if(m_voice[x].vol_ramp_ctrl & 0x20)
193                        set_irq(IRQ_VOLUME_RAMP,x);
194                  }
195               }
196            }
197         }
198      }
199      break;
200   }
201}
202
203void gf1_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
204{
205   int x,y;
206   //UINT32 count;
207
208   stream_sample_t* outputl = outputs[0];
209   stream_sample_t* outputr = outputs[1];
210   memset( outputl, 0x00, samples * sizeof(*outputl) );
211   memset( outputr, 0x00, samples * sizeof(*outputr) );
212
213   for(x=0;x<32;x++)  // for each voice
214   {
215      if(!(m_voice[x].voice_ctrl & 0x01))
216      {
217         stream_sample_t* left = outputl;
218         stream_sample_t* right = outputr;
219         UINT32 vol = (m_volume_table[(m_voice[x].current_vol & 0xfff0) >> 4]);
220         for(y=samples-1; y>=0; y--)
221         {
222            UINT32 current = m_voice[x].current_addr >> 9;
223            if((!(m_voice[x].voice_ctrl & 0x40)) && (m_voice[x].current_addr >= m_voice[x].end_addr) && !m_voice[x].rollover && !(m_voice[x].voice_ctrl & 0x01))
224            {
225               if(m_voice[x].vol_ramp_ctrl & 0x04)
226               {
227                  m_voice[x].rollover = true;  // set roll over condition - generate IRQ, but keep voice playing
228               }
229
230               // end voice, unless looping, or rollover is active, which disables looping
231               if(!m_voice[x].rollover)
232               {
233                  if(!(m_voice[x].voice_ctrl & 0x08))
234                     m_voice[x].voice_ctrl |= 0x01;
235                  {
236                     if(m_voice[x].voice_ctrl & 0x10)
237                        m_voice[x].voice_ctrl |= 0x40; // change direction
238                     else
239                        m_voice[x].current_addr = m_voice[x].start_addr; // start sample again
240                  }
241               }
242               if(m_voice[x].voice_ctrl & 0x20)
243                  set_irq(IRQ_WAVETABLE,x);
244            }
245            if((m_voice[x].voice_ctrl & 0x40) && (m_voice[x].current_addr <= m_voice[x].start_addr) && !m_voice[x].rollover && !(m_voice[x].voice_ctrl & 0x01))
246            {
247               if(m_voice[x].vol_ramp_ctrl & 0x04)
248               {
249                  m_voice[x].rollover = true;  // set roll over condition - generate IRQ, but keep voice playing
250               }
251
252               // end voice, unless looping, or rollover is active, which disables looping
253               if(!m_voice[x].rollover)
254               {
255                  // end voice, unless looping
256                  if(!(m_voice[x].voice_ctrl & 0x08))
257                     m_voice[x].voice_ctrl |= 0x01;
258                  {
259                     if(m_voice[x].voice_ctrl & 0x10)
260                        m_voice[x].voice_ctrl &= ~0x40; // change direction
261                     else
262                        m_voice[x].current_addr = m_voice[x].end_addr; // start sample again
263                  }
264               }
265               if(m_voice[x].voice_ctrl & 0x20)
266                  set_irq(IRQ_WAVETABLE,x);
267            }
268            if(m_voice[x].voice_ctrl & 0x20)
269            {  // 16-bit PCM (needs some work)
270               m_voice[x].sample = (m_wave_ram[(current & 0xffffe)+1] & 0x7f);
271               //m_voice[x].sample |= (m_wave_ram[current & 0xffffe]) >> 6;
272               if(m_wave_ram[(current & 0xffffe)+1] & 0x80)
273                  m_voice[x].sample = -m_voice[x].sample;
274            }
275            else
276            {  // 8-bit PCM
277               m_voice[x].sample = (m_wave_ram[current & 0xfffff] & 0x7f);
278               if(m_wave_ram[current & 0xfffff] & 0x80)
279                  m_voice[x].sample = -m_voice[x].sample;
280            }
281            // TODO: implement proper panning
282            (*left) += ((m_voice[x].sample) * (vol/256));
283            (*right) += ((m_voice[x].sample) * (vol/256));
284            left++;
285            right++;
286            if(m_voice[x].voice_ctrl & 0x40)  // voice direction
287               m_voice[x].current_addr -= (m_voice[x].freq_ctrl >> 1);
288            else
289               m_voice[x].current_addr += (m_voice[x].freq_ctrl >> 1);
290#ifdef LOG_SOUND
291            INT32 smp = (m_voice[x].sample) * (vol / 32);
292            fwrite(&smp,4,1,f);
293#endif
294         }
295      }
296   }
297}
298
299//**************************************************************************
300//  LIVE DEVICE
301//**************************************************************************
302
303//-------------------------------------------------
304//  gf1_device - constructor
305//-------------------------------------------------
306
307gf1_device::gf1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
308      : device_t(mconfig, GGF1, "Gravis GF1", tag, owner, clock),
309        device_sound_interface( mconfig, *this )
310{
311}
312
313void gf1_device::device_config_complete()
314{
315   // inherit a copy of the static data
316   const gf1_interface *intf = reinterpret_cast<const gf1_interface *>(static_config());
317   if (intf != NULL)
318      *static_cast<gf1_interface *>(this) = *intf;
319
320   // or initialize to defaults if none provided
321   else
322   {
323      memset(&wave_irq_cb, 0, sizeof(wave_irq_cb));
324      memset(&ramp_irq_cb, 0, sizeof(ramp_irq_cb));
325      memset(&timer1_irq_cb, 0, sizeof(timer1_irq_cb));
326      memset(&timer2_irq_cb, 0, sizeof(timer2_irq_cb));
327      memset(&dma_irq_cb, 0, sizeof(dma_irq_cb));
328      memset(&drq1_cb, 0, sizeof(drq1_cb));
329      memset(&drq2_cb, 0, sizeof(drq2_cb));
330   }
331}
332
333//-------------------------------------------------
334//  device_start - device-specific startup
335//-------------------------------------------------
336
337void gf1_device::device_start()
338{
339   // TODO: make DRAM size configurable.  Can be 256k, 512k, 768k, or 1024k
340   m_wave_ram = auto_alloc_array(machine(),UINT8,1024*1024);
341   memset(m_wave_ram,0,1024*1024);
342
343   m_stream = stream_alloc(0,2,44100);
344
345   // init timers
346   m_timer1 = timer_alloc(ADLIB_TIMER1);
347   m_timer2 = timer_alloc(ADLIB_TIMER2);
348   m_dmatimer = timer_alloc(DMA_TIMER);
349   m_voltimer = timer_alloc(VOL_RAMP_TIMER);
350
351   save_pointer(NAME(m_wave_ram),1024*1024);
352
353   m_wave_irq_func.resolve(wave_irq_cb, *this);
354   m_ramp_irq_func.resolve(ramp_irq_cb, *this);
355   m_timer1_irq_func.resolve(timer1_irq_cb, *this);
356   m_timer2_irq_func.resolve(timer2_irq_cb, *this);
357   m_dma_irq_func.resolve(dma_irq_cb, *this);
358   m_drq1.resolve(drq1_cb,*this);
359   m_drq2.resolve(drq2_cb,*this);
360
361   m_voice_irq_current = 0;
362   m_voice_irq_ptr = 0;
363
364    for (int i = 0; i<4096; i++)
365       m_volume_table[i] = 65536 / ((4096-i)*(log(2)/256));
366
367#ifdef LOG_SOUND
368   f = fopen("soundlog.bin","wb");
369#endif
370}
371
372//-------------------------------------------------
373//  device_reset - device-specific reset
374//-------------------------------------------------
375
376void gf1_device::device_reset()
377{
378   int x;
379
380   // init voices
381   for(x=0;x<32;x++)
382   {
383      m_voice[x].voice_ctrl = 0x01;  // stop all voices
384      m_voice[x].vol_ramp_ctrl = 0x01; // stop all volume ramps
385   }
386   m_irq_source = 0xe0;
387   m_active_voices = 14;
388   m_stream->set_sample_rate(44100);
389   m_voltimer->adjust(attotime::zero,0,attotime::from_usec(1000/(1.6*m_active_voices)));
390}
391
392void gf1_device::device_stop()
393{
394#ifdef SAVE_WAVE_RAM
395   FILE* f;
396   f=fopen("waveout.bin","wb");
397   fwrite(m_wave_ram,1024*1024,1,f);
398   fclose(f);
399#endif
400#ifdef LOG_SOUND
401   fclose(f);
402#endif
403}
404// ------------------------------------------------
405//   device I/O handlers
406// ------------------------------------------------
407
408READ8_MEMBER(gf1_device::global_reg_select_r)
409{
410   if(offset == 0)
411      return m_current_voice;
412   else
413      return m_current_reg;
414}
415
416WRITE8_MEMBER(gf1_device::global_reg_select_w)
417{
418   if(offset == 0)
419      m_current_voice = data & 0x1f;
420   else
421      m_current_reg = data;
422}
423
424READ8_MEMBER(gf1_device::global_reg_data_r)
425{
426   UINT16 ret = 0x00;
427
428   switch(m_current_reg)
429   {
430   case 0x41:  // DMA DRAM control
431      if(offset == 1)
432      {
433         ret = m_dma_dram_ctrl;
434         m_dma_dram_ctrl &= ~0x40;
435         m_dma_irq_func(0);
436         return ret;
437      }
438   case 0x45:  // Timer control
439      if(offset == 1)
440         return m_timer_ctrl & 0x0c;
441      break;
442   case 0x49:  // Sampling control
443      if(offset == 1)
444         return m_sampling_ctrl & 0xe7;
445   case 0x4c:  // Reset
446      if(offset == 1)
447         return m_reset;
448   case 0x80: // Voice control
449/* bit 0 - 1 if voice is stopped
450 * bit 6 - 1 if addresses are decreasing, can change when looping is enabled
451 * bit 7 - 1 if Wavetable IRQ is pending */
452      if(offset == 1)
453         return m_voice[m_current_voice].voice_ctrl;
454   case 0x81:  // Frequency Control
455      ret = m_voice[m_current_voice].freq_ctrl;
456      if(offset == 0)
457         return ret & 0x00ff;
458      else
459         return (ret >> 8) & 0x00ff;
460   case 0x82:  // Starting address (high 13 bits)
461      ret = (m_voice[m_current_voice].start_addr >> 16);
462      if(offset == 0)
463         return ret & 0x00ff;
464      else
465         return (ret >> 8) & 0x00ff;
466   case 0x83:  // Starting address (low 7 bits plus 4 bits fractional)
467      ret = (m_voice[m_current_voice].start_addr & 0xffff);
468      if(offset == 0)
469         return ret & 0x00ff;
470      else
471         return (ret >> 8) & 0x00ff;
472   case 0x84:  // End address (high 13 bits)
473      ret = (m_voice[m_current_voice].end_addr >> 16);
474      if(offset == 0)
475         return ret & 0x00ff;
476      else
477         return (ret >> 8) & 0x00ff;
478   case 0x85:  // End address (low 7 bits plus 4 bits fractional)
479      ret = (m_voice[m_current_voice].end_addr & 0xffff);
480      if(offset == 0)
481         return ret & 0x00ff;
482      else
483         return (ret >> 8) & 0x00ff;
484   case 0x86:  // Volume Ramp rate
485      if(offset == 1)
486         return m_voice[m_current_voice].vol_ramp_rate;
487   case 0x87:  // Volume Ramp start (high 4 bits = exponent, low 4 bits = mantissa)
488      if(offset == 1)
489         return m_voice[m_current_voice].vol_ramp_start;
490   case 0x88:  // Volume Ramp end (high 4 bits = exponent, low 4 bits = mantissa)
491      if(offset == 1)
492         return m_voice[m_current_voice].vol_ramp_end;
493   case 0x89:  // Current Volume (high 4 bits = exponent, middle 8 bits = mantissa, low 4 bits = 0 [reserved])
494      ret = m_voice[m_current_voice].current_vol;
495      if(offset == 0)
496         return ret & 0x00ff;
497      else
498         return (ret >> 8) & 0x00ff;
499   case 0x8a:  // Current position (high 13 bits)
500      ret = (m_voice[m_current_voice].current_addr >> 16);
501      if(offset == 0)
502         return ret & 0x00ff;
503      else
504         return (ret >> 8) & 0x00ff;
505   case 0x8b:  // Current position (low 7 bits, plus 9 bit fractional)
506      ret = (m_voice[m_current_voice].current_addr & 0xffff);
507      if(offset == 0)
508         return ret & 0x00ff;
509      else
510         return (ret >> 8) & 0x00ff;
511   case 0x8c:  // Pan position (4 bits, 0=full left, 15=full right)
512      if(offset == 1)
513         return m_voice[m_current_voice].pan_position;
514   case 0x8d:  // Volume Ramp control
515/* bit 0 - Ramp has stopped
516 * bit 6 - Ramp direction
517 * bit 7 - Ramp IRQ pending */
518      if(offset == 1)
519         return m_voice[m_current_voice].vol_ramp_ctrl;
520   case 0x8e:  // Active voices (6 bits, high 2 bits are always 1)
521      if(offset == 1)
522         return m_active_voices | 0xc0;
523   case 0x8f:  // IRQ source register
524      if(offset == 1)
525      {
526         ret = m_voice_irq_fifo[m_voice_irq_current % 32];
527         if((m_voice_irq_current % 32) != (m_voice_irq_ptr % 32))
528            m_voice_irq_current++;
529         else
530            ret = 0xe0;
531         m_wave_irq_func(0);
532         m_ramp_irq_func(0);
533         return ret;
534      }
535      break;
536   default:
537      logerror("GUS: Read from unimplemented or unknown global register %02x\n",m_current_reg);
538      return 0xff;
539   }
540   return 0xff;
541}
542
543WRITE8_MEMBER(gf1_device::global_reg_data_w)
544{
545   switch(m_current_reg)
546   {
547   case 0x00: // Voice control
548/* bit 1 - set to 1 to stop current voice
549 * bit 2 - set to 1 for 16-bit wave data, otherwise is 8-bit
550 * bit 3 - set to 1 to loop to start address when the end address is reached
551 * bit 4 - set to 1 to enable bi-directional looping
552 * bit 5 - set to 1 to enable wavetable IRQ when end address is reached */
553      if(offset == 1)
554      {
555         m_voice[m_current_voice].voice_ctrl = data & 0x7f;
556         m_voice[m_current_voice].rollover = false;
557         if(data & 0x02)
558         {
559            m_voice[m_current_voice].voice_ctrl |= 0x01;
560         }
561      }
562      logerror("GUS: Ch%i Voice control write %02x\n", m_current_voice,data);
563      break;
564   case 0x01: // Frequency Control
565/* bits 15-10 - Integer portion
566 * bits 9-1   - Fractional portion
567 * bit 0      - not used */
568      if(offset == 0)
569         m_voice[m_current_voice].freq_ctrl = (m_voice[m_current_voice].freq_ctrl & 0xff00) | data;
570      else
571         m_voice[m_current_voice].freq_ctrl = (m_voice[m_current_voice].freq_ctrl & 0x00ff) | (data << 8);
572      logerror("GUS: Ch%i Frequency control write %04x\n", m_current_voice, m_voice[m_current_voice].freq_ctrl);
573      break;
574   case 0x02:  // Starting address (high 13 bits)
575      if(offset == 0)
576         m_voice[m_current_voice].start_addr = (m_voice[m_current_voice].start_addr & 0xff00ffff) | (data << 16);
577      else
578         m_voice[m_current_voice].start_addr = (m_voice[m_current_voice].start_addr & 0x00ffffff) | (data << 24);
579      logerror("GUS: Ch%i [high] Start address set to %08x\n", m_current_voice,m_voice[m_current_voice].start_addr);
580      break;
581   case 0x03:  // Starting address (low 7 bits plus 4 bits fractional)
582      if(offset == 0)
583         m_voice[m_current_voice].start_addr = (m_voice[m_current_voice].start_addr & 0xffffff00) | data;
584      else
585         m_voice[m_current_voice].start_addr = (m_voice[m_current_voice].start_addr & 0xffff00ff) | (data << 8);
586      logerror("GUS: Ch%i [low] Start address set to %08x\n", m_current_voice,m_voice[m_current_voice].start_addr);
587      break;
588   case 0x04:  // End address (high 13 bits)
589      if(offset == 0)
590         m_voice[m_current_voice].end_addr = (m_voice[m_current_voice].end_addr & 0xff00ffff) | (data << 16);
591      else
592         m_voice[m_current_voice].end_addr = (m_voice[m_current_voice].end_addr & 0x00ffffff) | (data << 24);
593      logerror("GUS: Ch%i [high] End address set to %08x\n", m_current_voice,m_voice[m_current_voice].end_addr);
594      break;
595   case 0x05:  // End address (low 7 bits plus 4 bits fractional)
596      if(offset == 0)
597         m_voice[m_current_voice].end_addr = (m_voice[m_current_voice].end_addr & 0xffffff00) | data;
598      else
599         m_voice[m_current_voice].end_addr = (m_voice[m_current_voice].end_addr & 0xffff00ff) | (data << 8);
600      logerror("GUS: Ch%i [low] End address set to %08x\n", m_current_voice,m_voice[m_current_voice].end_addr);
601      break;
602   case 0x06:  // Volume Ramp rate
603      if(offset == 1)
604         m_voice[m_current_voice].vol_ramp_rate = data;
605      logerror("GUS: Ch%i Volume ramp rate write %02x\n", m_current_voice,data);
606      break;
607   case 0x07:  // Volume Ramp start (high 4 bits = exponent, low 4 bits = mantissa)
608      if(offset == 1)
609         m_voice[m_current_voice].vol_ramp_start = data;
610      logerror("GUS: Ch%i Volume ramp start write %02x\n", m_current_voice, data);
611      break;
612   case 0x08:  // Volume Ramp end (high 4 bits = exponent, low 4 bits = mantissa)
613      if(offset == 1)
614         m_voice[m_current_voice].vol_ramp_end = data;
615      logerror("GUS: Ch%i Volume ramp end write %02x\n", m_current_voice, data);
616      break;
617   case 0x09:  // Current Volume (high 4 bits = exponent, middle 8 bits = mantissa, low 4 bits = 0 [reserved])
618      if(offset == 0)
619         m_voice[m_current_voice].current_vol = (m_voice[m_current_voice].current_vol & 0xff00) | data;
620      else
621         m_voice[m_current_voice].current_vol = (m_voice[m_current_voice].current_vol & 0x00ff) | (data << 8);
622      logerror("GUS: Ch%i Current volume write %02x\n", m_current_voice, data);
623      break;
624   case 0x0a:  // Current position (high 13 bits)
625      if(offset == 0)
626         m_voice[m_current_voice].current_addr = (m_voice[m_current_voice].current_addr & 0xff00ffff) | (data << 16);
627      else
628         m_voice[m_current_voice].current_addr = (m_voice[m_current_voice].current_addr & 0x00ffffff) | (data << 24);
629      logerror("GUS: Ch%i Current address write %08x\n", m_current_voice, m_voice[m_current_voice].current_addr);
630      break;
631   case 0x0b:  // Current position (low 7 bits, plus 9 bit fractional)
632      if(offset == 0)
633         m_voice[m_current_voice].current_addr = (m_voice[m_current_voice].current_addr & 0xffffff00) | data;
634      else
635         m_voice[m_current_voice].current_addr = (m_voice[m_current_voice].current_addr & 0xffff00ff) | (data << 8);
636      logerror("GUS: Ch%i Current address write %08x\n", m_current_voice, m_voice[m_current_voice].current_addr);
637      break;
638   case 0x0c:  // Pan position (4 bits, 0=full left, 15=full right)
639      if(offset == 1)
640         m_voice[m_current_voice].pan_position = data & 0x0f;
641      logerror("GUS: Ch%i Pan Position write %02x\n", m_current_voice, data);
642      break;
643   case 0x0d:  // Volume Ramp control
644/* bit 1 - set to 1 to stop the ramp
645 * bit 2 - roll over condition (generate IRQ, and not stop playing voice, no looping)
646 * bit 3 - enable looping
647 * bit 4 - enable bi-directional looping
648 * bit 5 - rnable IRQ at end of ramp */
649      if(offset == 1)
650      {
651         m_voice[m_current_voice].vol_ramp_ctrl = data & 0x7f;
652         if(!(data & 0x01))
653            m_voice[m_current_voice].vol_count = 0;
654         if(data & 0x02)
655         {
656            m_voice[m_current_voice].vol_ramp_ctrl |= 0x01;
657         }
658      }
659      logerror("GUS: Ch%i Volume Ramp control write %02x\n", m_current_voice, data);
660      break;
661   case 0x0e:  // Active voices (6 bits, high 2 bits are always 1)
662      if(offset == 1)
663      {
664         m_active_voices = data & 0x3f;
665         if((data & 0x3f) < 14)
666            m_active_voices = 14;
667         if((data & 0x3f) > 32)
668            m_active_voices = 32;
669         m_stream->set_sample_rate(rate_table[m_active_voices]);
670         m_voltimer->adjust(attotime::zero,0,attotime::from_usec(1000/(1.6*m_active_voices)));
671      }
672      logerror("GUS: Active Voices write %02x (%i Hz)\n", data, rate_table[m_active_voices]);
673      break;
674   case 0x41:
675/* bit 0 - Enable the DMA channel.
676 * bit 1 - DMA transfer direction (1 = read from the GUS)
677 * bit 2 - DMA channel width (0=8-bit, 1=16-bit)
678 * bits 3,4 - DMA rate divider
679 * bit 5 - DMA terminal count IRQ enable
680 * bit 6 - DMA terminal count IRQ pending (read), Data size (write, 0=8bit, 1=16-bit, independant of channel size)
681 * bit 7 - Invert MSB of data
682 */
683      if(offset == 1)
684      {
685         m_dma_dram_ctrl = data & 0xbf;
686         m_dma_16bit = data & 0x40;
687         if(data & 0x01)
688            m_dmatimer->adjust(attotime::zero,0,attotime::from_nsec(500));  // a guess for now
689         else
690            m_dmatimer->adjust(attotime::zero,0,attotime::never);  // stop transfer
691      }
692      logerror("GUS: DMA DRAM control write %02x\n",data);
693      break;
694   case 0x42:  // DMA start address (high 16 bits, address lines 4-19)
695      if(offset == 0)
696         m_dma_start_addr = (m_dma_start_addr & 0xff00) | data;
697      else
698         m_dma_start_addr = (m_dma_start_addr & 0x00ff) | (data << 8);
699      m_dma_current = m_dma_start_addr << 4;
700      logerror("GUS: DMA start address set to %08x\n",m_dma_start_addr);
701      break;
702   case 0x43:  // DRAM I/O address (low 16 bits)
703      if(offset == 0)
704         m_dram_addr = (m_dram_addr & 0x000fff00) | data;
705      else
706         m_dram_addr = (m_dram_addr & 0x000f00ff) | (data << 8);
707      //logerror("GUS: [low] DRAM I/O address set to %08x\n",m_dram_addr);
708      break;
709   case 0x44:  // DRAM I/O address (high 4 bits)
710      if(offset == 1)
711         m_dram_addr = (m_dram_addr & 0x0000ffff) | (data << 16);
712      //logerror("GUS: [high] DRAM I/O address set to %08x\n",m_dram_addr);
713      break;
714   case 0x45:  // Timer control
715/* bit 3 - Enable timer 1 IRQ
716 * bit 4 - Enable timer 2 IRQ */
717      if(offset == 1)
718      {
719         m_timer_ctrl = data;
720         if(!(data & 0x04))
721         {
722            m_adlib_status &= ~0x40;
723            m_timer1_irq_func(0);
724         }
725         if(!(data & 0x08))
726         {
727            m_adlib_status &= ~0x20;
728            m_timer2_irq_func(0);
729         }
730         if((m_adlib_status & 0x60) != 0)
731            m_adlib_status &= ~0x80;
732      }
733      logerror("GUS: Timer control write %02x\n",data);
734      break;
735   case 0x46:  // Timer 1 count
736      if(offset == 1)
737      {
738         m_timer1_count = data;
739         m_timer1_value = data;
740         logerror("GUS: Timer 1 count write %02x\n",data);
741      }
742      break;
743   case 0x47:  // Timer 2 count
744      if(offset == 1)
745      {
746         m_timer2_count = data;
747         m_timer2_value = data;
748         logerror("GUS: Timer 2 count write %02x\n",data);
749      }
750      break;
751   case 0x48:  // Sampling Frequency - 9878400/(16*(FREQ+2))
752      if(offset == 0)
753         m_sampling_freq = (m_sampling_freq & 0xff00) | data;
754      else
755         m_sampling_freq = (m_sampling_freq & 0x00ff) | (data << 8);
756      logerror("GUS: Sampling frequency write %02x\n",data);
757      break;
758   case 0x49: // Sampling control
759/* bit 0 - Start sampling
760 * bit 1 - Mode (0=mono, 1=stereo)
761 * bit 2 - DMA width (0=8-bit, 1=16-bit)
762 * bit 5 - DMA IRQ enable
763 * bit 6 - DMA IRQ pending (read only)
764 * bit 7 - Invert MSB */
765      if(offset == 1)
766         m_sampling_ctrl = data;
767      logerror("GUS: Sampling control write %02x\n",data);
768      break;
769   case 0x4b:  // Joystick trim DAC
770      if(offset == 1)
771         m_joy_trim_dac = data;
772      logerror("GUS: Joystick trim DAC write %02x\n",data);
773      break;
774   case 0x4c:  // Reset
775      if(offset == 1)
776      {
777         if(!(data & 0x01))
778            device_reset();
779         m_reset = data;
780      }
781      logerror("GUS: Reset write %02x\n",data);
782      break;
783   default:
784      logerror("GUS: Write %02x to unimplemented or unknown global register %02x\n",data,m_current_reg);
785   }
786}
787
788/* port 0x3X7 - DRAM I/O
789 * read and write bytes directly to wavetable DRAM */
790READ8_MEMBER(gf1_device::dram_r)
791{
792   if(offset == 1)
793   {
794      return m_wave_ram[m_dram_addr & 0xfffff];
795   }
796   else
797      return 0xff;
798}
799
800WRITE8_MEMBER(gf1_device::dram_w)
801{
802   if(offset == 1)
803   {
804      m_wave_ram[m_dram_addr & 0xfffff] = data;
805   }
806}
807
808/* port 2XA - read selected adlib command?
809 * the GUS driver installation writes 0x55 to port 0x388, then expects to reads the same from 0x2XA */
810READ8_MEMBER(gf1_device::adlib_cmd_r)
811{
812   if(offset == 0)
813   {
814      return m_adlib_cmd;
815   }
816   else
817   {
818      // TODO
819      return 0xff;
820   }
821}
822
823/* port 0x2XB - set IRQ/DMA latch
824 * if IRQ (bit 6 of 0x2X0 = 1)
825 * bits 2-0 = channel 1 (GF1) IRQ selector
826 * 0 = reserved, 1 = IRQ2, 2 = IRQ5, 3 = IRQ3, 4 = IRQ7, 5 = IRQ11, 6 = IRQ12, 7 = IRQ13
827 * bits 5-3 = channel 2 (MIDI) IRQ selector
828 * 0 = No interrupt selected, rest are as for the GF1
829 * bit 6 = combine both IRQs using channel 1 IRQ
830 * if DMA (bit 6 of 0x2X0 = 0)
831 * bits 2-0 = DMA select register 1
832 * 0 = No DMA, 1 = DMA1, 2 = DMA3, 3 = DMA5, 4 = DMA6, 5 = DMA7
833 * bits 5-3 = DMA select register 2 (values same as reg 1)
834 * bit 6 = combine both on same DMA channel
835 */
836WRITE8_MEMBER(gf1_device::adlib_cmd_w)
837{
838   if(offset == 1)
839   {
840      if(m_mix_ctrl & 0x40)
841      {
842         switch(data & 0x07)
843         {
844         case 1:
845            m_gf1_irq = 2;
846            break;
847         case 2:
848            m_gf1_irq = 5;
849            break;
850         case 3:
851            m_gf1_irq = 3;
852            break;
853         case 4:
854            m_gf1_irq = 7;
855            break;
856         case 5:
857            m_gf1_irq = 11;
858            break;
859         case 6:
860            m_gf1_irq = 12;
861            break;
862         case 7:
863            m_gf1_irq = 15;
864            break;
865         default:
866            logerror("GUS: Invalid GF1 IRQ set! [%02x]\n",data);
867         }
868         switch((data >> 3) & 0x07)
869         {
870         case 0:
871            m_midi_irq = 0;
872            break;
873         case 1:
874            m_midi_irq = 2;
875            break;
876         case 2:
877            m_midi_irq = 5;
878            break;
879         case 3:
880            m_midi_irq = 3;
881            break;
882         case 4:
883            m_midi_irq = 7;
884            break;
885         case 5:
886            m_midi_irq = 11;
887            break;
888         case 6:
889            m_midi_irq = 12;
890            break;
891         case 7:
892            m_midi_irq = 15;
893            break;
894         default:
895            logerror("GUS: Invalid MIDI IRQ set! [%02x]\n",data);
896         }
897         if(data & 0x40)
898            m_irq_combine = 1;
899         else
900            m_irq_combine = 0;
901         logerror("GUS: IRQs set: GF1 = IRQ%i, MIDI = IRQ%i\n",m_gf1_irq,m_midi_irq);
902      }
903      else
904      {
905         switch(data & 0x07)
906         {
907         case 0:
908            m_dma_channel1 = 0;
909            break;
910         case 1:
911            m_dma_channel1 = 1;
912            break;
913         case 2:
914            m_dma_channel1 = 3;
915            break;
916         case 3:
917            m_dma_channel1 = 5;
918            break;
919         case 4:
920            m_dma_channel1 = 6;
921            break;
922         case 5:
923            m_dma_channel1 = 7;
924            break;
925         default:
926            logerror("GUS: Invalid DMA channel #1 set! [%02x]\n",data);
927         }
928         switch((data >> 3) & 0x07)
929         {
930         case 0:
931            m_dma_channel2 = 0;
932            break;
933         case 1:
934            m_dma_channel2 = 1;
935            break;
936         case 2:
937            m_dma_channel2 = 3;
938            break;
939         case 3:
940            m_dma_channel2 = 5;
941            break;
942         case 4:
943            m_dma_channel2 = 6;
944            break;
945         case 5:
946            m_dma_channel2 = 7;
947            break;
948         default:
949            logerror("GUS: Invalid DMA channel #2 set! [%02x]\n",data);
950         }
951         if(data & 0x40)
952            m_dma_combine = 1;
953         else
954            m_dma_combine = 0;
955         logerror("GUS: DMA channels set: DMA%i, DMA%i\n",m_dma_channel1,m_dma_channel2);
956      }
957   }
958}
959
960/* port 0x2X0 - Mix control register
961 * bit 0 - 0=Enable Line In
962 * bit 1 - 0=Enable Line Out
963 * bit 2 - 1=Enable MIC In
964 * bit 3 - Enable latches (once enabled, must remain enabled)
965 * bit 4 - Combine GF1 IRQs with MIDI IRQs
966 * bit 5 - Enable MIDI TxD to RxD loopback
967 * bit 6 - Control Reg Select - set next I/O write to 0x2XB to be DMA (0) or IRQ (1) channel latches */
968READ8_MEMBER(gf1_device::mix_ctrl_r)
969{
970   return 0xff;  // read only
971}
972
973WRITE8_MEMBER(gf1_device::mix_ctrl_w)
974{
975   if(offset == 0)
976      m_mix_ctrl = data;
977}
978
979void gf1_device::set_irq(UINT8 source, UINT8 voice)
980{
981   if(source & IRQ_WAVETABLE)
982   {
983      m_irq_source = 0xe0 | (voice & 0x1f);
984      m_irq_source &= ~0x80;
985      m_wave_irq_func(1);
986      m_voice_irq_fifo[m_voice_irq_ptr % 32] = m_irq_source;
987      m_voice_irq_ptr++;
988   }
989   if(source & IRQ_VOLUME_RAMP)
990   {
991      m_irq_source = 0xe0 | (voice & 0x1f);
992      m_irq_source &= ~0x40;
993      m_ramp_irq_func(1);
994      m_voice_irq_fifo[m_voice_irq_ptr % 32] = m_irq_source;
995      m_voice_irq_ptr++;
996   }
997}
998
999void gf1_device::reset_irq(UINT8 source)
1000{
1001   if(source & IRQ_WAVETABLE)
1002   {
1003      m_irq_source |= 0x80;
1004      m_wave_irq_func(0);
1005   }
1006   if(source & IRQ_VOLUME_RAMP)
1007   {
1008      m_irq_source |= 0x40;
1009      m_ramp_irq_func(0);
1010   }
1011}
1012
1013// TODO: support 16-bit transfers
1014UINT8 gf1_device::dack_r(int line)
1015{
1016   m_drq1(0);
1017   return m_wave_ram[m_dma_current++ & 0xfffff];
1018}
1019
1020void gf1_device::dack_w(int line,UINT8 data)
1021{
1022   if(m_dma_dram_ctrl & 0x80)  // flip data MSB
1023   {
1024      if(m_dma_16bit != 0) // if data is 16-bit
1025      {
1026         if(!(m_dma_current & 1))
1027            data ^= 0x80;
1028      }
1029      else  // data is 8-bit
1030      {
1031         data ^= 0x80;
1032      }
1033   }
1034   m_wave_ram[m_dma_current & 0xfffff] = data;
1035   m_dma_current++;
1036   m_drq1(0);
1037}
1038
1039void gf1_device::eop_w(int state)
1040{
1041   // end of transfer
1042   if(m_dma_dram_ctrl & 0x20)
1043   {
1044      m_dmatimer->adjust(attotime::zero,0,attotime::never);
1045      m_dma_dram_ctrl |= 0x40;
1046      m_dma_irq_func(1);
1047   }
1048}
1049
1050
1051/* 16-bit ISA card device implementation */
1052
1053static const acia6850_interface gus_midi_interface =
1054{
1055   GF1_CLOCK,
1056   GF1_CLOCK,  // a guess for now
1057
1058   DEVCB_NULL,
1059   DEVCB_NULL,
1060
1061   DEVCB_NULL,
1062   DEVCB_NULL,
1063   DEVCB_NULL,
1064
1065   DEVCB_NULL
1066   //DEVCB_LINE_MEMBER(isa16_gus_device,midi_irq)
1067};
1068
1069static const gf1_interface gus_gf1_config =
1070{
1071   DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,isa16_gus_device,wavetable_irq),
1072   DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,isa16_gus_device,volumeramp_irq),
1073   DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,isa16_gus_device,timer1_irq),
1074   DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,isa16_gus_device,timer2_irq),
1075   DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,isa16_gus_device,dma_irq),
1076   DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,isa16_gus_device,drq1_w),
1077   DEVCB_NULL
1078};
1079
1080static MACHINE_CONFIG_FRAGMENT( gus_config )
1081   MCFG_SPEAKER_STANDARD_STEREO("lspeaker","rspeaker")
1082   MCFG_SOUND_ADD("gf1",GGF1,GF1_CLOCK)
1083   MCFG_SOUND_CONFIG(gus_gf1_config)
1084   MCFG_SOUND_ROUTE(0,"lspeaker",0.50)
1085   MCFG_SOUND_ROUTE(1,"rspeaker",0.50)
1086//   MCFG_ACIA6850_ADD("midi",gus_midi_interface)
1087MACHINE_CONFIG_END
1088
1089//-------------------------------------------------
1090//  machine_config_additions - device-specific
1091//  machine configurations
1092//-------------------------------------------------
1093
1094machine_config_constructor isa16_gus_device::device_mconfig_additions() const
1095{
1096   return MACHINE_CONFIG_NAME( gus_config );
1097}
1098
1099
1100isa16_gus_device::isa16_gus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1101      : device_t(mconfig, ISA16_GUS, "Ultrasound", tag, owner, clock),
1102        device_isa16_card_interface( mconfig, *this )
1103{
1104}
1105
1106void isa16_gus_device::device_start()
1107{
1108   m_gf1 = subdevice<gf1_device>("gf1");
1109   //m_midi = subdevice<acia6850_device>("midi");
1110   set_isa_device();
1111   m_isa->install_device(0x0220, 0x022f, 0, 0, read8_delegate(FUNC(isa16_gus_device::board_r),this), write8_delegate(FUNC(isa16_gus_device::board_w),this) );
1112   m_isa->install_device(0x0320, 0x032f, 0, 0, read8_delegate(FUNC(isa16_gus_device::synth_r),this), write8_delegate(FUNC(isa16_gus_device::synth_w),this) );
1113   m_isa->install_device(0x0388, 0x0389, 0, 0, read8_delegate(FUNC(isa16_gus_device::adlib_r),this), write8_delegate(FUNC(isa16_gus_device::adlib_w),this) );
1114}
1115
1116void isa16_gus_device::device_reset()
1117{
1118}
1119
1120void isa16_gus_device::device_stop()
1121{
1122}
1123
1124READ8_MEMBER(isa16_gus_device::board_r)
1125{
1126   switch(offset)
1127   {
1128   case 0x00:
1129   case 0x01:
1130      return m_gf1->mix_ctrl_r(space,offset);
1131      /* port 0x2X6 - IRQ status (active high)
1132       * bit 0 - MIDI transmit IRQ
1133       * bit 1 - MIDI receive IRQ
1134       * bit 2 - Timer 1 IRQ
1135       * bit 3 - Timer 2 IRQ
1136       * bit 4 - reserved (always 0)
1137       * bit 5 - wavetable IRQ
1138       * bit 6 - volume ramp IRQ
1139       * bit 7 - DRAM TC DMA IRQ
1140       */
1141   case 0x06:
1142      return m_irq_status;
1143   case 0x08:
1144   case 0x09:
1145      return m_gf1->adlib_r(space,offset-8);
1146   case 0x0a:
1147   case 0x0b:
1148      return m_gf1->adlib_cmd_r(space,offset-10);
1149   default:
1150      logerror("GUS: Invalid or unimplemented read of port 0x2X%01x\n",offset);
1151      return 0xff;
1152   }
1153   return 0xff;
1154}
1155
1156WRITE8_MEMBER(isa16_gus_device::board_w)
1157{
1158   switch(offset)
1159   {
1160   case 0x00:
1161   case 0x01:
1162      m_gf1->mix_ctrl_w(space,offset,data);
1163      break;
1164   case 0x08:
1165   case 0x09:
1166      m_gf1->adlib_w(space,offset-8,data);
1167      break;
1168   case 0x0a:
1169   case 0x0b:
1170      m_gf1->adlib_cmd_w(space,offset-10,data);
1171   default:
1172      logerror("GUS: Invalid or unimplemented register write %02x of port 0x2X%01x\n",data,offset);
1173   }
1174}
1175
1176READ8_MEMBER(isa16_gus_device::synth_r)
1177{
1178   switch(offset)
1179   {
1180//   case 0x00:
1181//      return m_midi->status_read(space,0);
1182//   case 0x01:
1183//      return m_midi->data_read(space,0);
1184   case 0x02:
1185   case 0x03:
1186      return m_gf1->global_reg_select_r(space,offset-2);
1187   case 0x04:
1188   case 0x05:
1189      return m_gf1->global_reg_data_r(space,offset-4);
1190   case 0x06:
1191   case 0x07:
1192      return m_gf1->dram_r(space,offset-6);
1193   default:
1194      logerror("GUS: Invalid or unimplemented register read of port 0x3X%01x\n",offset);
1195      return 0xff;
1196   }
1197   return 0xff;
1198}
1199
1200WRITE8_MEMBER(isa16_gus_device::synth_w)
1201{
1202   switch(offset)
1203   {
1204   case 0x00:
1205//      m_midi->control_write(space,0,data);
1206      break;
1207   case 0x01:
1208//      m_midi->data_write(space,0,data);
1209      break;
1210   case 0x02:
1211   case 0x03:
1212      m_gf1->global_reg_select_w(space,offset-2,data);
1213      break;
1214   case 0x04:
1215   case 0x05:
1216      m_gf1->global_reg_data_w(space,offset-4,data);
1217      break;
1218   case 0x06:
1219   case 0x07:
1220      m_gf1->dram_w(space,offset-6,data);
1221      break;
1222   default:
1223      logerror("GUS: Invalid or unimplemented register write %02x of port 0x3X%01x\n",data,offset);
1224   }
1225}
1226
1227READ8_MEMBER(isa16_gus_device::adlib_r)
1228{
1229   return m_gf1->adlib_r(space,offset);
1230}
1231
1232WRITE8_MEMBER(isa16_gus_device::adlib_w)
1233{
1234   m_gf1->adlib_w(space,offset,data);
1235}
1236
1237WRITE_LINE_MEMBER(isa16_gus_device::wavetable_irq)
1238{
1239   if(state)
1240      set_irq(IRQ_WAVETABLE);
1241   else
1242      reset_irq(IRQ_WAVETABLE);
1243}
1244
1245WRITE_LINE_MEMBER(isa16_gus_device::volumeramp_irq)
1246{
1247   if(state)
1248      set_irq(IRQ_VOLUME_RAMP);
1249   else
1250      reset_irq(IRQ_VOLUME_RAMP);
1251}
1252
1253WRITE_LINE_MEMBER(isa16_gus_device::timer1_irq)
1254{
1255   if(state)
1256      set_irq(IRQ_TIMER1);
1257   else
1258      reset_irq(IRQ_TIMER1);
1259}
1260
1261WRITE_LINE_MEMBER(isa16_gus_device::timer2_irq)
1262{
1263   if(state)
1264      set_irq(IRQ_TIMER2);
1265   else
1266      reset_irq(IRQ_TIMER2);
1267}
1268
1269WRITE_LINE_MEMBER(isa16_gus_device::dma_irq)
1270{
1271   if(state)
1272      set_irq(IRQ_DRAM_TC_DMA);
1273   else
1274      reset_irq(IRQ_DRAM_TC_DMA);
1275}
1276
1277WRITE_LINE_MEMBER(isa16_gus_device::drq1_w)
1278{
1279   m_isa->set_dma_channel(m_gf1->dma_channel1(), this, TRUE);
1280   switch(m_gf1->dma_channel1())
1281   {
1282   case 1:
1283      m_isa->drq1_w(state);
1284      break;
1285   case 3:
1286      m_isa->drq3_w(state);
1287      break;
1288   case 5:
1289      m_isa->drq5_w(state);
1290      break;
1291   case 6:
1292      m_isa->drq6_w(state);
1293      break;
1294   case 7:
1295      m_isa->drq7_w(state);
1296      break;
1297   default:
1298      logerror("GUS: Invalid DMA channel %i, ignoring.\n",m_gf1->dma_channel1());
1299   }
1300}
1301
1302void isa16_gus_device::set_irq(UINT8 source)
1303{
1304   m_irq_status |= source;
1305
1306   switch(m_gf1->gf1_irq())
1307   {
1308   case 2:
1309      m_isa->irq2_w(1);
1310      break;
1311   case 3:
1312      m_isa->irq3_w(1);
1313      break;
1314   case 5:
1315      m_isa->irq5_w(1);
1316      break;
1317   case 7:
1318      m_isa->irq7_w(1);
1319      break;
1320   case 11:
1321      m_isa->irq11_w(1);
1322      break;
1323   case 12:
1324      m_isa->irq12_w(1);
1325      break;
1326   case 15:
1327      m_isa->irq15_w(1);
1328      break;
1329   }
1330   logerror("GUS: Set IRQ %02x\n",source);
1331}
1332
1333void isa16_gus_device::reset_irq(UINT8 source)
1334{
1335   m_irq_status &= ~source;
1336
1337   switch(m_gf1->gf1_irq())
1338   {
1339   case 2:
1340      m_isa->irq2_w(0);
1341      break;
1342   case 3:
1343      m_isa->irq3_w(0);
1344      break;
1345   case 5:
1346      m_isa->irq5_w(0);
1347      break;
1348   case 7:
1349      m_isa->irq7_w(0);
1350      break;
1351   case 11:
1352      m_isa->irq11_w(0);
1353      break;
1354   case 12:
1355      m_isa->irq12_w(0);
1356      break;
1357   case 15:
1358      m_isa->irq15_w(0);
1359      break;
1360   }
1361   logerror("GUS: Reset IRQ %02x\n",source);
1362}
1363
1364WRITE_LINE_MEMBER( isa16_gus_device::midi_irq )
1365{
1366   if(state)
1367      set_irq(IRQ_MIDI_TRANSMIT);
1368   else
1369      reset_irq(IRQ_MIDI_TRANSMIT);
1370}
1371
1372UINT8 isa16_gus_device::dack_r(int line)
1373{
1374   if(line == m_gf1->dma_channel1())
1375      return m_gf1->dack_r(line);
1376   else
1377      return 0;
1378}
1379
1380void isa16_gus_device::dack_w(int line,UINT8 data)
1381{
1382   if(line == m_gf1->dma_channel1())
1383      m_gf1->dack_w(line,data);
1384}
1385
1386void isa16_gus_device::eop_w(int state)
1387{
1388   m_gf1->eop_w(state);
1389}
1390
src/mess/machine/isa_gus.h
r0r14399
1/*
2 *  Gravis Ultrasound ISA card
3 *
4 *  Started: 28/01/2012
5 *
6 *  I/O port map (info from the Gravis Ultrasound SDK documentation):
7 *  Base port is 0x2X0 - where X is defined by a jumper
8 *
9 *  MIDI:
10 *  0x3X0 - MIDI Control (read), MIDI Status (write)
11 *  0x3X1 - MIDI Transmit (write), MIDI Receive (read)
12 *  MIDI operates identically to a 6850 UART
13 *
14 *  Joystick:
15 *  0x201 - Joystick trigger timer (write), Joystick data (read)
16 *
17 *  GF1 Synthesiser:
18 *  0x3X2 - Page register (voice select)
19 *  0x3X3 - Global Register select
20 *  0x3X4 - Global Data (low byte)
21 *  0x3X5 - Global Data (high byte)
22 *  0x2X6 - IRQ status register (read only, active high)
23 *  0x2X8 - Timer control register
24 *  0x2X9 - Timer data
25 *  0x3X7 - DRAM data (can be via DMA also)
26 *
27 *  Board:
28 *  0x2X0: Mix control register (write only)
29 *  0x2XB: IRQ/DMA control register (write only) - dependant on mix control bit 6
30 *  0x2XF: Register controls (board rev 3.4+ only)
31 *  0x7X6: Board version (read only, board rev 3.7+ only)
32 *
33 *  Mixer Control:
34 *  0x7X6: Control port (write only)
35 *  0x3X6: Data port (write only)
36 */
37
38#pragma once
39
40#ifndef __ISA_GUS_H__
41#define __ISA_GUS_H__
42
43#include "emu.h"
44#include "machine/isa.h"
45#include "machine/6850acia.h"
46
47//**************************************************************************
48//  TYPE DEFINITIONS
49//**************************************************************************
50
51// ======================> gf1_device
52
53#define GF1_CLOCK 9878400
54
55#define IRQ_MIDI_TRANSMIT 0x01
56#define IRQ_MIDI_RECEIVE  0x02
57#define IRQ_TIMER1        0x04
58#define IRQ_TIMER2        0x08
59#define IRQ_WAVETABLE     0x20
60#define IRQ_VOLUME_RAMP   0x40
61#define IRQ_DRAM_TC_DMA   0x80
62
63struct _gus_voice
64{
65   UINT8 voice_ctrl;
66   UINT16 freq_ctrl;
67   UINT32 start_addr;
68   UINT32 end_addr;
69   UINT8 vol_ramp_rate;
70   UINT8 vol_ramp_start;
71   UINT8 vol_ramp_end;
72   UINT16 current_vol;
73   UINT32 current_addr;
74   UINT8 pan_position;
75   UINT8 vol_ramp_ctrl;
76   UINT32 vol_count;
77   bool rollover;
78    INT32 sample;  // current sample data
79};
80typedef struct _gus_voice gus_voice;
81
82struct _gf1_interface
83{
84   devcb_write_line wave_irq_cb;
85   devcb_write_line ramp_irq_cb;
86   devcb_write_line timer1_irq_cb;
87   devcb_write_line timer2_irq_cb;
88   devcb_write_line dma_irq_cb;
89   devcb_write_line drq1_cb;
90   devcb_write_line drq2_cb;
91};
92typedef struct _gf1_interface gf1_interface;
93
94class gf1_device :
95      public device_t,
96      public device_sound_interface,
97      public gf1_interface
98{
99public:
100      // construction/destruction
101        gf1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
102
103        // current IRQ/DMA channel getters
104        UINT8 gf1_irq() { return m_gf1_irq; }
105        UINT8 midi_irq() { return m_midi_irq; }
106        UINT8 dma_channel1() { return m_dma_channel1; }
107        UINT8 dma_channel2() { return m_dma_channel2; }
108
109        DECLARE_READ8_MEMBER(global_reg_select_r);
110        DECLARE_WRITE8_MEMBER(global_reg_select_w);
111        DECLARE_READ8_MEMBER(global_reg_data_r);
112        DECLARE_WRITE8_MEMBER(global_reg_data_w);
113        DECLARE_READ8_MEMBER(dram_r);
114        DECLARE_WRITE8_MEMBER(dram_w);
115        DECLARE_READ8_MEMBER(adlib_r);
116        DECLARE_WRITE8_MEMBER(adlib_w);
117        DECLARE_READ8_MEMBER(adlib_cmd_r);
118        DECLARE_WRITE8_MEMBER(adlib_cmd_w);
119        DECLARE_READ8_MEMBER(mix_ctrl_r);
120        DECLARE_WRITE8_MEMBER(mix_ctrl_w);
121
122        // DMA signals
123       UINT8 dack_r(int line);
124       void dack_w(int line,UINT8 data);
125       void eop_w(int state);
126
127      // optional information overrides
128      virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
129      virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
130      virtual void device_config_complete();
131
132        // voice-specific registers
133        gus_voice m_voice[32];
134
135        // global registers (not voice-specific)
136        UINT8 m_dma_dram_ctrl;
137        UINT16 m_dma_start_addr;
138        UINT32 m_dram_addr;
139        UINT8 m_timer_ctrl;
140        UINT8 m_timer1_count;
141        UINT8 m_timer2_count;
142        UINT8 m_timer1_value;
143        UINT8 m_timer2_value;
144        UINT16 m_sampling_freq;
145        UINT8 m_sampling_ctrl;
146        UINT8 m_joy_trim_dac;
147        UINT8 m_reset;
148        UINT8 m_active_voices;
149        UINT8 m_irq_source;
150
151        void set_irq(UINT8 source, UINT8 voice);
152        void reset_irq(UINT8 source);
153
154        UINT8* m_wave_ram;
155
156protected:
157        // device-level overrides
158        virtual void device_start();
159        virtual void device_reset();
160        virtual void device_stop();
161
162        devcb_resolved_write_line m_wave_irq_func;
163        devcb_resolved_write_line m_ramp_irq_func;
164        devcb_resolved_write_line m_timer1_irq_func;
165        devcb_resolved_write_line m_timer2_irq_func;
166        devcb_resolved_write_line m_dma_irq_func;
167        devcb_resolved_write_line m_drq1;
168        devcb_resolved_write_line m_drq2;
169
170private:
171        // internal state
172        sound_stream* m_stream;
173
174        emu_timer* m_timer1;
175        emu_timer* m_timer2;
176        emu_timer* m_dmatimer;
177        emu_timer* m_voltimer;
178
179        UINT8 m_current_voice;
180        UINT8 m_current_reg;
181        UINT8 m_port;
182        UINT8 m_irq;
183        UINT8 m_dma;
184
185        UINT8 m_adlib_cmd;
186        UINT8 m_mix_ctrl;
187        UINT8 m_gf1_irq;
188        UINT8 m_midi_irq;
189        UINT8 m_dma_channel1;
190        UINT8 m_dma_channel2;
191        UINT8 m_irq_combine;
192        UINT8 m_dma_combine;
193        UINT8 m_adlib_timer_cmd;
194        UINT8 m_adlib_timer1_enable;
195        UINT8 m_adlib_timer2_enable;
196        UINT8 m_adlib_status;
197        UINT8 m_voice_irq_fifo[32];
198        UINT8 m_voice_irq_ptr;
199        UINT8 m_voice_irq_current;
200        UINT8 m_dma_16bit;  // set by bit 6 of the DMA DRAM control reg
201        UINT32 m_dma_current;
202        UINT32 m_volume_table[4096];
203
204       static const device_timer_id ADLIB_TIMER1 = 0;
205       static const device_timer_id ADLIB_TIMER2 = 1;
206       static const device_timer_id DMA_TIMER = 2;
207       static const device_timer_id VOL_RAMP_TIMER = 3;
208};
209
210class isa16_gus_device :
211      public device_t,
212      public device_isa16_card_interface
213{
214public:
215      isa16_gus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
216      void set_irq(UINT8 source);
217        void reset_irq(UINT8 source);
218
219      DECLARE_READ8_MEMBER(board_r);
220      DECLARE_READ8_MEMBER(synth_r);
221      DECLARE_WRITE8_MEMBER(board_w);
222      DECLARE_WRITE8_MEMBER(synth_w);
223      DECLARE_READ8_MEMBER(adlib_r);
224      DECLARE_WRITE8_MEMBER(adlib_w);
225        DECLARE_WRITE_LINE_MEMBER(midi_irq);
226        DECLARE_WRITE_LINE_MEMBER(wavetable_irq);
227        DECLARE_WRITE_LINE_MEMBER(volumeramp_irq);
228        DECLARE_WRITE_LINE_MEMBER(timer1_irq);
229        DECLARE_WRITE_LINE_MEMBER(timer2_irq);
230        DECLARE_WRITE_LINE_MEMBER(dma_irq);
231        DECLARE_WRITE_LINE_MEMBER(drq1_w);
232
233        // DMA overrides
234       virtual UINT8 dack_r(int line);
235       virtual void dack_w(int line,UINT8 data);
236       virtual void eop_w(int state);
237
238        // optional information overrides
239      virtual machine_config_constructor device_mconfig_additions() const;
240protected:
241        // device-level overrides
242        virtual void device_start();
243        virtual void device_reset();
244        virtual void device_stop();
245
246private:
247        gf1_device* m_gf1;
248        acia6850_device* m_midi;
249
250        UINT8 m_irq_status;
251};
252
253// device type definition
254extern const device_type GGF1;
255extern const device_type ISA16_GUS;
256
257#endif  /* __ISA_GUS_H__ */
src/mess/includes/at.h
r14398r14399
5151#include "machine/isa_gblaster.h"
5252#include "machine/isa_hdc.h"
5353#include "machine/isa_sblaster.h"
54#include "machine/isa_gus.h"
5455#include "machine/3c503.h"
5556#include "machine/ne1000.h"
5657#include "machine/ne2000.h"
src/mess/drivers/at.c
r14398r14399
372372   SLOT_INTERFACE("ide", ISA16_IDE)
373373   SLOT_INTERFACE("ne2000", NE2000)
374374   SLOT_INTERFACE("aha1542", AHA1542)
375   SLOT_INTERFACE("gus",ISA16_GUS)
375376SLOT_INTERFACE_END
376377
377378static MACHINE_CONFIG_FRAGMENT( at_motherboard )

Previous 15994 Revisions Next


© 1998-2018 The MESS Team