1
/************************************************************************
2
* sprint8 Sound System Analog emulation
3
* Sept 2009, Derrick Renaud
4
************************************************************************/
10
/* Discrete Sound Input Nodes */
11
#define SPRINT8_CRASH_EN NODE_01
12
#define SPRINT8_SCREECH_EN NODE_02
13
#define SPRINT8_ATTRACT_EN NODE_03
14
#define SPRINT8_MOTOR1_EN NODE_04
15
#define SPRINT8_MOTOR2_EN NODE_05
16
#define SPRINT8_MOTOR3_EN NODE_06
17
#define SPRINT8_MOTOR4_EN NODE_07
18
#define SPRINT8_MOTOR5_EN NODE_08
19
#define SPRINT8_MOTOR6_EN NODE_09
20
#define SPRINT8_MOTOR7_EN NODE_10
21
#define SPRINT8_MOTOR8_EN NODE_11
23
/* Discrete Sound Output Nodes */
24
#define SPRINT8_NOISE NODE_12
25
#define SPRINT8_MOTOR1_SND NODE_13
26
#define SPRINT8_MOTOR2_SND NODE_14
27
#define SPRINT8_MOTOR3_SND NODE_15
28
#define SPRINT8_MOTOR4_SND NODE_16
29
#define SPRINT8_MOTOR5_SND NODE_17
30
#define SPRINT8_MOTOR6_SND NODE_18
31
#define SPRINT8_MOTOR7_SND NODE_19
32
#define SPRINT8_MOTOR8_SND NODE_20
33
#define SPRINT8_CRASH_SCREECH_SND NODE_21
34
#define SPRINT8_AUDIO_1_2 NODE_22
35
#define SPRINT8_AUDIO_3_7 NODE_23
36
#define SPRINT8_AUDIO_5_6 NODE_24
37
#define SPRINT8_AUDIO_4_8 NODE_25
40
#define SPRINT8_R132_POT NODE_29
43
/* Parts List - Resistors */
44
#define SPRINT8_R1 RES_K(47)
45
#define SPRINT8_R3 RES_K(47)
46
#define SPRINT8_R4 RES_K(47)
47
#define SPRINT8_R19 RES_K(1)
48
#define SPRINT8_R20 RES_K(1)
49
#define SPRINT8_R27 RES_K(18)
50
#define SPRINT8_R28 820
51
#define SPRINT8_R29 RES_K(330)
52
#define SPRINT8_R39 RES_K(120)
53
#define SPRINT8_R40 RES_K(22)
54
#define SPRINT8_R41 RES_K(150)
55
#define SPRINT8_R89 RES_K(22)
56
#define SPRINT8_R91 RES_K(47)
57
#define SPRINT8_R93 RES_K(2.2)
58
#define SPRINT8_R96 RES_K(47)
59
#define SPRINT8_R97 RES_K(2.2)
60
#define SPRINT8_R99 RES_K(27)
61
#define SPRINT8_R100 RES_K(1)
62
#define SPRINT8_R101 RES_K(2.2)
63
#define SPRINT8_R132 RES_K(100)
64
#define SPRINT8_R145 RES_K(3.3)
65
#define SPRINT8_R146 RES_K(7.5)
66
#define SPRINT8_R147 100
67
#define SPRINT8_R148 RES_K(1)
68
#define SPRINT8_R149 RES_K(22)
70
/* Parts List - Capacitors */
71
#define SPRINT8_C8 CAP_U(.01)
72
#define SPRINT8_C17 CAP_U(.001)
73
#define SPRINT8_C18 CAP_U(.047)
74
#define SPRINT8_C19 CAP_U(.047)
75
#define SPRINT8_C26 CAP_U(100)
76
#define SPRINT8_C27 CAP_U(.22)
77
#define SPRINT8_C28 CAP_U(.1)
78
#define SPRINT8_C59 CAP_U(.1)
79
#define SPRINT8_C63 CAP_U(.1)
80
#define SPRINT8_C64 CAP_U(.1)
81
#define SPRINT8_C89 CAP_U(.1)
82
#define SPRINT8_C90 CAP_U(.1)
84
#define SPRINT8_HSYNC 15750.0 /* not checked */
85
#define SPRINT8_1V SPRINT8_HSYNC/2
86
#define SPRINT8_2V SPRINT8_1V/2
89
static const discrete_lfsr_desc sprint8_lfsr =
94
10, /* Use Bit 10 as XOR input 0 */
95
15, /* Use Bit 15 as XOR input 1 */
96
DISC_LFSR_XNOR, /* Feedback stage1 is XNOR */
97
DISC_LFSR_OR, /* Feedback stage2 is just stage 1 output OR with external feed */
98
DISC_LFSR_REPLACE, /* Feedback stage3 replaces the shifted register contents */
99
0x000001, /* Everything is shifted into the first bit only */
100
DISC_LFSR_FLAG_RESET_TYPE_L, /* Output is not inverted */
104
static const discrete_555_desc sprint8_crash_555a_desc =
107
5, DEFAULT_555_VALUES
110
static const discrete_integrate_info sprint8_crash_integrate =
112
DISC_INTEGRATE_OP_AMP_1,
113
SPRINT8_R99, SPRINT8_R97, SPRINT8_R96, SPRINT8_C59, /*r1, r2, r3, c, */
115
0, 0, 0 /* no functions */
118
static const discrete_555_desc sprint8_motor_555a_desc =
120
DISC_555_OUT_COUNT_F_X,
121
5, DEFAULT_555_VALUES
124
static const discrete_555_desc sprint8_motor_555m_desc =
126
DISC_555_OUT_ENERGY | DISC_555_TRIGGER_IS_COUNT,
127
5, DEFAULT_555_VALUES
130
static const discrete_op_amp_filt_info sprint8_motor_filter =
132
SPRINT8_R27, 0, SPRINT8_R28 + RES_2_PARALLEL(SPRINT8_R19, SPRINT8_R20), 0, SPRINT8_R29, /* r1, r2, r3, r4, rF, */
133
SPRINT8_C18, SPRINT8_C19, 0, /* c1, c2, c3, */
134
5.0 * RES_VOLTAGE_DIVIDER(SPRINT8_R19, SPRINT8_R20), 5, 0 /* vRef, vP, vN */
137
static const discrete_mixer_desc sprint8_crash_screech_mixer =
139
DISC_MIXER_IS_RESISTOR,
140
{SPRINT8_R149, SPRINT8_R91},
141
{0, NODE_80}, /* R93 switched in/out of circuit */
142
{0}, 0, 0, SPRINT8_C64, 0, 0, 1 /* c, rI, rF, cF, cAmp, vRef, gain */
145
static const discrete_mixer_desc sprint8_mixer =
147
DISC_MIXER_IS_RESISTOR,
148
{SPRINT8_R1 + SPRINT8_R100, SPRINT8_R3, SPRINT8_R4},
149
{0}, {0}, 0, 0, 0, SPRINT8_C8, 0, 1 /* r_nodes, c, rI, rF, cF, cAmp, vRef, gain */
153
/************************************************
155
************************************************/
156
/* The first (astable) 555 generates a quick falling pulse that triggers the second (monostable) 555.
157
* This pulse is passed through C17 and pulled up with R40. This pulse is too fast to emulate so
158
* we will just tell the monostable it was triggered once and ignore C17/R40.
160
#define SPRINT8_MOTOR_CIRCUIT(_car) \
161
DISCRETE_RCFILTER(NODE_RELATIVE(NODE_30, _car - 1), NODE_RELATIVE(SPRINT8_MOTOR1_EN, _car - 1), SPRINT8_R89, SPRINT8_C26) \
162
DISCRETE_ADDER2(NODE_RELATIVE(NODE_40, _car - 1), 1, NODE_RELATIVE(NODE_30, _car - 1), 0.7) /* add Q21 shift */ \
163
DISCRETE_555_ASTABLE_CV(NODE_RELATIVE(NODE_50, _car - 1), 1, SPRINT8_R39, 0, SPRINT8_C27, NODE_RELATIVE(NODE_40, _car - 1), &sprint8_motor_555a_desc) \
164
DISCRETE_555_MSTABLE(NODE_RELATIVE(NODE_60, _car - 1), 1, NODE_RELATIVE(NODE_50, _car - 1), SPRINT8_R41, SPRINT8_C28, &sprint8_motor_555m_desc) \
165
DISCRETE_OP_AMP_FILTER(NODE_RELATIVE(SPRINT8_MOTOR1_SND, _car - 1), 1, NODE_RELATIVE(NODE_60, _car - 1), 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &sprint8_motor_filter)
168
DISCRETE_SOUND_START( sprint8 )
169
/************************************************
170
* Input register mapping
171
************************************************/
172
DISCRETE_INPUT_LOGIC(SPRINT8_CRASH_EN)
173
DISCRETE_INPUT_NOT (SPRINT8_SCREECH_EN)
174
DISCRETE_INPUT_NOT (SPRINT8_ATTRACT_EN)
175
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR1_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
176
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR2_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
177
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR3_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
178
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR4_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
179
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR5_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
180
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR6_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
181
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR7_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
182
DISCRETE_INPUTX_LOGIC(SPRINT8_MOTOR8_EN, DEFAULT_TTL_V_LOGIC_1, 0, 0)
184
DISCRETE_TASK_START(0)
185
DISCRETE_ADJUSTMENT_TAG(SPRINT8_R132_POT, 0, SPRINT8_R132, DISC_LINADJ, "R132")
187
/************************************************
188
* Noise Generator, Crash, Screech
189
************************************************/
190
/* Address line A2 is used to XOR the feedback bits.
191
* This can not easily be implemented, so I just set the
192
* feedback as XNOR. */
193
DISCRETE_LFSR_NOISE(SPRINT8_NOISE, /* IC F7, pin 13 */
195
SPRINT8_ATTRACT_EN, /* RESET */
196
SPRINT8_2V, 1, 0, 0.5, &sprint8_lfsr) /* CLK,AMPL,FEED,BIAS,LFSRTB */
200
DISCRETE_TASK_START(1)
201
DISCRETE_GAIN(NODE_70, SPRINT8_NOISE, DEFAULT_TTL_V_LOGIC_1 * RES_VOLTAGE_DIVIDER(SPRINT8_R148, SPRINT8_R147))
202
DISCRETE_CRFILTER_VREF(NODE_71,
204
RES_2_PARALLEL(SPRINT8_R148, SPRINT8_R147) + RES_2_PARALLEL(RES_K(5), RES_K(10)),
206
5.0 * RES_VOLTAGE_DIVIDER(RES_K(5), RES_K(10))) /* ref to 555 CV pin */
207
DISCRETE_555_ASTABLE_CV(NODE_72,
208
SPRINT8_SCREECH_EN, /* RESET */
209
SPRINT8_R145, SPRINT8_R146, SPRINT8_C89,
211
&sprint8_crash_555a_desc)
212
DISCRETE_INTEGRATE(NODE_73, SPRINT8_CRASH_EN, 0, &sprint8_crash_integrate)
214
DISCRETE_SWITCH(NODE_80,
216
SPRINT8_NOISE, /* SWITCH */
217
SPRINT8_R93, 1) /* INP0,INP1*/
218
DISCRETE_SWITCH(NODE_74, /* effect of Q20 */
220
SPRINT8_NOISE, /* SWITCH */
221
NODE_73, 0) /* INP0,INP1*/
222
DISCRETE_MIXER2(NODE_75,
226
&sprint8_crash_screech_mixer)
228
DISCRETE_CRFILTER_VREF(NODE_76,
230
SPRINT8_R93 + SPRINT8_R91, SPRINT8_C63,
232
/* IC E5, pin 14 gain. Does not simulate minor DC offset caused by R93. */
233
DISCRETE_TRANSFORM5(NODE_77, NODE_76, 5, SPRINT8_R132_POT, SPRINT8_R101, 1, "01-23/4+*1+")
234
DISCRETE_CLAMP(SPRINT8_CRASH_SCREECH_SND, NODE_77, 0, 15.0 - 1.5)
237
/************************************************
239
************************************************/
240
DISCRETE_TASK_START(1)
241
SPRINT8_MOTOR_CIRCUIT(1)
242
SPRINT8_MOTOR_CIRCUIT(2)
245
DISCRETE_TASK_START(1)
246
SPRINT8_MOTOR_CIRCUIT(3)
247
SPRINT8_MOTOR_CIRCUIT(7)
250
DISCRETE_TASK_START(1)
251
SPRINT8_MOTOR_CIRCUIT(5)
252
SPRINT8_MOTOR_CIRCUIT(6)
255
DISCRETE_TASK_START(1)
256
SPRINT8_MOTOR_CIRCUIT(4)
257
SPRINT8_MOTOR_CIRCUIT(8)
260
/************************************************
262
************************************************/
263
DISCRETE_TASK_START(2)
264
DISCRETE_MIXER3(SPRINT8_AUDIO_1_2,
265
SPRINT8_ATTRACT_EN, /* ENAB */
266
SPRINT8_CRASH_SCREECH_SND,
270
DISCRETE_MIXER3(SPRINT8_AUDIO_3_7,
271
SPRINT8_ATTRACT_EN, /* ENAB */
272
SPRINT8_CRASH_SCREECH_SND,
276
DISCRETE_MIXER3(SPRINT8_AUDIO_5_6,
277
SPRINT8_ATTRACT_EN, /* ENAB */
278
SPRINT8_CRASH_SCREECH_SND,
282
DISCRETE_MIXER3(SPRINT8_AUDIO_4_8,
283
SPRINT8_ATTRACT_EN, /* ENAB */
284
SPRINT8_CRASH_SCREECH_SND,
288
DISCRETE_OUTPUT(SPRINT8_AUDIO_1_2, 65500.0/8)
289
DISCRETE_OUTPUT(SPRINT8_AUDIO_3_7, 65500.0/8)
290
DISCRETE_OUTPUT(SPRINT8_AUDIO_5_6, 65500.0/8)
291
DISCRETE_OUTPUT(SPRINT8_AUDIO_4_8, 65500.0/8)
296
WRITE8_DEVICE_HANDLER( sprint8_crash_w )
298
discrete_sound_w(device, SPRINT8_CRASH_EN, data & 0x01);
301
WRITE8_DEVICE_HANDLER( sprint8_screech_w )
303
discrete_sound_w(device, SPRINT8_SCREECH_EN, data & 0x01);
306
WRITE8_DEVICE_HANDLER( sprint8_attract_w )
308
discrete_sound_w(device, SPRINT8_ATTRACT_EN, data & 0x01);
311
WRITE8_DEVICE_HANDLER( sprint8_motor_w )
313
discrete_sound_w(device, NODE_RELATIVE(SPRINT8_MOTOR1_EN, offset & 0x07), data & 0x01);