1 // license:BSD-3-Clause
2 // copyright-holders:Derrick Renaud
3 /************************************************************************
4 * m79amb Sound System Analog emulation
5 * Nov 2008, Derrick Renaud
6 ************************************************************************/
7
8 #include "emu.h"
9 #include "includes/m79amb.h"
10 #include "sound/discrete.h"
11
12 #define TIME_OF_9602(r, c) (0.34 * (r) * (c) * (1.0 + 1.0 / (r)))
13 #define TIME_OF_9602_WITH_DIODE(r, c) (0.3 * (r) * (c))
14
15
16 /* Discrete Sound Input Nodes */
17 #define M79AMB_BOOM_EN NODE_01
18 #define M79AMB_THUD_EN NODE_02
19 #define M79AMB_SHOT_EN NODE_03
20 #define M79AMB_MC_REV_EN NODE_04
21 #define M79AMB_MC_CONTROL_EN NODE_05
22 #define M79AMB_TANK_TRUCK_JEEP_EN NODE_06
23 #define M79AMB_WHISTLE_A_EN NODE_07
24 #define M79AMB_WHISTLE_B_EN NODE_08
25
26 /* Discrete Sound Output Nodes */
27 #define M79AMB_BOOM_SND NODE_11
28 #define M79AMB_THUD_SND NODE_12
29 #define M79AMB_SHOT_SND NODE_13
30 #define M79AMB_MC_SND NODE_14
31 #define M79AMB_TANK_TRUCK_JEEP_SND NODE_15
32 #define M79AMB_WHISTLE_A_SND NODE_16
33 #define M79AMB_WHISTLE_B_SND NODE_17
34
35 /* Parts List - Resistors */
36 #define M79AMB_R2 RES_K(5.6)
37 #define M79AMB_R6 220
38 #define M79AMB_R9 RES_K(4.7)
39 #define M79AMB_R10 RES_K(2.2)
40 #define M79AMB_R12 RES_K(5.6)
41 #define M79AMB_R16 330
42 #define M79AMB_R19 RES_K(4.7)
43 #define M79AMB_R20 RES_K(2.2)
44 #define M79AMB_R22 RES_K(3.3)
45 #define M79AMB_R26 100
46 #define M79AMB_R29 RES_K(4.7)
47 #define M79AMB_R30 RES_K(1.5)
48 #define M79AMB_R35 RES_K(470)
49 #define M79AMB_R36 RES_K(39)
50 #define M79AMB_R37 RES_K(82)
51 #define M79AMB_R38 100
52 #define M79AMB_R39 RES_K(10)
53 #define M79AMB_R41 RES_K(2.2)
54 #define M79AMB_R42 RES_K(10)
55 #define M79AMB_R43 220
56 #define M79AMB_R44 RES_K(39)
57 #define M79AMB_R45 RES_K(82)
58 #define M79AMB_R46 RES_K(10)
59 #define M79AMB_R48 RES_K(2.2)
60 #define M79AMB_R49 RES_K(1)
61 #define M79AMB_R51 RES_K(39)
62 #define M79AMB_R52 RES_K(82)
63 #define M79AMB_R53 100
64 #define M79AMB_R54 RES_K(10)
65 #define M79AMB_R57 RES_K(2.2)
66 #define M79AMB_R58 RES_K(2.2)
67 #define M79AMB_R59 RES_K(1)
68 #define M79AMB_R61 RES_K(39)
69 #define M79AMB_R62 RES_K(82)
70 #define M79AMB_R63 100
71 #define M79AMB_R64 RES_K(10)
72 #define M79AMB_R67 RES_K(2.2)
73 #define M79AMB_R68 RES_K(2.2)
74 #define M79AMB_R69 RES_K(1)
75 #define M79AMB_R76 RES_K(2.7)
76 #define M79AMB_R77 RES_K(47)
77 #define M79AMB_R78 RES_K(47)
78 #define M79AMB_R79 RES_K(15)
79 #define M79AMB_R80 RES_K(22)
80 #define M79AMB_R81 RES_K(100)
81 #define M79AMB_R82 RES_K(100)
82 #define M79AMB_R83 RES_K(3.3)
83 #define M79AMB_R84 RES_K(50)
84 #define M79AMB_R86 470
85
86 /* Parts List - Capacitors */
87 #define M79AMB_C2 CAP_U(39)
88 #define M79AMB_C3 CAP_U(22)
89 #define M79AMB_C6 CAP_U(0.1)
90 #define M79AMB_C8 CAP_U(39)
91 #define M79AMB_C9 CAP_U(22)
92 #define M79AMB_C12 CAP_U(0.1)
93 #define M79AMB_C14 CAP_U(4.7)
94 #define M79AMB_C15 CAP_U(3.3)
95 #define M79AMB_C18 CAP_U(0.1)
96 #define M79AMB_C20 CAP_U(2.2)
97 #define M79AMB_C21 CAP_U(1)
98 #define M79AMB_C22 CAP_U(22)
99 #define M79AMB_C23 CAP_U(0.01)
100 #define M79AMB_C25 CAP_U(2.2)
101 #define M79AMB_C26 CAP_U(22)
102 #define M79AMB_C27 CAP_U(0.47)
103 #define M79AMB_C28 CAP_U(0.1)
104 #define M79AMB_C29 CAP_U(22)
105 #define M79AMB_C30 CAP_U(0.03)
106 #define M79AMB_C31 CAP_U(0.1)
107 #define M79AMB_C32 CAP_U(0.1)
108 #define M79AMB_C33 CAP_U(22)
109 #define M79AMB_C34 CAP_U(0.03)
110 #define M79AMB_C35 CAP_U(0.1)
111 #define M79AMB_C36 CAP_U(0.1)
112 #define M79AMB_C37 CAP_P(500)
113 #define M79AMB_C41 CAP_U(0.1)
114 #define M79AMB_C42 CAP_U(15)
115
116
117 static const discrete_mixer_desc m79amb_final_mix =
118 {
119 DISC_MIXER_IS_OP_AMP,
120 {
121 M79AMB_R76 + M79AMB_R9,
122 M79AMB_R77 + M79AMB_R19,
123 M79AMB_R78 + M79AMB_R29,
124 M79AMB_R79 + RES_2_PARALLEL(M79AMB_R41, M79AMB_R42 + M79AMB_R43),
125 M79AMB_R80 + RES_2_PARALLEL(M79AMB_R48, M79AMB_R49),
126 M79AMB_R81 + RES_2_PARALLEL(M79AMB_R59, M79AMB_R57 + M79AMB_R58),
127 M79AMB_R82 + RES_2_PARALLEL(M79AMB_R69, M79AMB_R67 + M79AMB_R68)
128 },
129 {0}, /* no r_nodes */
130 {M79AMB_C6, M79AMB_C12, M79AMB_C18, M79AMB_C23, M79AMB_C28, M79AMB_C32, M79AMB_C36},
131 0,
132 M79AMB_R83 + M79AMB_R84,
133 M79AMB_C37,
134 M79AMB_C42,
135 0,
136 1 /* gain */
137 };
138
139 DISCRETE_SOUND_START( m79amb_discrete )
140 /************************************************
141 * Input register mapping
142 ************************************************/
143 DISCRETE_INPUT_PULSE(M79AMB_BOOM_EN, 0)
144 DISCRETE_INPUT_PULSE(M79AMB_THUD_EN, 0)
145 DISCRETE_INPUT_PULSE(M79AMB_SHOT_EN, 0)
DISCRETE_INPUT_LOGIC(M79AMB_MC_REV_EN)146 DISCRETE_INPUT_LOGIC(M79AMB_MC_REV_EN)
147 DISCRETE_INPUT_LOGIC(M79AMB_MC_CONTROL_EN)
148 DISCRETE_INPUT_LOGIC(M79AMB_TANK_TRUCK_JEEP_EN)
149 DISCRETE_INPUT_LOGIC(M79AMB_WHISTLE_A_EN)
150 DISCRETE_INPUT_LOGIC(M79AMB_WHISTLE_B_EN)
151
152 /* Boom, Thud, Shot sounds need more accurate emulation */
153
154 /************************************************
155 * Boom
156 ************************************************/
157 DISCRETE_ONESHOT(NODE_20,
158 M79AMB_BOOM_EN, /* TRIG */
159 1, /* AMPL */
160 TIME_OF_9602_WITH_DIODE(M79AMB_R2, M79AMB_C2),
161 DISC_ONESHOT_REDGE | DISC_ONESHOT_RETRIG | DISC_OUT_ACTIVE_HIGH)
162 DISCRETE_RCDISC2(NODE_21,
163 NODE_20, /* Q1 base */
164 0, /* Q1 off, C3 discharges */
165 M79AMB_R9 + M79AMB_R10, /* discharges through amp/filter circuit */
166 12, /* Q1 on, C3 charges */
167 M79AMB_R6, /* Q2 on */
168 M79AMB_C3) /* controls amplitude */
169 DISCRETE_NOISE(M79AMB_BOOM_SND,
170 1, /* ENAB */
171 800, /* FREQ - Guess*/
172 NODE_21, /* AMP */
173 0) /* BIAS - fake AC is fine*/
174
175 /************************************************
176 * Thud
177 ************************************************/
178 DISCRETE_ONESHOT(NODE_30,
179 M79AMB_THUD_EN, /* TRIG */
180 1, /* AMPL */
181 TIME_OF_9602_WITH_DIODE(M79AMB_R12, M79AMB_C8),
182 DISC_ONESHOT_REDGE | DISC_ONESHOT_RETRIG | DISC_OUT_ACTIVE_HIGH)
183 DISCRETE_RCDISC2(NODE_31,
184 NODE_30, /* Q4 base */
185 0, /* Q4 off, C9 discharges */
186 M79AMB_R19 + M79AMB_R20, /* discharges through amp/filter circuit */
187 12, /* Q4 on, C9 charges */
188 M79AMB_R16, /* Q5 on */
189 M79AMB_C9) /* controls amplitude */
190 DISCRETE_NOISE(M79AMB_THUD_SND,
191 1, /* ENAB */
192 500, /* FREQ - Guess*/
193 NODE_31, /* AMP */
194 0) /* BIAS - fake AC is fine*/
195
196 /************************************************
197 * Shot
198 ************************************************/
199 DISCRETE_ONESHOT(NODE_40,
200 M79AMB_SHOT_EN, /* TRIG */
201 1, /* AMPL */
202 TIME_OF_9602_WITH_DIODE(M79AMB_R22, M79AMB_C14),
203 DISC_ONESHOT_REDGE | DISC_ONESHOT_RETRIG | DISC_OUT_ACTIVE_HIGH)
204 DISCRETE_RCDISC2(NODE_41,
205 NODE_40, /* Q7 base */
206 0, /* Q7 off, C15 discharges */
207 M79AMB_R29 + M79AMB_R30, /* discharges through amp/filter circuit */
208 12, /* Q7 on, C15 charges */
209 M79AMB_R26, /* Q8 on */
210 M79AMB_C15) /* controls amplitude */
211 DISCRETE_NOISE(M79AMB_SHOT_SND,
212 1, /* ENAB */
213 1000, /* FREQ - Guess*/
214 NODE_41, /* AMP */
215 0) /* BIAS - fake AC is fine*/
216
217 /************************************************
218 * MC
219 ************************************************/
220 /* not the best implementation of the pin 5 charge circuit, but it is within tolerance */
221 DISCRETE_RCDISC2(NODE_50,
222 M79AMB_MC_REV_EN,
223 /* R35 can be ignored on discharge */
224 RES_VOLTAGE_DIVIDER(M79AMB_R36 + M79AMB_R37, M79AMB_R38) * 12, /* Q12 on */
225 RES_2_PARALLEL(M79AMB_R36 + M79AMB_R37, M79AMB_R38), /* Q12 on */
226 12.0 * RES_VOLTAGE_DIVIDER(M79AMB_R36, M79AMB_R35), /* Q12 off */
227 RES_2_PARALLEL(M79AMB_R36, M79AMB_R35) + M79AMB_R37, /* Q12 off */
228 M79AMB_C20)
229 /* cap charge to B+ ratio changes voltage on pin 5 */
230 /* (iR36 + iR35 + iR37) * R36||R35||R37 where iR35 = 0/R35 = 0 */
231 DISCRETE_TRANSFORM4(NODE_51, 12.0 / M79AMB_R36, NODE_50, M79AMB_R37, RES_3_PARALLEL(M79AMB_R36, M79AMB_R35, M79AMB_R37), "012/+3*")
232 DISCRETE_566(NODE_52, /* IC U3, pin 4 */
233 NODE_51, /* IC U3, pin 5 */
234 M79AMB_R39, M79AMB_C21,
235 12, 0, 12, /* VPOS,VNEG,VCHARGE */
236 DISC_566_OUT_DC | DISC_566_OUT_TRIANGLE)
237 DISCRETE_CRFILTER(NODE_53,
238 NODE_52, M79AMB_R41 + M79AMB_R42 + M79AMB_R43, M79AMB_C22)
239 DISCRETE_MULTIPLY(NODE_54, NODE_53, M79AMB_MC_CONTROL_EN)
240 DISCRETE_GAIN(M79AMB_MC_SND, NODE_54, RES_VOLTAGE_DIVIDER(M79AMB_R41 + M79AMB_R42, 2200))//M79AMB_R43))
241
242 /************************************************
243 * Tank, Truck, Jeep
244 ************************************************/
245 DISCRETE_566(NODE_60, /* IC U4, pin 4 */
246 12.0 * RES_VOLTAGE_DIVIDER(M79AMB_R44, M79AMB_R45), /* IC U5, pin 5 */
247 M79AMB_R46, M79AMB_C25,
248 12, 0, 12, /* VPOS,VNEG,VCHARGE */
249 DISC_566_OUT_DC | DISC_566_OUT_TRIANGLE)
250 DISCRETE_ONOFF(NODE_61,
251 M79AMB_TANK_TRUCK_JEEP_EN, /* Q16, Q17 */
252 NODE_60)
253 DISCRETE_CRFILTER(NODE_62,
254 NODE_61, M79AMB_R48 + M79AMB_R49, M79AMB_C26)
255 DISCRETE_GAIN(NODE_63, NODE_62, RES_VOLTAGE_DIVIDER(M79AMB_R48, M79AMB_R49))
256 DISCRETE_RCFILTER(M79AMB_TANK_TRUCK_JEEP_SND,
257 NODE_63, RES_2_PARALLEL(M79AMB_R48, M79AMB_R49), M79AMB_C27)
258
259 /************************************************
260 * Whisle A
261 ************************************************/
262 DISCRETE_RCDISC2(NODE_70,
263 M79AMB_WHISTLE_A_EN,
264 RES_VOLTAGE_DIVIDER(M79AMB_R51 + M79AMB_R52, M79AMB_R53) * 12, /* Q15 on */
265 RES_2_PARALLEL(M79AMB_R53, M79AMB_R51 + M79AMB_R52), /* Q15 on */
266 12, M79AMB_R51 + M79AMB_R52, /* Q15 off */
267 M79AMB_C29)
268 /* cap charge to B+ ratio changes voltage on pin 5 */
269 DISCRETE_TRANSFORM3(NODE_71, 12, NODE_70, RES_VOLTAGE_DIVIDER(M79AMB_R51, M79AMB_R52), "01-2*1+")
270 DISCRETE_566(NODE_72, /* IC U5, pin 4 */
271 NODE_71, /* IC U5, pin 5 */
272 M79AMB_R54, M79AMB_C30,
273 12, 0, 12, /* VPOS,VNEG,VCHARGE */
274 DISC_566_OUT_DC | DISC_566_OUT_TRIANGLE)
275 DISCRETE_CRFILTER(NODE_73,
276 NODE_72, M79AMB_R57 + M79AMB_R58 + M79AMB_R59, M79AMB_C31)
277 DISCRETE_MULTIPLY(NODE_74, NODE_73, M79AMB_WHISTLE_A_EN) /* Q16, Q17 */
278 DISCRETE_GAIN(M79AMB_WHISTLE_A_SND, NODE_74, RES_VOLTAGE_DIVIDER(M79AMB_R57 + M79AMB_R58, M79AMB_R59))
279
280 /************************************************
281 * Whisle B
282 ************************************************/
283 DISCRETE_RCDISC2(NODE_80,
284 M79AMB_WHISTLE_B_EN,
285 RES_VOLTAGE_DIVIDER(M79AMB_R61 + M79AMB_R62, M79AMB_R63) * 12, /* Q18 on */
286 RES_2_PARALLEL(M79AMB_R63, M79AMB_R61 + M79AMB_R62), /* Q18 on */
287 12, M79AMB_R61 + M79AMB_R62, /* Q18 off */
288 M79AMB_C33)
289 /* cap charge to B+ ratio changes voltage on pin 5 */
290 DISCRETE_TRANSFORM3(NODE_81, 12, NODE_80, RES_VOLTAGE_DIVIDER(M79AMB_R61, M79AMB_R62), "01-2*1+")
291 DISCRETE_566(NODE_82, /* IC U5, pin 4 */
292 NODE_81, /* IC U5, pin 5 */
293 M79AMB_R64, M79AMB_C34,
294 12, 0, 12, /* VPOS,VNEG,VCHARGE */
295 DISC_566_OUT_DC | DISC_566_OUT_TRIANGLE)
296 DISCRETE_CRFILTER(NODE_83,
297 NODE_82, M79AMB_R67 + M79AMB_R68 + M79AMB_R69, M79AMB_C35)
298 DISCRETE_MULTIPLY(NODE_84, NODE_83, M79AMB_WHISTLE_B_EN) /* Q19, Q20*/
299 DISCRETE_GAIN(M79AMB_WHISTLE_B_SND, NODE_84, RES_VOLTAGE_DIVIDER(M79AMB_R67 + M79AMB_R68, M79AMB_R69))
300
301 /************************************************
302 * Mixer
303 ************************************************/
304 DISCRETE_MIXER7(NODE_90, /* IC U7, pin 6 */
305 1, /* ENAB */
306 M79AMB_BOOM_SND,
307 M79AMB_THUD_SND,
308 M79AMB_SHOT_SND,
309 M79AMB_MC_SND,
310 M79AMB_TANK_TRUCK_JEEP_SND,
311 M79AMB_WHISTLE_A_SND,
312 M79AMB_WHISTLE_B_SND,
313 &m79amb_final_mix)
314 DISCRETE_RCFILTER(NODE_91,
315 NODE_90, M79AMB_R86, M79AMB_C41)
316
317 DISCRETE_OUTPUT(NODE_91, 32000.0/5)
318
319 DISCRETE_SOUND_END
320
321
322 /* the ports are guessed from operation */
323 /* the schematics do not show the actual hookup */
324
325 void m79amb_state::m79amb_8000_w(uint8_t data)
326 {
327 /* these values are not latched */
328 /* they are pulsed when the port is addressed */
329 /* the discrete system will just trigger from them */
330 m_discrete->write(M79AMB_SHOT_EN, data & 0x01);
331 m_discrete->write(M79AMB_BOOM_EN, data & 0x02);
332 m_discrete->write(M79AMB_THUD_EN, data & 0x04);
333 }
334
m79amb_8003_w(uint8_t data)335 void m79amb_state::m79amb_8003_w(uint8_t data)
336 {
337 /* Self Test goes low on reset and lights LED */
338 /* LED goes off on pass */
339 m_self_test = BIT(data, 0);
340 m_discrete->write(M79AMB_MC_REV_EN, data & 0x02);
341 m_discrete->write(M79AMB_MC_CONTROL_EN, data & 0x04);
342 m_discrete->write(M79AMB_TANK_TRUCK_JEEP_EN, data & 0x08);
343 m_discrete->write(M79AMB_WHISTLE_B_EN, data & 0x10);
344 m_discrete->write(M79AMB_WHISTLE_A_EN, data & 0x20);
345 }
346