1 // license:BSD-3-Clause 2 // copyright-holders:Hans Andersson 3 /************************************************************************* 4 5 audio\tank8.c 6 7 *************************************************************************/ 8 #include "emu.h" 9 #include "includes/tank8.h" 10 #include "sound/discrete.h" 11 12 13 /************************************************************************/ 14 /* tank8 Sound System Analog emulation */ 15 /* Written by Hans Andersson. Feb 2005 */ 16 /************************************************************************/ 17 18 static const discrete_lfsr_desc tank8_lfsr = 19 { 20 DISC_CLK_IS_FREQ, 21 16, /* Bit Length */ 22 0, /* Reset Value */ 23 10, /* Use Bit 10 as F0 input 0 */ 24 15, /* Use Bit 15 as F0 input 1 */ 25 DISC_LFSR_XOR, /* F0 is XOR */ 26 DISC_LFSR_XOR, /* F1 is F0 XOR with external feed. External feed is (address line) A2 */ 27 DISC_LFSR_REPLACE, /* F2 replaces the shifted register contents */ 28 0x000001, /* Everything is shifted into the first bit only */ 29 1, /* Output is inverted by Q20 */ 30 12 /* Output bit */ 31 }; 32 33 static const discrete_integrate_info tank8_op1_integrate_info = 34 { 35 DISC_INTEGRATE_OP_AMP_1, 36 RES_K(27), /* R98 */ 37 RES_K(2.2), /* R97 */ 38 RES_K(47), /* R96 */ 39 CAP_U(0.22), /* C60 */ 40 5, 41 12, // B+ is 12V, not 15V shown in the schematic. 42 0, 43 0, 44 0, 45 }; 46 47 static const discrete_integrate_info tank8_op2_integrate_info = 48 { 49 DISC_INTEGRATE_OP_AMP_1, 50 RES_K(27), /* R99 */ 51 RES_K(2.2), /* R97 */ 52 RES_K(47), /* R96 */ 53 CAP_U(0.1), /* C59 */ 54 5, 55 12, // B+ is 12V, not 15V shown in the schematic. 56 0, 57 0, 58 0, 59 }; 60 61 static const discrete_555_desc tank8_555_a = 62 { 63 DISC_555_OUT_SQW | DISC_555_OUT_DC, 64 5, // B+ voltage of 555 65 DEFAULT_555_VALUES 66 }; 67 68 static const discrete_555_desc tank8_555_m = 69 { 70 DISC_555_OUT_SQW | DISC_555_OUT_DC | DISC_555_TRIGGER_IS_VOLTAGE, 71 5, // B+ voltage of 555 72 DEFAULT_555_VALUES 73 }; 74 75 76 static const discrete_op_amp_filt_info tank8_filt = 77 { 78 RES_K(18), // R56 79 0, 80 RES_K(0.820), //R57 81 0, 82 RES_K(330), //R58 83 CAP_U(.047), //C42 84 CAP_U(.047), //C43 85 0, 86 2.5, 87 5, /* VCC */ 88 0 /* VEE */ 89 }; 90 91 static const discrete_dac_r1_ladder tank8_dac = 92 { 93 1, 94 {RES_K(4.7)}, // R89 95 5, // 555 Vcc 96 RES_K(5), // 555 internal 97 RES_K(10), // 555 internal 98 CAP_U(100) // C26 99 }; 100 101 /* Nodes - Sounds */ 102 #define TANK8_MOTOR1 NODE_15 103 #define TANK8_MOTOR2 NODE_16 104 #define TANK8_MOTOR3 NODE_17 105 #define TANK8_MOTOR4 NODE_18 106 #define TANK8_MOTOR5 NODE_19 107 #define TANK8_MOTOR6 NODE_20 108 #define TANK8_MOTOR7 NODE_21 109 #define TANK8_MOTOR8 NODE_22 110 #define TANK8_CRASHEXPL NODE_23 111 #define TANK8_BUGLE NODE_24 112 #define TANK8_FINAL_MIX NODE_25 113 #define TANK8_A2_LINE NODE_26 114 115 116 DISCRETE_SOUND_START(tank8_discrete) 117 /************************************************/ 118 /* Tank8 sound system: 10 Sound Sources */ 119 /* Motor 1-8 */ 120 /* Crash */ 121 /* Explosion */ 122 /* Bugle */ 123 /************************************************/ 124 125 /************************************************/ 126 /* Input register mapping for tank8 */ 127 /************************************************/ 128 /* NODE */ 129 DISCRETE_INPUT_LOGIC(TANK8_CRASH_EN) 130 DISCRETE_INPUT_LOGIC(TANK8_EXPLOSION_EN) 131 DISCRETE_INPUT_LOGIC(TANK8_MOTOR1_EN) 132 DISCRETE_INPUT_LOGIC(TANK8_MOTOR2_EN) 133 DISCRETE_INPUT_LOGIC(TANK8_MOTOR3_EN) 134 DISCRETE_INPUT_LOGIC(TANK8_MOTOR4_EN) 135 DISCRETE_INPUT_LOGIC(TANK8_MOTOR5_EN) 136 DISCRETE_INPUT_LOGIC(TANK8_MOTOR6_EN) 137 DISCRETE_INPUT_LOGIC(TANK8_MOTOR7_EN) 138 DISCRETE_INPUT_LOGIC(TANK8_MOTOR8_EN) 139 DISCRETE_INPUT_NOT(TANK8_ATTRACT_EN) 140 DISCRETE_INPUT_LOGIC(TANK8_BUGLE_EN) 141 DISCRETE_INPUT_DATA(TANK8_BUGLE_DATA1) 142 DISCRETE_INPUT_DATA(TANK8_BUGLE_DATA2) 143 144 /************************************************/ 145 /* Motor sound circuit is based on a 556 VCO */ 146 /* with the input frequency set by a charging */ 147 /* Capacitor. The DAC emulates the 555's */ 148 /* internal CV resistance. */ 149 /* A 9334 has typical 3.6V output. */ 150 /************************************************/ 151 152 DISCRETE_LOGIC_INVERT(NODE_30, TANK8_MOTOR1_EN) 153 DISCRETE_DAC_R1(NODE_32, TANK8_MOTOR1_EN, 3.6, &tank8_dac) 154 DISCRETE_555_ASTABLE_CV(NODE_33, NODE_30, RES_K(220), RES_K(39), CAP_U(0.22), NODE_32, &tank8_555_a) 155 DISCRETE_CRFILTER_VREF(NODE_34, NODE_33, RES_K(22), CAP_U(0.001), 5.0) 156 DISCRETE_555_MSTABLE(NODE_35, 1, NODE_34, RES_K(56), CAP_U(0.1), &tank8_555_m) 157 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR1, 1, NODE_35, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 158 159 DISCRETE_LOGIC_INVERT(NODE_40, TANK8_MOTOR2_EN) 160 DISCRETE_DAC_R1(NODE_42, TANK8_MOTOR2_EN, 3.6, &tank8_dac) 161 DISCRETE_555_ASTABLE_CV(NODE_43, NODE_40, RES_K(220), RES_K(39), CAP_U(0.22), NODE_42, &tank8_555_a) 162 DISCRETE_CRFILTER_VREF(NODE_44, NODE_43, RES_K(22), CAP_U(0.001), 5.0) 163 DISCRETE_555_MSTABLE(NODE_45, 1, NODE_44, RES_K(56), CAP_U(0.1), &tank8_555_m) 164 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR2, 1, NODE_45, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 165 166 DISCRETE_LOGIC_INVERT(NODE_50, TANK8_MOTOR3_EN) 167 DISCRETE_DAC_R1(NODE_52, TANK8_MOTOR3_EN, 3.6, &tank8_dac) 168 DISCRETE_555_ASTABLE_CV(NODE_53, NODE_50, RES_K(220), RES_K(39), CAP_U(0.22), NODE_52, &tank8_555_a) 169 DISCRETE_CRFILTER_VREF(NODE_54, NODE_53, RES_K(22), CAP_U(0.001), 5.0) 170 DISCRETE_555_MSTABLE(NODE_55, 1, NODE_54, RES_K(56), CAP_U(0.1), &tank8_555_m) 171 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR3, 1, NODE_55, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 172 173 DISCRETE_LOGIC_INVERT(NODE_60, TANK8_MOTOR4_EN) 174 DISCRETE_DAC_R1(NODE_62, TANK8_MOTOR4_EN, 3.6, &tank8_dac) 175 DISCRETE_555_ASTABLE_CV(NODE_63, NODE_60, RES_K(220), RES_K(39), CAP_U(0.22), NODE_62, &tank8_555_a) 176 DISCRETE_CRFILTER_VREF(NODE_64, NODE_63, RES_K(22), CAP_U(0.001), 5.0) 177 DISCRETE_555_MSTABLE(NODE_65, 1, NODE_64, RES_K(56), CAP_U(0.1), &tank8_555_m) 178 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR4, 1, NODE_65, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 179 180 DISCRETE_LOGIC_INVERT(NODE_70, TANK8_MOTOR5_EN) 181 DISCRETE_DAC_R1(NODE_72, TANK8_MOTOR5_EN, 3.6, &tank8_dac) 182 DISCRETE_555_ASTABLE_CV(NODE_73, NODE_70, RES_K(220), RES_K(39), CAP_U(0.22), NODE_72, &tank8_555_a) 183 DISCRETE_CRFILTER_VREF(NODE_74, NODE_73, RES_K(22), CAP_U(0.001), 5.0) 184 DISCRETE_555_MSTABLE(NODE_75, 1, NODE_74, RES_K(56), CAP_U(0.1), &tank8_555_m) 185 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR5, 1, NODE_75, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 186 187 DISCRETE_LOGIC_INVERT(NODE_80, TANK8_MOTOR6_EN) 188 DISCRETE_DAC_R1(NODE_82, TANK8_MOTOR6_EN, 3.6, &tank8_dac) 189 DISCRETE_555_ASTABLE_CV(NODE_83, NODE_80, RES_K(220), RES_K(39), CAP_U(0.22), NODE_82, &tank8_555_a) 190 DISCRETE_CRFILTER_VREF(NODE_84, NODE_83, RES_K(22), CAP_U(0.001), 5.0) 191 DISCRETE_555_MSTABLE(NODE_85, 1, NODE_84, RES_K(56), CAP_U(0.1), &tank8_555_m) 192 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR6, 1, NODE_85, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 193 194 DISCRETE_LOGIC_INVERT(NODE_90, TANK8_MOTOR7_EN) 195 DISCRETE_DAC_R1(NODE_92, TANK8_MOTOR7_EN, 3.6, &tank8_dac) 196 DISCRETE_555_ASTABLE_CV(NODE_93, NODE_90, RES_K(220), RES_K(39), CAP_U(0.22), NODE_92, &tank8_555_a) 197 DISCRETE_CRFILTER_VREF(NODE_94, NODE_93, RES_K(22), CAP_U(0.001), 5.0) 198 DISCRETE_555_MSTABLE(NODE_95, 1, NODE_94, RES_K(56), CAP_U(0.1), &tank8_555_m) 199 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR7, 1, NODE_95, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 200 201 DISCRETE_LOGIC_INVERT(NODE_100, TANK8_MOTOR8_EN) 202 DISCRETE_DAC_R1(NODE_102, TANK8_MOTOR8_EN, 3.6, &tank8_dac) 203 DISCRETE_555_ASTABLE_CV(NODE_103, NODE_100, RES_K(220), RES_K(39), CAP_U(0.22), NODE_102, &tank8_555_a) 204 DISCRETE_CRFILTER_VREF(NODE_104, NODE_103, RES_K(22), CAP_U(0.001), 5.0) 205 DISCRETE_555_MSTABLE(NODE_105, 1, NODE_104, RES_K(56), CAP_U(0.1), &tank8_555_m) 206 DISCRETE_OP_AMP_FILTER(TANK8_MOTOR8, 1, NODE_105, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &tank8_filt) 207 208 /************************************************/ 209 /* Bugle call is built from 9316 counter */ 210 /* counter is clocked by the 1V signal. */ 211 /* 1V = HSYNC/2 */ 212 /* = 15750/2 */ 213 /************************************************/ 214 DISCRETE_DIVIDE(NODE_110,1,TANK8_BUGLE_DATA1,7875.0) 215 DISCRETE_DIVIDE(NODE_111,1,TANK8_BUGLE_DATA2,7875.0) 216 DISCRETE_SQUAREWAVE2(NODE_112,TANK8_BUGLE_EN,3.4, NODE_110, NODE_111,1.7,0) 217 DISCRETE_RCDISC3(NODE_113,1, NODE_112, RES_K(10),RES_K(1),CAP_U(0.1), 0.5) 218 DISCRETE_CRFILTER(TANK8_BUGLE, NODE_113, RES_K(47), CAP_U(.01)) 219 220 /************************************************/ 221 /* Noise generator is built from 2 shift */ 222 /* registers that are clocked by the 2V signal. */ 223 /* 2V = HSYNC/4 */ 224 /* = 15750/4 */ 225 /************************************************/ 226 /* The A2 address line is also mixed in to the noise generator, 227 * but that is currently not implemented. */ 228 DISCRETE_CONSTANT(TANK8_A2_LINE,1) 229 DISCRETE_LFSR_NOISE(NODE_120, TANK8_ATTRACT_EN, TANK8_ATTRACT_EN, 15750.0/4, 1, TANK8_A2_LINE, 0, &tank8_lfsr) 230 231 /************************************************/ 232 /* Explosion envelope is created by integrating */ 233 /* a constant voltage */ 234 /************************************************/ 235 DISCRETE_INTEGRATE(NODE_121, TANK8_EXPLOSION_EN, 0, &tank8_op1_integrate_info) 236 DISCRETE_GAIN(NODE_122, NODE_121, RES_K(2.2)/(RES_K(1.0)+RES_K(2.2))) 237 238 /************************************************/ 239 /* Crash envelope is created by integrating */ 240 /* a constant voltage */ 241 /************************************************/ 242 DISCRETE_INTEGRATE(NODE_123, TANK8_CRASH_EN, 0, &tank8_op2_integrate_info) 243 DISCRETE_GAIN(NODE_124, NODE_123, RES_K(1)/(RES_K(1.0)+RES_K(2.2))) 244 245 /************************************************/ 246 /* Add the envelopes and apply it to the noise */ 247 /* generator */ 248 /************************************************/ 249 DISCRETE_ADDER2(NODE_125, 1 , NODE_122, NODE_124 ) 250 DISCRETE_MULTIPLY(NODE_126, NODE_120, NODE_125 ) 251 DISCRETE_RCFILTER(NODE_127, NODE_126, RES_K(47), CAP_U(0.1)) 252 DISCRETE_ADJUSTMENT(NODE_128, 253 1.0, // min gain of E5 254 1.0 + 100.0/22, // max gain of E5 = 1 + r132/r101 255 DISC_LINADJ, "CRASH") 256 DISCRETE_MULTIPLY(NODE_129, NODE_127, NODE_128 ) 257 DISCRETE_CLAMP(TANK8_CRASHEXPL, NODE_129, -(12.0 - OP_AMP_VP_RAIL_OFFSET)/2, (12.0 - OP_AMP_VP_RAIL_OFFSET)/2) 258 259 /************************************************/ 260 /* Combine all 10 sound sources. */ 261 /************************************************/ 262 DISCRETE_ADDER4(NODE_130, 1, TANK8_MOTOR1, TANK8_MOTOR2, TANK8_MOTOR3, TANK8_MOTOR4) 263 DISCRETE_MULTADD(NODE_131, NODE_130, 1.0, -10) 264 DISCRETE_ADDER4(NODE_132, 1, TANK8_MOTOR5, TANK8_MOTOR6, TANK8_MOTOR7, TANK8_MOTOR8) 265 DISCRETE_MULTADD(NODE_133, NODE_132, 1.0, -10) 266 DISCRETE_ADDER4(TANK8_FINAL_MIX, TANK8_ATTRACT_EN, TANK8_CRASHEXPL, TANK8_BUGLE, NODE_131, NODE_133) 267 268 DISCRETE_OUTPUT(TANK8_FINAL_MIX, 5000) 269 DISCRETE_SOUND_END 270