1 // license:BSD-3-Clause
2 // copyright-holders:Derrick Renaud
3 /*************************************************************************
4 
5     audio\dragrace.c
6 
7 *************************************************************************/
8 #include "emu.h"
9 #include "includes/dragrace.h"
10 #include "sound/discrete.h"
11 
12 /************************************************************************/
13 /* dragrace Sound System Analog emulation                                  */
14 /************************************************************************/
15 
16 static const discrete_lfsr_desc dragrace_lfsr =
17 {
18 	DISC_CLK_IS_FREQ,
19 	16,         /* Bit Length */
20 	0,          /* Reset Value */
21 	0,          /* Use Bit 0 as XOR input 0 */
22 	14,         /* Use Bit 14 as XOR input 1 */
23 	DISC_LFSR_XNOR,     /* Feedback stage1 is XNOR */
24 	DISC_LFSR_OR,       /* Feedback stage2 is just stage 1 output OR with external feed */
25 	DISC_LFSR_REPLACE,  /* Feedback stage3 replaces the shifted register contents */
26 	0x000001,       /* Everything is shifted into the first bit only */
27 	0,          /* Output is already inverted by XNOR */
28 	15          /* Output bit */
29 };
30 
31 /* Nodes - Sounds */
32 #define DRAGRACE_NOISE          NODE_10
33 #define DRAGRACE_SCREECH1_SND   NODE_11
34 #define DRAGRACE_SCREECH2_SND   NODE_12
35 #define DRAGRACE_LOTONE_SND     NODE_13
36 #define DRAGRACE_HITONE_SND     NODE_14
37 #define DRAGRACE_TONE_SND       NODE_15
38 #define DRAGRACE_EXPLODE1_SND   NODE_16
39 #define DRAGRACE_EXPLODE2_SND   NODE_17
40 #define DRAGRACE_MOTOR1_SND     NODE_18
41 #define DRAGRACE_MOTOR2_SND     NODE_19
42 
43 DISCRETE_SOUND_START(dragrace_discrete)
44 	/************************************************/
45 	/* dragrace  Effects Relataive Gain Table       */
46 	/*                                              */
47 	/* Effect  V-ampIn  Gain ratio        Relative  */
48 	/* LoTone   3.8     10/32               593.8   */
49 	/* HiTone   3.8     10/32               593.8   */
50 	/* Screech  3.8     10/330               57.6   */
51 	/* Motor    3.8     10/32.67            581.6   */
52 	/* Explode  5.0     10/25              1000.0   */
53 	/************************************************/
54 
55 
56 	/************************************************/
57 	/* Input register mapping for dragrace          */
58 	/************************************************/
59 	DISCRETE_INPUT_LOGIC(DRAGRACE_SCREECH1_EN)
60 	DISCRETE_INPUT_LOGIC(DRAGRACE_SCREECH2_EN)
61 	DISCRETE_INPUT_LOGIC(DRAGRACE_LOTONE_EN)
62 	DISCRETE_INPUT_LOGIC(DRAGRACE_HITONE_EN)
63 	DISCRETE_INPUT_LOGIC(DRAGRACE_EXPLODE1_EN)
64 	DISCRETE_INPUT_LOGIC(DRAGRACE_EXPLODE2_EN)
65 	DISCRETE_INPUT_DATA (DRAGRACE_MOTOR1_DATA)
66 	DISCRETE_INPUT_DATA (DRAGRACE_MOTOR2_DATA)
67 	DISCRETE_INPUT_LOGIC(DRAGRACE_MOTOR1_EN)
68 	DISCRETE_INPUT_LOGIC(DRAGRACE_MOTOR2_EN)
69 	DISCRETE_INPUT_LOGIC(DRAGRACE_KLEXPL1_EN)
70 	DISCRETE_INPUT_LOGIC(DRAGRACE_KLEXPL2_EN)
71 	DISCRETE_INPUT_LOGIC(DRAGRACE_ATTRACT_EN)
72 
73 	/************************************************/
74 	/* Motor sound circuit is based on a 556 VCO    */
75 	/* with the input frequency set by the MotorSND */
76 	/* latch (4 bit). This freqency is then used to */
77 	/* driver a modulo 12 counter, with div6, 4 & 3 */
78 	/* summed as the output of the circuit.         */
79 	/* VCO Output is Sq wave = 27-382Hz             */
80 	/*  F1 freq - (Div6)                            */
81 	/*  F2 freq = (Div4)                            */
82 	/*  F3 freq = (Div3) 33.3% duty, 33.3 deg phase */
83 	/* To generate the frequency we take the freq.  */
84 	/* diff. and /15 to get all the steps between   */
85 	/* 0 - 15.  Then add the low frequency and send */
86 	/* that value to a squarewave generator.        */
87 	/* Also as the frequency changes, it ramps due  */
88 	/* to a 2.2uf capacitor on the R-ladder.        */
89 	/* Note the VCO freq. is controlled by a 250k   */
90 	/* pot.  The freq. used here is for the pot set */
91 	/* to 125k.  The low freq is allways the same.  */
92 	/* This adjusts the high end.                   */
93 	/* 0k = 214Hz.   250k = 4416Hz                  */
94 	/* NOTE: freqs are ripped from Sprint for now.  */
95 	/************************************************/
96 	DISCRETE_RCFILTER(NODE_20, DRAGRACE_MOTOR1_DATA, 119898, 2.2e-6)
97 	DISCRETE_ADJUSTMENT(NODE_21, (214.0-27.0)/12/31, (4416.0-27.0)/12/31, DISC_LOGADJ, "MOTOR1")
98 	DISCRETE_MULTIPLY(NODE_22, NODE_20, NODE_21)
99 
100 	DISCRETE_MULTADD(NODE_23, NODE_22, 2, 27.0/6)   /* F1 = /12*2 = /6 */
101 	DISCRETE_SQUAREWAVE(NODE_24, 1, NODE_23, (581.6/3), 50.0, 0, 0)
102 	DISCRETE_RCFILTER(NODE_25, NODE_24, 10000, 1e-7)
103 
104 	DISCRETE_MULTADD(NODE_26, NODE_22, 3, 27.0/4)   /* F2 = /12*3 = /4 */
105 	DISCRETE_SQUAREWAVE(NODE_27, 1, NODE_26, (581.6/3), 50.0, 0, 0)
106 	DISCRETE_RCFILTER(NODE_28, NODE_27, 10000, 1e-7)
107 
108 	DISCRETE_MULTADD(NODE_29, NODE_22, 4, 27.0/3)   /* F3 = /12*4 = /3 */
109 	DISCRETE_SQUAREWAVE(NODE_30, 1, NODE_29, (581.6/3), 100.0/3, 0, 360.0/3)
110 	DISCRETE_RCFILTER(NODE_31, NODE_30, 10000, 1e-7)
111 
112 	DISCRETE_ADDER3(DRAGRACE_MOTOR1_SND, DRAGRACE_MOTOR1_EN, NODE_25, NODE_28, NODE_31)
113 
114 	/************************************************/
115 	/* Car2 motor sound is basically the same as    */
116 	/* Car1.  But I shifted the frequencies up for  */
117 	/* it to sound different from car1.             */
118 	/************************************************/
119 	DISCRETE_RCFILTER(NODE_40, DRAGRACE_MOTOR2_DATA, 119898, 2.2e-6)
120 	DISCRETE_ADJUSTMENT(NODE_41, (214.0-27.0)/12/31, (4416.0-27.0)/12/31, DISC_LOGADJ, "MOTOR2")
121 	DISCRETE_MULTIPLY(NODE_42, NODE_40, NODE_41)
122 
123 	DISCRETE_MULTADD(NODE_43, NODE_42, 2, 27.0/6)   /* F1 = /12*2 = /6 */
124 	DISCRETE_SQUAREWAVE(NODE_44, 1, NODE_43, (581.6/3), 50.0, 0, 0)
125 	DISCRETE_RCFILTER(NODE_45, NODE_44, 10000, 1e-7)
126 
127 	DISCRETE_MULTADD(NODE_46, NODE_42, 3, 27.0/4)   /* F2 = /12*3 = /4 */
128 	DISCRETE_SQUAREWAVE(NODE_47, 1, NODE_46, (581.6/3), 50.0, 0, 0)
129 	DISCRETE_RCFILTER(NODE_48, NODE_47, 10000, 1e-7)
130 
131 	DISCRETE_MULTADD(NODE_49, NODE_42, 4, 27.0/3)   /* F3 = /12*4 = /3 */
132 	DISCRETE_SQUAREWAVE(NODE_50, 1, NODE_49, (581.6/3), 100.0/3, 0, 360.0/3)
133 	DISCRETE_RCFILTER(NODE_51, NODE_50, 10000, 1e-7)
134 
135 	DISCRETE_ADDER3(DRAGRACE_MOTOR2_SND, DRAGRACE_MOTOR2_EN, NODE_45, NODE_48, NODE_51)
136 
137 	/************************************************/
138 	/* Explosion circuit is built around a noise    */
139 	/* generator built from 2 shift registers that  */
140 	/* are clocked by the 1V signal.                */
141 	/* 1V = HSYNC/2                                 */
142 	/*    = 15750/2                                 */
143 	/* Output is integrated to apply decay.         */
144 	/************************************************/
145 	DISCRETE_LFSR_NOISE(DRAGRACE_NOISE, 1, DRAGRACE_ATTRACT_EN, 15750.0/2, 1.0, 0, 0, &dragrace_lfsr)
146 
147 	DISCRETE_RAMP(NODE_61, DRAGRACE_EXPLODE1_EN, DRAGRACE_EXPLODE1_EN, (1000.0-0.0)/1, 1000.0, 0.0, 1000.0)
148 	DISCRETE_MULTIPLY(NODE_62, DRAGRACE_NOISE, NODE_61)
149 	DISCRETE_RCFILTER(NODE_63, NODE_62, 1500, 2.2e-7)
150 	DISCRETE_MULTIPLY(DRAGRACE_EXPLODE1_SND, NODE_63, DRAGRACE_KLEXPL1_EN)
151 
152 	DISCRETE_RAMP(NODE_66, DRAGRACE_EXPLODE2_EN, DRAGRACE_EXPLODE2_EN, (1000.0-0.0)/1, 1000.0, 0.0, 1000.0)
153 	DISCRETE_MULTIPLY(NODE_67, DRAGRACE_NOISE, NODE_66)
154 	DISCRETE_RCFILTER(NODE_68, NODE_67, 1500, 2.2e-7)
155 	DISCRETE_MULTIPLY(DRAGRACE_EXPLODE2_SND, NODE_68, DRAGRACE_KLEXPL2_EN)
156 
157 	/************************************************/
158 	/* Skid circuits takes the noise output from    */
159 	/* the crash circuit and applies +ve feedback   */
160 	/* to cause oscillation. There is also an RC    */
161 	/* filter on the input to the feedback cct.     */
162 	/* RC is 1K & 10uF                              */
163 	/* Feedback cct is modelled by using the RC out */
164 	/* as the frequency input on a VCO,             */
165 	/* breadboarded freq range as:                  */
166 	/*  0 = 940Hz, 34% duty                         */
167 	/*  1 = 630Hz, 29% duty                         */
168 	/*  the duty variance is so small we ignore it  */
169 	/************************************************/
170 	DISCRETE_INVERT(NODE_70, DRAGRACE_NOISE)
171 	DISCRETE_MULTADD(NODE_71, NODE_70, 940.0-630.0, ((940.0-630.0)/2)+630.0)
172 	DISCRETE_RCFILTER(NODE_72, NODE_71, 1000, 1e-5)
173 	DISCRETE_SQUAREWAVE(NODE_73, 1, NODE_72, 407.8, 31.5, 0, 0.0)
174 	DISCRETE_ONOFF(DRAGRACE_SCREECH1_SND, DRAGRACE_SCREECH1_EN, NODE_73)
175 	DISCRETE_ONOFF(DRAGRACE_SCREECH2_SND, DRAGRACE_SCREECH2_EN, NODE_73)
176 
177 	/************************************************/
178 	/* LoTone = 32V = 15750Hz/2/32                  */
179 	/* HiTone =  4V = 15750Hz/2/4                   */
180 	/************************************************/
181 	DISCRETE_SQUAREWFIX(DRAGRACE_LOTONE_SND, DRAGRACE_LOTONE_EN, 15750.0/2/32,  593.8, 50.0, 0, 0.0)
182 	DISCRETE_SQUAREWFIX(DRAGRACE_HITONE_SND, DRAGRACE_HITONE_EN, 15750.0/2/4,   593.8, 50.0, 0, 0.0)
183 	DISCRETE_ADDER2(DRAGRACE_TONE_SND, 1, DRAGRACE_LOTONE_SND, DRAGRACE_HITONE_SND)
184 
185 	/************************************************/
186 	/* Combine all 5 sound sources.                 */
187 	/* Add some final gain to get to a good sound   */
188 	/* level.                                       */
189 	/************************************************/
190 	DISCRETE_ADDER4(NODE_90, DRAGRACE_ATTRACT_EN, DRAGRACE_TONE_SND, DRAGRACE_MOTOR1_SND, DRAGRACE_EXPLODE1_SND, DRAGRACE_SCREECH1_SND)
191 	DISCRETE_ADDER4(NODE_91, DRAGRACE_ATTRACT_EN, DRAGRACE_TONE_SND, DRAGRACE_MOTOR2_SND, DRAGRACE_EXPLODE2_SND, DRAGRACE_SCREECH2_SND)
192 
193 	DISCRETE_OUTPUT(NODE_90, 65534.0/(593.8+581.6+1000.0+57.6))
194 	DISCRETE_OUTPUT(NODE_91, 65534.0/(593.8+581.6+1000.0+57.6))
195 DISCRETE_SOUND_END
196