mirror of
https://github.com/holub/mame
synced 2025-06-05 12:26:35 +03:00
Fix indentation. (nw)
This commit is contained in:
parent
9534a0233c
commit
76b92133dd
@ -13,39 +13,39 @@
|
|||||||
|
|
||||||
namespace netlist
|
namespace netlist
|
||||||
{
|
{
|
||||||
namespace analog
|
namespace analog
|
||||||
{
|
|
||||||
|
|
||||||
class diode
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {}
|
|
||||||
diode(const nl_double Is, const nl_double n)
|
|
||||||
{
|
|
||||||
m_Is = Is;
|
|
||||||
m_VT = 0.0258 * n;
|
|
||||||
m_VT_inv = 1.0 / m_VT;
|
|
||||||
}
|
|
||||||
void set(const nl_double Is, const nl_double n)
|
|
||||||
{
|
|
||||||
m_Is = Is;
|
|
||||||
m_VT = 0.0258 * n;
|
|
||||||
m_VT_inv = 1.0 / m_VT;
|
|
||||||
}
|
|
||||||
nl_double I(const nl_double V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; }
|
|
||||||
nl_double g(const nl_double V) const { return m_Is * m_VT_inv * std::exp(V * m_VT_inv); }
|
|
||||||
nl_double V(const nl_double I) const { return std::log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
|
|
||||||
nl_double gI(const nl_double I) const { return m_VT_inv * (I + m_Is); }
|
|
||||||
|
|
||||||
private:
|
class diode
|
||||||
nl_double m_Is;
|
{
|
||||||
nl_double m_VT;
|
public:
|
||||||
nl_double m_VT_inv;
|
diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {}
|
||||||
};
|
diode(const nl_double Is, const nl_double n)
|
||||||
|
{
|
||||||
|
m_Is = Is;
|
||||||
|
m_VT = 0.0258 * n;
|
||||||
|
m_VT_inv = 1.0 / m_VT;
|
||||||
|
}
|
||||||
|
void set(const nl_double Is, const nl_double n)
|
||||||
|
{
|
||||||
|
m_Is = Is;
|
||||||
|
m_VT = 0.0258 * n;
|
||||||
|
m_VT_inv = 1.0 / m_VT;
|
||||||
|
}
|
||||||
|
nl_double I(const nl_double V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; }
|
||||||
|
nl_double g(const nl_double V) const { return m_Is * m_VT_inv * std::exp(V * m_VT_inv); }
|
||||||
|
nl_double V(const nl_double I) const { return std::log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
|
||||||
|
nl_double gI(const nl_double I) const { return m_VT_inv * (I + m_Is); }
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
private:
|
||||||
// nld_Q - Base classes
|
nl_double m_Is;
|
||||||
// -----------------------------------------------------------------------------
|
nl_double m_VT;
|
||||||
|
nl_double m_VT_inv;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// nld_Q - Base classes
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! Class representing the bjt model paramers.
|
/*! Class representing the bjt model paramers.
|
||||||
*
|
*
|
||||||
@ -124,341 +124,341 @@ private:
|
|||||||
|
|
||||||
// Have a common start for transistors
|
// Have a common start for transistors
|
||||||
|
|
||||||
NETLIB_OBJECT(Q)
|
NETLIB_OBJECT(Q)
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum q_type {
|
enum q_type {
|
||||||
BJT_NPN,
|
BJT_NPN,
|
||||||
BJT_PNP
|
BJT_PNP
|
||||||
|
};
|
||||||
|
|
||||||
|
NETLIB_CONSTRUCTOR(Q)
|
||||||
|
, m_model(*this, "MODEL", "NPN")
|
||||||
|
, m_qtype(BJT_NPN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NETLIB_IS_DYNAMIC(true)
|
||||||
|
|
||||||
|
//NETLIB_RESETI();
|
||||||
|
NETLIB_UPDATEI();
|
||||||
|
|
||||||
|
q_type qtype() const { return m_qtype; }
|
||||||
|
bool is_qtype(q_type atype) const { return m_qtype == atype; }
|
||||||
|
void set_qtype(q_type atype) { m_qtype = atype; }
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bjt_model_t m_model;
|
||||||
|
private:
|
||||||
|
q_type m_qtype;
|
||||||
};
|
};
|
||||||
|
|
||||||
NETLIB_CONSTRUCTOR(Q)
|
NETLIB_OBJECT_DERIVED(QBJT, Q)
|
||||||
, m_model(*this, "MODEL", "NPN")
|
|
||||||
, m_qtype(BJT_NPN)
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
|
NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
|
||||||
|
{ }
|
||||||
|
|
||||||
NETLIB_IS_DYNAMIC(true)
|
protected:
|
||||||
|
|
||||||
//NETLIB_RESETI();
|
private:
|
||||||
NETLIB_UPDATEI();
|
};
|
||||||
|
|
||||||
q_type qtype() const { return m_qtype; }
|
|
||||||
bool is_qtype(q_type atype) const { return m_qtype == atype; }
|
|
||||||
void set_qtype(q_type atype) { m_qtype = atype; }
|
|
||||||
protected:
|
|
||||||
|
|
||||||
bjt_model_t m_model;
|
|
||||||
private:
|
|
||||||
q_type m_qtype;
|
|
||||||
};
|
|
||||||
|
|
||||||
NETLIB_OBJECT_DERIVED(QBJT, Q)
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// nld_QBJT_switch
|
// nld_QBJT_switch
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* + - C
|
* + - C
|
||||||
* B ----VVV----+ |
|
* B ----VVV----+ |
|
||||||
* | |
|
* | |
|
||||||
* Rb Rc
|
* Rb Rc
|
||||||
* Rb Rc
|
* Rb Rc
|
||||||
* Rb Rc
|
* Rb Rc
|
||||||
* | |
|
* | |
|
||||||
* +----+----+
|
* +----+----+
|
||||||
* |
|
* |
|
||||||
* E
|
* E
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
|
NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
|
||||||
{
|
|
||||||
NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
|
|
||||||
, m_RB(*this, "m_RB", true)
|
|
||||||
, m_RC(*this, "m_RC", true)
|
|
||||||
, m_BC_dummy(*this, "m_BC", true)
|
|
||||||
, m_gB(1e-9)
|
|
||||||
, m_gC(1e-9)
|
|
||||||
, m_V(0.0)
|
|
||||||
, m_state_on(*this, "m_state_on", 0)
|
|
||||||
{
|
{
|
||||||
register_subalias("B", m_RB.m_P);
|
NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
|
||||||
register_subalias("E", m_RB.m_N);
|
, m_RB(*this, "m_RB", true)
|
||||||
register_subalias("C", m_RC.m_P);
|
, m_RC(*this, "m_RC", true)
|
||||||
//register_term("_E1", m_RC.m_N);
|
, m_BC_dummy(*this, "m_BC", true)
|
||||||
|
, m_gB(1e-9)
|
||||||
//register_term("_B1", m_BC_dummy.m_P);
|
, m_gC(1e-9)
|
||||||
//register_term("_C1", m_BC_dummy.m_N);
|
, m_V(0.0)
|
||||||
|
, m_state_on(*this, "m_state_on", 0)
|
||||||
connect(m_RB.m_N, m_RC.m_N);
|
|
||||||
|
|
||||||
connect(m_RB.m_P, m_BC_dummy.m_P);
|
|
||||||
connect(m_RC.m_P, m_BC_dummy.m_N);
|
|
||||||
}
|
|
||||||
|
|
||||||
NETLIB_RESETI();
|
|
||||||
NETLIB_UPDATEI();
|
|
||||||
NETLIB_UPDATE_PARAMI();
|
|
||||||
NETLIB_UPDATE_TERMINALSI();
|
|
||||||
|
|
||||||
private:
|
|
||||||
nld_twoterm m_RB;
|
|
||||||
nld_twoterm m_RC;
|
|
||||||
|
|
||||||
// FIXME: this is needed so we have all terminals belong to one net list
|
|
||||||
|
|
||||||
nld_twoterm m_BC_dummy;
|
|
||||||
|
|
||||||
nl_double m_gB; // base conductance / switch on
|
|
||||||
nl_double m_gC; // collector conductance / switch on
|
|
||||||
nl_double m_V; // internal voltage source
|
|
||||||
state_var<unsigned> m_state_on;
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// nld_QBJT_EB
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
|
|
||||||
, m_gD_BC(*this, "m_D_BC")
|
|
||||||
, m_gD_BE(*this, "m_D_BE")
|
|
||||||
, m_D_CB(*this, "m_D_CB", true)
|
|
||||||
, m_D_EB(*this, "m_D_EB", true)
|
|
||||||
, m_D_EC(*this, "m_D_EC", true)
|
|
||||||
, m_alpha_f(0)
|
|
||||||
, m_alpha_r(0)
|
|
||||||
{
|
|
||||||
register_subalias("E", m_D_EB.m_P); // Cathode
|
|
||||||
register_subalias("B", m_D_EB.m_N); // Anode
|
|
||||||
|
|
||||||
register_subalias("C", m_D_CB.m_P); // Cathode
|
|
||||||
|
|
||||||
connect(m_D_EB.m_P, m_D_EC.m_P);
|
|
||||||
connect(m_D_EB.m_N, m_D_CB.m_N);
|
|
||||||
connect(m_D_CB.m_P, m_D_EC.m_N);
|
|
||||||
|
|
||||||
if (m_model.m_CJE > 0.0)
|
|
||||||
{
|
{
|
||||||
create_and_register_subdevice("m_CJE", m_CJE);
|
register_subalias("B", m_RB.m_P);
|
||||||
connect("B", "m_CJE.1");
|
register_subalias("E", m_RB.m_N);
|
||||||
connect("E", "m_CJE.2");
|
register_subalias("C", m_RC.m_P);
|
||||||
|
//register_term("_E1", m_RC.m_N);
|
||||||
|
|
||||||
|
//register_term("_B1", m_BC_dummy.m_P);
|
||||||
|
//register_term("_C1", m_BC_dummy.m_N);
|
||||||
|
|
||||||
|
connect(m_RB.m_N, m_RC.m_N);
|
||||||
|
|
||||||
|
connect(m_RB.m_P, m_BC_dummy.m_P);
|
||||||
|
connect(m_RC.m_P, m_BC_dummy.m_N);
|
||||||
}
|
}
|
||||||
if (m_model.m_CJC > 0.0)
|
|
||||||
|
NETLIB_RESETI();
|
||||||
|
NETLIB_UPDATEI();
|
||||||
|
NETLIB_UPDATE_PARAMI();
|
||||||
|
NETLIB_UPDATE_TERMINALSI();
|
||||||
|
|
||||||
|
private:
|
||||||
|
nld_twoterm m_RB;
|
||||||
|
nld_twoterm m_RC;
|
||||||
|
|
||||||
|
// FIXME: this is needed so we have all terminals belong to one net list
|
||||||
|
|
||||||
|
nld_twoterm m_BC_dummy;
|
||||||
|
|
||||||
|
nl_double m_gB; // base conductance / switch on
|
||||||
|
nl_double m_gC; // collector conductance / switch on
|
||||||
|
nl_double m_V; // internal voltage source
|
||||||
|
state_var<unsigned> m_state_on;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// nld_QBJT_EB
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
|
||||||
|
, m_gD_BC(*this, "m_D_BC")
|
||||||
|
, m_gD_BE(*this, "m_D_BE")
|
||||||
|
, m_D_CB(*this, "m_D_CB", true)
|
||||||
|
, m_D_EB(*this, "m_D_EB", true)
|
||||||
|
, m_D_EC(*this, "m_D_EC", true)
|
||||||
|
, m_alpha_f(0)
|
||||||
|
, m_alpha_r(0)
|
||||||
{
|
{
|
||||||
create_and_register_subdevice("m_CJC", m_CJC);
|
register_subalias("E", m_D_EB.m_P); // Cathode
|
||||||
connect("B", "m_CJC.1");
|
register_subalias("B", m_D_EB.m_N); // Anode
|
||||||
connect("C", "m_CJC.2");
|
|
||||||
|
register_subalias("C", m_D_CB.m_P); // Cathode
|
||||||
|
|
||||||
|
connect(m_D_EB.m_P, m_D_EC.m_P);
|
||||||
|
connect(m_D_EB.m_N, m_D_CB.m_N);
|
||||||
|
connect(m_D_CB.m_P, m_D_EC.m_N);
|
||||||
|
|
||||||
|
if (m_model.m_CJE > 0.0)
|
||||||
|
{
|
||||||
|
create_and_register_subdevice("m_CJE", m_CJE);
|
||||||
|
connect("B", "m_CJE.1");
|
||||||
|
connect("E", "m_CJE.2");
|
||||||
|
}
|
||||||
|
if (m_model.m_CJC > 0.0)
|
||||||
|
{
|
||||||
|
create_and_register_subdevice("m_CJC", m_CJC);
|
||||||
|
connect("B", "m_CJC.1");
|
||||||
|
connect("C", "m_CJC.2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
NETLIB_RESETI();
|
||||||
|
NETLIB_UPDATEI();
|
||||||
|
NETLIB_UPDATE_PARAMI();
|
||||||
|
NETLIB_UPDATE_TERMINALSI();
|
||||||
|
|
||||||
|
private:
|
||||||
|
generic_diode m_gD_BC;
|
||||||
|
generic_diode m_gD_BE;
|
||||||
|
|
||||||
|
nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
|
||||||
|
nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
|
||||||
|
nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
|
||||||
|
|
||||||
|
nl_double m_alpha_f;
|
||||||
|
nl_double m_alpha_r;
|
||||||
|
|
||||||
|
NETLIB_SUBXX(analog, C) m_CJE;
|
||||||
|
NETLIB_SUBXX(analog, C) m_CJC;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// nld_Q
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NETLIB_UPDATE(Q)
|
||||||
|
{
|
||||||
|
// netlist().solver()->schedule1();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// nld_QBJT_switch
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
NETLIB_RESET(QBJT_switch)
|
||||||
|
{
|
||||||
|
NETLIB_NAME(Q)::reset();
|
||||||
|
|
||||||
|
m_state_on = 0;
|
||||||
|
|
||||||
|
m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0);
|
||||||
|
m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0);
|
||||||
|
|
||||||
|
m_BC_dummy.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NETLIB_UPDATE(QBJT_switch)
|
||||||
|
{
|
||||||
|
if (!m_RB.m_P.net().isRailNet())
|
||||||
|
m_RB.m_P.solve_now(); // Basis
|
||||||
|
else if (!m_RB.m_N.net().isRailNet())
|
||||||
|
m_RB.m_N.solve_now(); // Emitter
|
||||||
|
else if (!m_RC.m_P.net().isRailNet())
|
||||||
|
m_RC.m_P.solve_now(); // Collector
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NETLIB_UPDATE_PARAM(QBJT_switch)
|
||||||
|
{
|
||||||
|
nl_double IS = m_model.m_IS;
|
||||||
|
nl_double BF = m_model.m_BF;
|
||||||
|
nl_double NF = m_model.m_NF;
|
||||||
|
//nl_double VJE = m_model.dValue("VJE", 0.75);
|
||||||
|
|
||||||
|
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||||
|
|
||||||
|
nl_double alpha = BF / (1.0 + BF);
|
||||||
|
|
||||||
|
diode d(IS, NF);
|
||||||
|
|
||||||
|
// Assume 5mA Collector current for switch operation
|
||||||
|
|
||||||
|
m_V = d.V(0.005 / alpha);
|
||||||
|
|
||||||
|
/* Base current is 0.005 / beta
|
||||||
|
* as a rough estimate, we just scale the conductance down */
|
||||||
|
|
||||||
|
m_gB = 1.0 / (m_V/(0.005 / BF));
|
||||||
|
|
||||||
|
//m_gB = d.gI(0.005 / alpha);
|
||||||
|
|
||||||
|
if (m_gB < exec().gmin())
|
||||||
|
m_gB = exec().gmin();
|
||||||
|
m_gC = d.gI(0.005); // very rough estimate
|
||||||
|
}
|
||||||
|
|
||||||
|
NETLIB_UPDATE_TERMINALS(QBJT_switch)
|
||||||
|
{
|
||||||
|
const nl_double m = (is_qtype( BJT_NPN) ? 1 : -1);
|
||||||
|
|
||||||
|
const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0;
|
||||||
|
if (m_state_on ^ new_state)
|
||||||
|
{
|
||||||
|
const nl_double gb = new_state ? m_gB : exec().gmin();
|
||||||
|
const nl_double gc = new_state ? m_gC : exec().gmin();
|
||||||
|
const nl_double v = new_state ? m_V * m : 0;
|
||||||
|
|
||||||
|
m_RB.set_G_V_I(gb, v, 0.0);
|
||||||
|
m_RC.set_G_V_I(gc, 0.0, 0.0);
|
||||||
|
m_state_on = new_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
NETLIB_RESETI();
|
// ----------------------------------------------------------------------------------------
|
||||||
NETLIB_UPDATEI();
|
// nld_Q - Ebers Moll
|
||||||
NETLIB_UPDATE_PARAMI();
|
// ----------------------------------------------------------------------------------------
|
||||||
NETLIB_UPDATE_TERMINALSI();
|
|
||||||
|
|
||||||
private:
|
|
||||||
generic_diode m_gD_BC;
|
|
||||||
generic_diode m_gD_BE;
|
|
||||||
|
|
||||||
nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
|
|
||||||
nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
|
|
||||||
nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
|
|
||||||
|
|
||||||
nl_double m_alpha_f;
|
|
||||||
nl_double m_alpha_r;
|
|
||||||
|
|
||||||
NETLIB_SUBXX(analog, C) m_CJE;
|
|
||||||
NETLIB_SUBXX(analog, C) m_CJC;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
NETLIB_UPDATE(QBJT_EB)
|
||||||
// nld_Q
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
NETLIB_UPDATE(Q)
|
|
||||||
{
|
|
||||||
// netlist().solver()->schedule1();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
// nld_QBJT_switch
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
NETLIB_RESET(QBJT_switch)
|
|
||||||
{
|
|
||||||
NETLIB_NAME(Q)::reset();
|
|
||||||
|
|
||||||
m_state_on = 0;
|
|
||||||
|
|
||||||
m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0);
|
|
||||||
m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0);
|
|
||||||
|
|
||||||
m_BC_dummy.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NETLIB_UPDATE(QBJT_switch)
|
|
||||||
{
|
|
||||||
if (!m_RB.m_P.net().isRailNet())
|
|
||||||
m_RB.m_P.solve_now(); // Basis
|
|
||||||
else if (!m_RB.m_N.net().isRailNet())
|
|
||||||
m_RB.m_N.solve_now(); // Emitter
|
|
||||||
else if (!m_RC.m_P.net().isRailNet())
|
|
||||||
m_RC.m_P.solve_now(); // Collector
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NETLIB_UPDATE_PARAM(QBJT_switch)
|
|
||||||
{
|
|
||||||
nl_double IS = m_model.m_IS;
|
|
||||||
nl_double BF = m_model.m_BF;
|
|
||||||
nl_double NF = m_model.m_NF;
|
|
||||||
//nl_double VJE = m_model.dValue("VJE", 0.75);
|
|
||||||
|
|
||||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
|
||||||
|
|
||||||
nl_double alpha = BF / (1.0 + BF);
|
|
||||||
|
|
||||||
diode d(IS, NF);
|
|
||||||
|
|
||||||
// Assume 5mA Collector current for switch operation
|
|
||||||
|
|
||||||
m_V = d.V(0.005 / alpha);
|
|
||||||
|
|
||||||
/* Base current is 0.005 / beta
|
|
||||||
* as a rough estimate, we just scale the conductance down */
|
|
||||||
|
|
||||||
m_gB = 1.0 / (m_V/(0.005 / BF));
|
|
||||||
|
|
||||||
//m_gB = d.gI(0.005 / alpha);
|
|
||||||
|
|
||||||
if (m_gB < exec().gmin())
|
|
||||||
m_gB = exec().gmin();
|
|
||||||
m_gC = d.gI(0.005); // very rough estimate
|
|
||||||
}
|
|
||||||
|
|
||||||
NETLIB_UPDATE_TERMINALS(QBJT_switch)
|
|
||||||
{
|
|
||||||
const nl_double m = (is_qtype( BJT_NPN) ? 1 : -1);
|
|
||||||
|
|
||||||
const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0;
|
|
||||||
if (m_state_on ^ new_state)
|
|
||||||
{
|
{
|
||||||
const nl_double gb = new_state ? m_gB : exec().gmin();
|
if (!m_D_EB.m_P.net().isRailNet())
|
||||||
const nl_double gc = new_state ? m_gC : exec().gmin();
|
m_D_EB.m_P.solve_now(); // Basis
|
||||||
const nl_double v = new_state ? m_V * m : 0;
|
else if (!m_D_EB.m_N.net().isRailNet())
|
||||||
|
m_D_EB.m_N.solve_now(); // Emitter
|
||||||
m_RB.set_G_V_I(gb, v, 0.0);
|
else
|
||||||
m_RC.set_G_V_I(gc, 0.0, 0.0);
|
m_D_CB.m_N.solve_now(); // Collector
|
||||||
m_state_on = new_state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
// nld_Q - Ebers Moll
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
NETLIB_UPDATE(QBJT_EB)
|
|
||||||
{
|
|
||||||
if (!m_D_EB.m_P.net().isRailNet())
|
|
||||||
m_D_EB.m_P.solve_now(); // Basis
|
|
||||||
else if (!m_D_EB.m_N.net().isRailNet())
|
|
||||||
m_D_EB.m_N.solve_now(); // Emitter
|
|
||||||
else
|
|
||||||
m_D_CB.m_N.solve_now(); // Collector
|
|
||||||
}
|
|
||||||
|
|
||||||
NETLIB_RESET(QBJT_EB)
|
|
||||||
{
|
|
||||||
NETLIB_NAME(Q)::reset();
|
|
||||||
if (m_CJE)
|
|
||||||
{
|
|
||||||
m_CJE->reset();
|
|
||||||
m_CJE->m_C.setTo(m_model.m_CJE);
|
|
||||||
}
|
|
||||||
if (m_CJC)
|
|
||||||
{
|
|
||||||
m_CJC->reset();
|
|
||||||
m_CJC->m_C.setTo(m_model.m_CJC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
NETLIB_RESET(QBJT_EB)
|
||||||
|
{
|
||||||
|
NETLIB_NAME(Q)::reset();
|
||||||
|
if (m_CJE)
|
||||||
|
{
|
||||||
|
m_CJE->reset();
|
||||||
|
m_CJE->m_C.setTo(m_model.m_CJE);
|
||||||
|
}
|
||||||
|
if (m_CJC)
|
||||||
|
{
|
||||||
|
m_CJC->reset();
|
||||||
|
m_CJC->m_C.setTo(m_model.m_CJC);
|
||||||
|
}
|
||||||
|
|
||||||
NETLIB_UPDATE_TERMINALS(QBJT_EB)
|
}
|
||||||
{
|
|
||||||
const nl_double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0);
|
|
||||||
|
|
||||||
m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity);
|
NETLIB_UPDATE_TERMINALS(QBJT_EB)
|
||||||
m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
|
{
|
||||||
|
const nl_double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0);
|
||||||
|
|
||||||
const nl_double gee = m_gD_BE.G();
|
m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity);
|
||||||
const nl_double gcc = m_gD_BC.G();
|
m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
|
||||||
const nl_double gec = m_alpha_r * gcc;
|
|
||||||
const nl_double gce = m_alpha_f * gee;
|
|
||||||
const nl_double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I();
|
|
||||||
const nl_double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I();
|
|
||||||
const nl_double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity;
|
|
||||||
const nl_double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity;
|
|
||||||
|
|
||||||
m_D_EB.set_mat( gee, gec - gee, -Ie,
|
const nl_double gee = m_gD_BE.G();
|
||||||
gce - gee, gee - gec, Ie);
|
const nl_double gcc = m_gD_BC.G();
|
||||||
m_D_CB.set_mat( gcc, gce - gcc, -Ic,
|
const nl_double gec = m_alpha_r * gcc;
|
||||||
gec - gcc, gcc - gce, Ic);
|
const nl_double gce = m_alpha_f * gee;
|
||||||
m_D_EC.set_mat( 0, -gec, 0,
|
const nl_double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I();
|
||||||
-gce, 0, 0);
|
const nl_double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I();
|
||||||
}
|
const nl_double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity;
|
||||||
|
const nl_double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity;
|
||||||
|
|
||||||
|
m_D_EB.set_mat( gee, gec - gee, -Ie,
|
||||||
|
gce - gee, gee - gec, Ie);
|
||||||
|
m_D_CB.set_mat( gcc, gce - gcc, -Ic,
|
||||||
|
gec - gcc, gcc - gce, Ic);
|
||||||
|
m_D_EC.set_mat( 0, -gec, 0,
|
||||||
|
-gce, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NETLIB_UPDATE_PARAM(QBJT_EB)
|
NETLIB_UPDATE_PARAM(QBJT_EB)
|
||||||
{
|
{
|
||||||
nl_double IS = m_model.m_IS;
|
nl_double IS = m_model.m_IS;
|
||||||
nl_double BF = m_model.m_BF;
|
nl_double BF = m_model.m_BF;
|
||||||
nl_double NF = m_model.m_NF;
|
nl_double NF = m_model.m_NF;
|
||||||
nl_double BR = m_model.m_BR;
|
nl_double BR = m_model.m_BR;
|
||||||
nl_double NR = m_model.m_NR;
|
nl_double NR = m_model.m_NR;
|
||||||
//nl_double VJE = m_model.dValue("VJE", 0.75);
|
//nl_double VJE = m_model.dValue("VJE", 0.75);
|
||||||
|
|
||||||
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
|
||||||
|
|
||||||
m_alpha_f = BF / (1.0 + BF);
|
m_alpha_f = BF / (1.0 + BF);
|
||||||
m_alpha_r = BR / (1.0 + BR);
|
m_alpha_r = BR / (1.0 + BR);
|
||||||
|
|
||||||
m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin());
|
m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin());
|
||||||
m_gD_BC.set_param(IS / m_alpha_r, NR, exec().gmin());
|
m_gD_BC.set_param(IS / m_alpha_r, NR, exec().gmin());
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace analog
|
} // namespace analog
|
||||||
|
|
||||||
namespace devices {
|
namespace devices {
|
||||||
NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB, "QBJT_EB", "MODEL")
|
NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB, "QBJT_EB", "MODEL")
|
||||||
NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch, "QBJT_SW", "MODEL")
|
NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch, "QBJT_SW", "MODEL")
|
||||||
} // namespace devices
|
} // namespace devices
|
||||||
|
|
||||||
} // namespace netlist
|
} // namespace netlist
|
||||||
|
Loading…
Reference in New Issue
Block a user