summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/mame/audio/madalien.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/mame/audio/madalien.c')
-rw-r--r--trunk/src/mame/audio/madalien.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/trunk/src/mame/audio/madalien.c b/trunk/src/mame/audio/madalien.c
new file mode 100644
index 00000000000..45997f39bff
--- /dev/null
+++ b/trunk/src/mame/audio/madalien.c
@@ -0,0 +1,259 @@
+/************************************************************************
+ * madalien Sound System Analog emulation
+ * Aug 2008, Derrick Renaud
+ ************************************************************************/
+
+#include "emu.h"
+#include "includes/madalien.h"
+#include "sound/discrete.h"
+
+
+/* Discrete Sound Input Nodes */
+/* see also "madalien.h" */
+#define MADALIEN_8910_PORTA_1 NODE_03
+#define MADALIEN_8910_PORTA_2 NODE_04
+#define MADALIEN_8910_PORTA_3 NODE_05
+#define MADALIEN_8910_PORTA_4 NODE_06
+#define MADALIEN_8910_PORTA_5 NODE_07
+#define MADALIEN_8910_PORTA_6 NODE_08
+#define MADALIEN_8910_PORTA_8 NODE_09
+
+#define MADALIEN_8910_PORTB_1 NODE_10
+#define MADALIEN_8910_PORTB_23 NODE_11
+#define MADALIEN_8910_PORTB_45 NODE_12
+#define MADALIEN_8910_PORTB_6 NODE_13
+#define MADALIEN_8910_PORTB_7 NODE_14
+
+#define MADALIEN_8910_PSG_A NODE_15
+#define MADALIEN_8910_PSG_B NODE_16
+#define MADALIEN_8910_PSG_C NODE_17
+
+
+static const discrete_op_amp_filt_info madalien_psg_a_filter =
+{
+ RES_K(1)+ 270, 0, RES_K(10), 0, RES_K(100), CAP_U(.1), CAP_U(.1), 0, 0, 5, -5
+};
+
+static const discrete_op_amp_filt_info madalien_psg_c_filter =
+{
+ RES_K(1)+ 270, 0, RES_K(10), 0, RES_K(100), CAP_U(.068), CAP_U(.068), 0, 0, 5, -5
+};
+
+static const discrete_mixer_desc madalien_psg_mix =
+{
+ DISC_MIXER_IS_RESISTOR,
+ {RES_K(10), RES_K(10), RES_K(10)},
+ {0}, {0}, 0, 0, 0, 0, 0, 1
+};
+
+static const discrete_555_desc madalien_555_1f =
+{
+ // the 555 will clock a 74161, which counts on rising edges
+ DISC_555_TRIGGER_IS_LOGIC | DISC_555_OUT_DC | DISC_555_OUT_COUNT_R_X,
+ 5.0-.5, // B+ voltage of 555 - diode drop
+ DEFAULT_555_VALUES
+};
+
+static const discrete_555_desc madalien_555_1c =
+{
+ // the 555 will clock a 74161, which counts on rising edges
+ DISC_555_TRIGGER_IS_LOGIC | DISC_555_OUT_DC | DISC_555_OUT_COUNT_R_X,
+ 5, // B+ voltage of 555
+ DEFAULT_555_VALUES
+};
+
+static const discrete_555_desc madalien_555_1l =
+{
+ DISC_555_TRIGGER_IS_LOGIC | DISC_555_OUT_DC | DISC_555_OUT_CAP,
+ 5, // B+ voltage of 555
+ DEFAULT_555_VALUES
+};
+
+static const discrete_comp_adder_table madalien_555_1f_r_select =
+{
+ DISC_COMP_P_RESISTOR, 0, 2,
+ {RES_K(22+1), RES_K(15+1)}
+};
+
+static const discrete_comp_adder_table madalien_effect_1b_vol_r =
+{
+ DISC_COMP_P_RESISTOR, 0, 2,
+ {270, RES_K(22) + 270}
+};
+
+static const discrete_dac_r1_ladder madalien_effect1a_dac =
+{
+ 4,
+ {RES_K(22), RES_K(22), 0, RES_K(22)},
+ 0, 0, 0, 0
+};
+
+static const discrete_dac_r1_ladder madalien_effect1b_dac =
+{
+ 2,
+ {RES_K(22), RES_K(22)},
+ 0, 0, 0, 0
+};
+
+static const discrete_dac_r1_ladder madalien_effect2_dac =
+{
+ 4,
+ {0, RES_K(33), RES_K(22), RES_K(33)},
+ 0, 0, 0, 0
+};
+
+// resistor effect of 555 internal resistors at pin 5
+static const discrete_mixer_desc madalien_555_1c_cv =
+{
+ DISC_MIXER_IS_RESISTOR,
+ {RES_K(1.5), RES_K(5)},
+ {0}, {0}, 0, RES_K(10), 0, 0, 0, 1
+};
+
+static const discrete_mixer_desc madalien_final_mix =
+{
+ DISC_MIXER_IS_RESISTOR,
+ {RES_K(10), RES_K(10)/3, RES_K(10), RES_K(10),
+ RES_K(22) + RES_K(22)/3,
+ RES_K(22) + RES_K(22) + RES_K(22)/2,
+ RES_K(33) + 1.0 / (1.0/RES_K(33) + 1.0/RES_K(22) + 1.0/RES_K(33))},
+ {MADALIEN_8910_PORTA_1, 0, MADALIEN_8910_PORTA_5, MADALIEN_8910_PORTA_8, MADALIEN_8910_PORTB_1, NODE_59, 0},
+ {0}, 0,
+ RES_K(100),
+ 0, CAP_U(1), 0,
+ 32768.0/DEFAULT_TTL_V_LOGIC_1 // final gain
+};
+
+DISCRETE_SOUND_START( madalien )
+ /************************************************
+ * Input register mapping
+ ************************************************/
+ DISCRETE_INPUT_DATA(MADALIEN_8910_PORTA)
+ DISCRETE_INPUT_DATA(MADALIEN_8910_PORTB)
+
+ /************************************************
+ * Convert to individual bits
+ ************************************************/
+ // Port A is used to turn filtering on/off.
+ // 1 - player shot, siren, music
+ // turn bit into 4066 Ron value of 270 ohms @ 5V
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTA_1, MADALIEN_8910_PORTA, 0x01, 270, "01&2*")
+ // 2 - player explosion
+ DISCRETE_TRANSFORM2(MADALIEN_8910_PORTA_2, MADALIEN_8910_PORTA, 0x02, "01&")
+ // 3 - rub wall
+ DISCRETE_TRANSFORM2(MADALIEN_8910_PORTA_3, MADALIEN_8910_PORTA, 0x04, "01&")
+ // 4 - is it even triggered?
+ DISCRETE_TRANSFORM2(MADALIEN_8910_PORTA_4, MADALIEN_8910_PORTA, 0x08, "01&")
+ // 5 - siren, music (out of phase copy of 1 for echo effect)
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTA_5, MADALIEN_8910_PORTA, 0x10, 270, "01&2*")
+ // 6 - enemy explosions
+ DISCRETE_TRANSFORM2(MADALIEN_8910_PORTA_6, MADALIEN_8910_PORTA, 0x20, "01&")
+ // 8 - enemy spin, beep
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTA_8, MADALIEN_8910_PORTA, 0x80, 270, "01&2*")
+
+ //Port B controls motor sounds
+ // 1,2,3 - Player motor volume
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTB_1, MADALIEN_8910_PORTB, 0x01, 270, "01&2*")
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTB_23, MADALIEN_8910_PORTB, 0x06, 2, "01&2/")
+ // 4,5 - Player motor speed
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTB_45, MADALIEN_8910_PORTB, 0x18, 8, "01&2/")
+ // 6 - Enemy motor enable
+ DISCRETE_TRANSFORM2(MADALIEN_8910_PORTB_6, MADALIEN_8910_PORTB, 0x20, "01&")
+ // 7 - Enemy motor speed
+ // convert bit 7 to voltage level
+ // 2 diodes reduce voltage by 1V.
+ DISCRETE_TRANSFORM3(MADALIEN_8910_PORTB_7, MADALIEN_8910_PORTB, 0x40, (DEFAULT_TTL_V_LOGIC_1 - 1) / 0x40, "01&2*")
+
+ /************************************************
+ * PSG input streams
+ ************************************************/
+ // AY-3-8910 PSG have a 1Vpp level
+ DISCRETE_INPUTX_STREAM(MADALIEN_8910_PSG_A, 0, 2.0/32768, .250)
+ DISCRETE_INPUTX_STREAM(MADALIEN_8910_PSG_B, 1, 2.0/32768, .250)
+ DISCRETE_INPUTX_STREAM(MADALIEN_8910_PSG_C, 2, 2.0/32768, .250)
+
+ /************************************************
+ * AY-3-8910 filtering
+ ************************************************/
+ // top op-amp
+ DISCRETE_ONOFF(NODE_20, MADALIEN_8910_PORTA_2, MADALIEN_8910_PSG_A)
+ DISCRETE_OP_AMP_FILTER(NODE_21, 1, NODE_20, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &madalien_psg_a_filter)
+
+ // middle op-amp
+ // pin 3
+ DISCRETE_MULTIPLY(NODE_30, MADALIEN_8910_PSG_B, RES_K(3.3)/(RES_K(3.3)+RES_K(3.3)))
+ DISCRETE_ONOFF(NODE_31, MADALIEN_8910_PORTA_4, NODE_30)
+ // pin 2
+ DISCRETE_TRANSFORM3(NODE_32, MADALIEN_8910_PSG_A, NODE_30, -RES_K(10)/RES_K(3.3), "01-2*1+")
+ // pin 1
+ DISCRETE_SWITCH(NODE_33, 1, MADALIEN_8910_PORTA_3, NODE_31, NODE_32)
+ DISCRETE_CLAMP(NODE_34, NODE_33, -5, 5.0-1.5)
+
+ // bottom op-amp
+ DISCRETE_ONOFF(NODE_40, MADALIEN_8910_PORTA_6, MADALIEN_8910_PSG_B)
+ DISCRETE_OP_AMP_FILTER(NODE_41, 1, NODE_40, 0, DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &madalien_psg_c_filter)
+
+ DISCRETE_MIXER3(NODE_48, 1, NODE_21, NODE_33, NODE_41, &madalien_psg_mix)
+
+ /************************************************
+ * Player motor
+ ************************************************/
+ DISCRETE_555_ASTABLE(NODE_50, // cap is buffered by op-amp 2D.
+ 1, // always enabled
+ RES_K(4.7),
+ RES_K(22),
+ CAP_U(2.2),
+ &madalien_555_1l)
+ // The speed frequencies seem strange but the components have been GuruVerified
+ // There is not much change in selected frequency. 99Hz, 110.6Hz, 124Hz
+ DISCRETE_COMP_ADDER(NODE_51, MADALIEN_8910_PORTB_45, &madalien_555_1f_r_select)
+ DISCRETE_555_ASTABLE_CV(NODE_52, // IC 1F pin 3 out
+ MADALIEN_8910_PORTB_45, // enabled by gate O2 pin 13
+ NODE_51,
+ RES_K(10), // per actual board
+ CAP_U(.22),
+ NODE_50, // IC 1F pin 5 in
+ &madalien_555_1f)
+ // convert reset to active high for module use
+ DISCRETE_LOGIC_INVERT(NODE_53, MADALIEN_8910_PORTB_45)
+ DISCRETE_COUNTER(NODE_54, 1,
+ NODE_53, // pin 7 in
+ NODE_52, // pin 1 in
+ 0, 15, 1, 0, DISC_CLK_BY_COUNT) // 4-bit binary up counter
+ DISCRETE_DAC_R1(NODE_55, NODE_54, DEFAULT_TTL_V_LOGIC_1, &madalien_effect1a_dac)
+ DISCRETE_DAC_R1(NODE_56, NODE_54, DEFAULT_TTL_V_LOGIC_1, &madalien_effect1b_dac)
+ DISCRETE_RCFILTER(NODE_57, NODE_56, RES_K(22)/2 + RES_K(22), CAP_U(.033))
+ DISCRETE_COMP_ADDER(NODE_59, MADALIEN_8910_PORTB_23, &madalien_effect_1b_vol_r)
+
+ /************************************************
+ * Enemy motor
+ ************************************************/
+ DISCRETE_CRFILTER(NODE_60, MADALIEN_8910_PORTB_7, RES_K(100), CAP_U(4.7))
+ // 2 diodes clamp it positive.
+ DISCRETE_CLAMP(NODE_62, NODE_60, 0, 12)
+ // the 0.047uF cap to ground just removes real world spikes.
+ // it does not have to be simulated.
+ DISCRETE_MIXER2(NODE_64, 1, NODE_62, 5, &madalien_555_1c_cv)
+ DISCRETE_555_ASTABLE_CV(NODE_65, // IC 1C pin 3 out
+ MADALIEN_8910_PORTB_6,
+ RES_K(47),
+ RES_K(22),
+ CAP_U(.033),
+ NODE_64, // IC 1C pin 5 in
+ &madalien_555_1c)
+ // convert reset to active high for module use
+ DISCRETE_LOGIC_INVERT(NODE_66, MADALIEN_8910_PORTB_6)
+ DISCRETE_COUNTER(NODE_67, 1,
+ NODE_66, // pin 7 in
+ NODE_65, // pin 1 in
+ 0, 15, 1, 0, DISC_CLK_BY_COUNT) // 4-bit binary up counter
+ DISCRETE_DAC_R1(NODE_68, NODE_67, DEFAULT_TTL_V_LOGIC_1, &madalien_effect2_dac)
+
+ /************************************************
+ * Mixer
+ ************************************************/
+ DISCRETE_MIXER7(NODE_90, 1, MADALIEN_8910_PSG_A, NODE_48, MADALIEN_8910_PSG_B, MADALIEN_8910_PSG_C, NODE_56, NODE_57, NODE_68, &madalien_final_mix)
+
+ DISCRETE_OUTPUT(NODE_90, 1.1)
+
+DISCRETE_SOUND_END