summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/canyon.cpp
blob: f928c997e693f4891a223e214460935b7cafbf2a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// license:BSD-3-Clause
// copyright-holders:Mike Balfour
/*************************************************************************

    audio\canyon.c

*************************************************************************/
#include "emu.h"
#include "includes/canyon.h"
#include "sound/discrete.h"


/*************************************
 *
 *  Write handlers
 *
 *************************************/

WRITE8_MEMBER(canyon_state::canyon_motor_w)
{
	m_discrete->write(NODE_RELATIVE(CANYON_MOTOR1_DATA, (offset & 0x01)), data & 0x0f);
}


WRITE8_MEMBER(canyon_state::canyon_explode_w)
{
	m_discrete->write(CANYON_EXPLODE_DATA, data >> 4);
}


/************************************************************************/
/* canyon Sound System Analog emulation                                 */
/************************************************************************/

static const discrete_555_desc canyonWhistl555 =
{
	DISC_555_OUT_CAP | DISC_555_OUT_AC,
	5,      // B+ voltage of 555
	DEFAULT_555_VALUES
};

static const discrete_lfsr_desc canyon_lfsr =
{
	DISC_CLK_IS_FREQ,
	16,                 /* Bit Length */
	0,                  /* Reset Value */
	6,                  /* Use Bit 6 as XOR input 0 */
	8,                  /* Use Bit 8 as XOR input 1 */
	DISC_LFSR_XNOR,     /* Feedback stage1 is XNOR */
	DISC_LFSR_OR,       /* Feedback stage2 is just stage 1 output OR with external feed */
	DISC_LFSR_REPLACE,  /* Feedback stage3 replaces the shifted register contents */
	0x000001,           /* Everything is shifted into the first bit only */
	0,                  /* Output is not inverted, Active Low Reset */
	15                  /* Output bit */
};

/* Nodes - Sounds */
#define CANYON_MOTORSND1        NODE_10
#define CANYON_MOTORSND2        NODE_11
#define CANYON_EXPLODESND       NODE_12
#define CANYON_WHISTLESND1      NODE_13
#define CANYON_WHISTLESND2      NODE_14
#define CANYON_NOISE            NODE_15

