diff options
author | 2008-08-28 20:58:05 +0000 | |
---|---|---|
committer | 2008-08-28 20:58:05 +0000 | |
commit | ae10d3987a3b966661a54d9659a687364fa302d8 (patch) | |
tree | eac883e2d1b530ba63cd400004f9f774230772d7 /src/emu | |
parent | e5fbac92cf0ca948fb4a0a553d83390358c21bc6 (diff) |
Optimized DISCRETE_RCINTEGRATE and DISCRETE_555_ASTABLE.
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/sound/disc_dev.c | 74 | ||||
-rw-r--r-- | src/emu/sound/disc_flt.c | 81 | ||||
-rw-r--r-- | src/emu/sound/discrete.h | 1 |
3 files changed, 105 insertions, 51 deletions
diff --git a/src/emu/sound/disc_dev.c b/src/emu/sound/disc_dev.c index 9764bede8b5..3528a384a35 100644 --- a/src/emu/sound/disc_dev.c +++ b/src/emu/sound/disc_dev.c @@ -38,6 +38,12 @@ struct dsd_555_astbl_context double v_out_high; /* Logic 1 voltage level */ double v_charge; double *v_charge_node; /* point to output of node */ + int has_rc_nodes; + double exp_bleed; + double exp_charge; + double exp_discharge; + double t_rc_charge; + double t_rc_discharge; }; struct dsd_555_mstbl_context @@ -127,6 +133,12 @@ struct dsd_ls624_context #define DSD_555_ASTBL__C (*(node->input[3])) #define DSD_555_ASTBL__CTRLV (*(node->input[4])) +/* charge/discharge constants */ +#define DSD_555_ASTBL_T_RC_BLEED (DEFAULT_555_CAP_BLEED * DSD_555_ASTBL__C) +/* Use quick charge if specified. */ +#define DSD_555_ASTBL_T_RC_CHARGE ((DSD_555_ASTBL__R1 + ((info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) ? 0 : DSD_555_ASTBL__R2)) * DSD_555_ASTBL__C) +#define DSD_555_ASTBL_T_RC_DISCHARGE (DSD_555_ASTBL__R2 * DSD_555_ASTBL__C) + static void dsd_555_astbl_step(node_description *node) { const discrete_555_desc *info = node->custom; @@ -139,7 +151,8 @@ static void dsd_555_astbl_step(node_description *node) double t_rc = 0; /* RC time constant */ double v_cap = context->cap_voltage; /* Current voltage on capacitor, before dt */ double v_cap_next = 0; /* Voltage on capacitor, after dt */ - double v_charge; + double v_charge, exponent; + int update_exponent, update_t_rc; if(DSD_555_ASTBL__RESET) { @@ -217,6 +230,8 @@ static void dsd_555_astbl_step(node_description *node) else { /* Keep looping until all toggling in time sample is used up. */ + update_t_rc = context->has_rc_nodes; + update_exponent = update_t_rc; do { if (context->flip_flop) @@ -225,16 +240,28 @@ static void dsd_555_astbl_step(node_description *node) { /* Oscillation disabled because there is no longer any charge resistor. */ /* Bleed the cap due to circuit losses. */ - t_rc = DEFAULT_555_CAP_BLEED * DSD_555_ASTBL__C; - v_cap_next = v_cap - (v_cap * (1.0 - exp(-(dt / t_rc )))); + if (update_exponent) + { + t_rc = DSD_555_ASTBL_T_RC_BLEED; + exponent = 1.0 - exp(-(dt / t_rc)); + } + else + exponent = context->exp_bleed; + v_cap_next = v_cap - (v_cap * exponent); dt = 0; } else { /* Charging */ - /* Use quick charge if specified. */ - t_rc = (DSD_555_ASTBL__R1 + ((info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) ? 0 : DSD_555_ASTBL__R2)) * DSD_555_ASTBL__C; - v_cap_next = v_cap + ((v_charge - v_cap) * (1.0 - exp(-(dt / t_rc )))); + if (update_t_rc) + t_rc = DSD_555_ASTBL_T_RC_CHARGE; + else + t_rc = context->t_rc_charge; + if (update_exponent) + exponent = 1.0 - exp(-(dt / t_rc )); + else + exponent = context->exp_charge; + v_cap_next = v_cap + ((v_charge - v_cap) * exponent); dt = 0; /* has it charged past upper limit? */ @@ -246,6 +273,7 @@ static void dsd_555_astbl_step(node_description *node) v_cap = context->threshold; context->flip_flop = 0; count_f++; + update_exponent = 1; } } } @@ -254,8 +282,15 @@ static void dsd_555_astbl_step(node_description *node) /* Discharging */ if(DSD_555_ASTBL__R2 != 0) { - t_rc = DSD_555_ASTBL__R2 * DSD_555_ASTBL__C; - v_cap_next = v_cap - (v_cap * (1 - exp(-(dt / t_rc )))); + if (update_t_rc) + t_rc = DSD_555_ASTBL_T_RC_DISCHARGE; + else + t_rc = context->t_rc_discharge; + if (update_exponent) + exponent = 1.0 - exp(-(dt / t_rc )); + else + exponent = context->exp_discharge; + v_cap_next = v_cap - (v_cap * exponent); dt = 0; } else @@ -268,12 +303,12 @@ static void dsd_555_astbl_step(node_description *node) if (v_cap_next <= context->trigger) { /* calculate the overshoot time */ - if (dt == 0) - dt = t_rc * log(1.0 / (1.0 - ((context->trigger - v_cap_next) / v_cap))); + dt = t_rc * log(1.0 / (1.0 - ((context->trigger - v_cap_next) / v_cap))); x_time = dt; v_cap = context->trigger; context->flip_flop = 1; count_r++; + update_exponent = 1; } } } while(dt); @@ -324,6 +359,9 @@ static void dsd_555_astbl_reset(node_description *node) struct dsd_555_astbl_context *context = node->context; node_description *v_charge_node; + double neg_dt = 0.0 - discrete_current_context->sample_time; + double t_rc; + context->use_ctrlv = (node->input_is_node >> 4) & 1; context->output_type = info->options & DISC_555_OUT_MASK; @@ -355,6 +393,22 @@ static void dsd_555_astbl_reset(node_description *node) context->trigger = info->v_pos / 3.0; } + /* optimization if none of the values are nodes */ + context->has_rc_nodes = 0; + if (node->input_is_node & 0x0e) + context->has_rc_nodes = 1; + else + { + t_rc = DSD_555_ASTBL_T_RC_BLEED; + context->exp_bleed = 1.0 - exp(neg_dt / t_rc); + t_rc = DSD_555_ASTBL_T_RC_CHARGE; + context->exp_charge = 1.0 - exp(neg_dt / t_rc); + context->t_rc_charge = t_rc; + t_rc = DSD_555_ASTBL_T_RC_DISCHARGE; + context->exp_discharge = 1.0 - exp(neg_dt / t_rc); + context->t_rc_discharge = t_rc; + } + context->output_is_ac = info->options & DISC_555_OUT_AC; /* Calculate DC shift needed to make squarewave waveform AC */ context->ac_shift = context->output_is_ac ? -context->v_out_high / 2.0 : 0; diff --git a/src/emu/sound/disc_flt.c b/src/emu/sound/disc_flt.c index 81def840584..37280859fdf 100644 --- a/src/emu/sound/disc_flt.c +++ b/src/emu/sound/disc_flt.c @@ -103,19 +103,17 @@ struct dst_rcfilter_sw_context struct dst_rcintegrate_context { - int state; - double t; /* time */ - double f; /* RCINTEGRATE */ - double R1; /* RCINTEGRATE */ - double R2; /* RCINTEGRATE */ - double R3; /* RCINTEGRATE */ - double C; /* RCINTEGRATE */ - double vCap; /* RCDISC_MOD */ - double vCE; /* RCINTEGRATE */ - double exponent0; - double exponent1; - double exp_exponent0;/* RCINTEGRATE */ - double exp_exponent1;/* RCINTEGRATE */ + int type; + double gain_r1_r2; + double f; /* r2,r3 gain */ + double vCap; + double vCE; + double exponent0; + double exponent1; + double exp_exponent0; + double exp_exponent1; + double c_exp0; + double c_exp1; }; /************************************************************************ @@ -1186,40 +1184,40 @@ static void dst_rcintegrate_step(node_description *node) struct dst_rcintegrate_context *context = node->context; double diff, u, iQ, iQc, iC, RG, vE; - double dt, vP; + double vP; if(DST_RCINTEGRATE__ENABLE) { u = DST_RCINTEGRATE__IN1; vP = DST_RCINTEGRATE__VP; - dt = discrete_current_context->sample_time; - if ( u-0.7 < context->vCap*context->R2/(context->R1+context->R2)) + + if ( u - 0.7 < context->vCap * context->gain_r1_r2) { /* discharge .... */ - diff = 0.0 - context->vCap; - iC = 0.0 - context->C / context->exponent1 * diff * context->exp_exponent1; /* iC */ - diff = diff - (diff * context->exp_exponent1); + diff = 0.0 - context->vCap; + iC = 0.0 - context->c_exp1 * diff; /* iC */ + diff -= diff * context->exp_exponent1; context->vCap += diff; iQ = 0; - vE = context->vCap*context->R2/(context->R1+context->R2); - RG = vE/(-iC); + vE = context->vCap * context->gain_r1_r2; + RG = vE / (-iC); } else { /* charging */ - diff = (vP - context->vCE) * context->f - context->vCap; - iC = 0.0 - context->C / context->exponent0 * diff * context->exp_exponent0; /* iC */ - diff = diff - (diff * context->exp_exponent0); + diff = (vP - context->vCE) * context->f - context->vCap; + iC = 0.0 - context->c_exp0 * diff; /* iC */ + diff -= diff * context->exp_exponent0; context->vCap += diff; - iQ = iC + (iC * context->R1 + context->vCap) / context->R2; - RG = (vP - context->vCE)/iQ; - vE = (RG - context->R3) / RG * (vP - context->vCE); + iQ = iC + (iC * DST_RCINTEGRATE__R1 + context->vCap) / DST_RCINTEGRATE__R2; + RG = (vP - context->vCE) / iQ; + vE = (RG - DST_RCINTEGRATE__R3) / RG * (vP - context->vCE); } u = DST_RCINTEGRATE__IN1; - if (u > 0.7+vE) - vE = u-0.7; + if (u > 0.7 + vE) + vE = u - 0.7; iQc = EM_IC(u - vE); context->vCE = MIN(vP - 0.1, vP - RG * iQc); @@ -1229,9 +1227,9 @@ static void dst_rcintegrate_step(node_description *node) */ context->vCE = MAX(context->vCE, 0.1 ); - context->vCE = 0.1 * context->vCE + 0.9 * (vP - vE - iQ * context->R3); + context->vCE = 0.1 * context->vCE + 0.9 * (vP - vE - iQ * DST_RCINTEGRATE__R3); - switch (context->state) + switch (context->type) { case DISC_RC_INTEGRATE_TYPE1: node->output[0] = context->vCap; @@ -1240,7 +1238,7 @@ static void dst_rcintegrate_step(node_description *node) node->output[0] = vE; break; case DISC_RC_INTEGRATE_TYPE3: - node->output[0] = MAX(0, vP - iQ * context->R3); + node->output[0] = MAX(0, vP - iQ * DST_RCINTEGRATE__R3); break; } } @@ -1256,24 +1254,25 @@ static void dst_rcintegrate_reset(node_description *node) double r; double dt = discrete_current_context->sample_time; - node->output[0]=0; - - context->state = DST_RCINTEGRATE__TYPE; - context->R1 = DST_RCINTEGRATE__R1; - context->R2 = DST_RCINTEGRATE__R2; - context->R3 = DST_RCINTEGRATE__R3; - context->C = DST_RCINTEGRATE__C; + context->type = DST_RCINTEGRATE__TYPE; context->vCap = 0; context->vCE = 0; - r = context->R1 / context->R2 * context->R3 + context->R1 + context->R3; + /* pre-calculate fixed values */ + context->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; - context->f = DST_RCINTEGRATE__R2/(DST_RCINTEGRATE__R2+DST_RCINTEGRATE__R3); + context->f = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R3, DST_RCINTEGRATE__R2); context->exponent0 = -1.0 * r * context->f * DST_RCINTEGRATE__C; context->exponent1 = -1.0 * (DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R2) * DST_RCINTEGRATE__C; context->exp_exponent0 = exp(dt / context->exponent0); context->exp_exponent1 = exp(dt / context->exponent1); + context->c_exp0 = DST_RCINTEGRATE__C / context->exponent0 * context->exp_exponent0; + context->c_exp1 = DST_RCINTEGRATE__C / context->exponent1 * context->exp_exponent1; + + node->output[0] = 0; } diff --git a/src/emu/sound/discrete.h b/src/emu/sound/discrete.h index e6a50e4b5b4..7df1941e85f 100644 --- a/src/emu/sound/discrete.h +++ b/src/emu/sound/discrete.h @@ -206,6 +206,7 @@ * DISCRETE_SQUAREWAVE2(NODE,ENAB,AMPL,T_OFF,T_ON,BIAS,TSHIFT) * DISCRETE_TRIANGLEWAVE(NODE,ENAB,FREQ,AMP,BIAS,PHASE) * + * DISCRETE_INVERTER_OSC(NODE,ENAB,MOD,RCHARGE,RP,C,R2,INFO) * DISCRETE_OP_AMP_OSCILLATOR(NODE,ENAB,INFO) * DISCRETE_OP_AMP_VCO1(NODE,ENAB,VMOD1,INFO) * DISCRETE_OP_AMP_VCO2(NODE,ENAB,VMOD1,VMOD2,INFO) |