mirror of
https://github.com/holub/mame
synced 2025-06-30 16:00:01 +03:00
Optimized DISCRETE_555_CC
Fixed bug in my recent DISCRETE_MIXER update. Note: the DISCRETE_MIXER bug caused most of the speed increase of its optimization and caused some games to crash. Donkey Kong is now at 14% faster on my machine then when I started. Better then nothing.
This commit is contained in:
parent
c3f7d110df
commit
d900cdd023
@ -73,6 +73,16 @@ struct dsd_555_cc_context
|
||||
double trigger;
|
||||
double v_out_high; /* Logic 1 voltage level */
|
||||
double v_cc_source;
|
||||
int has_rc_nodes;
|
||||
double exp_bleed;
|
||||
double exp_charge;
|
||||
double exp_discharge;
|
||||
double exp_discharge_01;
|
||||
double exp_discharge_no_i;
|
||||
double t_rc_charge;
|
||||
double t_rc_discharge;
|
||||
double t_rc_discharge_01;
|
||||
double t_rc_discharge_no_i;
|
||||
};
|
||||
|
||||
struct dsd_555_vco1_context
|
||||
@ -133,6 +143,9 @@ struct dsd_ls624_context
|
||||
#define DSD_555_ASTBL__C (*(node->input[3]))
|
||||
#define DSD_555_ASTBL__CTRLV (*(node->input[4]))
|
||||
|
||||
/* bit mask of the above RC inputs */
|
||||
#define DSD_555_ASTBL_RC_MASK 0x0e
|
||||
|
||||
/* charge/discharge constants */
|
||||
#define DSD_555_ASTBL_T_RC_BLEED (DEFAULT_555_CAP_BLEED * DSD_555_ASTBL__C)
|
||||
/* Use quick charge if specified. */
|
||||
@ -399,7 +412,7 @@ static void dsd_555_astbl_reset(node_description *node)
|
||||
|
||||
/* optimization if none of the values are nodes */
|
||||
context->has_rc_nodes = 0;
|
||||
if (node->input_is_node & 0x0e)
|
||||
if (node->input_is_node & DSD_555_ASTBL_RC_MASK)
|
||||
context->has_rc_nodes = 1;
|
||||
else
|
||||
{
|
||||
@ -586,6 +599,17 @@ static void dsd_555_mstbl_reset(node_description *node)
|
||||
#define DSD_555_CC__RGND (*(node->input[5]))
|
||||
#define DSD_555_CC__RDIS (*(node->input[6]))
|
||||
|
||||
/* bit mask of the above RC inputs not including DSD_555_CC__R */
|
||||
#define DSD_555_CC_RC_MASK 0x78
|
||||
|
||||
/* charge/discharge constants */
|
||||
#define DSD_555_CC_T_RC_BLEED (DEFAULT_555_CAP_BLEED * DSD_555_CC__C)
|
||||
#define DSD_555_CC_T_RC_DISCHARGE_01 (DSD_555_CC__RDIS * DSD_555_CC__C)
|
||||
#define DSD_555_CC_T_RC_DISCHARGE_NO_I (DSD_555_CC__RGND * DSD_555_CC__C)
|
||||
#define DSD_555_CC_T_RC_CHARGE (r_charge * DSD_555_CC__C)
|
||||
#define DSD_555_CC_T_RC_DISCHARGE (r_discharge * DSD_555_CC__C)
|
||||
|
||||
|
||||
static void dsd_555_cc_step(node_description *node)
|
||||
{
|
||||
const discrete_555_cc_desc *info = node->custom;
|
||||
@ -606,6 +630,8 @@ static void dsd_555_cc_step(node_description *node)
|
||||
double v_cap_next = 0; /* Voltage on capacitor, after dt */
|
||||
double v_vcharge_limit; /* vIn and the junction voltage limit the max charging voltage from i */
|
||||
double r_temp; /* play thing */
|
||||
double exponent;
|
||||
int update_exponent, update_t_rc;
|
||||
|
||||
|
||||
if (DSD_555_CC__RESET)
|
||||
@ -629,46 +655,50 @@ static void dsd_555_cc_step(node_description *node)
|
||||
vi = i * DSD_555_CC__RDIS;
|
||||
}
|
||||
else
|
||||
switch (context->type) /* see dsd_555_cc_reset for descriptions */
|
||||
{
|
||||
case 1:
|
||||
r_discharge = DSD_555_CC__RDIS;
|
||||
case 0:
|
||||
break;
|
||||
case 3:
|
||||
r_discharge = (DSD_555_CC__RDIS * DSD_555_CC__RGND) / (DSD_555_CC__RDIS + DSD_555_CC__RGND);
|
||||
case 2:
|
||||
r_charge = DSD_555_CC__RGND;
|
||||
vi = i * r_charge;
|
||||
break;
|
||||
case 4:
|
||||
r_charge = DSD_555_CC__RBIAS;
|
||||
vi = i * r_charge;
|
||||
v_bias = info->v_pos;
|
||||
break;
|
||||
case 5:
|
||||
r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
|
||||
vi = i * DSD_555_CC__RBIAS;
|
||||
v_bias = info->v_pos;
|
||||
r_discharge = DSD_555_CC__RDIS;
|
||||
break;
|
||||
case 6:
|
||||
r_charge = (DSD_555_CC__RBIAS * DSD_555_CC__RGND) / (DSD_555_CC__RBIAS + DSD_555_CC__RGND);
|
||||
vi = i * r_charge;
|
||||
v_bias = info->v_pos * (DSD_555_CC__RGND / (DSD_555_CC__RBIAS + DSD_555_CC__RGND));
|
||||
break;
|
||||
case 7:
|
||||
r_temp = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
|
||||
r_charge = (r_temp * DSD_555_CC__RGND) / (r_temp + DSD_555_CC__RGND);
|
||||
r_temp += DSD_555_CC__RGND;
|
||||
r_temp = DSD_555_CC__RGND / r_temp; /* now has voltage divider ratio, not resistance */
|
||||
vi = i * DSD_555_CC__RBIAS * r_temp;
|
||||
v_bias = info->v_pos * r_temp;
|
||||
r_discharge = (DSD_555_CC__RGND * DSD_555_CC__RDIS) / (DSD_555_CC__RGND + DSD_555_CC__RDIS);
|
||||
break;
|
||||
switch (context->type) /* see dsd_555_cc_reset for descriptions */
|
||||
{
|
||||
case 1:
|
||||
r_discharge = DSD_555_CC__RDIS;
|
||||
case 0:
|
||||
break;
|
||||
case 3:
|
||||
r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
|
||||
case 2:
|
||||
r_charge = DSD_555_CC__RGND;
|
||||
vi = i * r_charge;
|
||||
break;
|
||||
case 4:
|
||||
r_charge = DSD_555_CC__RBIAS;
|
||||
vi = i * r_charge;
|
||||
v_bias = info->v_pos;
|
||||
break;
|
||||
case 5:
|
||||
r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
|
||||
vi = i * DSD_555_CC__RBIAS;
|
||||
v_bias = info->v_pos;
|
||||
r_discharge = DSD_555_CC__RDIS;
|
||||
break;
|
||||
case 6:
|
||||
r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
|
||||
vi = i * r_charge;
|
||||
v_bias = info->v_pos * RES_VOLTAGE_DIVIDER(DSD_555_CC__RGND, DSD_555_CC__RBIAS);
|
||||
break;
|
||||
case 7:
|
||||
r_temp = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
|
||||
r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
|
||||
r_temp += DSD_555_CC__RGND;
|
||||
r_temp = DSD_555_CC__RGND / r_temp; /* now has voltage divider ratio, not resistance */
|
||||
vi = i * DSD_555_CC__RBIAS * r_temp;
|
||||
v_bias = info->v_pos * r_temp;
|
||||
r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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->type <= 1)
|
||||
@ -681,8 +711,14 @@ static void dsd_555_cc_step(node_description *node)
|
||||
/* No charging current, so we have to discharge the cap
|
||||
* due to cap and circuit losses.
|
||||
*/
|
||||
t_rc = DEFAULT_555_CAP_BLEED * DSD_555_CC__C;
|
||||
v_cap_next = v_cap - (v_cap * (1.0 - exp(-(dt / t_rc ))));
|
||||
if (update_exponent)
|
||||
{
|
||||
t_rc = DSD_555_CC_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
|
||||
@ -707,13 +743,21 @@ static void dsd_555_cc_step(node_description *node)
|
||||
v_cap = context->threshold;
|
||||
context->flip_flop = 0;
|
||||
count_f++;
|
||||
update_exponent = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (DSD_555_CC__RDIS)
|
||||
else if (DSD_555_CC__RDIS != 0)
|
||||
{
|
||||
/* Discharging */
|
||||
t_rc = DSD_555_CC__RDIS * DSD_555_CC__C;
|
||||
if (update_t_rc)
|
||||
t_rc = DSD_555_CC_T_RC_DISCHARGE_01;
|
||||
else
|
||||
t_rc = context->t_rc_discharge_01;
|
||||
if (update_exponent)
|
||||
exponent = 1.0 - exp(-(dt / t_rc));
|
||||
else
|
||||
exponent = context->exp_discharge_01;
|
||||
|
||||
if (info->options & DISCRETE_555_CC_TO_CAP)
|
||||
{
|
||||
@ -722,11 +766,11 @@ static void dsd_555_cc_step(node_description *node)
|
||||
/* If the cap voltage is past the current source charging limit
|
||||
* then only the bias voltage will charge the cap. */
|
||||
v = (v_cap < v_vcharge_limit) ? vi : v_vcharge_limit;
|
||||
v_cap_next = v_cap + ((v - v_cap) * (1.0 - exp(-(dt / t_rc ))));
|
||||
v_cap_next = v_cap + ((v - v_cap) * exponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
v_cap_next = v_cap - (v_cap * (1.0 - exp(-(dt / t_rc ))));
|
||||
v_cap_next = v_cap - (v_cap * exponent);
|
||||
}
|
||||
|
||||
dt = 0;
|
||||
@ -738,6 +782,7 @@ static void dsd_555_cc_step(node_description *node)
|
||||
v_cap = context->trigger;
|
||||
context->flip_flop = 1;
|
||||
count_r++;
|
||||
update_exponent = 1;
|
||||
}
|
||||
}
|
||||
else /* Immediate discharge. No change in dt. */
|
||||
@ -758,8 +803,16 @@ static void dsd_555_cc_step(node_description *node)
|
||||
/* No charging current, so we have to discharge the cap
|
||||
* due to rGnd.
|
||||
*/
|
||||
t_rc = DSD_555_CC__RGND * DSD_555_CC__C;
|
||||
v_cap_next = v_cap - (v_cap * (1.0 - exp(-(dt / t_rc ))));
|
||||
if (update_t_rc)
|
||||
t_rc = DSD_555_CC_T_RC_DISCHARGE_NO_I;
|
||||
else
|
||||
t_rc = context->t_rc_discharge_no_i;
|
||||
if (update_exponent)
|
||||
exponent = 1.0 - exp(-(dt / t_rc));
|
||||
else
|
||||
exponent = context->exp_discharge_no_i;
|
||||
|
||||
v_cap_next = v_cap - (v_cap * exponent);
|
||||
dt = 0;
|
||||
}
|
||||
else
|
||||
@ -771,8 +824,16 @@ static void dsd_555_cc_step(node_description *node)
|
||||
if (v_cap < v_vcharge_limit) v += vi;
|
||||
else if (context->type <= 3) v = v_vcharge_limit;
|
||||
|
||||
t_rc = r_charge * DSD_555_CC__C;
|
||||
v_cap_next = v_cap + ((v - v_cap) * (1.0 - exp(-(dt / t_rc ))));
|
||||
if (update_t_rc)
|
||||
t_rc = DSD_555_CC_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 - v_cap) * exponent);
|
||||
dt = 0;
|
||||
|
||||
/* has it charged past upper limit? */
|
||||
@ -784,14 +845,23 @@ static void dsd_555_cc_step(node_description *node)
|
||||
v_cap = context->threshold;
|
||||
context->flip_flop = 0;
|
||||
count_f++;
|
||||
update_exponent = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Discharging */
|
||||
if (r_discharge)
|
||||
{
|
||||
t_rc = r_discharge * DSD_555_CC__C;
|
||||
v_cap_next = v_cap - (v_cap * (1.0 - exp(-(dt / t_rc ))));
|
||||
if (update_t_rc)
|
||||
t_rc = DSD_555_CC_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;
|
||||
|
||||
/* has it discharged past lower limit? */
|
||||
@ -803,6 +873,7 @@ static void dsd_555_cc_step(node_description *node)
|
||||
v_cap = context->trigger;
|
||||
context->flip_flop = 1;
|
||||
count_r++;
|
||||
update_exponent = 1;
|
||||
}
|
||||
}
|
||||
else /* Immediate discharge. No change in dt. */
|
||||
@ -864,6 +935,9 @@ static void dsd_555_cc_reset(node_description *node)
|
||||
const discrete_555_cc_desc *info = node->custom;
|
||||
struct dsd_555_cc_context *context = node->context;
|
||||
|
||||
double neg_dt = 0.0 - discrete_current_context->sample_time;
|
||||
double r_temp, r_discharge = 0, r_charge = 0, t_rc;
|
||||
|
||||
context->flip_flop = 1;
|
||||
context->cap_voltage = 0;
|
||||
|
||||
@ -884,9 +958,63 @@ static void dsd_555_cc_reset(node_description *node)
|
||||
/* There are 8 different types of basic oscillators
|
||||
* depending on the resistors used. We will determine
|
||||
* the type of circuit at reset, because the ciruit type
|
||||
* is constant.
|
||||
* is constant. See Below.
|
||||
*/
|
||||
context->type = (DSD_555_CC__RDIS > 0) | ((DSD_555_CC__RGND > 0) << 1) | ((DSD_555_CC__RBIAS > 0) << 2);
|
||||
|
||||
/* optimization if none of the values are nodes */
|
||||
context->has_rc_nodes = 0;
|
||||
if (node->input_is_node & DSD_555_CC_RC_MASK)
|
||||
context->has_rc_nodes = 1;
|
||||
else
|
||||
{
|
||||
switch (context->type) /* see dsd_555_cc_reset for descriptions */
|
||||
{
|
||||
case 1:
|
||||
r_discharge = DSD_555_CC__RDIS;
|
||||
case 0:
|
||||
break;
|
||||
case 3:
|
||||
r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
|
||||
case 2:
|
||||
r_charge = DSD_555_CC__RGND;
|
||||
break;
|
||||
case 4:
|
||||
r_charge = DSD_555_CC__RBIAS;
|
||||
break;
|
||||
case 5:
|
||||
r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
|
||||
r_discharge = DSD_555_CC__RDIS;
|
||||
break;
|
||||
case 6:
|
||||
r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
|
||||
break;
|
||||
case 7:
|
||||
r_temp = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
|
||||
r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
|
||||
r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
|
||||
break;
|
||||
}
|
||||
|
||||
t_rc = DSD_555_CC_T_RC_BLEED;
|
||||
context->exp_bleed = 1.0 - exp(neg_dt / t_rc);
|
||||
t_rc = DSD_555_CC_T_RC_DISCHARGE_01;
|
||||
context->exp_discharge_01 = 1.0 - exp(neg_dt / t_rc);
|
||||
context->t_rc_discharge_01 = t_rc;
|
||||
t_rc = DSD_555_CC_T_RC_DISCHARGE_NO_I;
|
||||
context->exp_discharge_no_i = 1.0 - exp(neg_dt / t_rc);
|
||||
context->t_rc_discharge_no_i = t_rc;
|
||||
t_rc = DSD_555_CC_T_RC_CHARGE;
|
||||
context->exp_charge = 1.0 - exp(neg_dt / t_rc);
|
||||
context->t_rc_charge = t_rc;
|
||||
t_rc = DSD_555_CC_T_RC_DISCHARGE;
|
||||
context->exp_discharge = 1.0 - exp(neg_dt / t_rc);
|
||||
context->t_rc_discharge = t_rc;
|
||||
}
|
||||
|
||||
/* Step to set the output */
|
||||
dsd_555_cc_step(node);
|
||||
|
||||
/*
|
||||
* TYPES:
|
||||
* Note: These are equivalent circuits shown without the 555 circuitry.
|
||||
@ -1019,9 +1147,6 @@ static void dsd_555_cc_reset(node_description *node)
|
||||
* | | | v = vi = i * rGnd
|
||||
* gnd gnd discharge Rc = rDischarge
|
||||
*/
|
||||
|
||||
/* Step to set the output */
|
||||
dsd_555_cc_step(node);
|
||||
}
|
||||
|
||||
|
||||
|
@ -270,7 +270,7 @@ static void dst_clamp_step(node_description *node)
|
||||
* Mar 2004, D Renaud.
|
||||
************************************************************************/
|
||||
#define DST_DAC_R1__ENABLE (*(node->input[0]))
|
||||
#define DST_DAC_R1__DATA (int)(*(node->input[1]))
|
||||
#define DST_DAC_R1__DATA (*(node->input[1]))
|
||||
#define DST_DAC_R1__VON (*(node->input[2]))
|
||||
|
||||
static void dst_dac_r1_step(node_description *node)
|
||||
@ -283,7 +283,7 @@ static void dst_dac_r1_step(node_description *node)
|
||||
|
||||
i_total = context->i_bias;
|
||||
|
||||
data = (int)DST_DAC_R1__DATA;
|
||||
data = (int)DST_DAC_R1__DATA;
|
||||
x_time = DST_DAC_R1__DATA - data;
|
||||
|
||||
if (DST_DAC_R1__ENABLE)
|
||||
@ -315,6 +315,7 @@ static void dst_dac_r1_step(node_description *node)
|
||||
}
|
||||
|
||||
v = i_total * context->r_total;
|
||||
context->last_data = data;
|
||||
|
||||
/* Filter if needed, else just output voltage */
|
||||
node->output[0] = info->cFilter ? node->output[0] + ((v - node->output[0]) * context->exponent) : v;
|
||||
@ -365,7 +366,7 @@ static void dst_dac_r1_reset(node_description *node)
|
||||
context->r_total = 0;
|
||||
for(bit = 0; bit < info->ladderLength; bit++)
|
||||
{
|
||||
if (info->r[bit])
|
||||
if (info->r[bit] != 0)
|
||||
context->r_total += 1.0 / info->r[bit];
|
||||
}
|
||||
if (info->rBias) context->r_total += 1.0 / info->rBias;
|
||||
@ -1143,10 +1144,10 @@ static void dst_mixer_reset(node_description *node)
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
r_node = discrete_find_node(NULL, info->r_node[bit]);
|
||||
if (r_node)
|
||||
if (r_node != NULL)
|
||||
{
|
||||
context->r_node[bit] = &(r_node->output[NODE_CHILD_NODE_NUM(info->r_node[bit])]);
|
||||
context->r_node_bit_flag |= bit << 1;
|
||||
context->r_node_bit_flag |= 1 << bit;
|
||||
}
|
||||
else
|
||||
context->r_node[bit] = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user