diff options
author | 2014-03-19 17:40:26 +0000 | |
---|---|---|
committer | 2014-03-19 17:40:26 +0000 | |
commit | 6127b13ea525eeb5d0b315cbdd02501db525ecfd (patch) | |
tree | e1f4382933d7a68e59f77c53780095a7fe8d760e /src/emu/sound/disc_flt.inc | |
parent | 60bc9376487678a14b74c261c17e29bf8b036e46 (diff) |
renamed disc_*.c to disc_*.inc
Diffstat (limited to 'src/emu/sound/disc_flt.inc')
-rw-r--r-- | src/emu/sound/disc_flt.inc | 1436 |
1 files changed, 1436 insertions, 0 deletions
diff --git a/src/emu/sound/disc_flt.inc b/src/emu/sound/disc_flt.inc new file mode 100644 index 00000000000..4edda799999 --- /dev/null +++ b/src/emu/sound/disc_flt.inc @@ -0,0 +1,1436 @@ +/************************************************************************ + * + * MAME - Discrete sound system emulation library + * + * Written by Keith Wilkins (mame@esplexo.co.uk) + * + * (c) K.Wilkins 2000 + * + *********************************************************************** + * + * DST_CRFILTER - Simple CR filter & also highpass filter + * DST_FILTER1 - Generic 1st order filter + * DST_FILTER2 - Generic 2nd order filter + * DST_OP_AMP_FILT - Op Amp filter circuits + * DST_RC_CIRCUIT_1 - RC charge/discharge circuit + * DST_RCDISC - Simple discharging RC + * DST_RCDISC2 - Simple charge R1/C, discharge R0/C + * DST_RCDISC3 - Simple charge R1/c, discharge R0*R1/(R0+R1)/C + * DST_RCDISC4 - Various charge/discharge circuits + * DST_RCDISC5 - Diode in series with R//C + * DST_RCDISC_MOD - RC triggered by logic and modulated + * DST_RCFILTER - Simple RC filter & also lowpass filter + * DST_RCFILTER_SW - Usage of node_description values for switchable RC filter + * DST_RCINTEGRATE - Two diode inputs, transistor and a R/C charge + * discharge network + * DST_SALLEN_KEY - Sallen-Key filter circuit + * + ************************************************************************/ + + +/************************************************************************ + * + * DST_CRFILTER - Usage of node_description values for CR filter + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * input[4] - Voltage reference. Usually 0V. + * + ************************************************************************/ +#define DST_CRFILTER__IN DISCRETE_INPUT(0) +#define DST_CRFILTER__R DISCRETE_INPUT(1) +#define DST_CRFILTER__C DISCRETE_INPUT(2) +#define DST_CRFILTER__VREF DISCRETE_INPUT(3) + +DISCRETE_STEP(dst_crfilter) +{ + if (UNEXPECTED(m_has_rc_nodes)) + { + double rc = DST_CRFILTER__R * DST_CRFILTER__C; + if (rc != m_rc) + { + m_rc = rc; + m_exponent = RC_CHARGE_EXP(rc); + } + } + + double v_out = DST_CRFILTER__IN - m_vCap; + double v_diff = v_out - DST_CRFILTER__VREF; + set_output(0, v_out); + m_vCap += v_diff * m_exponent; +} + +DISCRETE_RESET(dst_crfilter) +{ + m_has_rc_nodes = this->input_is_node() & 0x6; + m_rc = DST_CRFILTER__R * DST_CRFILTER__C; + m_exponent = RC_CHARGE_EXP(m_rc); + m_vCap = 0; + set_output(0, DST_CRFILTER__IN); +} + + +/************************************************************************ + * + * DST_FILTER1 - Generic 1st order filter + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Frequency value (initialization only) + * input[3] - Filter type (initialization only) + * + ************************************************************************/ +#define DST_FILTER1__ENABLE DISCRETE_INPUT(0) +#define DST_FILTER1__IN DISCRETE_INPUT(1) +#define DST_FILTER1__FREQ DISCRETE_INPUT(2) +#define DST_FILTER1__TYPE DISCRETE_INPUT(3) + +static void calculate_filter1_coefficients(discrete_base_node *node, double fc, double type, + struct discrete_filter_coeff &coeff) +{ + double den, w, two_over_T; + + /* calculate digital filter coefficents */ + /*w = 2.0*M_PI*fc; no pre-warping */ + w = node->sample_rate()*2.0*tan(M_PI*fc/node->sample_rate()); /* pre-warping */ + two_over_T = 2.0*node->sample_rate(); + + den = w + two_over_T; + coeff.a1 = (w - two_over_T)/den; + if (type == DISC_FILTER_LOWPASS) + { + coeff.b0 = coeff.b1 = w/den; + } + else if (type == DISC_FILTER_HIGHPASS) + { + coeff.b0 = two_over_T/den; + coeff.b1 = -(coeff.b0); + } + else + { + /* FIXME: reenable */ + //node->m_device->discrete_log("calculate_filter1_coefficients() - Invalid filter type for 1st order filter."); + } +} + +DISCRETE_STEP(dst_filter1) +{ + double gain = 1.0; + double v_out; + + if (DST_FILTER1__ENABLE == 0.0) + { + gain = 0.0; + } + + v_out = -m_fc.a1*m_fc.y1 + m_fc.b0*gain*DST_FILTER1__IN + m_fc.b1*m_fc.x1; + + m_fc.x1 = gain*DST_FILTER1__IN; + m_fc.y1 = v_out; + set_output(0, v_out); +} + +DISCRETE_RESET(dst_filter1) +{ + calculate_filter1_coefficients(this, DST_FILTER1__FREQ, DST_FILTER1__TYPE, m_fc); + set_output(0, 0); +} + + +/************************************************************************ + * + * DST_FILTER2 - Generic 2nd order filter + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Frequency value (initialization only) + * input[3] - Damping value (initialization only) + * input[4] - Filter type (initialization only) + * + ************************************************************************/ +#define DST_FILTER2__ENABLE DISCRETE_INPUT(0) +#define DST_FILTER2__IN DISCRETE_INPUT(1) +#define DST_FILTER2__FREQ DISCRETE_INPUT(2) +#define DST_FILTER2__DAMP DISCRETE_INPUT(3) +#define DST_FILTER2__TYPE DISCRETE_INPUT(4) + +static void calculate_filter2_coefficients(discrete_base_node *node, + double fc, double d, double type, + struct discrete_filter_coeff &coeff) +{ + double w; /* cutoff freq, in radians/sec */ + double w_squared; + double den; /* temp variable */ + double two_over_T = 2 * node->sample_rate(); + double two_over_T_squared = two_over_T * two_over_T; + + /* calculate digital filter coefficents */ + /*w = 2.0*M_PI*fc; no pre-warping */ + w = node->sample_rate() * 2.0 * tan(M_PI * fc / node->sample_rate()); /* pre-warping */ + w_squared = w * w; + + den = two_over_T_squared + d*w*two_over_T + w_squared; + + coeff.a1 = 2.0 * (-two_over_T_squared + w_squared) / den; + coeff.a2 = (two_over_T_squared - d * w * two_over_T + w_squared) / den; + + if (type == DISC_FILTER_LOWPASS) + { + coeff.b0 = coeff.b2 = w_squared/den; + coeff.b1 = 2.0 * (coeff.b0); + } + else if (type == DISC_FILTER_BANDPASS) + { + coeff.b0 = d * w * two_over_T / den; + coeff.b1 = 0.0; + coeff.b2 = -(coeff.b0); + } + else if (type == DISC_FILTER_HIGHPASS) + { + coeff.b0 = coeff.b2 = two_over_T_squared / den; + coeff.b1 = -2.0 * (coeff.b0); + } + else + { + /* FIXME: reenable */ + //node->device->discrete_log("calculate_filter2_coefficients() - Invalid filter type for 2nd order filter."); + } +} + +DISCRETE_STEP(dst_filter2) +{ + double gain = 1.0; + double v_out; + + if (DST_FILTER2__ENABLE == 0.0) + { + gain = 0.0; + } + + v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 + + m_fc.b0 * gain * DST_FILTER2__IN + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2; + + m_fc.x2 = m_fc.x1; + m_fc.x1 = gain * DST_FILTER2__IN; + m_fc.y2 = m_fc.y1; + m_fc.y1 = v_out; + set_output(0, v_out); +} + +DISCRETE_RESET(dst_filter2) +{ + calculate_filter2_coefficients(this, DST_FILTER2__FREQ, DST_FILTER2__DAMP, DST_FILTER2__TYPE, + m_fc); + set_output(0, 0); +} + + +/************************************************************************ + * + * DST_OP_AMP_FILT - Op Amp filter circuit RC filter + * + * input[0] - Enable input value + * input[1] - IN0 node + * input[2] - IN1 node + * input[3] - Filter Type + * + * also passed discrete_op_amp_filt_info structure + * + * Mar 2004, D Renaud. + ************************************************************************/ +#define DST_OP_AMP_FILT__ENABLE DISCRETE_INPUT(0) +#define DST_OP_AMP_FILT__INP1 DISCRETE_INPUT(1) +#define DST_OP_AMP_FILT__INP2 DISCRETE_INPUT(2) +#define DST_OP_AMP_FILT__TYPE DISCRETE_INPUT(3) + +DISCRETE_STEP(dst_op_amp_filt) +{ + DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info) + double v_out = 0; + + double i, v = 0; + + if (DST_OP_AMP_FILT__ENABLE) + { + if (m_is_norton) + { + v = DST_OP_AMP_FILT__INP1 - OP_AMP_NORTON_VBE; + if (v < 0) v = 0; + } + else + { + /* Millman the input voltages. */ + i = m_iFixed; + switch (m_type) + { + case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A: + i += (DST_OP_AMP_FILT__INP1 - DST_OP_AMP_FILT__INP2) / info->r1; + if (info->r2 != 0) + i += (m_vP - DST_OP_AMP_FILT__INP2) / info->r2; + if (info->r3 != 0) + i += (m_vN - DST_OP_AMP_FILT__INP2) / info->r3; + break; + default: + i += (DST_OP_AMP_FILT__INP1 - m_vRef) / info->r1; + if (info->r2 != 0) + i += (DST_OP_AMP_FILT__INP2 - m_vRef) / info->r2; + break; + } + v = i * m_rTotal; + } + + switch (m_type) + { + case DISC_OP_AMP_FILTER_IS_LOW_PASS_1: + m_vC1 += (v - m_vC1) * m_exponentC1; + v_out = m_vC1 * m_gain + info->vRef; + break; + + case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A: + m_vC1 += (v - m_vC1) * m_exponentC1; + v_out = m_vC1 * m_gain + DST_OP_AMP_FILT__INP2; + break; + + case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1: + v_out = (v - m_vC1) * m_gain + info->vRef; + m_vC1 += (v - m_vC1) * m_exponentC1; + break; + + case DISC_OP_AMP_FILTER_IS_BAND_PASS_1: + v_out = (v - m_vC2); + m_vC2 += (v - m_vC2) * m_exponentC2; + m_vC1 += (v_out - m_vC1) * m_exponentC1; + v_out = m_vC1 * m_gain + info->vRef; + break; + + case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON: + m_vC1 += (v - m_vC1) * m_exponentC1; + m_vC2 += (m_vC1 - m_vC2) * m_exponentC2; + v = m_vC2; + v_out = v - m_vC3; + m_vC3 += (v - m_vC3) * m_exponentC3; + i = v_out / m_rTotal; + v_out = (m_iFixed - i) * info->rF; + break; + + case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON: + v_out = v - m_vC1; + m_vC1 += (v - m_vC1) * m_exponentC1; + i = v_out / m_rTotal; + v_out = (m_iFixed - i) * info->rF; + break; + + case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M: + case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON: + v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 + + m_fc.b0 * v + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2 + + m_vRef; + m_fc.x2 = m_fc.x1; + m_fc.x1 = v; + m_fc.y2 = m_fc.y1; + break; + } + + /* Clip the output to the voltage rails. + * This way we get the original distortion in all it's glory. + */ + if (v_out > m_vP) v_out = m_vP; + if (v_out < m_vN) v_out = m_vN; + m_fc.y1 = v_out - m_vRef; + set_output(0, v_out); + } + else + set_output(0, 0); + +} + +DISCRETE_RESET(dst_op_amp_filt) +{ + DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info) + + /* Convert the passed filter type into an int for easy use. */ + m_type = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_FILTER_TYPE_MASK; + m_is_norton = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_IS_NORTON; + + if (m_is_norton) + { + m_vRef = 0; + m_rTotal = info->r1; + if (m_type == (DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON)) + m_rTotal += info->r2 + info->r3; + + /* Setup the current to the + input. */ + m_iFixed = (info->vP - OP_AMP_NORTON_VBE) / info->r4; + + /* Set the output max. */ + m_vP = info->vP - OP_AMP_NORTON_VBE; + m_vN = info->vN; + } + else + { + m_vRef = info->vRef; + /* Set the output max. */ + m_vP = info->vP - OP_AMP_VP_RAIL_OFFSET; + m_vN = info->vN; + + /* Work out the input resistance. It is all input and bias resistors in parallel. */ + m_rTotal = 1.0 / info->r1; /* There has to be an R1. Otherwise the table is wrong. */ + if (info->r2 != 0) m_rTotal += 1.0 / info->r2; + if (info->r3 != 0) m_rTotal += 1.0 / info->r3; + m_rTotal = 1.0 / m_rTotal; + + m_iFixed = 0; + + m_rRatio = info->rF / (m_rTotal + info->rF); + m_gain = -info->rF / m_rTotal; + } + + switch (m_type) + { + case DISC_OP_AMP_FILTER_IS_LOW_PASS_1: + case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A: + m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1); + m_exponentC2 = 0; + break; + case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1: + m_exponentC1 = RC_CHARGE_EXP(m_rTotal * info->c1); + m_exponentC2 = 0; + break; + case DISC_OP_AMP_FILTER_IS_BAND_PASS_1: + m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1); + m_exponentC2 = RC_CHARGE_EXP(m_rTotal * info->c2); + break; + case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON: + if (info->r2 == 0) + m_rTotal = info->r1; + else + m_rTotal = RES_2_PARALLEL(info->r1, info->r2); + case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M: + { + double fc = 1.0 / (2 * M_PI * sqrt(m_rTotal * info->rF * info->c1 * info->c2)); + double d = (info->c1 + info->c2) / sqrt(info->rF / m_rTotal * info->c1 * info->c2); + double gain = -info->rF / m_rTotal * info->c2 / (info->c1 + info->c2); + + calculate_filter2_coefficients(this, fc, d, DISC_FILTER_BANDPASS, m_fc); + m_fc.b0 *= gain; + m_fc.b1 *= gain; + m_fc.b2 *= gain; + + if (m_is_norton) + m_vRef = (info->vP - OP_AMP_NORTON_VBE) / info->r3 * info->rF; + else + m_vRef = info->vRef; + + break; + } + case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON: + m_exponentC1 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1, info->r2 + info->r3 + info->r4) * info->c1); + m_exponentC2 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1 + info->r2, info->r3 + info->r4) * info->c2); + m_exponentC3 = RC_CHARGE_EXP((info->r1 + info->r2 + info->r3 + info->r4) * info->c3); + break; + case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON: + m_exponentC1 = RC_CHARGE_EXP(info->r1 * info->c1); + break; + } + + /* At startup there is no charge on the caps and output is 0V in relation to vRef. */ + m_vC1 = 0; + m_vC1b = 0; + m_vC2 = 0; + m_vC3 = 0; + + set_output(0, info->vRef); +} + + +/************************************************************************ + * + * DST_RC_CIRCUIT_1 - RC charge/discharge circuit + * + ************************************************************************/ +#define DST_RC_CIRCUIT_1__IN0 DISCRETE_INPUT(0) +#define DST_RC_CIRCUIT_1__IN1 DISCRETE_INPUT(1) +#define DST_RC_CIRCUIT_1__R DISCRETE_INPUT(2) +#define DST_RC_CIRCUIT_1__C DISCRETE_INPUT(3) + +#define CD4066_R_ON 270 + +DISCRETE_STEP( dst_rc_circuit_1 ) +{ + if (DST_RC_CIRCUIT_1__IN0 == 0) + if (DST_RC_CIRCUIT_1__IN1 == 0) + /* cap is floating and does not change charge */ + /* output is pulled to ground */ + set_output(0, 0); + else + { + /* cap is discharged */ + m_v_cap -= m_v_cap * m_exp_2; + set_output(0, m_v_cap * m_v_drop); + } + else + if (DST_RC_CIRCUIT_1__IN1 == 0) + { + /* cap is charged */ + m_v_cap += (5.0 - m_v_cap) * m_exp_1; + /* output is pulled to ground */ + set_output(0, 0); + } + else + { + /* cap is charged slightly less */ + m_v_cap += (m_v_charge_1_2 - m_v_cap) * m_exp_1_2; + set_output(0, m_v_cap * m_v_drop); + } +} + +DISCRETE_RESET( dst_rc_circuit_1 ) +{ + /* the charging voltage across the cap based on in2*/ + m_v_drop = RES_VOLTAGE_DIVIDER(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R); + m_v_charge_1_2 = 5.0 * m_v_drop; + m_v_cap = 0; + + /* precalculate charging exponents */ + /* discharge cap - in1 = 0, in2 = 1*/ + m_exp_2 = RC_CHARGE_EXP((CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C); + /* charge cap - in1 = 1, in2 = 0 */ + m_exp_1 = RC_CHARGE_EXP(CD4066_R_ON * DST_RC_CIRCUIT_1__C); + /* charge cap - in1 = 1, in2 = 1 */ + m_exp_1_2 = RC_CHARGE_EXP(RES_2_PARALLEL(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C); + + /* starts at 0 until cap starts charging */ + set_output(0, 0); +} + +/************************************************************************ + * + * DST_RCDISC - Usage of node_description values for RC discharge + * (inverse slope of DST_RCFILTER) + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCDISC__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISC__IN DISCRETE_INPUT(1) +#define DST_RCDISC__R DISCRETE_INPUT(2) +#define DST_RCDISC__C DISCRETE_INPUT(3) + +DISCRETE_STEP(dst_rcdisc) +{ + switch (m_state) + { + case 0: /* waiting for trigger */ + if(DST_RCDISC__ENABLE) + { + m_state = 1; + m_t = 0; + } + set_output(0, 0); + break; + + case 1: + if (DST_RCDISC__ENABLE) + { + set_output(0, DST_RCDISC__IN * exp(m_t / m_exponent0)); + m_t += this->sample_time(); + } else + { + m_state = 0; + } + } +} + +DISCRETE_RESET(dst_rcdisc) +{ + set_output(0, 0); + + m_state = 0; + m_t = 0; + m_exponent0=-1.0 * DST_RCDISC__R * DST_RCDISC__C; +} + + +/************************************************************************ + * + * DST_RCDISC2 - Usage of node_description values for RC discharge + * Has switchable charge resistor/input + * + * input[0] - Switch input value + * input[1] - input[0] value + * input[2] - Resistor0 value (initialization only) + * input[3] - input[1] value + * input[4] - Resistor1 value (initialization only) + * input[5] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCDISC2__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISC2__IN0 DISCRETE_INPUT(1) +#define DST_RCDISC2__R0 DISCRETE_INPUT(2) +#define DST_RCDISC2__IN1 DISCRETE_INPUT(3) +#define DST_RCDISC2__R1 DISCRETE_INPUT(4) +#define DST_RCDISC2__C DISCRETE_INPUT(5) + +DISCRETE_STEP(dst_rcdisc2) +{ + double diff; + + /* Works differently to other as we are always on, no enable */ + /* exponential based in difference between input/output */ + + diff = ((DST_RCDISC2__ENABLE == 0) ? DST_RCDISC2__IN0 : DST_RCDISC2__IN1) - m_v_out; + diff = diff - (diff * ((DST_RCDISC2__ENABLE == 0) ? m_exponent0 : m_exponent1)); + m_v_out += diff; + set_output(0, m_v_out); +} + +DISCRETE_RESET(dst_rcdisc2) +{ + m_v_out = 0; + + m_state = 0; + m_t = 0; + m_exponent0 = RC_DISCHARGE_EXP(DST_RCDISC2__R0 * DST_RCDISC2__C); + m_exponent1 = RC_DISCHARGE_EXP(DST_RCDISC2__R1 * DST_RCDISC2__C); +} + +/************************************************************************ + * + * DST_RCDISC3 - Usage of node_description values for RC discharge + * + * + * input[0] - Enable + * input[1] - input value + * input[2] - Resistor0 value (initialization only) + * input[4] - Resistor1 value (initialization only) + * input[5] - Capacitor Value (initialization only) + * input[6] - Diode Junction voltage (initialization only) + * + ************************************************************************/ +#define DST_RCDISC3__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISC3__IN DISCRETE_INPUT(1) +#define DST_RCDISC3__R1 DISCRETE_INPUT(2) +#define DST_RCDISC3__R2 DISCRETE_INPUT(3) +#define DST_RCDISC3__C DISCRETE_INPUT(4) +#define DST_RCDISC3__DJV DISCRETE_INPUT(5) + +DISCRETE_STEP(dst_rcdisc3) +{ + double diff; + + /* Exponential based in difference between input/output */ + + if(DST_RCDISC3__ENABLE) + { + diff = DST_RCDISC3__IN - m_v_out; + if (m_v_diode > 0) + { + if (diff > 0) + { + diff = diff * m_exponent0; + } + else if (diff < -m_v_diode) + { + diff = diff * m_exponent1; + } + else + { + diff = diff * m_exponent0; + } + } + else + { + if (diff < 0) + { + diff = diff * m_exponent0; + } + else if (diff > -m_v_diode) + { + diff = diff * m_exponent1; + } + else + { + diff = diff * m_exponent0; + } + } + m_v_out += diff; + set_output(0, m_v_out); + } + else + { + set_output(0, 0); + } +} + +DISCRETE_RESET(dst_rcdisc3) +{ + m_v_out = 0; + + m_state = 0; + m_t = 0; + m_v_diode = DST_RCDISC3__DJV; + m_exponent0 = RC_CHARGE_EXP(DST_RCDISC3__R1 * DST_RCDISC3__C); + m_exponent1 = RC_CHARGE_EXP(RES_2_PARALLEL(DST_RCDISC3__R1, DST_RCDISC3__R2) * DST_RCDISC3__C); +} + + +/************************************************************************ + * + * DST_RCDISC4 - Various charge/discharge circuits + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - R1 Resistor value (initialization only) + * input[2] - R2 Resistor value (initialization only) + * input[4] - C1 Capacitor Value (initialization only) + * input[4] - vP power source (initialization only) + * input[4] - circuit type (initialization only) + * + ************************************************************************/ +#define DST_RCDISC4__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISC4__IN DISCRETE_INPUT(1) +#define DST_RCDISC4__R1 DISCRETE_INPUT(2) +#define DST_RCDISC4__R2 DISCRETE_INPUT(3) +#define DST_RCDISC4__R3 DISCRETE_INPUT(4) +#define DST_RCDISC4__C1 DISCRETE_INPUT(5) +#define DST_RCDISC4__VP DISCRETE_INPUT(6) +#define DST_RCDISC4__TYPE DISCRETE_INPUT(7) + +DISCRETE_STEP(dst_rcdisc4) +{ + int inp1 = (DST_RCDISC4__IN == 0) ? 0 : 1; + double v_out = 0; + + if (DST_RCDISC4__ENABLE == 0) + { + set_output(0, 0); + return; + } + + switch (m_type) + { + case 1: + case 3: + m_vC1 += ((m_v[inp1] - m_vC1) * m_exp[inp1]); + v_out = m_vC1; + break; + } + + /* clip output */ + if (v_out > m_max_out) v_out = m_max_out; + if (v_out < 0) v_out = 0; + set_output(0, v_out); +} + +DISCRETE_RESET( dst_rcdisc4) +{ + double v, i, r, rT; + + m_type = 0; + /* some error checking. */ + if (DST_RCDISC4__R1 <= 0 || DST_RCDISC4__R2 <= 0 || DST_RCDISC4__C1 <= 0 || (DST_RCDISC4__R3 <= 0 && m_type == 1)) + { + m_device->discrete_log("Invalid component values in NODE_%d.\n", this->index()); + return; + } + if (DST_RCDISC4__VP < 3) + { + m_device->discrete_log("vP must be >= 3V in NODE_%d.\n", this->index()); + return; + } + if (DST_RCDISC4__TYPE < 1 || DST_RCDISC4__TYPE > 3) + { + m_device->discrete_log("Invalid circuit type in NODE_%d.\n", this->index()); + return; + } + + m_vC1 = 0; + /* store type as integer */ + m_type = (int)DST_RCDISC4__TYPE; + /* setup the maximum op-amp output. */ + m_max_out = DST_RCDISC4__VP - OP_AMP_VP_RAIL_OFFSET; + + switch (m_type) + { + case 1: + /* We will simulate this as a voltage divider with 2 states depending + * on the input. But we have to take the diodes into account. + */ + v = DST_RCDISC4__VP - .5; /* diode drop */ + + /* When the input is 1, both R1 & R3 are basically in parallel. */ + r = RES_2_PARALLEL(DST_RCDISC4__R1, DST_RCDISC4__R3); + rT = DST_RCDISC4__R2 + r; + i = v / rT; + m_v[1] = i * r + .5; + rT = RES_2_PARALLEL(DST_RCDISC4__R2, r); + m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1); + + /* When the input is 0, R1 is out of circuit. */ + rT = DST_RCDISC4__R2 + DST_RCDISC4__R3; + i = v / rT; + m_v[0] = i * DST_RCDISC4__R3 + .5; + rT = RES_2_PARALLEL(DST_RCDISC4__R2, DST_RCDISC4__R3); + m_exp[0] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1); + break; + + case 3: + /* We will simulate this as a voltage divider with 2 states depending + * on the input. The 1k pullup is in parallel with the internal TTL + * resistance, so we will just use .5k in series with R1. + */ + r = 500.0 + DST_RCDISC4__R1; + m_v[1] = RES_VOLTAGE_DIVIDER(r, DST_RCDISC4__R2) * (5.0 - 0.5); + rT = RES_2_PARALLEL(r, DST_RCDISC4__R2); + m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1); + + /* When the input is 0, R1 is out of circuit. */ + m_v[0] = 0; + m_exp[0] = RC_CHARGE_EXP(DST_RCDISC4__R2 * DST_RCDISC4__C1); + break; + } +} + +/************************************************************************ + * + * DST_RCDISC5 - Diode in series with R//C + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCDISC5__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISC5__IN DISCRETE_INPUT(1) +#define DST_RCDISC5__R DISCRETE_INPUT(2) +#define DST_RCDISC5__C DISCRETE_INPUT(3) + +DISCRETE_STEP( dst_rcdisc5) +{ + double diff,u; + + /* Exponential based in difference between input/output */ + + u = DST_RCDISC5__IN - 0.7; /* Diode drop */ + if( u < 0) + u = 0; + + diff = u - m_v_cap; + + if(DST_RCDISC5__ENABLE) + { + if(diff < 0) + diff = diff * m_exponent0; + + m_v_cap += diff; + set_output(0, m_v_cap); + } + else + { + if(diff > 0) + m_v_cap = u; + + set_output(0, 0); + } +} + +DISCRETE_RESET( dst_rcdisc5) +{ + set_output(0, 0); + + m_state = 0; + m_t = 0; + m_v_cap = 0; + m_exponent0 = RC_CHARGE_EXP(DST_RCDISC5__R * DST_RCDISC5__C); +} + + +/************************************************************************ + * + * DST_RCDISC_MOD - RC triggered by logic and modulated + * + * input[0] - Enable input value + * input[1] - input value 1 + * input[2] - input value 2 + * input[3] - Resistor 1 value (initialization only) + * input[4] - Resistor 2 value (initialization only) + * input[5] - Resistor 3 value (initialization only) + * input[6] - Resistor 4 value (initialization only) + * input[7] - Capacitor Value (initialization only) + * input[8] - Voltage Value (initialization only) + * + ************************************************************************/ +#define DST_RCDISC_MOD__IN1 DISCRETE_INPUT(0) +#define DST_RCDISC_MOD__IN2 DISCRETE_INPUT(1) +#define DST_RCDISC_MOD__R1 DISCRETE_INPUT(2) +#define DST_RCDISC_MOD__R2 DISCRETE_INPUT(3) +#define DST_RCDISC_MOD__R3 DISCRETE_INPUT(4) +#define DST_RCDISC_MOD__R4 DISCRETE_INPUT(5) +#define DST_RCDISC_MOD__C DISCRETE_INPUT(6) +#define DST_RCDISC_MOD__VP DISCRETE_INPUT(7) + +DISCRETE_STEP(dst_rcdisc_mod) +{ + double diff, v_cap, u, vD; + int mod_state, mod1_state, mod2_state; + + /* Exponential based in difference between input/output */ + v_cap = m_v_cap; + + mod1_state = DST_RCDISC_MOD__IN1 > 0.5; + mod2_state = DST_RCDISC_MOD__IN2 > 0.6; + mod_state = (mod2_state << 1) + mod1_state; + + u = mod1_state ? 0 : DST_RCDISC_MOD__VP; + /* Clamp */ + diff = u - v_cap; + vD = diff * m_vd_gain[mod_state]; + if (vD < -0.6) + { + diff = u + 0.6 - v_cap; + diff -= diff * m_exp_low[mod1_state]; + v_cap += diff; + set_output(0, mod2_state ? 0 : -0.6); + } + else + { + diff -= diff * m_exp_high[mod_state]; + v_cap += diff; + /* neglecting current through R3 drawn by next8 node */ + set_output(0, mod2_state ? 0: (u - v_cap) * m_gain[mod1_state]); + } + m_v_cap = v_cap; +} + +DISCRETE_RESET(dst_rcdisc_mod) +{ + double rc[2], rc2[2]; + + /* pre-calculate fixed values */ + /* DST_RCDISC_MOD__IN1 <= 0.5 */ + rc[0] = DST_RCDISC_MOD__R1 + DST_RCDISC_MOD__R2; + if (rc[0] < 1) rc[0] = 1; + m_exp_low[0] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[0]); + m_gain[0] = RES_VOLTAGE_DIVIDER(rc[0], DST_RCDISC_MOD__R4); + /* DST_RCDISC_MOD__IN1 > 0.5 */ + rc[1] = DST_RCDISC_MOD__R2; + if (rc[1] < 1) rc[1] = 1; + m_exp_low[1] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[1]); + m_gain[1] = RES_VOLTAGE_DIVIDER(rc[1], DST_RCDISC_MOD__R4); + /* DST_RCDISC_MOD__IN2 <= 0.6 */ + rc2[0] = DST_RCDISC_MOD__R4; + /* DST_RCDISC_MOD__IN2 > 0.6 */ + rc2[1] = RES_2_PARALLEL(DST_RCDISC_MOD__R3, DST_RCDISC_MOD__R4); + /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 <= 0.6 */ + m_exp_high[0] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[0])); + m_vd_gain[0] = RES_VOLTAGE_DIVIDER(rc[0], rc2[0]); + /* DST_RCDISC_MOD__IN1 > 0.5 && DST_RCDISC_MOD__IN2 <= 0.6 */ + m_exp_high[1] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[0])); + m_vd_gain[1] = RES_VOLTAGE_DIVIDER(rc[1], rc2[0]); + /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 > 0.6 */ + m_exp_high[2] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[1])); + m_vd_gain[2] = RES_VOLTAGE_DIVIDER(rc[0], rc2[1]); + /* DST_RCDISC_MOD__IN1 > 0.5 && DST_RCDISC_MOD__IN2 > 0.6 */ + m_exp_high[3] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[1])); + m_vd_gain[3] = RES_VOLTAGE_DIVIDER(rc[1], rc2[1]); + + m_v_cap = 0; + set_output(0, 0); +} + +/************************************************************************ + * + * DST_RCFILTER - Usage of node_description values for RC filter + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * input[4] - Voltage reference. Usually 0V. + * + ************************************************************************/ +#define DST_RCFILTER__VIN DISCRETE_INPUT(0) +#define DST_RCFILTER__R DISCRETE_INPUT(1) +#define DST_RCFILTER__C DISCRETE_INPUT(2) +#define DST_RCFILTER__VREF DISCRETE_INPUT(3) + +DISCRETE_STEP(dst_rcfilter) +{ + if (EXPECTED(m_is_fast)) + m_v_out += ((DST_RCFILTER__VIN - m_v_out) * m_exponent); + else + { + if (UNEXPECTED(m_has_rc_nodes)) + { + double rc = DST_RCFILTER__R * DST_RCFILTER__C; + if (rc != m_rc) + { + m_rc = rc; + m_exponent = RC_CHARGE_EXP(rc); + } + } + + /************************************************************************/ + /* Next Value = PREV + (INPUT_VALUE - PREV)*(1-(EXP(-TIMEDELTA/RC))) */ + /************************************************************************/ + + m_vCap += ((DST_RCFILTER__VIN - m_v_out) * m_exponent); + m_v_out = m_vCap + DST_RCFILTER__VREF; + } + set_output(0, m_v_out); +} + + +DISCRETE_RESET(dst_rcfilter) +{ + m_has_rc_nodes = this->input_is_node() & 0x6; + m_rc = DST_RCFILTER__R * DST_RCFILTER__C; + m_exponent = RC_CHARGE_EXP(m_rc); + m_vCap = 0; + m_v_out = 0; + /* FIXME --> we really need another class here */ + if (!m_has_rc_nodes && DST_RCFILTER__VREF == 0) + m_is_fast = 1; + else + m_is_fast = 0; +} + +/************************************************************************ + * + * DST_RCFILTER_SW - Usage of node_description values for switchable RC filter + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * input[4] - Voltage reference. Usually 0V. + * + ************************************************************************/ +#define DST_RCFILTER_SW__ENABLE DISCRETE_INPUT(0) +#define DST_RCFILTER_SW__VIN DISCRETE_INPUT(1) +#define DST_RCFILTER_SW__SWITCH DISCRETE_INPUT(2) +#define DST_RCFILTER_SW__R DISCRETE_INPUT(3) +#define DST_RCFILTER_SW__C(x) DISCRETE_INPUT(4+x) + +/* 74HC4066 : 15 + * 74VHC4066 : 15 + * UTC4066 : 270 @ 5VCC, 80 @ 15VCC + * CD4066BC : 270 (Fairchild) + * + * The choice below makes scramble sound about "right". For future error reports, + * we need the exact type of switch and at which voltage (5, 12?) it is operated. + */ +#define CD4066_ON_RES (40) + +// FIXME: This needs optimization ! +DISCRETE_STEP(dst_rcfilter_sw) +{ + int i; + int bits = (int)DST_RCFILTER_SW__SWITCH; + double us = 0; + double vIn = DST_RCFILTER_SW__VIN; + double v_out; + + if (EXPECTED(DST_RCFILTER_SW__ENABLE)) + { + switch (bits) + { + case 0: + v_out = vIn; + break; + case 1: + m_vCap[0] += (vIn - m_vCap[0]) * m_exp0; + v_out = m_vCap[0] + (vIn - m_vCap[0]) * m_factor; + break; + case 2: + m_vCap[1] += (vIn - m_vCap[1]) * m_exp1; + v_out = m_vCap[1] + (vIn - m_vCap[1]) * m_factor; + break; + default: + for (i = 0; i < 4; i++) + { + if (( bits & (1 << i)) != 0) + us += m_vCap[i]; + } + v_out = m_f1[bits] * vIn + m_f2[bits] * us; + for (i = 0; i < 4; i++) + { + if (( bits & (1 << i)) != 0) + m_vCap[i] += (v_out - m_vCap[i]) * m_exp[i]; + } + } + set_output(0, v_out); + } + else + { + set_output(0, 0); + } +} + +DISCRETE_RESET(dst_rcfilter_sw) +{ + int i, bits; + + for (i = 0; i < 4; i++) + { + m_vCap[i] = 0; + m_exp[i] = RC_CHARGE_EXP( CD4066_ON_RES * DST_RCFILTER_SW__C(i)); + } + + for (bits=0; bits < 15; bits++) + { + double rs = 0; + + for (i = 0; i < 4; i++) + { + if (( bits & (1 << i)) != 0) + rs += DST_RCFILTER_SW__R; + } + m_f1[bits] = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES); + m_f2[bits] = DST_RCFILTER_SW__R / (CD4066_ON_RES + rs); + } + + + /* fast cases */ + m_exp0 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(0)); + m_exp1 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(1)); + m_factor = RES_VOLTAGE_DIVIDER(DST_RCFILTER_SW__R, CD4066_ON_RES); + + set_output(0, 0); +} + + +/************************************************************************ + * + * DST_RCINTEGRATE - Two diode inputs, transistor and a R/C charge + * discharge network + * + * input[0] - Enable input value + * input[1] - input value 1 + * input[2] - input value 2 + * input[3] - Resistor 1 value (initialization only) + * input[4] - Resistor 2 value (initialization only) + * input[5] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCINTEGRATE__IN1 DISCRETE_INPUT(0) +#define DST_RCINTEGRATE__R1 DISCRETE_INPUT(1) +#define DST_RCINTEGRATE__R2 DISCRETE_INPUT(2) +#define DST_RCINTEGRATE__R3 DISCRETE_INPUT(3) +#define DST_RCINTEGRATE__C DISCRETE_INPUT(4) +#define DST_RCINTEGRATE__VP DISCRETE_INPUT(5) +#define DST_RCINTEGRATE__TYPE DISCRETE_INPUT(6) + +/* Ebers-Moll large signal model + * Couriersud: + * The implementation avoids all iterative approaches in order not to burn cycles + * We will calculate Ic from vBE and use this as an indication where to go. + * The implementation may oscillate if you change the weighting factors at the + * end. + * + * This implementation is not perfect, but does it's job in dkong' + */ + +/* reverse saturation current */ +#define IES 7e-15 +#define ALPHAT 0.99 +#define KT 0.026 +#define EM_IC(x) (ALPHAT * IES * exp( (x) / KT - 1.0 )) + +DISCRETE_STEP( dst_rcintegrate) +{ + double diff, u, iQ, iQc, iC, RG, vE; + double vP; + + u = DST_RCINTEGRATE__IN1; + vP = DST_RCINTEGRATE__VP; + + if ( u - 0.7 < m_vCap * m_gain_r1_r2) + { + /* discharge .... */ + diff = 0.0 - m_vCap; + iC = m_c_exp1 * diff; /* iC */ + diff -= diff * m_exp_exponent1; + m_vCap += diff; + iQ = 0; + vE = m_vCap * m_gain_r1_r2; + RG = vE / iC; + } + else + { + /* charging */ + diff = (vP - m_vCE) * m_f - m_vCap; + iC = 0.0 - m_c_exp0 * diff; /* iC */ + diff -= diff * m_exp_exponent0; + m_vCap += diff; + iQ = iC + (iC * DST_RCINTEGRATE__R1 + m_vCap) / DST_RCINTEGRATE__R2; + RG = (vP - m_vCE) / iQ; + vE = (RG - DST_RCINTEGRATE__R3) / RG * (vP - m_vCE); + } + + + u = DST_RCINTEGRATE__IN1; + if (u > 0.7 + vE) + { + vE = u - 0.7; + //iQc = EM_IC(u - vE); + iQc = m_EM_IC_0_7; + } + else + iQc = EM_IC(u - vE); + + m_vCE = MIN(vP - 0.1, vP - RG * iQc); + + /* Avoid oscillations + * The method tends to largely overshoot - no wonder without + * iterative solution approximation + */ + + m_vCE = MAX(m_vCE, 0.1 ); + m_vCE = 0.1 * m_vCE + 0.9 * (vP - vE - iQ * DST_RCINTEGRATE__R3); + + switch (m_type) + { + case DISC_RC_INTEGRATE_TYPE1: + set_output(0, m_vCap); + break; + case DISC_RC_INTEGRATE_TYPE2: + set_output(0, vE); + break; + case DISC_RC_INTEGRATE_TYPE3: + set_output(0, MAX(0, vP - iQ * DST_RCINTEGRATE__R3)); + break; + } +} + +DISCRETE_RESET(dst_rcintegrate) +{ + double r; + double dt = this->sample_time(); + + m_type = DST_RCINTEGRATE__TYPE; + + m_vCap = 0; + m_vCE = 0; + + /* pre-calculate fixed values */ + m_gain_r1_r2 = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R1, DST_RCINTEGRATE__R2); + + r = DST_RCINTEGRATE__R1 / DST_RCINTEGRATE__R2 * DST_RCINTEGRATE__R3 + DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R3; + + m_f = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R3, DST_RCINTEGRATE__R2); + m_exponent0 = -1.0 * r * m_f * DST_RCINTEGRATE__C; + m_exponent1 = -1.0 * (DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R2) * DST_RCINTEGRATE__C; + m_exp_exponent0 = exp(dt / m_exponent0); + m_exp_exponent1 = exp(dt / m_exponent1); + m_c_exp0 = DST_RCINTEGRATE__C / m_exponent0 * m_exp_exponent0; + m_c_exp1 = DST_RCINTEGRATE__C / m_exponent1 * m_exp_exponent1; + + m_EM_IC_0_7 = EM_IC(0.7); + + set_output(0, 0); +} + +/************************************************************************ + * + * DST_SALLEN_KEY - Sallen-Key filter circuit + * + * input[0] - Enable input value + * input[1] - IN0 node + * input[3] - Filter Type + * + * also passed discrete_op_amp_filt_info structure + * + * 2008, couriersud + ************************************************************************/ +#define DST_SALLEN_KEY__ENABLE DISCRETE_INPUT(0) +#define DST_SALLEN_KEY__INP0 DISCRETE_INPUT(1) +#define DST_SALLEN_KEY__TYPE DISCRETE_INPUT(2) + +DISCRETE_STEP(dst_sallen_key) +{ + double gain = 1.0; + double v_out; + + if (DST_SALLEN_KEY__ENABLE == 0.0) + { + gain = 0.0; + } + + v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 + + m_fc.b0 * gain * DST_SALLEN_KEY__INP0 + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2; + + m_fc.x2 = m_fc.x1; + m_fc.x1 = gain * DST_SALLEN_KEY__INP0; + m_fc.y2 = m_fc.y1; + m_fc.y1 = v_out; + set_output(0, v_out); +} + +DISCRETE_RESET(dst_sallen_key) +{ + DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info) + + double freq, q; + + switch ((int) DST_SALLEN_KEY__TYPE) + { + case DISC_SALLEN_KEY_LOW_PASS: + freq = 1.0 / ( 2.0 * M_PI * sqrt(info->c1 * info->c2 * info->r1 * info->r2)); + q = sqrt(info->c1 * info->c2 * info->r1 * info->r2) / (info->c2 * (info->r1 + info->r2)); + break; + default: + fatalerror("Unknown sallen key filter type\n"); + } + + calculate_filter2_coefficients(this, freq, 1.0 / q, DISC_FILTER_LOWPASS, m_fc); + set_output(0, 0); +} + + +/* !!!!!!!!!!! NEW FILTERS for testing !!!!!!!!!!!!!!!!!!!!! */ + + +/************************************************************************ + * + * DST_RCFILTERN - Usage of node_description values for RC filter + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCFILTERN__ENABLE DISCRETE_INPUT(0) +#define DST_RCFILTERN__IN DISCRETE_INPUT(1) +#define DST_RCFILTERN__R DISCRETE_INPUT(2) +#define DST_RCFILTERN__C DISCRETE_INPUT(3) + +#if 0 +DISCRETE_RESET(dst_rcfilterN) +{ +#if 0 + double f=1.0/(2*M_PI* DST_RCFILTERN__R * DST_RCFILTERN__C); + +/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */ +/* Put this stuff in a context */ + + this->m_input[2] = f; + this->m_input[3] = DISC_FILTER_LOWPASS; + + /* Use first order filter */ + dst_filter1_reset(node); +#endif +} +#endif + +/************************************************************************ + * + * DST_RCDISCN - Usage of node_description values for RC discharge + * (inverse slope of DST_RCFILTER) + * + * input[0] - Enable input value + * input[1] - input value + * input[2] - Resistor value (initialization only) + * input[3] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCDISCN__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISCN__IN DISCRETE_INPUT(1) +#define DST_RCDISCN__R DISCRETE_INPUT(2) +#define DST_RCDISCN__C DISCRETE_INPUT(3) + +DISCRETE_RESET(dst_rcdiscN) +{ +#if 0 + double f = 1.0 / (2 * M_PI * DST_RCDISCN__R * DST_RCDISCN__C); + +/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */ +/* Put this stuff in a context */ + + this->m_input[2] = f; + this->m_input[3] = DISC_FILTER_LOWPASS; + + /* Use first order filter */ + dst_filter1_reset(node); +#endif +} + +DISCRETE_STEP(dst_rcdiscN) +{ + double gain = 1.0; + double v_out; + + if (DST_RCDISCN__ENABLE == 0.0) + { + gain = 0.0; + } + + /* A rise in the input signal results in an instant charge, */ + /* else discharge through the RC to zero */ + if (gain* DST_RCDISCN__IN > m_x1) + v_out = gain* DST_RCDISCN__IN; + else + v_out = -m_a1*m_y1; + + m_x1 = gain* DST_RCDISCN__IN; + m_y1 = v_out; + set_output(0, v_out); +} + + +/************************************************************************ + * + * DST_RCDISC2N - Usage of node_description values for RC discharge + * Has switchable charge resistor/input + * + * input[0] - Switch input value + * input[1] - input[0] value + * input[2] - Resistor0 value (initialization only) + * input[3] - input[1] value + * input[4] - Resistor1 value (initialization only) + * input[5] - Capacitor Value (initialization only) + * + ************************************************************************/ +#define DST_RCDISC2N__ENABLE DISCRETE_INPUT(0) +#define DST_RCDISC2N__IN0 DISCRETE_INPUT(1) +#define DST_RCDISC2N__R0 DISCRETE_INPUT(2) +#define DST_RCDISC2N__IN1 DISCRETE_INPUT(3) +#define DST_RCDISC2N__R1 DISCRETE_INPUT(4) +#define DST_RCDISC2N__C DISCRETE_INPUT(5) + + +DISCRETE_STEP(dst_rcdisc2N) +{ + double inp = ((DST_RCDISC2N__ENABLE == 0) ? DST_RCDISC2N__IN0 : DST_RCDISC2N__IN1); + double v_out; + + if (DST_RCDISC2N__ENABLE == 0) + v_out = -m_fc0.a1*m_y1 + m_fc0.b0*inp + m_fc0.b1 * m_x1; + else + v_out = -m_fc1.a1*m_y1 + m_fc1.b0*inp + m_fc1.b1*m_x1; + + m_x1 = inp; + m_y1 = v_out; + set_output(0, v_out); +} + +DISCRETE_RESET(dst_rcdisc2N) +{ + double f1,f2; + + f1 = 1.0 / (2 * M_PI * DST_RCDISC2N__R0 * DST_RCDISC2N__C); + f2 = 1.0 / (2 * M_PI * DST_RCDISC2N__R1 * DST_RCDISC2N__C); + + calculate_filter1_coefficients(this, f1, DISC_FILTER_LOWPASS, m_fc0); + calculate_filter1_coefficients(this, f2, DISC_FILTER_LOWPASS, m_fc1); + + /* Initialize the object */ + set_output(0, 0); +} |