mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +03:00
netlist: Document alternative approach to CD4016. (nw)
The CD4016 is an analog switch IC. Document an experimental approach to implement the analog switch as a 3 terminal element which is completely being dealt with as part as the linear system. The intention was to improve convergence when the switch is in a feedback loop. One example are two-opamp tridiagonal wave generators. Unfortunately the approach did not work out and in addition was performing far worse than the net-separating original code. Also updated comment in nld_generic_models.h.
This commit is contained in:
parent
5cd3a44607
commit
1af4b9f870
@ -14,7 +14,9 @@
|
|||||||
//
|
//
|
||||||
// Set to 0 to use a linearized diode model in the range exceeding
|
// Set to 0 to use a linearized diode model in the range exceeding
|
||||||
// maximum dissipation. The intention is to have a faster
|
// maximum dissipation. The intention is to have a faster
|
||||||
// convergence but this yet not really is observable
|
// convergence. On selected circuits (LM3900 trapezoidal) this is
|
||||||
|
// observable and has a 10% impact.
|
||||||
|
// FIXME: More research needed
|
||||||
//
|
//
|
||||||
|
|
||||||
#define USE_TEXTBOOK_DIODE (1)
|
#define USE_TEXTBOOK_DIODE (1)
|
||||||
|
@ -11,6 +11,20 @@
|
|||||||
#include "netlist/solver/nld_solver.h"
|
#include "netlist/solver/nld_solver.h"
|
||||||
#include "nlid_system.h"
|
#include "nlid_system.h"
|
||||||
|
|
||||||
|
// This is an experimental approach to implement the analog switch.
|
||||||
|
// This will make the switch a 3 terminal element which is completely
|
||||||
|
// being dealt with as part as the linear system.
|
||||||
|
//
|
||||||
|
// The intention was to improve convergence when the switch is in a feedback
|
||||||
|
// loop. One example are two-opamp tridiagonal wave generators.
|
||||||
|
// Unfortunately the approach did not work out and in addition was performing
|
||||||
|
// far worse than the net-separating original code.
|
||||||
|
//
|
||||||
|
// FIXME: The transfer function needs review
|
||||||
|
//
|
||||||
|
|
||||||
|
#define USE_DYNAMIC_APPROACH (0)
|
||||||
|
|
||||||
namespace netlist
|
namespace netlist
|
||||||
{
|
{
|
||||||
namespace devices
|
namespace devices
|
||||||
@ -27,36 +41,22 @@ namespace netlist
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NETLIB_RESETI();
|
NETLIB_RESETI()
|
||||||
NETLIB_UPDATEI();
|
|
||||||
|
|
||||||
private:
|
|
||||||
nld_power_pins m_supply;
|
|
||||||
analog::NETLIB_SUB(R_base) m_R;
|
|
||||||
|
|
||||||
analog_input_t m_control;
|
|
||||||
param_fp_t m_base_r;
|
|
||||||
state_var<bool> m_last;
|
|
||||||
};
|
|
||||||
|
|
||||||
NETLIB_RESET(CD4066_GATE)
|
|
||||||
{
|
{
|
||||||
// Start in off condition
|
// Start in off condition
|
||||||
// FIXME: is ROFF correct?
|
// FIXME: is ROFF correct?
|
||||||
m_R.set_R(plib::reciprocal(exec().gmin()));
|
m_R.set_R(plib::reciprocal(exec().gmin()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NETLIB_UPDATE(CD4066_GATE)
|
NETLIB_UPDATEI()
|
||||||
{
|
{
|
||||||
nl_fptype sup = (m_supply.VCC().Q_Analog() - m_supply.GND().Q_Analog());
|
nl_fptype sup = (m_supply.VCC().Q_Analog() - m_supply.GND().Q_Analog());
|
||||||
nl_fptype low = nlconst::magic(0.45) * sup;
|
|
||||||
nl_fptype high = nlconst::magic(0.55) * sup;
|
|
||||||
nl_fptype in = m_control() - m_supply.GND().Q_Analog();
|
nl_fptype in = m_control() - m_supply.GND().Q_Analog();
|
||||||
nl_fptype rON = m_base_r() * nlconst::magic(5.0) / sup;
|
nl_fptype rON = m_base_r() * nlconst::magic(5.0) / sup;
|
||||||
nl_fptype R = -nlconst::one();
|
nl_fptype R = -nlconst::one();
|
||||||
|
nl_fptype low = nlconst::magic(0.45) * sup;
|
||||||
|
nl_fptype high = nlconst::magic(0.55) * sup;
|
||||||
bool new_state(false);
|
bool new_state(false);
|
||||||
|
|
||||||
if (in < low)
|
if (in < low)
|
||||||
{
|
{
|
||||||
R = plib::reciprocal(exec().gmin());
|
R = plib::reciprocal(exec().gmin());
|
||||||
@ -66,7 +66,6 @@ namespace netlist
|
|||||||
R = rON;
|
R = rON;
|
||||||
new_state = true;
|
new_state = true;
|
||||||
}
|
}
|
||||||
//printf("%s %f %f %g\n", name().c_str(), sup, in, R);
|
|
||||||
if (R > nlconst::zero() && (m_last != new_state))
|
if (R > nlconst::zero() && (m_last != new_state))
|
||||||
{
|
{
|
||||||
m_last = new_state;
|
m_last = new_state;
|
||||||
@ -76,7 +75,76 @@ namespace netlist
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NETLIB_DEVICE_IMPL(CD4066_GATE, "CD4066_GATE", "")
|
private:
|
||||||
|
nld_power_pins m_supply;
|
||||||
|
analog::NETLIB_SUB(R_base) m_R;
|
||||||
|
analog_input_t m_control;
|
||||||
|
param_fp_t m_base_r;
|
||||||
|
state_var<bool> m_last;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
NETLIB_OBJECT(CD4066_GATE_DYNAMIC)
|
||||||
|
{
|
||||||
|
NETLIB_CONSTRUCTOR(CD4066_GATE_DYNAMIC)
|
||||||
|
NETLIB_FAMILY("CD4XXX")
|
||||||
|
, m_supply(*this, "VDD", "VSS")
|
||||||
|
, m_R(*this, "R", true)
|
||||||
|
, m_DUM1(*this, "_DUM1", true)
|
||||||
|
, m_DUM2(*this, "_DUM2", true)
|
||||||
|
, m_base_r(*this, "BASER", nlconst::magic(270.0))
|
||||||
|
, m_last(*this, "m_last", false)
|
||||||
|
{
|
||||||
|
register_subalias("CTL", m_DUM1.m_P); // Cathode
|
||||||
|
|
||||||
|
connect(m_DUM1.m_P, m_DUM2.m_P);
|
||||||
|
connect(m_DUM1.m_N, m_R.m_P);
|
||||||
|
connect(m_DUM2.m_N, m_R.m_N);
|
||||||
|
}
|
||||||
|
|
||||||
|
NETLIB_RESETI()
|
||||||
|
{
|
||||||
|
// Start in off condition
|
||||||
|
// FIXME: is ROFF correct?
|
||||||
|
}
|
||||||
|
|
||||||
|
NETLIB_UPDATEI()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NETLIB_UPDATE_TERMINALSI()
|
||||||
|
{
|
||||||
|
nl_fptype sup = (m_supply.VCC().Q_Analog() - m_supply.GND().Q_Analog());
|
||||||
|
nl_fptype in = m_DUM1.m_P.net().Q_Analog() - m_supply.GND().Q_Analog();
|
||||||
|
nl_fptype rON = m_base_r() * nlconst::magic(5.0) / sup;
|
||||||
|
nl_fptype R = std::exp(-(in / sup - 0.55) * 25.0) + rON;
|
||||||
|
nl_fptype G = plib::reciprocal(R);
|
||||||
|
// dI/dVin = (VR1-VR2)*(1.0/sup*b) * exp((Vin/sup-a) * b)
|
||||||
|
const auto dfdz = 25.0/(R*sup) * m_R.deltaV();
|
||||||
|
const auto Ieq = dfdz * in;
|
||||||
|
m_R.set_mat( G, -G, 0.0,
|
||||||
|
-G, G, 0.0);
|
||||||
|
//VIN VR1
|
||||||
|
m_DUM1.set_mat( 0.0, 0.0, 0.0, // IIN
|
||||||
|
dfdz, 0.0, Ieq); // IR1
|
||||||
|
m_DUM2.set_mat( 0.0, 0.0, 0.0, // IIN
|
||||||
|
-dfdz, 0.0, -Ieq); // IR2
|
||||||
|
}
|
||||||
|
NETLIB_IS_DYNAMIC(true)
|
||||||
|
|
||||||
|
private:
|
||||||
|
nld_power_pins m_supply;
|
||||||
|
analog::nld_twoterm m_R;
|
||||||
|
analog::nld_twoterm m_DUM1;
|
||||||
|
analog::nld_twoterm m_DUM2;
|
||||||
|
param_fp_t m_base_r;
|
||||||
|
state_var<bool> m_last;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !USE_DYNAMIC_APPROACH
|
||||||
|
NETLIB_DEVICE_IMPL(CD4066_GATE, "CD4066_GATE", "")
|
||||||
|
#else
|
||||||
|
NETLIB_DEVICE_IMPL_ALIAS(CD4066_GATE, CD4066_GATE_DYNAMIC, "CD4066_GATE", "")
|
||||||
|
#endif
|
||||||
} //namespace devices
|
} //namespace devices
|
||||||
} // namespace netlist
|
} // namespace netlist
|
||||||
|
Loading…
Reference in New Issue
Block a user