mirror of
https://github.com/holub/mame
synced 2025-06-30 07:58:56 +03:00
Optimized DISCRETE_RCINTEGRATE and DISCRETE_555_ASTABLE.
This commit is contained in:
parent
e5fbac92cf
commit
ae10d3987a
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
context->f = DST_RCINTEGRATE__R2/(DST_RCINTEGRATE__R2+DST_RCINTEGRATE__R3);
|
||||
r = DST_RCINTEGRATE__R1 / DST_RCINTEGRATE__R2 * DST_RCINTEGRATE__R3 + DST_RCINTEGRATE__R1 + 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user