1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /*************************************************************************
4 
5     Sega Z80-3D system
6 
7 *************************************************************************/
8 
9 #include "emu.h"
10 #include "includes/turbo.h"
11 #include "sound/samples.h"
12 #include "speaker.h"
13 
14 
15 #define DISCRETE_TEST (0)
16 
17 
18 
19 /*************************************
20  *
21  *  Turbo shared state updates
22  *
23  *************************************/
24 
turbo_update_samples()25 void turbo_state::turbo_update_samples()
26 {
27 	/* accelerator sounds */
28 	/* BSEL == 3 --> off */
29 	/* BSEL == 2 --> standard */
30 	/* BSEL == 1 --> tunnel */
31 	/* BSEL == 0 --> ??? */
32 	if (m_turbo_bsel == 3 && m_samples->playing(5))
33 		m_samples->stop(5);
34 	else if (m_turbo_bsel != 3 && !m_samples->playing(5))
35 		m_samples->start(5, 7, true);
36 	if (m_samples->playing(5))
37 		m_samples->set_frequency(5, m_samples->base_frequency(5) * ((m_turbo_accel & 0x3f) / 5.25 + 1));
38 }
39 
40 
41 #if (DISCRETE_TEST)
42 
TIMER_CALLBACK_MEMBER(turbo_state::update_sound_a)43 TIMER_CALLBACK_MEMBER(turbo_state::update_sound_a)
44 {
45 	discrete_device *discrete = machine.device<discrete_device>("discrete");
46 	int data = param;
47 
48 	/* missing short crash sample, but I've never seen it triggered */
49 	discrete->write(0, !(data & 0x01));
50 	discrete->write(1, (data >> 1) & 1);
51 	discrete->write(2, (data >> 2) & 1);
52 	discrete->write(3, (data >> 3) & 1);
53 	discrete->write(4, (data >> 4) & 1);
54 	discrete->write(5, !(data & 0x20));
55 	discrete->write(6, !(data & 0x40));
56 
57 if (!((data >> 1) & 1)) osd_printf_debug("/TRIG1\n");
58 if (!((data >> 2) & 1)) osd_printf_debug("/TRIG2\n");
59 if (!((data >> 3) & 1)) osd_printf_debug("/TRIG3\n");
60 if (!((data >> 4) & 1)) osd_printf_debug("/TRIG4\n");
61 
62 //  osel = (osel & 6) | ((data >> 5) & 1);
63 //  turbo_update_samples(samples);
64 }
65 #endif
66 
67 
68 
69 /*************************************
70  *
71  *  Turbo PPI write handlers
72  *
73  *************************************/
74 
turbo_sound_a_w(u8 data)75 void turbo_state::turbo_sound_a_w(u8 data)
76 {
77 #if (!DISCRETE_TEST)
78 #endif
79 #if (!DISCRETE_TEST)
80 	uint8_t diff = data ^ m_sound_state[0];
81 #endif
82 	m_sound_state[0] = data;
83 
84 #if (!DISCRETE_TEST)
85 
86 	/* /CRASH.S: channel 0 */
87 	if ((diff & 0x01) && !(data & 0x01)) m_samples->start(0, 5);
88 
89 	/* /TRIG1: channel 1 */
90 	if ((diff & 0x02) && !(data & 0x02)) m_samples->start(1, 0);
91 
92 	/* /TRIG2: channel 1 */
93 	if ((diff & 0x04) && !(data & 0x04)) m_samples->start(1, 1);
94 
95 	/* /TRIG3: channel 1 */
96 	if ((diff & 0x08) && !(data & 0x08)) m_samples->start(1, 2);
97 
98 	/* /TRIG4: channel 1 */
99 	if ((diff & 0x10) && !(data & 0x10)) m_samples->start(1, 3);
100 
101 	/* OSEL0 */
102 	m_turbo_osel = (m_turbo_osel & 6) | ((data >> 5) & 1);
103 
104 	/* /SLIP: channel 2 */
105 	if ((diff & 0x40) && !(data & 0x40)) m_samples->start(2, 4);
106 
107 	/* /CRASH.L: channel 3 */
108 	if ((diff & 0x80) && !(data & 0x80)) m_samples->start(3, 5);
109 
110 	/* update any samples */
111 	turbo_update_samples();
112 
113 #else
114 
115 	if (((data ^ m_last_sound_a) & 0x1e) && (m_last_sound_a & 0x1e) != 0x1e)
116 		machine().scheduler().timer_set(attotime::from_hz(20000), FUNC(update_sound_a), data);
117 	else
118 		update_sound_a(data);
119 
120 	m_last_sound_a = data;
121 
122 #endif
123 }
124 
125 
turbo_sound_b_w(u8 data)126 void turbo_state::turbo_sound_b_w(u8 data)
127 {
128 	uint8_t diff = data ^ m_sound_state[1];
129 	m_sound_state[1] = data;
130 
131 	/* ACC0-ACC5 */
132 	m_turbo_accel = data & 0x3f;
133 	output().set_value("tachometer", m_turbo_accel);
134 
135 	/* /AMBU: channel 4 */
136 	if ((diff & 0x40) && !(data & 0x40) && !m_samples->playing(4)) m_samples->start(4, 8, true);
137 	if ((diff & 0x40) &&  (data & 0x40)) m_samples->stop(4);
138 
139 	/* /SPIN: channel 2 */
140 	if ((diff & 0x80) && !(data & 0x80)) m_samples->start(2, 6);
141 
142 	/* update any samples */
143 	turbo_update_samples();
144 }
145 
146 
turbo_sound_c_w(u8 data)147 void turbo_state::turbo_sound_c_w(u8 data)
148 {
149 	/* OSEL1-2 */
150 	m_turbo_osel = (m_turbo_osel & 1) | ((data & 3) << 1);
151 
152 	/* BSEL0-1 */
153 	m_turbo_bsel = (data >> 2) & 3;
154 
155 	/* SPEED0-3 */
156 	output().set_value("speed", (data >> 4) & 0x0f);
157 
158 	/* update any samples */
159 	turbo_update_samples();
160 }
161 
162 
163 
164 /*************************************
165  *
166  *  Turbo sound hardware description
167  *
168  *************************************/
169 
170 static const char *const turbo_sample_names[] =
171 {
172 	"*turbo",
173 	"01",       /* 0: Trig1 */
174 	"02",       /* 1: Trig2 */
175 	"03",       /* 2: Trig3 */
176 	"04",       /* 3: Trig4 */
177 	"05",       /* 4: Screech */
178 	"06",       /* 5: Crash */
179 	"skidding", /* 6: Spin */
180 	"idle",     /* 7: Idle */
181 	"ambulanc", /* 8: Ambulance */
182 	nullptr
183 };
184 
185 
turbo_samples(machine_config & config)186 void turbo_state::turbo_samples(machine_config &config)
187 {
188 	/* this is the cockpit speaker configuration */
189 	SPEAKER(config, "fspeaker", 0.0, 0.0, 1.0);     // front
190 	SPEAKER(config, "bspeaker",  0.0, 0.0, -0.5);   // back
191 	SPEAKER(config, "lspeaker", -0.2, 0.0, 1.0);    // left
192 	SPEAKER(config, "rspeaker", 0.2, 0.0, 1.0);     // right
193 
194 	SAMPLES(config, m_samples);
195 	m_samples->set_channels(10);
196 	m_samples->set_samples_names(turbo_sample_names);
197 
198 	/* channel 0 = CRASH.S -> CRASH.S/SM */
199 	m_samples->add_route(0, "fspeaker", 0.25);
200 
201 	/* channel 1 = TRIG1-4 -> ALARM.M/F/R/L */
202 	m_samples->add_route(1, "fspeaker", 0.25);
203 	m_samples->add_route(1, "rspeaker", 0.25);
204 	m_samples->add_route(1, "lspeaker",  0.25);
205 
206 	/* channel 2 = SLIP/SPIN -> SKID.F/R/L/M */
207 	m_samples->add_route(2, "fspeaker", 0.25);
208 	m_samples->add_route(2, "rspeaker", 0.25);
209 	m_samples->add_route(2, "lspeaker",  0.25);
210 
211 	/* channel 3 = CRASH.L -> CRASH.L/LM */
212 	m_samples->add_route(3, "bspeaker",  0.25);
213 
214 	/* channel 4 = AMBU -> AMBULANCE/AMBULANCE.M */
215 	m_samples->add_route(4, "fspeaker", 0.25);
216 
217 	/* channel 5 = ACCEL+BSEL -> MYCAR.F/W/M + MYCAR0.F/M + MYCAR1.F/M */
218 	m_samples->add_route(5, "fspeaker", 0.25);
219 	m_samples->add_route(5, "bspeaker",  0.25);
220 
221 	/* channel 6 = OSEL -> OCAR.F/FM */
222 	m_samples->add_route(6, "fspeaker", 0.25);
223 
224 	/* channel 7 = OSEL -> OCAR.L/LM */
225 	m_samples->add_route(7, "lspeaker",  0.25);
226 
227 	/* channel 8 = OSEL -> OCAR.R/RM */
228 	m_samples->add_route(8, "rspeaker", 0.25);
229 
230 	/* channel 9 = OSEL -> OCAR.W/WM */
231 	m_samples->add_route(9, "bspeaker",  0.25);
232 }
233 
234 /*
235     Cockpit: CN2 1+2 -> FRONT
236              CN2 3+4 -> REAR
237              CN2 5+6 -> RIGHT
238              CN2 7+8 -> LEFT
239 
240     Upright: CN2 1+2 -> UPPER
241              CN2 3+4 -> LOWER
242 
243     F.OUT = CRASH.S +
244             ALARM.F +
245             SKID.F +
246             OCAR.F +
247             MYCAR.F +
248             MYCAR0.F +
249             MYCAR1.F +
250             AMBULACE
251 
252     W.OUT = CRASH.L +
253             OCAR.W +
254             MYCAR.W +
255             MYCAR0.W +
256             MYCAR1.W +
257             SLF
258 
259     R.OUT = ALARM.R +
260             SKID.R +
261             OCAR.R
262 
263     L.OUT = ALARM.L +
264             SKID.L +
265             OCAR.L
266 
267     M.OUT = CRASH.SM +
268             CRASH.LM +
269             SKID.M +
270             ALARM.M +
271             AMBULACE.M +
272             MYCAR.M +
273             MYCAR0.M +
274             MYCAR1.M +
275             OCAR.FM +
276             OCAR.LM +
277             OCAR.RM +
278             OCAR.WM
279 */
280 
281 
282 
283 /*************************************
284  *
285  *  Subroc 3D PPI write handlers
286  *
287  *************************************/
288 
subroc3d_sound_a_w(u8 data)289 void turbo_state::subroc3d_sound_a_w(u8 data)
290 {
291 	m_sound_state[0] = data;
292 
293 	/* DIS0-3 contained in bits 0-3 */
294 	/* DIR0-2 contained in bits 4-6 */
295 }
296 
297 
subroc3d_update_volume(int leftchan,uint8_t dis,uint8_t dir)298 inline void turbo_state::subroc3d_update_volume(int leftchan, uint8_t dis, uint8_t dir)
299 {
300 	float volume = (float)(15 - dis) / 16.0f;
301 	float lvol, rvol;
302 
303 	/* compute the left/right volume from the data */
304 	if (dir != 7)
305 	{
306 		lvol = volume * (float)(6 - dir) / 6.0f;
307 		rvol = volume * (float)dir / 6.0f;
308 	}
309 	else
310 		lvol = rvol = 0;
311 
312 	/* if the sample is playing, adjust it */
313 	m_samples->set_volume(leftchan + 0, lvol);
314 	m_samples->set_volume(leftchan + 1, rvol);
315 }
316 
317 
subroc3d_sound_b_w(u8 data)318 void turbo_state::subroc3d_sound_b_w(u8 data)
319 {
320 	uint8_t diff = data ^ m_sound_state[1];
321 	m_sound_state[1] = data;
322 
323 	/* bit 0 latches direction/volume for missile */
324 	if ((diff & 0x01) && (data & 0x01))
325 	{
326 		m_subroc3d_mdis = m_sound_state[0] & 0x0f;
327 		m_subroc3d_mdir = (m_sound_state[0] >> 4) & 0x07;
328 		if (!m_samples->playing(0))
329 		{
330 			m_samples->start(0, 0, true);
331 			m_samples->start(1, 0, true);
332 		}
333 		subroc3d_update_volume(0, m_subroc3d_mdis, m_subroc3d_mdir);
334 	}
335 
336 	/* bit 1 latches direction/volume for torpedo */
337 	if ((diff & 0x02) && (data & 0x02))
338 	{
339 		m_subroc3d_tdis = m_sound_state[0] & 0x0f;
340 		m_subroc3d_tdir = (m_sound_state[0] >> 4) & 0x07;
341 		if (!m_samples->playing(2))
342 		{
343 			m_samples->start(2, 1, true);
344 			m_samples->start(3, 1, true);
345 		}
346 		subroc3d_update_volume(2, m_subroc3d_tdis, m_subroc3d_tdir);
347 	}
348 
349 	/* bit 2 latches direction/volume for fighter */
350 	if ((diff & 0x04) && (data & 0x04))
351 	{
352 		m_subroc3d_fdis = m_sound_state[0] & 0x0f;
353 		m_subroc3d_fdir = (m_sound_state[0] >> 4) & 0x07;
354 		if (!m_samples->playing(4))
355 		{
356 			m_samples->start(4, 2, true);
357 			m_samples->start(5, 2, true);
358 		}
359 		subroc3d_update_volume(4, m_subroc3d_fdis, m_subroc3d_fdir);
360 	}
361 
362 	/* bit 3 latches direction/volume for hit */
363 	if ((diff & 0x08) && (data & 0x08))
364 	{
365 		m_subroc3d_hdis = m_sound_state[0] & 0x0f;
366 		m_subroc3d_hdir = (m_sound_state[0] >> 4) & 0x07;
367 		subroc3d_update_volume(6, m_subroc3d_hdis, m_subroc3d_hdir);
368 	}
369 }
370 
371 
subroc3d_sound_c_w(u8 data)372 void turbo_state::subroc3d_sound_c_w(u8 data)
373 {
374 	uint8_t diff = data ^ m_sound_state[2];
375 	m_sound_state[2] = data;
376 
377 	/* /FIRE TRIG */
378 	/* FIRE SELECT */
379 	if ((diff & 0x01) && (data & 0x01))
380 		m_samples->start(8, (data & 0x02) ? 6 : 5);
381 
382 	/* /SHIP EXP TRIG -> MY SHIP EXP: channel 9 */
383 	if ((diff & 0x04) && (data & 0x04))
384 		m_samples->start(9, 7);
385 
386 	/* /HIT TRIG -> HIT.L/R: channels 6+7 */
387 	if ((diff & 0x08) && (data & 0x08))
388 	{
389 		m_samples->start(6, (m_sound_state[0] & 0x80) ? 4 : 3);
390 		m_samples->start(7, (m_sound_state[0] & 0x80) ? 4 : 3);
391 	}
392 
393 	/* /ALARM TRIG -> ALARM.M: channel 10 */
394 	/* ALARM SELECT */
395 	if ((diff & 0x10) && (data & 0x10))
396 		m_samples->start(10, (data & 0x20) ? 10 : 9);
397 
398 	/* /PROLOGUE */
399 	if (!m_samples->playing(11))
400 		m_samples->start(11, 8, true);
401 	m_samples->set_volume(11, (data & 0x40) ? 0 : 1.0);
402 
403 	/* /GAME START */
404 	machine().sound().system_mute(data & 0x80);
405 }
406 
407 
408 
409 /*************************************
410  *
411  *  Subroc 3D sound hardware description
412  *
413  *************************************/
414 
415 static const char *const subroc3d_sample_names[] =
416 {
417 	"*subroc3d",
418 	"01",   /*  0: enemy missile */
419 	"02",   /*  1: enemy torpedo */
420 	"03",   /*  2: enemy fighter */
421 	"04",   /*  3: explosion in sky */
422 	"05",   /*  4: explosion on sea */
423 	"06",   /*  5: missile shoot */
424 	"07",   /*  6: torpedo shoot */
425 	"08",   /*  7: my ship expl */
426 	"09",   /*  8: prolog sound */
427 	"11",   /*  9: alarm 0 */
428 	"12",   /* 10: alarm 1 */
429 	nullptr
430 };
431 
subroc3d_samples(machine_config & config)432 void turbo_state::subroc3d_samples(machine_config &config)
433 {
434 	SPEAKER(config, "lspeaker").front_left();
435 	SPEAKER(config, "rspeaker").front_right();
436 
437 	SAMPLES(config, m_samples);
438 	m_samples->set_channels(12);
439 	m_samples->set_samples_names(subroc3d_sample_names);
440 
441 	/* MISSILE in channels 0 and 1 */
442 	m_samples->add_route(0, "lspeaker", 0.25);
443 	m_samples->add_route(1, "rspeaker", 0.25);
444 
445 	/* TORPEDO in channels 2 and 3 */
446 	m_samples->add_route(2, "lspeaker", 0.25);
447 	m_samples->add_route(3, "rspeaker", 0.25);
448 
449 	/* FIGHTER in channels 4 and 5 */
450 	m_samples->add_route(4, "lspeaker", 0.25);
451 	m_samples->add_route(5, "rspeaker", 0.25);
452 
453 	/* HIT in channels 6 and 7 */
454 	m_samples->add_route(6, "lspeaker", 0.25);
455 	m_samples->add_route(7, "rspeaker", 0.25);
456 
457 	/* FIRE sound in channel 8 */
458 	m_samples->add_route(8, "lspeaker", 0.25);
459 	m_samples->add_route(8, "rspeaker", 0.25);
460 
461 	/* SHIP EXP sound in channel 9 */
462 	m_samples->add_route(9, "lspeaker", 0.25);
463 	m_samples->add_route(9, "rspeaker", 0.25);
464 
465 	/* ALARM TRIG sound in channel 10 */
466 	m_samples->add_route(10, "lspeaker", 0.25);
467 	m_samples->add_route(10, "rspeaker", 0.25);
468 
469 	/* PROLOGUE sound in channel 11 */
470 	m_samples->add_route(11, "lspeaker", 0.25);
471 	m_samples->add_route(11, "rspeaker", 0.25);
472 }
473 
474 
475 
476 /*************************************
477  *
478  *  Buck Rogers PPI write handlers
479  *
480  *************************************/
481 
buckrog_update_samples()482 void turbo_state::buckrog_update_samples()
483 {
484 	/* accelerator sounds */
485 	if (m_samples->playing(5))
486 		m_samples->set_frequency(5, m_samples->base_frequency(5) * (m_buckrog_myship / 100.25 + 1));
487 }
488 
489 
buckrog_sound_a_w(u8 data)490 void turbo_state::buckrog_sound_a_w(u8 data)
491 {
492 	uint8_t diff = data ^ m_sound_state[0];
493 	m_sound_state[0] = data;
494 
495 	/* clock HIT DIS from bits 0-2 */
496 	if ((diff & 0x10) && (data & 0x10))
497 		m_samples->set_volume(3, (float)(/*7 - */(data & 7)) / 7.0f);
498 
499 	/* clock ACC from bits 0-3 */
500 	if ((diff & 0x20) && (data & 0x20))
501 	{
502 		m_buckrog_myship = data & 0x0f;
503 		buckrog_update_samples();
504 	}
505 
506 	/* /ALARM0: channel 0 */
507 	if ((diff & 0x40) && !(data & 0x40)) m_samples->start(0, 0);
508 
509 	/* /ALARM1: channel 0 */
510 	if ((diff & 0x80) && !(data & 0x80)) m_samples->start(0, 1);
511 }
512 
513 
buckrog_sound_b_w(u8 data)514 void turbo_state::buckrog_sound_b_w(u8 data)
515 {
516 	uint8_t diff = data ^ m_sound_state[1];
517 	m_sound_state[1] = data;
518 
519 	/* /ALARM3: channel 0 */
520 	if ((diff & 0x01) && !(data & 0x01)) m_samples->start(0, 2);
521 
522 	/* /ALARM4: channel 0 */
523 	if ((diff & 0x02) && !(data & 0x02)) m_samples->start(0, 3);
524 
525 	/* /FIRE: channel 1 */
526 	if ((diff & 0x04) && !(data & 0x04)) m_samples->start(1, 5);
527 
528 	/* /EXP: channel 2 */
529 	if ((diff & 0x08) && !(data & 0x08)) m_samples->start(2, 4);
530 
531 	/* /HIT: channel 3 */
532 	if ((diff & 0x10) && !(data & 0x10))
533 	{
534 		m_samples->start(3, 7);
535 		buckrog_update_samples();
536 	}
537 
538 	/* /REBOUND: channel 4 */
539 	if ((diff & 0x20) && !(data & 0x20)) m_samples->start(4, 6);
540 
541 	/* SHIP: channel 5 */
542 	if ((diff & 0x40) &&  (data & 0x40) && !m_samples->playing(5))
543 	{
544 		m_samples->start(5, 8, true);
545 		buckrog_update_samples();
546 	}
547 	if ((diff & 0x40) && !(data & 0x40) &&  m_samples->playing(5)) m_samples->stop(5);
548 
549 	/* GAME ON */
550 	machine().sound().system_enable(data & 0x80);
551 }
552 
553 
554 
555 /*************************************
556  *
557  *  Sound interfaces
558  *
559  *************************************/
560 
561 static const char *const buckrog_sample_names[]=
562 {
563 	"*buckrog",
564 	"alarm0",   /* 0 */
565 	"alarm1",   /* 1 */
566 	"alarm2",   /* 2 */
567 	"alarm3",   /* 3 */
568 	"exp",      /* 4 */
569 	"fire",     /* 5 */
570 	"rebound",  /* 6 */
571 	"hit",      /* 7 */
572 	"shipsnd1", /* 8 */
573 	"shipsnd2", /* 9 */
574 	"shipsnd3", /* 10 */
575 	nullptr
576 };
577 
578 
buckrog_samples(machine_config & config)579 void turbo_state::buckrog_samples(machine_config &config)
580 {
581 	SPEAKER(config, "mono").front_center();
582 	SAMPLES(config, m_samples);
583 	m_samples->set_channels(6);
584 	m_samples->set_samples_names(buckrog_sample_names);
585 	m_samples->add_route(ALL_OUTPUTS, "mono", 0.25);
586 }
587 
588 
589 
590 /*************************************
591  *
592  *  Discrete test code
593  *
594  *************************************/
595 
596 #if (DISCRETE_TEST)
597 
598 /* Nodes - Inputs */
599 #define TURBO_CRASH_EN          NODE_01
600 #define TURBO_TRIG1_INV         NODE_02
601 #define TURBO_TRIG2_INV         NODE_03
602 #define TURBO_TRIG3_INV         NODE_04
603 #define TURBO_TRIG4_INV         NODE_05
604 #define TURBO_SLIP_EN           NODE_06
605 #define TURBO_CRASHL_EN         NODE_07
606 #define TURBO_ACC_VAL           NODE_08
607 #define TURBO_AMBU_EN           NODE_09
608 #define TURBO_SPIN_EN           NODE_10
609 #define TURBO_OSEL_VAL          NODE_11
610 #define TURBO_BSEL_VAL          NODE_12
611 
612 /* Nodes - Sounds */
613 #define FIRETRUCK_NOISE         NODE_20
614 
615 static const discrete_555_desc turbo_alarm_555 =
616 {
617 	DISC_555_OUT_SQW | DISC_555_OUT_DC,
618 	5,              // B+ voltage of 555
619 	DEFAULT_555_VALUES,
620 };
621 
622 DISCRETE_SOUND_START(turbo_discrete)
623 	/************************************************/
624 	/* Input register mapping for turbo             */
625 	/************************************************/
626 	/*                  NODE             ADDR  MASK    GAIN    OFFSET  INIT */
627 	DISCRETE_INPUT(TURBO_CRASH_EN       ,0x00,0x001f,                  0.0)
628 	DISCRETE_INPUT(TURBO_TRIG1_INV      ,0x01,0x001f,                  1.0)
629 	DISCRETE_INPUT(TURBO_TRIG2_INV      ,0x02,0x001f,                  1.0)
630 	DISCRETE_INPUT(TURBO_TRIG3_INV      ,0x03,0x001f,                  1.0)
631 	DISCRETE_INPUT(TURBO_TRIG4_INV      ,0x04,0x001f,                  1.0)
632 	DISCRETE_INPUT(TURBO_SLIP_EN        ,0x05,0x001f,                  0.0)
633 	DISCRETE_INPUT(TURBO_CRASHL_EN      ,0x06,0x001f,                  0.0)
634 	DISCRETE_INPUT(TURBO_ACC_VAL        ,0x07,0x001f,                  0.0)
635 	DISCRETE_INPUT(TURBO_AMBU_EN        ,0x08,0x001f,                  0.0)
636 	DISCRETE_INPUT(TURBO_SPIN_EN        ,0x09,0x001f,                  0.0)
637 	DISCRETE_INPUT(TURBO_OSEL_VAL       ,0x0a,0x001f,                  0.0)
638 	DISCRETE_INPUT(TURBO_BSEL_VAL       ,0x0b,0x001f,                  0.0)
639 
640 	/************************************************/
641 	/* Alarm sounds                                 */
642 	/************************************************/
643 
644 	// 5-5-5 counter provides the input clock
645 	DISCRETE_555_ASTABLE(NODE_50,1,470,120,0.1e-6,&turbo_alarm_555)
646 	// which clocks a 74393 dual 4-bit counter, clocked on the falling edge
647 	DISCRETE_COUNTER(NODE_51,1,0,NODE_50,0,15,1,0,DISC_CLK_ON_F_EDGE)
648 	// the high bit of this counter
649 	DISCRETE_TRANSFORM2(NODE_52,NODE_51,8,"01/")
650 	// clocks the other half of the 74393
651 	DISCRETE_COUNTER(NODE_53,1,0,NODE_52,0,15,1,0,DISC_CLK_ON_F_EDGE)
652 
653 	// trig1 triggers a LS123 retriggerable multivibrator
654 	DISCRETE_ONESHOT(NODE_60,TURBO_TRIG1_INV,5.0,(0.33e-9)*47*1e6, DISC_ONESHOT_FEDGE|DISC_ONESHOT_RETRIG|DISC_OUT_ACTIVE_HIGH)
655 	// which interacts with bit 0 of the second counter
656 	DISCRETE_TRANSFORM2(NODE_61,NODE_53,1,"01&")
657 	// via a NAND
658 	DISCRETE_LOGIC_NAND(NODE_62,1,NODE_60,NODE_61)
659 
660 	// trig2 triggers a LS123 retriggerable multivibrator
661 	DISCRETE_ONESHOT(NODE_65,TURBO_TRIG2_INV,5.0,(0.33e-9)*47*10e6,DISC_ONESHOT_FEDGE|DISC_ONESHOT_RETRIG|DISC_OUT_ACTIVE_HIGH)
662 	// which interacts with bit 3 of the first counter via a NAND
663 	DISCRETE_LOGIC_NAND(NODE_66,1,NODE_65,NODE_52)
664 
665 	// trig3 triggers a LS123 retriggerable multivibrator
666 	DISCRETE_ONESHOT(NODE_70,TURBO_TRIG3_INV,5.0,(0.33e-9)*47*33e6,DISC_ONESHOT_FEDGE|DISC_ONESHOT_RETRIG|DISC_OUT_ACTIVE_HIGH)
667 	// which interacts with bit 2 of the first counter
668 	DISCRETE_TRANSFORM3(NODE_71,NODE_51,4,1,"01/2&")
669 	// via a NAND
670 	DISCRETE_LOGIC_NAND(NODE_72,1,NODE_70,NODE_71)
671 
672 	// trig4 triggers a LS123 retriggerable multivibrator
673 	DISCRETE_ONESHOT(NODE_75,TURBO_TRIG4_INV,5.0,(0.33e-9)*47*10e6,DISC_ONESHOT_FEDGE|DISC_ONESHOT_RETRIG|DISC_OUT_ACTIVE_HIGH)
674 	// which interacts with bit 1 of the first counter
675 	DISCRETE_TRANSFORM3(NODE_76,NODE_51,2,1,"01/2&")
676 	// via a NAND
677 	DISCRETE_LOGIC_NAND(NODE_77,1,NODE_75,NODE_76)
678 
679 	// everything is effectively NANDed together
680 	DISCRETE_LOGIC_NAND4(NODE_80,1,NODE_62,NODE_66,NODE_72,NODE_77)
681 
682 /*
683 
684     the rest of the circuit looks like this:
685 
686                       +5V            +12V                                +---+
687                        ^              ^   +--------+               1K    v   |
688                        |              |   | |\     |           +---NNN--NNN--+
689                        Z 1K       10K Z   | | \    |           | |\     20K  |   +--|(----> ALARM_M
690                        Z              Z   +-|- \   |           | | \         |   |  4.7u
691                        |              |     |   >--+---NNNN----+-|- \        |   +--|(----> ALARM_F
692                        +--NNNN--|(----+-----|+ /        22K      |   >-------+---+  4.7u
693     +-\                |  5.1K  4.7u  |     | /             +6V--|+ /            +--|(----> ALARM_R
694     |  >o---(NODE_62)--+              Z     |/                   | /             |  4.7u
695     +-/                |          10K Z                          |/              +--|(----> ALARM_L
696                        |              |                                             4.7u
697     +-\                |              v
698     |  >o---(NODE_66)--+             GND
699     +-/                |
700                        |
701     +-\                |
702     |  >o---(NODE_72)--+
703     +-/                |
704                        |
705     +-\                |
706     |  >o---(NODE_77)--+
707     +-/
708 
709 
710 */
711 
712 	/************************************************/
713 	/* Combine all 7 sound sources.                 */
714 	/************************************************/
715 
716 	DISCRETE_OUTPUT(NODE_80, 16000)
717 DISCRETE_SOUND_END
718 
719 #endif
720