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