DISCRETE_SOUND_START(canyon_discrete)
	/************************************************/
	/* Canyon sound system: 5 Sound Sources         */
	/*                     Relative Volume          */
	/*    1/2) Motor           14.29%               */
	/*      3) Explode        100.00%               */
	/*    4/5) Whistle         51.94%               */
	/* Relative volumes calculated from resitor     */
	/* network in combiner circuit taking voltages  */
	/* into account                                 */
	/*                                              */
	/* Motor   3.8V * 5/(5+100) = 0.1810            */
	/* Explode 3.8V * 5/(5+10)  = 1.2667            */
	/* Whistle 5.0V * 5/(5+33)  = 0.6579            */
	/*                                              */
	/************************************************/

	/************************************************/
	/* Input register mapping for canyon            */
	/************************************************/
	DISCRETE_INPUTX_DATA (CANYON_MOTOR1_DATA , -1, 0x0f, 0)
	DISCRETE_INPUTX_DATA (CANYON_MOTOR2_DATA , -1, 0x0f, 0)
	DISCRETE_INPUT_LOGIC (CANYON_WHISTLE1_EN)
	DISCRETE_INPUT_LOGIC (CANYON_WHISTLE2_EN)
	DISCRETE_INPUT_NOT   (CANYON_ATTRACT1_EN)
	DISCRETE_INPUT_NOT   (CANYON_ATTRACT2_EN)
	DISCRETE_INPUTX_DATA (CANYON_EXPLODE_DATA, 1000.0/15.0, 0,     0.0)

	/************************************************/
	/* Motor sound circuit is based on a 556 VCO    */
	/* with the input frequency set by the MotorSND */
	/* latch (4 bit). This freqency is then used to */
	/* driver a modulo 12 counter, with div6, 4 & 3 */
	/* summed as the output of the circuit.         */
	/* VCO Output is Sq wave = 27-382Hz             */
	/*  F1 freq - (Div6)                            */
	/*  F2 freq = (Div4)                            */
	/*  F3 freq = (Div3) 33.3% duty, 33.3 deg phase */
	/* To generate the frequency we take the freq.  */
	/* diff. and /15 to get all the steps between   */
	/* 0 - 15.  Then add the low frequency and send */
	/* that value to a squarewave generator.        */
	/* Also as the frequency changes, it ramps due  */
	/* to a 1uf capacitor on the R-ladder.          */
	/* Note the VCO freq. is controlled by a 250k   */
	/* pot.  The freq. used here is for the pot set */
	/* to 125k.  The low freq is allways the same.  */
	/* This adjusts the high end.                   */
	/* 0k = 214Hz.   250k = 4416Hz                  */
	/************************************************/
	DISCRETE_RCFILTER(NODE_20, CANYON_MOTOR1_DATA, 123000, 1e-6)
	DISCRETE_ADJUSTMENT(NODE_21, (214.0-27.0)/12/15, (4416.0-27.0)/12/15, DISC_LOGADJ, "MOTOR1")
	DISCRETE_MULTIPLY(NODE_22, NODE_20, NODE_21)

	DISCRETE_MULTADD(NODE_23, NODE_22, 2, 27.0/6)   /* F1 = /12*2 = /6 */
	DISCRETE_SQUAREWAVE(NODE_24, 1, NODE_23, (142.9/3), 50.0, 0, 0)
	DISCRETE_RCFILTER(NODE_25, NODE_24, 10000, 1e-7)

	DISCRETE_MULTADD(NODE_26, NODE_22, 3, 27.0/4)   /* F2 = /12*3 = /4 */
	DISCRETE_SQUAREWAVE(NODE_27, 1, NODE_26, (142.9/3), 50.0, 0, 0)
	DISCRETE_RCFILTER(NODE_28, NODE_27, 10000, 1e-7)

	DISCRETE_MULTADD(NODE_29, NODE_22, 4, 27.0/3)   /* F3 = /12*4 = /3 */
	DISCRETE_SQUAREWAVE(NODE_30, 1, NODE_29, (142.9/3), 100.0/3, 0, 360.0/3)
	DISCRETE_RCFILTER(NODE_31, NODE_30, 10000, 1e-7)

	DISCRETE_ADDER3(CANYON_MOTORSND1, CANYON_ATTRACT1_EN, NODE_25, NODE_28, NODE_31)

	/************************************************/
	/* The motor2 sound is basically the same as    */
	/* for 1.  But I shifted the frequencies up for */
	/* it to sound different from motor 1.          */
	/************************************************/
	DISCRETE_RCFILTER(NODE_40, CANYON_MOTOR2_DATA, 123000, 1e-6)
	DISCRETE_ADJUSTMENT(NODE_41, (214.0-27.0)/12/15, (4416.0-27.0)/12/15, DISC_LOGADJ, "MOTOR2")
	DISCRETE_MULTIPLY(NODE_42, NODE_40, NODE_41)

	DISCRETE_MULTADD(NODE_43, NODE_42, 2, 27.0/6)   /* F1 = /12*2 = /6 */
	DISCRETE_SQUAREWAVE(NODE_44, 1, NODE_43, (142.9/3), 50.0, 0, 0)
	DISCRETE_RCFILTER(NODE_45, NODE_44, 10000, 1e-7)

	DISCRETE_MULTADD(NODE_46, NODE_42, 3, 27.0/4)   /* F2 = /12*3 = /4 */
	DISCRETE_SQUAREWAVE(NODE_47, 1, NODE_46, (142.9/3), 50.0, 0, 0)
	DISCRETE_RCFILTER(NODE_48, NODE_47, 10000, 1e-7)

	DISCRETE_MULTADD(NODE_49, NODE_42, 4, 27.0/3)   /* F3 = /12*4 = /3 */
	DISCRETE_SQUAREWAVE(NODE_50, 1, NODE_49, (142.9/3), 100.0/3, 0, 360.0/3)
	DISCRETE_RCFILTER(NODE_51, NODE_50, 10000, 1e-7)

	DISCRETE_ADDER3(CANYON_MOTORSND2, CANYON_ATTRACT2_EN, NODE_45, NODE_48, NODE_51)

	/************************************************/
	/* Explode circuit is built around a noise      */
	/* generator built from 2 shift registers that  */
	/* are clocked by the 2V signal.                */
	/* 2V = HSYNC/4                                 */
	/*    = 15750/4                                 */
	/* Output is binary weighted with 4 bits of     */
	/* crash volume.                                */
	/************************************************/
	DISCRETE_LOGIC_OR(NODE_60, CANYON_ATTRACT1_EN, CANYON_ATTRACT2_EN)
	DISCRETE_LFSR_NOISE(CANYON_NOISE, NODE_60, NODE_60, 15750.0/4, 1.0, 0, 0, &canyon_lfsr)

	DISCRETE_MULTIPLY(NODE_61, CANYON_NOISE, CANYON_EXPLODE_DATA)
	DISCRETE_RCFILTER(CANYON_EXPLODESND, NODE_61, 545, 5e-6)

	/************************************************/
	/* Whistle circuit is a 555 capacitor charge    */
	/* waveform.  The original game pot varies from */
	/* 0-100k, but we are going to limit it because */
	/* below 50k the frequency is too high.         */
	/* When triggered it starts at it's highest     */
	/* frequency, then decays at the rate set by    */
	/* a 68k resistor and 22uf capacitor.           */
	/************************************************/
	DISCRETE_ADJUSTMENT(NODE_70, 50000, 100000, DISC_LINADJ, "WHISTLE1")    /* R59 */
	DISCRETE_MULTADD(NODE_71, CANYON_WHISTLE1_EN, 3.05-0.33, 0.33)
	DISCRETE_RCDISC2(NODE_72, CANYON_WHISTLE1_EN, NODE_71, 1.0, NODE_71, 68000.0, 2.2e-5)   /* CV */
	DISCRETE_555_ASTABLE_CV(NODE_73, CANYON_WHISTLE1_EN, 33000, NODE_70, 1e-8, NODE_72, &canyonWhistl555)
	DISCRETE_MULTIPLY(CANYON_WHISTLESND1, NODE_73, 519.4/3.3)

	DISCRETE_ADJUSTMENT(NODE_75, 50000, 100000, DISC_LINADJ, "WHISTLE2")    /* R69 */
	DISCRETE_MULTADD(NODE_76, CANYON_WHISTLE2_EN, 3.05-0.33, 0.33)
	DISCRETE_RCDISC2(NODE_77, CANYON_WHISTLE2_EN, NODE_76, 1.0, NODE_76, 68000.0, 2.2e-5)   /* CV */
	DISCRETE_555_ASTABLE_CV(NODE_78, CANYON_WHISTLE2_EN, 33000, NODE_75, 1e-8, NODE_77, &canyonWhistl555)
	DISCRETE_MULTIPLY(CANYON_WHISTLESND2, NODE_78, 519.4/3.3)

	/************************************************/
	/* Combine all 5 sound sources.                 */
	/* Add some final gain to get to a good sound   */
	/* level.                                       */
	/************************************************/
	DISCRETE_ADDER3(NODE_90, 1, CANYON_MOTORSND1, CANYON_EXPLODESND, CANYON_WHISTLESND1)
	DISCRETE_ADDER3(NODE_91, 1, CANYON_MOTORSND2, CANYON_EXPLODESND, CANYON_WHISTLESND2)

	DISCRETE_OUTPUT(NODE_90, 77)
	DISCRETE_OUTPUT(NODE_91, 77)
DISCRETE_SOUND_END