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