// license:BSD-3-Clause // copyright-holders:Derrick Renaud /************************************************************************ * copsnrob Sound System Analog emulation * Nov 2010, Derrick Renaud ************************************************************************/ #include "emu.h" #include "includes/copsnrob.h" #include "sound/discrete.h" #include "speaker.h" /* Discrete Sound Input Nodes */ #define COPSNROB_MOTOR0_INV NODE_01 #define COPSNROB_MOTOR1_INV NODE_02 #define COPSNROB_MOTOR2_INV NODE_03 #define COPSNROB_MOTOR3_INV NODE_04 #define COPSNROB_ZINGS_INV NODE_05 #define COPSNROB_FIRES_INV NODE_06 #define COPSNROB_CRASH_INV NODE_07 #define COPSNROB_SCREECH_INV NODE_08 #define COPSNROB_AUDIO_ENABLE NODE_09 /* Discrete Sound Output Nodes */ #define COPSNROB_MOTOR0_SND NODE_11 #define COPSNROB_MOTOR1_SND NODE_12 #define COPSNROB_MOTOR2_SND NODE_13 #define COPSNROB_MOTOR3_SND NODE_14 #define COPSNROB_FZ_SND NODE_15 #define COPSNROB_CRASH_SND NODE_16 #define COPSNROB_SCREECH_SND NODE_17 #define COPSNROB_NOISE_1 NODE_18 #define COPSNROB_NOISE_2 NODE_18_01 /* Parts List - Resistors */ #define COPSNROB_R16 RES_K(10) #define COPSNROB_R18 RES_K(100) #define COPSNROB_R19 RES_K(100) #define COPSNROB_R20 RES_K(100) #define COPSNROB_R21 RES_K(47) #define COPSNROB_R25 RES_K(47) #define COPSNROB_R26 RES_K(150) #define COPSNROB_R27 RES_K(22) #define COPSNROB_R28 RES_K(18) #define COPSNROB_R33 RES_K(10) #define COPSNROB_R35 RES_K(10) #define COPSNROB_R36 RES_K(15) #define COPSNROB_R37 RES_K(4.7) #define COPSNROB_R38 RES_K(15) #define COPSNROB_R39 RES_K(10) #define COPSNROB_R41 RES_K(33) #define COPSNROB_R42 RES_K(33) #define COPSNROB_R47 RES_K(10) #define COPSNROB_R48 RES_K(1) #define COPSNROB_R49 RES_K(47) #define COPSNROB_R50 RES_K(47) #define COPSNROB_R53 RES_K(47) #define COPSNROB_R54 RES_K(22) #define COPSNROB_R55 RES_K(47) #define COPSNROB_R56 RES_K(470) #define COPSNROB_R57 RES_K(820) #define COPSNROB_R58 RES_K(68) #define COPSNROB_R59 RES_K(1) #define COPSNROB_R64 RES_K(47) #define COPSNROB_R65 RES_K(4.7) #define COPSNROB_R66 RES_K(1.5) #define COPSNROB_R69 RES_K(330) #define COPSNROB_R70 RES_K(330) #define COPSNROB_R71 RES_K(100) #define COPSNROB_R72 RES_K(100) #define COPSNROB_R73 RES_K(47) #define COPSNROB_R74 RES_K(1) #define COPSNROB_R75 RES_K(1) #define COPSNROB_R76 RES_K(12) #define COPSNROB_R77 RES_K(33) #define COPSNROB_R78 RES_K(100) #define COPSNROB_R79 RES_K(2.2) #define COPSNROB_R80 RES_K(1) #define COPSNROB_R81 RES_K(8.2) #define COPSNROB_R82 RES_K(3.9) #define COPSNROB_R83 RES_K(27) #define COPSNROB_R84 RES_K(15) #define COPSNROB_R85 (330) #define COPSNROB_R86 RES_K(330) #define COPSNROB_R87 (820) #define COPSNROB_R88 RES_K(1) #define COPSNROB_R89 RES_K(1) #define COPSNROB_R92 RES_K(100) #define COPSNROB_R93 RES_K(100) #define COPSNROB_R94 RES_K(10) /* Parts List - Capacitors */ #define COPSNROB_C3 CAP_U(100) #define COPSNROB_C12 CAP_U(0.1) #define COPSNROB_C13 CAP_U(0.1) #define COPSNROB_C17 CAP_U(0.001) #define COPSNROB_C19 CAP_U(10) #define COPSNROB_C20 CAP_U(0.01) #define COPSNROB_C23 CAP_U(0.1) #define COPSNROB_C24 CAP_U(0.22) #define COPSNROB_C28 CAP_U(1) #define COPSNROB_C30 CAP_U(0.01) #define COPSNROB_C31 CAP_U(0.1) #define COPSNROB_C32 CAP_U(5) #define COPSNROB_C33 CAP_U(10) #define COPSNROB_C36 CAP_U(100) #define COPSNROB_C39 CAP_U(0.1) #define COPSNROB_C37 CAP_U(0.1) #define COPSNROB_C40 CAP_U(0.1) #define COPSNROB_C41 CAP_U(0.03) #define COPSNROB_C42 CAP_U(0.047) #define COPSNROB_C43 CAP_U(0.047) #define COPSNROB_C55 CAP_U(0.1) #define COPSNROB_C58 CAP_U(0.1) #define COPSNROB_C59 CAP_U(0.1) /* Timing values */ #define COPSNROB_2V (15750/2/2) /* has to be verified */ static const discrete_555_desc copsnrob_motor23_555_1 = { DISC_555_OUT_SQW, 5, DEFAULT_555_VALUES }; static const discrete_555_desc copsnrob_motor23_555_2 = { DISC_555_OUT_ENERGY | DISC_555_TRIGGER_IS_VOLTAGE, 5, DEFAULT_555_VALUES }; static const discrete_op_amp_filt_info copsnrob_motor23_filter = { COPSNROB_R28, 0, COPSNROB_R87, 0, COPSNROB_R86, /* r1, r2, r3, r4, rF */ COPSNROB_C42, COPSNROB_C43, 0, /* c1, c2, c3 */ 5.0 * RES_VOLTAGE_DIVIDER(COPSNROB_R88, COPSNROB_R89), 5, 0 /* vRef, vP, vN */ }; static const discrete_dac_r1_ladder copsnrob_crash_dac = { 4, /* ladderLength */ {COPSNROB_R81, COPSNROB_R82, COPSNROB_R79, COPSNROB_R80}, 0, 0, 0, COPSNROB_C58 /* vBias, rBias, rGnd, cFilter */ }; static const discrete_mixer_desc copsnrob_final_mixer01 = { DISC_MIXER_IS_RESISTOR, {COPSNROB_R21, COPSNROB_R25, COPSNROB_R33, COPSNROB_R70, COPSNROB_R71}, {0}, {0}, 0, COPSNROB_R35, 0, COPSNROB_C59, /* r_node{}, c{}, rI, rF, cF, cAmp */ 0, 1 /* vRef, gain */ }; static const discrete_dac_r1_ladder copsnrob_motor01_cc_dac = { 1, /* ladderLength */ {COPSNROB_R56}, 5.0 - 0.5, COPSNROB_R58, COPSNROB_R57, COPSNROB_C33 /* vBias; rBias; rGnd; cFilter */ }; static const discrete_dac_r1_ladder copsnrob_motor01_out_dac = { 4, /* ladderLength */ {COPSNROB_R20, COPSNROB_R18, 0, COPSNROB_R19}, 0, 0, 0, COPSNROB_C12 /* vBias; rBias; rGnd; cFilter */ }; static const discrete_mixer_desc copsnrob_final_mixer23 = { DISC_MIXER_IS_RESISTOR, {COPSNROB_R93, COPSNROB_R92, COPSNROB_R72, COPSNROB_R69, COPSNROB_R16}, {0}, {0}, 0, COPSNROB_R94, 0, COPSNROB_C55, /* r_node{}, c{}, rI, rF, cF, cAmp */ 0, 1 /* vRef, gain */ }; static const discrete_dac_r1_ladder copsnrob_motor23_cv_dac = { 1, /* ladderLength */ {COPSNROB_R65}, 5, RES_K(5), RES_K(10), COPSNROB_C36 /* vBias; rBias; rGnd; cFilter */ }; static const discrete_555_cc_desc copsnrob_motor01_555cc = { DISC_555_OUT_COUNT_R | DISCRETE_555_CC_TO_DISCHARGE_PIN, 5, /* v_pos */ DEFAULT_555_CC_SOURCE, 1, /* v_out_high - ignored */ 0.6 /* v_cc_junction */ }; #define COPSNROB_MOTOR01_BASE_NODE NODE_20 #define COPSNROB_MOTOR23_BASE_NODE NODE_30 #define COPSNROB_NODE(_base, _num, _offset) NODE_RELATIVE(_base, _num * 100 + _offset) #define COPSNROB_MOTOR01_NODE(_num, _offset) COPSNROB_NODE(COPSNROB_MOTOR01_BASE_NODE, _num, _offset) #define COPSNROB_MOTOR23_NODE(_num, _offset) COPSNROB_NODE(COPSNROB_MOTOR23_BASE_NODE, _num, _offset) /************************************************ * MOTOR0/1 Definition Start ************************************************/ #define COPSNROB_MOTOR01(_output, _input, _num) \ /* simulate the RC connected to the transistor with a DAC */ \ DISCRETE_DAC_R1(COPSNROB_MOTOR01_NODE(_num, 0), \ _input, 4.2, &copsnrob_motor01_cc_dac) /* DATA; VDATA - TTL with light load */ \ DISCRETE_555_CC(COPSNROB_MOTOR01_NODE(_num, 1), /* IC F2, pin 10 from IC F3, pin 9 */ \ 1, /* RESET - IC F3, pin 10 */ \ COPSNROB_MOTOR01_NODE(_num, 0), /* VIN */ \ COPSNROB_R53, COPSNROB_C20, 0, 0, COPSNROB_R39, /* R; C; RBIAS; RGND; RDIS */ \ &copsnrob_motor01_555cc) \ /* IC D2, pin 12 and IC E3, pin 5 make a /4 counter */ \ DISCRETE_COUNTER(COPSNROB_MOTOR01_NODE(_num, 2), /* IC E3, pin 5 */ \ 1, 0, /* ENAB; RESET */ \ COPSNROB_MOTOR01_NODE(_num, 1), /* IC D2, pin 1 */ \ 0, 3, DISC_COUNT_UP, 0, DISC_CLK_BY_COUNT) /* MIN; MAX; DIR; INIT0; CLKTYPE */ \ DISCRETE_COUNTER_7492(COPSNROB_MOTOR01_NODE(_num, 3), /* IC E3, pins 11, 9, & 8 */\ 1, 0, /* ENAB; RESET */ \ COPSNROB_MOTOR01_NODE(_num, 1), /* IC E3, pin 14 */ \ DISC_CLK_BY_COUNT) /* CLKTYPE */ \ DISCRETE_TRANSFORM3(COPSNROB_MOTOR01_NODE(_num, 4), \ COPSNROB_MOTOR01_NODE(_num, 2), /* INP0 */ \ COPSNROB_MOTOR01_NODE(_num, 3), 2, /* INP1, INP2 */ \ "02&2/12*+") /* get bits ready for DAC */\ DISCRETE_DAC_R1(_output, \ COPSNROB_MOTOR01_NODE(_num, 4), 4.2, &copsnrob_motor01_out_dac) /* DATA; VDATA - TTL with light load */ /************************************************ * MOTOR0/1 Definition Start ************************************************/ /************************************************ * MOTOR2/3 Definition Start ************************************************/ #define COPSNROB_MOTOR23(_output, _input, _num) \ /* simulate the RC connected to the 555 CV pin with a DAC */ \ DISCRETE_DAC_R1(COPSNROB_MOTOR23_NODE(_num, 0), \ _input, 4.2, &copsnrob_motor23_cv_dac) /* DATA; VDATA - TTL with light load */ \ DISCRETE_555_ASTABLE_CV(COPSNROB_MOTOR23_NODE(_num, 1), /* IC J2, pin 5 */ \ 1, /* RESET */ \ COPSNROB_R64, COPSNROB_R42, COPSNROB_C24, \ COPSNROB_MOTOR23_NODE(_num, 0), /* CTRLV - IC J2, pin 3 */ \ &copsnrob_motor23_555_1) \ DISCRETE_CRFILTER_VREF(COPSNROB_MOTOR23_NODE(_num, 2), \ COPSNROB_MOTOR23_NODE(_num, 1), /* IN0 */ \ RES_3_PARALLEL(COPSNROB_R27, RES_K(10), RES_K(5)), COPSNROB_C17, /* R is in parallel with 555 internal R */ \ 5.0 * RES_VOLTAGE_DIVIDER(RES_2_PARALLEL(COPSNROB_R27, RES_K(10)), RES_K(5))) /* VREF */ \ DISCRETE_555_MSTABLE(COPSNROB_MOTOR23_NODE(_num, 3), /* IC J3, pin 9 */ \ 1, /* RESET */ \ COPSNROB_MOTOR23_NODE(_num, 2), /* IC J3, pin 8 */ \ COPSNROB_R41, COPSNROB_C23, \ &copsnrob_motor23_555_2) \ DISCRETE_OP_AMP_FILTER(_output, /* IC L4, pin 7 */ \ 1, /* ENAB */ \ COPSNROB_MOTOR23_NODE(_num, 3), 0, /* INP0; INP1 */ \ DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &copsnrob_motor23_filter) /************************************************ * MOTOR2/3 Definition End ************************************************/ /************************************************ * CUSTOM_NOISE Definition Start * - output is energy ************************************************/ #define COPSNROB_CUSTOM_NOISE__FREQ DISCRETE_INPUT(0) DISCRETE_CLASS_STEP_RESET(copsnrob_custom_noise, 2, int m_flip_flop; int m_noise1_had_xtime; int m_noise2_had_xtime; uint8_t m_high_byte; uint8_t m_low_byte; double m_t_used; double m_t1; ); #define COPSNROB_CUSTOM_NOISE_HIGH 4.2 DISCRETE_STEP(copsnrob_custom_noise) { double t_used = m_t_used; double t1 = m_t1; double x_time = 0; uint8_t low_byte = m_low_byte; uint8_t high_byte = m_high_byte; uint8_t xnor_out; /* IC F2, pin 2 */ int last_noise1_bit = (low_byte >> 4) & 0x01; int last_noise2_bit = (low_byte >> 5) & 0x01; t_used += this->sample_time(); /* This clock will never run faster then the sample rate, * so we do not bother to check. */ if (t_used > t1) { /* calculate the overshoot time */ t_used -= t1; m_flip_flop ^= 1; /* clocks on low to high */ if (m_flip_flop) { int new_noise_bit; /* shift */ xnor_out = (((low_byte >> 6) & 0x01) ^ (high_byte & 0x01)) ^ 0x01; low_byte = (low_byte << 1) | ((high_byte >> 7) & 0x01); high_byte = (high_byte << 1) | xnor_out; if (high_byte == 0xff) /* IC H1, pin 8 */ high_byte = 0; m_low_byte = low_byte; m_high_byte = high_byte; /* Convert last switch time to a ratio */ x_time = t_used / this->sample_time(); /* use x_time if bit changed */ new_noise_bit = (low_byte >> 4) & 0x01; if (last_noise1_bit != new_noise_bit) { set_output(0, COPSNROB_CUSTOM_NOISE_HIGH * (new_noise_bit ? x_time : (1.0 - x_time))); m_noise1_had_xtime = 1; } new_noise_bit = (low_byte >> 5) & 0x01; if (last_noise2_bit != new_noise_bit) { set_output(1, COPSNROB_CUSTOM_NOISE_HIGH * (new_noise_bit ? x_time : (1.0 - x_time))); m_noise2_had_xtime = 1; } } } else { /* see if we need to move from x_time state to full state */ if (m_noise1_had_xtime) { set_output(0, COPSNROB_CUSTOM_NOISE_HIGH * last_noise1_bit); m_noise1_had_xtime = 0; } if (m_noise2_had_xtime) { set_output(1, COPSNROB_CUSTOM_NOISE_HIGH * last_noise2_bit); m_noise2_had_xtime = 0; } } m_t_used = t_used; } DISCRETE_RESET(copsnrob_custom_noise) { m_t1 = 0.5 / COPSNROB_CUSTOM_NOISE__FREQ ; m_flip_flop = 0; m_low_byte = 0; m_high_byte = 0; m_noise1_had_xtime = 0; m_noise2_had_xtime = 0; m_t_used = 0; } /************************************************ * CUSTOM_NOISE Definition End ************************************************/ /************************************************ * CUSTOM_ZINGS_555_MONOSTABLE Definition Start * - output is energy ************************************************/ #define COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__TRIG DISCRETE_INPUT(0) #define COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__R DISCRETE_INPUT(1) #define COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__C DISCRETE_INPUT(2) DISCRETE_CLASS_STEP_RESET(copsnrob_zings_555_monostable, 1, double m_rc; double m_exponent; double m_v_cap; int m_flip_flop; ); DISCRETE_STEP(copsnrob_zings_555_monostable) { const double v_threshold = 5.0 * 2 / 3; const double v_out_high = 5.0 - 0.5; /* light load */ int ff_set = COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__TRIG < (5.0 / 3) ? 1 : 0; int flip_flop = m_flip_flop; double v_cap = m_v_cap; double x_time = 0; /* From testing a real IC */ /* Trigger going low overides everything. It forces the FF/Output high. * If Threshold is high, the output will still go high as long as trigger is low. * The output will then go low when trigger rises above it's 1/3VCC value. * If threshold is below it's 2/3VCC value, the output will remain high. */ if (ff_set) { flip_flop = 1; m_flip_flop = flip_flop; } if (flip_flop) { double v_diff = v_out_high - v_cap; /* charge */ v_cap += v_diff * m_exponent; /* no state change if trigger is low */ if (!ff_set && (v_cap > v_threshold)) { double rc = m_rc; flip_flop = 0; m_flip_flop = flip_flop; /* calculate overshoot */ x_time = rc * log(1.0 / (1.0 - ((v_cap - v_threshold) / v_diff))); /* discharge the overshoot */ v_cap = v_threshold; v_cap -= v_cap * RC_CHARGE_EXP_DT(rc, x_time); x_time /= this->sample_time(); } } else { /* Optimization - already discharged */ if (v_cap == 0) return; /* discharge */ v_cap -= v_cap * m_exponent; /* Optimization - close enough to 0 to be 0 */ if (v_cap < 0.000001) v_cap = 0; } m_v_cap = v_cap; if (x_time > 0) set_output(0, v_out_high * x_time); else if (flip_flop) set_output(0, v_out_high); else set_output(0, 0.0); } DISCRETE_RESET(copsnrob_zings_555_monostable) { m_rc = COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__R * COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__C; m_exponent = RC_CHARGE_EXP(m_rc); m_v_cap = 0; m_flip_flop = 0; set_output(0, 0.0); } /************************************************ * CUSTOM_ZINGS_555_MONOSTABLE Definition End ************************************************/ /************************************************ * CUSTOM_ZINGS_555_ASTABLE Definition Start * - output is energy ************************************************/ #define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__RESET DISCRETE_INPUT(0) #define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R1 DISCRETE_INPUT(1) #define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R2 DISCRETE_INPUT(2) #define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__C1 DISCRETE_INPUT(3) #define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__C2 DISCRETE_INPUT(4) #define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__HIGH 4.5 DISCRETE_CLASS_STEP_RESET(copsnrob_zings_555_astable, 1, double m_r2c2; double m_r_total_cv; double m_exponent1; double m_exponent2; double m_v_cap1; double m_v_cap2; int m_flip_flop; ); DISCRETE_STEP(copsnrob_zings_555_astable) { double v_trigger, v_threshold; double v1 = COPSNROB_CUSTOM_ZINGS_555_ASTABLE__RESET; double v_cap1 = m_v_cap1; double v_cap2 = m_v_cap2; double dt = 0; int reset_active = (v1 < 0.7) ? 1 : 0; int flip_flop = m_flip_flop; /* calculate voltage at CV pin */ /* start by adding currents */ double v_cv = 5.0 / RES_K(5); v_cv += v1 / COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R1; /* convert to voltage */ v_cv *= m_r_total_cv; /* The reset voltage also charges the CV cap */ double v_diff1 = v_cv - v_cap1; /* optimization - if charged close enough to voltage */ if (fabs(v_diff1) < 0.000001) v_cap1 = v_cv; else v_cap1 += v_diff1 * m_exponent1; m_v_cap1 = v_cap1; if (reset_active) { if (flip_flop) m_flip_flop = 0; /* we still need to discharge C2 */ /* Optimization - only discharge if needed */ if (v_cap2 != 0) { /* discharge */ v_cap2 -= v_cap2 * m_exponent2; /* Optimization - close enough to 0 to be 0 */ if (v_cap2 < 0.000001) set_output(0, 0.0); else set_output(0, v_cap2); } return; } v_threshold = v_cap1 * 2 / 3; v_trigger = v_cap1 / 3; /* This oscillator will never create a frequency greater then 1/2 the sample rate, * so we won't worry about missing samples */ /* No need to optimize the charge circuit. It always charges/discharges to a voltage * greater then it will ever reach. */ if (flip_flop) { /* charge */ double v_diff2 = COPSNROB_CUSTOM_ZINGS_555_ASTABLE__HIGH - v_cap2; v_cap2 += v_diff2 * m_exponent2; if (v_cap2 > v_threshold) { double r2c2 = m_r2c2; m_flip_flop = 0; /* calculate overshoot */ dt = r2c2 * log(1.0 / (1.0 - ((v_cap2 - v_threshold) / v_diff2))); /* discharge the overshoot */ v_cap2 = v_threshold; v_cap2 -= v_cap2 * RC_CHARGE_EXP_DT(r2c2, dt); } } else { /* discharge */ double v_diff2 = v_cap2; v_cap2 -= v_diff2 * m_exponent2; if (v_cap2 < v_trigger) { double r2c2 = m_r2c2; m_flip_flop = 1; /* calculate overshoot */ dt = r2c2 * log(1.0 / (1.0 - ((v_trigger - v_cap2) / v_diff2))); /* charge the overshoot */ v_cap2 = v_trigger; v_cap2 += (COPSNROB_CUSTOM_ZINGS_555_ASTABLE__HIGH - v_cap2) * RC_CHARGE_EXP_DT(r2c2, dt); } } if (v_cap2 > 0) m_v_cap2 = v_cap2; else m_v_cap2 = 0.0; set_output(0, m_v_cap2); } DISCRETE_RESET(copsnrob_zings_555_astable) { m_r_total_cv = RES_3_PARALLEL(COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R1, RES_K(10), RES_K(5)); m_r2c2 = COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R2 * COPSNROB_CUSTOM_ZINGS_555_ASTABLE__C2; m_exponent1 = RC_CHARGE_EXP(COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R1 * COPSNROB_CUSTOM_ZINGS_555_ASTABLE__C1); m_exponent2 = RC_CHARGE_EXP(m_r2c2); m_v_cap1 = 0; m_flip_flop = 0; m_v_cap2 = 0.0; /* charge on C2 */ } /************************************************ * CUSTOM_ZINGS_555_ASTABLE Definition End ************************************************/ static DISCRETE_SOUND_START(copsnrob_discrete) /************************************************ * Input register mapping ************************************************/ DISCRETE_INPUT_LOGIC(COPSNROB_MOTOR0_INV) DISCRETE_INPUT_LOGIC(COPSNROB_MOTOR1_INV) DISCRETE_INPUT_LOGIC(COPSNROB_MOTOR2_INV) DISCRETE_INPUT_LOGIC(COPSNROB_MOTOR3_INV) /* !! DISABLED UNTIL ADDRESS IS FOUND !! */ // DISCRETE_INPUTX_LOGIC(COPSNROB_ZINGS_INV, 4, 0, 0) // DISCRETE_INPUT_LOGIC(COPSNROB_FIRES_INV) DISCRETE_INPUT_NOT(COPSNROB_CRASH_INV) /* inverted for counter use */ DISCRETE_INPUT_LOGIC(COPSNROB_SCREECH_INV) DISCRETE_INPUT_NOT(COPSNROB_AUDIO_ENABLE) /* IC A1, pins 2 & 12 */ /* These inputs are disabled until their address triggers are determined. * Then these constants can be removed. */ DISCRETE_CONSTANT(COPSNROB_ZINGS_INV, 4) /* data bit will be normally high, when it goes low it triggers the one-shot which has a minimum on time of 0.2s */ DISCRETE_CONSTANT(COPSNROB_FIRES_INV, 4) /* data bit will be normally high */ /************************************************ * MOTOR0/1 ************************************************/ COPSNROB_MOTOR01(COPSNROB_MOTOR0_SND, COPSNROB_MOTOR0_INV, 0) COPSNROB_MOTOR01(COPSNROB_MOTOR1_SND, COPSNROB_MOTOR1_INV, 1) /************************************************ * MOTOR2/3 ************************************************/ COPSNROB_MOTOR23(COPSNROB_MOTOR2_SND, COPSNROB_MOTOR2_INV, 0) COPSNROB_MOTOR23(COPSNROB_MOTOR3_SND, COPSNROB_MOTOR3_INV, 1) /************************************************ * CRASH ************************************************/ DISCRETE_CUSTOM1(COPSNROB_NOISE_1, copsnrob_custom_noise, /* IC J2, pin 10 */ COPSNROB_2V, /* CLK */ nullptr) /* COPSNROB_NOISE_2 derived from sub out of above custom module - IC J2, pin 11 */ /* We use the measured 555 timer frequency (IC M3) for speed */ DISCRETE_COUNTER(NODE_40, /* IC L2 */ NODE_41, /* ENAB - IC L2, pin 14 */ COPSNROB_CRASH_INV, /* RESET - IC L2, pin 11 */ 92, /* IC L2, pin 4 - freq measured */ 0, 15, DISC_COUNT_DOWN, 15, DISC_CLK_IS_FREQ) /* MIN; MAX; DIR; INIT0; CLKTYPE */ DISCRETE_TRANSFORM2(NODE_41, /* IC M2, pin 3 - goes high at count 0 */ NODE_40, 0, "01=!") /* -we will invert it for use by the counter module */ DISCRETE_SWITCH(NODE_42, /* IC L3 */ 1, COPSNROB_NOISE_2, 0, NODE_40) /* ENAB; SWITCH; INP0; INP1 */ DISCRETE_DAC_R1(COPSNROB_CRASH_SND, NODE_42, 3.8, /* DATA; VDATA */ &copsnrob_crash_dac) /************************************************ * SCREECH ************************************************/ DISCRETE_CONSTANT(COPSNROB_SCREECH_SND, 0) /************************************************ * FZ (Fires, Zings) ************************************************/ DISCRETE_CUSTOM3(NODE_60, copsnrob_zings_555_monostable, /* IC D3, pin 5 */ /* We can ignore R47 & R48 */ COPSNROB_ZINGS_INV, /* IC D3, pin 6 */ COPSNROB_R38, COPSNROB_C19, nullptr) DISCRETE_CUSTOM5(NODE_61, copsnrob_zings_555_astable, /* IC D3, pin 8 & 12 */ NODE_60, /* IC D3, pin 10 */ COPSNROB_R36, COPSNROB_R37, COPSNROB_C3, COPSNROB_C13, nullptr) /* FIX - do a better implemetation of IC L4 */ DISCRETE_CRFILTER_VREF(NODE_62, /* IC L4, pin 9 */ NODE_61, /* IN0 */ COPSNROB_R26, COPSNROB_C39, 5.0 * RES_VOLTAGE_DIVIDER(COPSNROB_R74, COPSNROB_R75)) /* VREF */ DISCRETE_GAIN(COPSNROB_FZ_SND, /* IC L4, pin 8 */ NODE_62, COPSNROB_R73 / COPSNROB_R26) /************************************************ * MIXER ************************************************/ DISCRETE_MIXER5(NODE_90, /* IC B3, pin 3 */ COPSNROB_AUDIO_ENABLE, /* ENAB */ COPSNROB_MOTOR1_SND, COPSNROB_MOTOR0_SND, COPSNROB_FZ_SND, COPSNROB_SCREECH_SND, COPSNROB_CRASH_SND, &copsnrob_final_mixer01) DISCRETE_MIXER5(NODE_91, /* IC P3, pin 3 */ COPSNROB_AUDIO_ENABLE, /* ENAB */ COPSNROB_MOTOR3_SND, COPSNROB_MOTOR2_SND, COPSNROB_CRASH_SND, COPSNROB_SCREECH_SND, COPSNROB_FZ_SND, &copsnrob_final_mixer23) DISCRETE_OUTPUT(NODE_90, 32767.0*3.5) DISCRETE_OUTPUT(NODE_91, 32767.0*3.5) DISCRETE_SOUND_END WRITE_LINE_MEMBER(copsnrob_state::one_start_w) { /* One Start */ m_leds[0] = state ? 0 :1; } void copsnrob_state::copsnrob_audio(machine_config &config) { /* sound hardware */ SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); discrete_sound_device &discrete(DISCRETE(config, "discrete", copsnrob_discrete)); discrete.add_route(0, "lspeaker", 1.0); discrete.add_route(1, "rspeaker", 1.0); f9334_device &latch(F9334(config, "latch")); // H3 on audio board latch.q_out_cb<0>().set("discrete", FUNC(discrete_device::write_line)); latch.q_out_cb<1>().set("discrete", FUNC(discrete_device::write_line)); latch.q_out_cb<2>().set("discrete", FUNC(discrete_device::write_line)); latch.q_out_cb<3>().set("discrete", FUNC(discrete_device::write_line)); latch.q_out_cb<4>().set("discrete", FUNC(discrete_device::write_line)); latch.q_out_cb<5>().set("discrete", FUNC(discrete_device::write_line)); latch.q_out_cb<6>().set(FUNC(copsnrob_state::one_start_w)); latch.q_out_cb<7>().set("discrete", FUNC(discrete_device::write_line)); }