1 /*****************************************************************************
2 SN76477 pins and assigned interface variables/functions
3
4 SN76477_envelope_w()
5 / \
6 [ 1] ENV SEL 1 ENV SEL 2 [28]
7 [ 2] GND MIXER C [27] \
8 SN76477_noise_clock_w [ 3] NOISE EXT OSC MIXER A [26] > SN76477_mixer_w()
9 noise_res [ 4] RES NOISE OSC MIXER B [25] /
10 filter_res [ 5] NOISE FILTER RES O/S RES [24] oneshot_res
11 filter_cap [ 6] NOISE FILTER CAP O/S CAP [23] oneshot_cap
12 decay_res [ 7] DECAY RES VCO SEL [22] SN76477_vco_w()
13 attack_decay_cap [ 8] A/D CAP SLF CAP [21] slf_cap
14 SN76477_enable_w() [ 9] ENABLE SLF RES [20] slf_res
15 attack_res [10] ATTACK RES PITCH [19] pitch_voltage
16 amplitude_res [11] AMP VCO RES [18] vco_res
17 feedback_res [12] FEEDBACK VCO CAP [17] vco_cap
18 [13] OUTPUT VCO EXT CONT [16] vco_voltage
19 [14] Vcc +5V REG OUT [15]
20
21 All resistor values in Ohms.
22 All capacitor values in Farads.
23 Use RES_K, RES_M and CAP_U, CAP_N, CAP_P macros to convert
24 magnitudes, eg. 220k = RES_K(220), 47nF = CAP_N(47)
25
26 *****************************************************************************/
27
28 #include "driver.h"
29
30 #define VERBOSE -1
31
32 #if VERBOSE >= 0
33 #define LOG(n,x) if( VERBOSE >= (n) ) logerror x
34 #else
35 #define LOG(n,x)
36 #endif
37
38 #define CHECK_CHIP_NUM
39 #define CHECK_CHIP_NUM_AND_RANGE(BITS,FUNC)
40
41 #define VMIN 0x0000
42 #define VMAX 0x7fff
43
44 struct SN76477 {
45 int channel; /* returned by stream_init() */
46
47 int samplerate; /* from Machine->sample_rate */
48 int vol; /* current volume (attack/decay) */
49 int vol_count; /* volume adjustment counter */
50 int vol_rate; /* volume adjustment rate - dervied from attack/decay */
51 int vol_step; /* volume adjustment step */
52
53 float slf_count; /* SLF emulation */
54 float slf_freq; /* frequency - derived */
55 float slf_level; /* triangular wave level */
56 int slf_dir; /* triangular wave direction */
57 int slf_out; /* rectangular output signal state */
58
59 float vco_count; /* VCO emulation */
60 float vco_freq; /* frequency - derived */
61 float vco_step; /* modulated frequency - derived */
62 int vco_out; /* rectangular output signal state */
63
64 int noise_count; /* NOISE emulation */
65 int noise_clock; /* external clock signal */
66 int noise_freq; /* filter frequency - derived */
67 int noise_poly; /* polynome */
68 int noise_out; /* rectangular output signal state */
69
70 void *envelope_timer; /* ENVELOPE timer */
71 int envelope_state; /* attack / decay toggle */
72
73 float attack_time; /* ATTACK time (time until vol reaches 100%) */
74 float decay_time; /* DECAY time (time until vol reaches 0%) */
75 timer_tm oneshot_time; /* ONE-SHOT time */
76 void *oneshot_timer; /* ONE-SHOT timer */
77
78 int envelope; /* pin 1, pin 28 */
79 float noise_res; /* pin 4 */
80 float filter_res; /* pin 5 */
81 float filter_cap; /* pin 6 */
82 float decay_res; /* pin 7 */
83 float attack_decay_cap;/* pin 8 */
84 int enable; /* pin 9 */
85 float attack_res; /* pin 10 */
86 float amplitude_res; /* pin 11 */
87 float feedback_res; /* pin 12 */
88 float vco_voltage; /* pin 16 */
89 float vco_cap; /* pin 17 */
90 float vco_res; /* pin 18 */
91 float pitch_voltage; /* pin 19 */
92 float slf_res; /* pin 20 */
93 float slf_cap; /* pin 21 */
94 int vco_select; /* pin 22 */
95 float oneshot_cap; /* pin 23 */
96 float oneshot_res; /* pin 24 */
97 int mixer; /* pin 25,26,27 */
98
99 INT16 vol_lookup[VMAX+1-VMIN]; /* volume lookup table */
100 };
101
102 static struct SN76477interface *intf;
103 static struct SN76477 *sn76477[MAX_SN76477];
104
attack_decay(int param)105 static void attack_decay(int param)
106 {
107 struct SN76477 *sn = sn76477[param];
108 sn->envelope_state ^= 1;
109 if( sn->envelope_state )
110 {
111 /* start ATTACK */
112 sn->vol_rate = ( sn->attack_time > 0 ) ? VMAX / sn->attack_time : VMAX;
113 sn->vol_step = +1;
114 LOG(2,("SN76477 #%d: ATTACK rate %d/%d = %d/sec\n", param, sn->vol_rate, sn->samplerate, sn->vol_rate/sn->samplerate));
115 }
116 else
117 {
118 /* start DECAY */
119 sn->vol = VMAX; /* just in case... */
120 sn->vol_rate = ( sn->decay_time > 0 ) ? VMAX / sn->decay_time : VMAX;
121 sn->vol_step = -1;
122 LOG(2,("SN76477 #%d: DECAY rate %d/%d = %d/sec\n", param, sn->vol_rate, sn->samplerate, sn->vol_rate/sn->samplerate));
123 }
124 }
125
vco_envelope_cb(int param)126 static void vco_envelope_cb(int param)
127 {
128 attack_decay(param);
129 }
130
oneshot_envelope_cb(int param)131 static void oneshot_envelope_cb(int param)
132 {
133 struct SN76477 *sn = sn76477[param];
134 sn->oneshot_timer = NULL;
135 attack_decay(param);
136 }
137
138 #if VERBOSE
139 /*
140 static const char *mixer_mode[8] = {
141 "VCO",
142 "SLF",
143 "Noise",
144 "VCO/Noise",
145 "SLF/Noise",
146 "SLF/VCO/Noise",
147 "SLF/VCO",
148 "Inhibit"
149 };
150 */
151 #endif
152
153 /*****************************************************************************
154 * set MIXER select inputs
155 *****************************************************************************/
SN76477_mixer_w(int chip,int data)156 void SN76477_mixer_w(int chip, int data)
157 {
158 struct SN76477 *sn = sn76477[chip];
159
160 CHECK_CHIP_NUM_AND_RANGE(7,SN76477_mixer_w);
161
162 if( data == sn->mixer )
163 return;
164 stream_update(sn->channel, 0);
165 sn->mixer = data;
166 LOG(1,("SN76477 #%d: MIXER mode %d [%s]\n", chip, sn->mixer, mixer_mode[sn->mixer]));
167 }
168
SN76477_mixer_a_w(int chip,int data)169 void SN76477_mixer_a_w(int chip, int data)
170 {
171 struct SN76477 *sn = sn76477[chip];
172
173 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_mixer_a_w);
174
175 data = data ? 1 : 0;
176 if( data == (sn->mixer & 1) )
177 return;
178 stream_update(sn->channel, 0);
179 sn->mixer = (sn->mixer & ~1) | data;
180 LOG(1,("SN76477 #%d: MIXER mode %d [%s]\n", chip, sn->mixer, mixer_mode[sn->mixer]));
181 }
182
SN76477_mixer_b_w(int chip,int data)183 void SN76477_mixer_b_w(int chip, int data)
184 {
185 struct SN76477 *sn = sn76477[chip];
186
187 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_mixer_b_w);
188
189 data = data ? 2 : 0;
190 if( data == (sn->mixer & 2) )
191 return;
192 stream_update(sn->channel, 0);
193 sn->mixer = (sn->mixer & ~2) | data;
194 LOG(1,("SN76477 #%d: MIXER mode %d [%s]\n", chip, sn->mixer, mixer_mode[sn->mixer]));
195 }
196
SN76477_mixer_c_w(int chip,int data)197 void SN76477_mixer_c_w(int chip, int data)
198 {
199 struct SN76477 *sn = sn76477[chip];
200
201 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_mixer_c_w);
202
203 data = data ? 4 : 0;
204 if( data == (sn->mixer & 4) )
205 return;
206 stream_update(sn->channel, 0);
207 sn->mixer = (sn->mixer & ~4) | data;
208 LOG(1,("SN76477 #%d: MIXER mode %d [%s]\n", chip, sn->mixer, mixer_mode[sn->mixer]));
209 }
210
211 #if VERBOSE
212 /*
213 static const char *envelope_mode[4] = {
214 "VCO",
215 "One-Shot",
216 "Mixer only",
217 "VCO with alternating Polarity"
218 };
219 */
220 #endif
221
222 /*****************************************************************************
223 * set ENVELOPE select inputs
224 *****************************************************************************/
SN76477_envelope_w(int chip,int data)225 void SN76477_envelope_w(int chip, int data)
226 {
227 struct SN76477 *sn = sn76477[chip];
228
229 CHECK_CHIP_NUM_AND_RANGE(3,SN76477_envelope_w);
230
231 if( data == sn->envelope )
232 return;
233 stream_update(sn->channel, 0);
234 sn->envelope = data;
235 LOG(1,("SN76477 #%d: ENVELOPE mode %d [%s]\n", chip, sn->envelope, envelope_mode[sn->envelope]));
236 }
237
SN76477_envelope_1_w(int chip,int data)238 void SN76477_envelope_1_w(int chip, int data)
239 {
240 struct SN76477 *sn = sn76477[chip];
241
242 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_envelope_1_w);
243
244 if( data == (sn->envelope & 1) )
245 return;
246 stream_update(sn->channel, 0);
247 sn->envelope = (sn->envelope & ~1) | data;
248 LOG(1,("SN76477 #%d: ENVELOPE mode %d [%s]\n", chip, sn->envelope, envelope_mode[sn->envelope]));
249 }
250
SN76477_envelope_2_w(int chip,int data)251 void SN76477_envelope_2_w(int chip, int data)
252 {
253 struct SN76477 *sn = sn76477[chip];
254
255 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_envelope_2_w);
256
257 data <<= 1;
258
259 if( data == (sn->envelope & 2) )
260 return;
261 stream_update(sn->channel, 0);
262 sn->envelope = (sn->envelope & ~2) | data;
263 LOG(1,("SN76477 #%d: ENVELOPE mode %d [%s]\n", chip, sn->envelope, envelope_mode[sn->envelope]));
264 }
265
266 /*****************************************************************************
267 * set VCO external/SLF input
268 *****************************************************************************/
SN76477_vco_w(int chip,int data)269 void SN76477_vco_w(int chip, int data)
270 {
271 struct SN76477 *sn = sn76477[chip];
272
273 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_vco_w);
274
275 if( data == sn->vco_select )
276 return;
277 stream_update(sn->channel, 0);
278 sn->vco_select = data;
279 LOG(1,("SN76477 #%d: VCO select %d [%s]\n", chip, sn->vco_select, sn->vco_select ? "Internal (SLF)" : "External (Pin 16)"));
280 }
281
282 /*****************************************************************************
283 * set VCO enable input
284 *****************************************************************************/
SN76477_enable_w(int chip,int data)285 void SN76477_enable_w(int chip, int data)
286 {
287 struct SN76477 *sn = sn76477[chip];
288
289 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_enable_w);
290
291 if( data == sn->enable )
292 return;
293 stream_update(sn->channel, 0);
294 sn->enable = data;
295 sn->envelope_state = data;
296 if( sn->envelope_timer )
297 timer_remove(sn->envelope_timer);
298 sn->envelope_timer = NULL;
299 if( sn->oneshot_timer )
300 timer_remove(sn->oneshot_timer);
301 sn->oneshot_timer = NULL;
302 if( sn->enable == 0 )
303 {
304 switch( sn->envelope )
305 {
306 case 0: /* VCO */
307 if( sn->vco_res > 0 && sn->vco_cap > 0 )
308 sn->envelope_timer = timer_pulse(TIME_IN_HZ(0.64/(sn->vco_res * sn->vco_cap)), chip, vco_envelope_cb);
309 else
310 oneshot_envelope_cb(chip);
311 break;
312 case 1: /* One-Shot */
313 oneshot_envelope_cb(chip);
314 if (sn->oneshot_time > 0)
315 sn->oneshot_timer = timer_set(sn->oneshot_time, chip, oneshot_envelope_cb);
316 break;
317 case 2: /* MIXER only */
318 sn->vol = VMAX;
319 break;
320 default: /* VCO with alternating polariy */
321 /* huh? */
322 if( sn->vco_res > 0 && sn->vco_cap > 0 )
323 sn->envelope_timer = timer_pulse(TIME_IN_HZ(0.64/(sn->vco_res * sn->vco_cap)/2), chip, vco_envelope_cb);
324 else
325 oneshot_envelope_cb(chip);
326 break;
327 }
328 }
329 else
330 {
331 switch( sn->envelope )
332 {
333 case 0: /* VCO */
334 if( sn->vco_res > 0 && sn->vco_cap > 0 )
335 sn->envelope_timer = timer_pulse(TIME_IN_HZ(0.64/(sn->vco_res * sn->vco_cap)), chip, vco_envelope_cb);
336 else
337 oneshot_envelope_cb(chip);
338 break;
339 case 1: /* One-Shot */
340 oneshot_envelope_cb(chip);
341 break;
342 case 2: /* MIXER only */
343 sn->vol = VMIN;
344 break;
345 default: /* VCO with alternating polariy */
346 /* huh? */
347 if( sn->vco_res > 0 && sn->vco_cap > 0 )
348 sn->envelope_timer = timer_pulse(TIME_IN_HZ(0.64/(sn->vco_res * sn->vco_cap)/2), chip, vco_envelope_cb);
349 else
350 oneshot_envelope_cb(chip);
351 break;
352 }
353 }
354 LOG(1,("SN76477 #%d: ENABLE line %d [%s]\n", chip, sn->enable, sn->enable ? "Inhibited" : "Enabled" ));
355 }
356
357 /*****************************************************************************
358 * set NOISE external signal (pin 3)
359 *****************************************************************************/
SN76477_noise_clock_w(int chip,int data)360 void SN76477_noise_clock_w(int chip, int data)
361 {
362 struct SN76477 *sn = sn76477[chip];
363
364 CHECK_CHIP_NUM_AND_RANGE(1,SN76477_noise_clock_w);
365
366 if( data == sn->noise_clock )
367 return;
368 stream_update(sn->channel, 0);
369 sn->noise_clock = data;
370 /* on the rising edge shift the polynome */
371 if( sn->noise_clock )
372 sn->noise_poly = ((sn->noise_poly << 7) + (sn->noise_poly >> 10) + 0x18000) & 0x1ffff;
373 }
374
375 /*****************************************************************************
376 * set NOISE resistor (pin 4)
377 *****************************************************************************/
SN76477_set_noise_res(int chip,float res)378 void SN76477_set_noise_res(int chip, float res)
379 {
380 struct SN76477 *sn = sn76477[chip];
381
382 CHECK_CHIP_NUM;
383
384 stream_update(sn->channel, 0);
385 sn->noise_res = res;
386 }
387
388 /*****************************************************************************
389 * set NOISE FILTER resistor (pin 5)
390 *****************************************************************************/
SN76477_set_filter_res(int chip,float res)391 void SN76477_set_filter_res(int chip, float res)
392 {
393 struct SN76477 *sn = sn76477[chip];
394
395 CHECK_CHIP_NUM;
396
397 if( res == sn->filter_res )
398 return;
399 stream_update(sn->channel, 0);
400 sn->filter_res = res;
401 if( sn->filter_res > 0 && sn->filter_cap > 0 )
402 {
403 sn->noise_freq = (int)(1.28 / (sn->filter_res * sn->filter_cap));
404 LOG(1,("SN76477 #%d: NOISE FILTER freqency %d\n", chip, sn->noise_freq));
405 }
406 else
407 sn->noise_freq = sn->samplerate;
408 }
409
410 /*****************************************************************************
411 * set NOISE FILTER capacitor (pin 6)
412 *****************************************************************************/
SN76477_set_filter_cap(int chip,float cap)413 void SN76477_set_filter_cap(int chip, float cap)
414 {
415 struct SN76477 *sn = sn76477[chip];
416
417 CHECK_CHIP_NUM;
418
419 if( cap == sn->filter_cap )
420 return;
421 stream_update(sn->channel, 0);
422 sn->filter_cap = cap;
423 if( sn->filter_res > 0 && sn->filter_cap > 0 )
424 {
425 sn->noise_freq = (int)(1.28 / (sn->filter_res * sn->filter_cap));
426 LOG(1,("SN76477 #%d: NOISE FILTER freqency %d\n", chip, sn->noise_freq));
427 }
428 else
429 sn->noise_freq = sn->samplerate;
430 }
431
432 /*****************************************************************************
433 * set DECAY resistor (pin 7)
434 *****************************************************************************/
SN76477_set_decay_res(int chip,float res)435 void SN76477_set_decay_res(int chip, float res)
436 {
437 struct SN76477 *sn = sn76477[chip];
438
439 CHECK_CHIP_NUM;
440
441 if( res == sn->decay_res )
442 return;
443 stream_update(sn->channel, 0);
444 sn->decay_res = res;
445 sn->decay_time = sn->decay_res * sn->attack_decay_cap;
446 LOG(1,("SN76477 #%d: DECAY time is %fs\n", chip, sn->decay_time));
447 }
448
449 /*****************************************************************************
450 * set ATTACK/DECAY capacitor (pin 8)
451 *****************************************************************************/
SN76477_set_attack_decay_cap(int chip,float cap)452 void SN76477_set_attack_decay_cap(int chip, float cap)
453 {
454 struct SN76477 *sn = sn76477[chip];
455
456 CHECK_CHIP_NUM;
457
458 if( cap == sn->attack_decay_cap )
459 return;
460 stream_update(sn->channel, 0);
461 sn->attack_decay_cap = cap;
462 sn->decay_time = sn->decay_res * sn->attack_decay_cap;
463 sn->attack_time = sn->attack_res * sn->attack_decay_cap;
464 LOG(1,("SN76477 #%d: ATTACK time is %fs\n", chip, sn->attack_time));
465 LOG(1,("SN76477 #%d: DECAY time is %fs\n", chip, sn->decay_time));
466 }
467
468 /*****************************************************************************
469 * set ATTACK resistor (pin 10)
470 *****************************************************************************/
SN76477_set_attack_res(int chip,float res)471 void SN76477_set_attack_res(int chip, float res)
472 {
473 struct SN76477 *sn = sn76477[chip];
474
475 CHECK_CHIP_NUM;
476
477 if( res == sn->attack_res )
478 return;
479 stream_update(sn->channel, 0);
480 sn->attack_res = res;
481 sn->attack_time = sn->attack_res * sn->attack_decay_cap;
482 LOG(1,("SN76477 #%d: ATTACK time is %fs\n", chip, sn->attack_time));
483 }
484
485 /*****************************************************************************
486 * set AMP resistor (pin 11)
487 *****************************************************************************/
SN76477_set_amplitude_res(int chip,float res)488 void SN76477_set_amplitude_res(int chip, float res)
489 {
490 struct SN76477 *sn = sn76477[chip];
491 int i;
492
493 CHECK_CHIP_NUM;
494
495 if( res == sn->amplitude_res )
496 return;
497 stream_update(sn->channel, 0);
498 sn->amplitude_res = res;
499 if( sn->amplitude_res > 0 )
500 {
501 #if VERBOSE
502 int clip = 0;
503 #endif
504 for( i = 0; i < VMAX+1; i++ )
505 {
506 int vol = (int)((3.4 * sn->feedback_res / sn->amplitude_res) * 32767 * i / (VMAX+1));
507 #if VERBOSE
508 if( vol > 32767 && !clip )
509 clip = i;
510 LOG(3,("%d\n", vol));
511 #endif
512 if( vol > 32767 ) vol = 32767;
513 sn->vol_lookup[i] = vol * intf->mixing_level[chip] / 100;
514 }
515 LOG(1,("SN76477 #%d: volume range from -%d to +%d (clip at %d%%)\n", chip, sn->vol_lookup[VMAX-VMIN], sn->vol_lookup[VMAX-VMIN], clip * 100 / 256));
516 }
517 else
518 {
519 memset(sn->vol_lookup, 0, sizeof(sn->vol_lookup));
520 }
521 }
522
523 /*****************************************************************************
524 * set FEEDBACK resistor (pin 12)
525 *****************************************************************************/
SN76477_set_feedback_res(int chip,float res)526 void SN76477_set_feedback_res(int chip, float res)
527 {
528 struct SN76477 *sn = sn76477[chip];
529 int i;
530
531 CHECK_CHIP_NUM;
532
533 if( res == sn->feedback_res )
534 return;
535 stream_update(sn->channel, 0);
536 sn->feedback_res = res;
537 if( sn->amplitude_res > 0 )
538 {
539 #if VERBOSE
540 int clip = 0;
541 #endif
542 for( i = 0; i < VMAX+1; i++ )
543 {
544 int vol = (int)((3.4 * sn->feedback_res / sn->amplitude_res) * 32767 * i / (VMAX+1));
545 #if VERBOSE
546 if( vol > 32767 && !clip ) clip = i;
547 #endif
548 if( vol > 32767 ) vol = 32767;
549 sn->vol_lookup[i] = vol * intf->mixing_level[chip] / 100;
550 }
551 LOG(1,("SN76477 #%d: volume range from -%d to +%d (clip at %d%%)\n", chip, sn->vol_lookup[VMAX-VMIN], sn->vol_lookup[VMAX-VMIN], clip * 100 / 256));
552 }
553 else
554 {
555 memset(sn->vol_lookup, 0, sizeof(sn->vol_lookup));
556 }
557 }
558
559 /*****************************************************************************
560 * set PITCH voltage (pin 19)
561 * TODO: fill with live...
562 *****************************************************************************/
SN76477_set_pitch_voltage(int chip,float voltage)563 void SN76477_set_pitch_voltage(int chip, float voltage)
564 {
565 struct SN76477 *sn = sn76477[chip];
566
567 CHECK_CHIP_NUM;
568
569 if( voltage == sn->pitch_voltage )
570 return;
571 stream_update(sn->channel, 0);
572 sn->pitch_voltage = voltage;
573 LOG(1,("SN76477 #%d: VCO pitch voltage %f (%d%% duty cycle)\n", chip, sn->pitch_voltage, 0));
574 }
575
576 /*****************************************************************************
577 * set VCO resistor (pin 18)
578 *****************************************************************************/
SN76477_set_vco_res(int chip,float res)579 void SN76477_set_vco_res(int chip, float res)
580 {
581 struct SN76477 *sn = sn76477[chip];
582
583 CHECK_CHIP_NUM;
584
585 if( res == sn->vco_res )
586 return;
587 stream_update(sn->channel, 0);
588 sn->vco_res = res;
589 if( sn->vco_res > 0 && sn->vco_cap > 0 )
590 {
591 sn->vco_freq = 0.64 / (sn->vco_res * sn->vco_cap);
592 LOG(1,("SN76477 #%d: VCO freqency %f\n", chip, sn->vco_freq));
593 }
594 else
595 sn->vco_freq = 0;
596 }
597
598 /*****************************************************************************
599 * set VCO capacitor (pin 17)
600 *****************************************************************************/
SN76477_set_vco_cap(int chip,float cap)601 void SN76477_set_vco_cap(int chip, float cap)
602 {
603 struct SN76477 *sn = sn76477[chip];
604
605 CHECK_CHIP_NUM;
606
607 if( cap == sn->vco_cap )
608 return;
609 stream_update(sn->channel, 0);
610 sn->vco_cap = cap;
611 if( sn->vco_res > 0 && sn->vco_cap > 0 )
612 {
613 sn->vco_freq = 0.64 / (sn->vco_res * sn->vco_cap);
614 LOG(1,("SN76477 #%d: VCO freqency %f\n", chip, sn->vco_freq));
615 }
616 else
617 sn->vco_freq = 0;
618 }
619
620 /*****************************************************************************
621 * set VCO voltage (pin 16)
622 *****************************************************************************/
SN76477_set_vco_voltage(int chip,float voltage)623 void SN76477_set_vco_voltage(int chip, float voltage)
624 {
625 struct SN76477 *sn = sn76477[chip];
626
627 CHECK_CHIP_NUM;
628
629 if( voltage == sn->vco_voltage )
630 return;
631 stream_update(sn->channel, 0);
632 sn->vco_voltage = voltage;
633 LOG(1,("SN76477 #%d: VCO ext. voltage %f (%f * %f = %f Hz)\n", chip,
634 sn->vco_voltage,
635 sn->vco_freq,
636 10.0 * (5.0 - sn->vco_voltage) / 5.0,
637 sn->vco_freq * 10.0 * (5.0 - sn->vco_voltage) / 5.0));
638 }
639
640 /*****************************************************************************
641 * set SLF resistor (pin 20)
642 *****************************************************************************/
SN76477_set_slf_res(int chip,float res)643 void SN76477_set_slf_res(int chip, float res)
644 {
645 struct SN76477 *sn = sn76477[chip];
646
647 CHECK_CHIP_NUM;
648
649 if( res == sn->slf_res )
650 return;
651 stream_update(sn->channel, 0);
652 sn->slf_res = res;
653 if( sn->slf_res > 0 && sn->slf_cap > 0 )
654 {
655 sn->slf_freq = 0.64 / (sn->slf_res * sn->slf_cap);
656 LOG(1,("SN76477 #%d: SLF freqency %f\n", chip, sn->slf_freq));
657 }
658 else
659 sn->slf_freq = 0;
660 }
661
662 /*****************************************************************************
663 * set SLF capacitor (pin 21)
664 *****************************************************************************/
SN76477_set_slf_cap(int chip,float cap)665 void SN76477_set_slf_cap(int chip, float cap)
666 {
667 struct SN76477 *sn = sn76477[chip];
668
669 CHECK_CHIP_NUM;
670
671 if( cap == sn->slf_cap )
672 return;
673 stream_update(sn->channel, 0);
674 sn->slf_cap = cap;
675 if( sn->slf_res > 0 && sn->slf_cap > 0 )
676 {
677 sn->slf_freq = 0.64 / (sn->slf_res * sn->slf_cap);
678 LOG(1,("SN76477 #%d: SLF freqency %f\n", chip, sn->slf_freq));
679 }
680 else
681 sn->slf_freq = 0;
682 }
683
684 /*****************************************************************************
685 * set ONESHOT resistor (pin 24)
686 *****************************************************************************/
SN76477_set_oneshot_res(int chip,float res)687 void SN76477_set_oneshot_res(int chip, float res)
688 {
689 struct SN76477 *sn = sn76477[chip];
690
691 CHECK_CHIP_NUM;
692 if( res == sn->oneshot_res )
693 return;
694 sn->oneshot_res = res;
695 sn->oneshot_time = TIME_IN_SEC(0.8 * sn->oneshot_res * sn->oneshot_cap);
696 LOG(1,("SN76477 #%d: ONE-SHOT time %fs\n", chip, sn->oneshot_time));
697 }
698
699 /*****************************************************************************
700 * set ONESHOT capacitor (pin 23)
701 *****************************************************************************/
SN76477_set_oneshot_cap(int chip,float cap)702 void SN76477_set_oneshot_cap(int chip, float cap)
703 {
704 struct SN76477 *sn = sn76477[chip];
705
706 CHECK_CHIP_NUM;
707
708 if( cap == sn->oneshot_cap )
709 return;
710 sn->oneshot_cap = cap;
711 sn->oneshot_time = TIME_IN_SEC(0.8 * sn->oneshot_res * sn->oneshot_cap);
712 LOG(1,("SN76477 #%d: ONE-SHOT time %fs\n", chip, sn->oneshot_time));
713 }
714
715 #define UPDATE_SLF \
716 /************************************* \
717 * SLF super low frequency oscillator \
718 * frequency = 0.64 / (r_slf * c_slf) \
719 *************************************/ \
720 sn->slf_count -= sn->slf_freq; \
721 while( sn->slf_count <= 0 ) \
722 { \
723 sn->slf_count += sn->samplerate; \
724 sn->slf_out ^= 1; \
725 }
726
727 #define UPDATE_VCO \
728 /************************************ \
729 * VCO voltage controlled oscilator \
730 * min. freq = 0.64 / (r_vco * c_vco) \
731 * freq. range is approx. 10:1 \
732 ************************************/ \
733 if( sn->vco_select ) \
734 { \
735 /* VCO is controlled by SLF */ \
736 if( sn->slf_dir == 0 ) \
737 { \
738 sn->slf_level -= sn->slf_freq * 2 * 5.0 / sn->samplerate; \
739 if( sn->slf_level <= 0.0 ) \
740 { \
741 sn->slf_level = 0.0; \
742 sn->slf_dir = 1; \
743 } \
744 } \
745 else \
746 if( sn->slf_dir == 1 ) \
747 { \
748 sn->slf_level += sn->slf_freq * 2 * 5.0 / sn->samplerate; \
749 if( sn->slf_level >= 5.0 ) \
750 { \
751 sn->slf_level = 5.0; \
752 sn->slf_dir = 0; \
753 } \
754 } \
755 sn->vco_step = sn->vco_freq * sn->slf_level; \
756 } \
757 else \
758 { \
759 /* VCO is controlled by external voltage */ \
760 sn->vco_step = sn->vco_freq * sn->vco_voltage; \
761 } \
762 sn->vco_count -= sn->vco_step; \
763 while( sn->vco_count <= 0 ) \
764 { \
765 sn->vco_count += sn->samplerate; \
766 sn->vco_out ^= 1; \
767 }
768
769 #define UPDATE_NOISE \
770 /************************************* \
771 * NOISE pseudo rand number generator \
772 *************************************/ \
773 if( sn->noise_res > 0 ) \
774 sn->noise_poly = ( (sn->noise_poly << 7) + \
775 (sn->noise_poly >> 10) + \
776 0x18000 ) & 0x1ffff; \
777 \
778 /* low pass filter: sample every noise_freq pseudo random value */ \
779 sn->noise_count -= sn->noise_freq; \
780 while( sn->noise_count <= 0 ) \
781 { \
782 sn->noise_count = sn->samplerate; \
783 sn->noise_out = sn->noise_poly & 1; \
784 }
785
786 #define UPDATE_VOLUME \
787 /************************************* \
788 * VOLUME adjust for attack/decay \
789 *************************************/ \
790 sn->vol_count -= sn->vol_rate; \
791 if( sn->vol_count <= 0 ) \
792 { \
793 int n = - sn->vol_count / sn->samplerate + 1; /* number of steps */ \
794 sn->vol_count += n * sn->samplerate; \
795 sn->vol += n * sn->vol_step; \
796 if( sn->vol < VMIN ) sn->vol = VMIN; \
797 if( sn->vol > VMAX ) sn->vol = VMAX; \
798 LOG(3,("SN76477 #%d: vol = $%04X\n", chip, sn->vol)); \
799 }
800
801
802 /*****************************************************************************
803 * mixer select 0 0 0 : VCO
804 *****************************************************************************/
SN76477_update_0(int chip,INT16 * buffer,int length)805 static void SN76477_update_0(int chip, INT16 *buffer, int length)
806 {
807 struct SN76477 *sn = sn76477[chip];
808 while( length-- )
809 {
810 UPDATE_VCO;
811 UPDATE_VOLUME;
812 *buffer++ = sn->vco_out ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
813 }
814 }
815
816 /*****************************************************************************
817 * mixer select 0 0 1 : SLF
818 *****************************************************************************/
SN76477_update_1(int chip,INT16 * buffer,int length)819 static void SN76477_update_1(int chip, INT16 *buffer, int length)
820 {
821 struct SN76477 *sn = sn76477[chip];
822 while( length-- )
823 {
824 UPDATE_SLF;
825 UPDATE_VOLUME;
826 *buffer++ = sn->slf_out ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
827 }
828 }
829
830 /*****************************************************************************
831 * mixer select 0 1 0 : NOISE
832 *****************************************************************************/
SN76477_update_2(int chip,INT16 * buffer,int length)833 static void SN76477_update_2(int chip, INT16 *buffer, int length)
834 {
835 struct SN76477 *sn = sn76477[chip];
836 while( length-- )
837 {
838 UPDATE_NOISE;
839 UPDATE_VOLUME;
840 *buffer++ = sn->noise_out ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
841 }
842 }
843
844 /*****************************************************************************
845 * mixer select 0 1 1 : VCO and NOISE
846 *****************************************************************************/
SN76477_update_3(int chip,INT16 * buffer,int length)847 static void SN76477_update_3(int chip, INT16 *buffer, int length)
848 {
849 struct SN76477 *sn = sn76477[chip];
850 while( length-- )
851 {
852 UPDATE_VCO;
853 UPDATE_NOISE;
854 UPDATE_VOLUME;
855 *buffer++ = (sn->vco_out & sn->noise_out) ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
856 }
857 }
858
859 /*****************************************************************************
860 * mixer select 1 0 0 : SLF and NOISE
861 *****************************************************************************/
SN76477_update_4(int chip,INT16 * buffer,int length)862 static void SN76477_update_4(int chip, INT16 *buffer, int length)
863 {
864 struct SN76477 *sn = sn76477[chip];
865 while( length-- )
866 {
867 UPDATE_SLF;
868 UPDATE_NOISE;
869 UPDATE_VOLUME;
870 *buffer++ = (sn->slf_out & sn->noise_out) ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
871 }
872 }
873
874 /*****************************************************************************
875 * mixer select 1 0 1 : VCO, SLF and NOISE
876 *****************************************************************************/
SN76477_update_5(int chip,INT16 * buffer,int length)877 static void SN76477_update_5(int chip, INT16 *buffer, int length)
878 {
879 struct SN76477 *sn = sn76477[chip];
880 while( length-- )
881 {
882 UPDATE_SLF;
883 UPDATE_VCO;
884 UPDATE_NOISE;
885 UPDATE_VOLUME;
886 *buffer++ = (sn->vco_out & sn->slf_out & sn->noise_out) ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
887 }
888 }
889
890 /*****************************************************************************
891 * mixer select 1 1 0 : VCO and SLF
892 *****************************************************************************/
SN76477_update_6(int chip,INT16 * buffer,int length)893 static void SN76477_update_6(int chip, INT16 *buffer, int length)
894 {
895 struct SN76477 *sn = sn76477[chip];
896 while( length-- )
897 {
898 UPDATE_SLF;
899 UPDATE_VCO;
900 UPDATE_VOLUME;
901 *buffer++ = (sn->vco_out & sn->slf_out) ? sn->vol_lookup[sn->vol-VMIN] : -sn->vol_lookup[sn->vol-VMIN];
902 }
903 }
904
905 /*****************************************************************************
906 * mixer select 1 1 1 : Inhibit
907 *****************************************************************************/
SN76477_update_7(int chip,INT16 * buffer,int length)908 static void SN76477_update_7(int chip, INT16 *buffer, int length)
909 {
910 while( length-- )
911 *buffer++ = 0;
912 }
913
SN76477_sound_update(int param,INT16 * buffer,int length)914 static void SN76477_sound_update(int param, INT16 *buffer, int length)
915 {
916 struct SN76477 *sn = sn76477[param];
917 if( sn->enable )
918 {
919 SN76477_update_7(param,buffer,length);
920 }
921 else
922 {
923 switch( sn->mixer )
924 {
925 case 0:
926 SN76477_update_0(param,buffer,length);
927 break;
928 case 1:
929 SN76477_update_1(param,buffer,length);
930 break;
931 case 2:
932 SN76477_update_2(param,buffer,length);
933 break;
934 case 3:
935 SN76477_update_3(param,buffer,length);
936 break;
937 case 4:
938 SN76477_update_4(param,buffer,length);
939 break;
940 case 5:
941 SN76477_update_5(param,buffer,length);
942 break;
943 case 6:
944 SN76477_update_6(param,buffer,length);
945 break;
946 default:
947 SN76477_update_7(param,buffer,length);
948 break;
949 }
950 }
951 }
952
SN76477_sh_start(const struct MachineSound * msound)953 int SN76477_sh_start(const struct MachineSound *msound)
954 {
955 int i;
956 intf = (struct SN76477interface*)msound->sound_interface;
957
958 for( i = 0; i < intf->num; i++ )
959 {
960 char name[16];
961
962 sn76477[i] = (struct SN76477*)malloc(sizeof(struct SN76477));
963 if( !sn76477[i] )
964 {
965 LOG(0,("%s failed to malloc struct SN76477\n", name));
966 return 1;
967 }
968 memset(sn76477[i], 0, sizeof(struct SN76477));
969
970 sprintf(name, "SN76477 #%d", i);
971 sn76477[i]->channel = stream_init(name, intf->mixing_level[i], Machine->sample_rate, i, SN76477_sound_update);
972 if( sn76477[i]->channel == -1 )
973 {
974 LOG(0,("%s stream_init failed\n", name));
975 return 1;
976 }
977 sn76477[i]->samplerate = Machine->sample_rate ? Machine->sample_rate : 1;
978 /* set up interface (default) values */
979 SN76477_set_noise_res(i, intf->noise_res[i]);
980 SN76477_set_filter_res(i, intf->filter_res[i]);
981 SN76477_set_filter_cap(i, intf->filter_cap[i]);
982 SN76477_set_decay_res(i, intf->decay_res[i]);
983 SN76477_set_attack_decay_cap(i, intf->attack_decay_cap[i]);
984 SN76477_set_attack_res(i, intf->attack_res[i]);
985 SN76477_set_amplitude_res(i, intf->amplitude_res[i]);
986 SN76477_set_feedback_res(i, intf->feedback_res[i]);
987 SN76477_set_oneshot_res(i, intf->oneshot_res[i]);
988 SN76477_set_oneshot_cap(i, intf->oneshot_cap[i]);
989 SN76477_set_pitch_voltage(i, intf->pitch_voltage[i]);
990 SN76477_set_slf_res(i, intf->slf_res[i]);
991 SN76477_set_slf_cap(i, intf->slf_cap[i]);
992 SN76477_set_vco_res(i, intf->vco_res[i]);
993 SN76477_set_vco_cap(i, intf->vco_cap[i]);
994 SN76477_set_vco_voltage(i, intf->vco_voltage[i]);
995 SN76477_mixer_w(i, 0x07); /* turn off mixing */
996 SN76477_envelope_w(i, 0x03); /* envelope inputs open */
997 SN76477_enable_w(i, 0x01); /* enable input open */
998 }
999 return 0;
1000 }
1001
SN76477_sh_stop(void)1002 void SN76477_sh_stop(void)
1003 {
1004 int i;
1005 for( i = 0; i < intf->num; i++ )
1006 {
1007 if( sn76477[i] )
1008 {
1009 if( sn76477[i]->envelope_timer )
1010 timer_remove(sn76477[i]->envelope_timer);
1011 free(sn76477[i]);
1012 }
1013 sn76477[i] = NULL;
1014 }
1015 }
1016
SN76477_sh_update(void)1017 void SN76477_sh_update(void)
1018 {
1019 int i;
1020 for( i = 0; i < intf->num; i++ )
1021 stream_update(i,0);
1022 }
1023
1024