1 // license:BSD-3-Clause
2 // copyright-holders:Mike Balfour
3 /*************************************************************************
4 
5     audio\avalnche.c
6 
7 *************************************************************************/
8 
9 #include "emu.h"
10 #include "includes/avalnche.h"
11 #include "sound/discrete.h"
12 #include "speaker.h"
13 
14 
15 /* Avalanche Discrete Sound Input Nodes */
16 #define AVALNCHE_AUD0_EN            NODE_01
17 #define AVALNCHE_AUD1_EN            NODE_02
18 #define AVALNCHE_AUD2_EN            NODE_03
19 #define AVALNCHE_SOUNDLVL_DATA      NODE_04
20 #define AVALNCHE_ATTRACT_EN         NODE_05
21 
22 
23 /***************************************************************************
24   Avalanche memory audio output handlers
25 ***************************************************************************/
26 
avalnche_noise_amplitude_w(uint8_t data)27 void avalnche_state::avalnche_noise_amplitude_w(uint8_t data)
28 {
29 	m_discrete->write(AVALNCHE_SOUNDLVL_DATA, data & 0x3f);
30 }
31 
32 
33 /***************************************************************************
34   Avalanche sound system analog emulation
35 ***************************************************************************/
36 
37 static const discrete_lfsr_desc avalnche_lfsr={
38 	DISC_CLK_IS_FREQ,
39 	16,         /* Bit Length */
40 	0,          /* Reset Value */
41 	0,          /* Use Bit 0 as XOR input 0 */
42 	14,         /* Use Bit 14 as XOR input 1 */
43 	DISC_LFSR_XNOR,     /* Feedback stage1 is XNOR */
44 	DISC_LFSR_OR,       /* Feedback stage2 is just stage 1 output OR with external feed */
45 	DISC_LFSR_REPLACE,  /* Feedback stage3 replaces the shifted register contents */
46 	0x000001,       /* Everything is shifted into the first bit only */
47 	0,          /* Output is already inverted by XNOR */
48 	15          /* Output bit */
49 };
50 
51 /* Nodes - Sounds */
52 #define AVALNCHE_NOISE              NODE_10
53 #define AVALNCHE_AUD1_SND           NODE_11
54 #define AVALNCHE_AUD2_SND           NODE_12
55 #define AVALNCHE_SOUNDLVL_AUD0_SND  NODE_13
56 
57 static DISCRETE_SOUND_START(avalnche_discrete)
58 	/************************************************/
59 	/* avalnche  Effects Relataive Gain Table       */
60 	/*                                              */
61 	/* Effect    V-ampIn  Gain ratio      Relative  */
62 	/* Aud0       3.8     50/(50+33+39)     725.6   */
63 	/* Aud1       3.8     50/(50+68)        750.2   */
64 	/* Aud2       3.8     50/(50+68)        750.2   */
65 	/* Soundlvl   3.8     50/(50+33+.518)  1000.0   */
66 	/************************************************/
67 
68 	/************************************************/
69 	/* Input register mapping for avalnche          */
70 	/************************************************/
71 	/*                    NODE                    GAIN      OFFSET  INIT */
DISCRETE_INPUT_LOGIC(AVALNCHE_AUD0_EN)72 	DISCRETE_INPUT_LOGIC (AVALNCHE_AUD0_EN)
73 	DISCRETE_INPUT_LOGIC (AVALNCHE_AUD1_EN)
74 	DISCRETE_INPUT_LOGIC (AVALNCHE_AUD2_EN)
75 	DISCRETE_INPUTX_DATA (AVALNCHE_SOUNDLVL_DATA, 500.0/63, 0,      0.0)
76 	DISCRETE_INPUT_NOT   (AVALNCHE_ATTRACT_EN)
77 
78 	/************************************************/
79 	/* Aud0 = 2V  = HSYNC/4 = 15750/4               */
80 	/* Aud1 = 32V = HSYNC/64 = 15750/64             */
81 	/* Aud2 = 8V  = HSYNC/16 = 15750/16             */
82 	/************************************************/
83 	DISCRETE_SQUAREWFIX(NODE_20, AVALNCHE_AUD0_EN, 15750.0/4,  725.6, 50.0, 0, 0.0) // Aud0
84 	DISCRETE_SQUAREWFIX(AVALNCHE_AUD1_SND, AVALNCHE_AUD1_EN, 15750.0/64, 750.2, 50.0, 0, 0.0)
85 	DISCRETE_SQUAREWFIX(AVALNCHE_AUD2_SND, AVALNCHE_AUD2_EN, 15750.0/16, 750.2, 50.0, 0, 0.0)
86 
87 	/************************************************/
88 	/* Soundlvl is variable amplitude, filtered     */
89 	/* random noise.                                */
90 	/* LFSR clk = 16V = 15750.0Hz/16/2              */
91 	/************************************************/
92 	DISCRETE_LFSR_NOISE(AVALNCHE_NOISE, AVALNCHE_ATTRACT_EN, AVALNCHE_ATTRACT_EN, 15750.0, AVALNCHE_SOUNDLVL_DATA, 0, 0, &avalnche_lfsr)
93 	DISCRETE_ADDER2(NODE_30, 1, NODE_20, AVALNCHE_NOISE)
94 	DISCRETE_RCFILTER(AVALNCHE_SOUNDLVL_AUD0_SND, NODE_30, 556.7, 1e-7)
95 
96 	/************************************************/
97 	/* Final mix and output.                        */
98 	/************************************************/
99 	DISCRETE_ADDER3(NODE_90, AVALNCHE_ATTRACT_EN, AVALNCHE_AUD1_SND, AVALNCHE_AUD2_SND, AVALNCHE_SOUNDLVL_AUD0_SND)
100 
101 	DISCRETE_OUTPUT(NODE_90, 65534.0/(725.6+750.2+750.2+1000.0))
102 DISCRETE_SOUND_END
103 
104 
105 void avalnche_state::avalnche_sound(machine_config &config)
106 {
107 	SPEAKER(config, "mono").front_center();
108 
109 	DISCRETE(config, m_discrete, avalnche_discrete).add_route(ALL_OUTPUTS, "mono", 1.0);
110 
111 	m_latch->q_out_cb<1>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_ATTRACT_EN>));
112 	m_latch->q_out_cb<4>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_AUD0_EN>));
113 	m_latch->q_out_cb<5>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_AUD1_EN>));
114 	m_latch->q_out_cb<6>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_AUD2_EN>));
115 }
116 
117 
acatch_sound(machine_config & config)118 void avalnche_state::acatch_sound(machine_config &config)
119 {
120 	// just a stub here...
121 	m_latch->q_out_cb<1>().set_nop(); // It is attract_enable just like avalnche, but not hooked up yet.
122 	m_latch->q_out_cb<4>().set(FUNC(avalnche_state::catch_aud0_w));
123 	m_latch->q_out_cb<5>().set(FUNC(avalnche_state::catch_aud1_w));
124 	m_latch->q_out_cb<6>().set(FUNC(avalnche_state::catch_aud2_w));
125 }
126 
127 
128 /***************************************************************************
129   Catch memory audio output handlers
130 ***************************************************************************/
131 
WRITE_LINE_MEMBER(avalnche_state::catch_aud0_w)132 WRITE_LINE_MEMBER(avalnche_state::catch_aud0_w)
133 {
134 	/* Different from avalnche, it plays a sound (offset 0/1/2) on data bit 0 rising edge.
135 	There's no indication that the game silences sound, it's probably done automatically. */
136 }
137 
WRITE_LINE_MEMBER(avalnche_state::catch_aud1_w)138 WRITE_LINE_MEMBER(avalnche_state::catch_aud1_w)
139 {
140 }
141 
WRITE_LINE_MEMBER(avalnche_state::catch_aud2_w)142 WRITE_LINE_MEMBER(avalnche_state::catch_aud2_w)
143 {
144 }
145