summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/analog/nld_bjt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/analog/nld_bjt.cpp')
-rw-r--r--src/lib/netlist/analog/nld_bjt.cpp632
1 files changed, 330 insertions, 302 deletions
diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp
index 6f4a2db86bf..aef920635fe 100644
--- a/src/lib/netlist/analog/nld_bjt.cpp
+++ b/src/lib/netlist/analog/nld_bjt.cpp
@@ -5,47 +5,49 @@
*
*/
-#include "../solver/nld_solver.h"
+#include "netlist/solver/nld_solver.h"
+#include "netlist/nl_setup.h"
#include "nlid_twoterm.h"
-#include "../nl_setup.h"
+
#include <cmath>
namespace netlist
{
- namespace analog
- {
-
-class diode
+namespace analog
{
-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); }
+ using constants = plib::constants<nl_double>;
-private:
- nl_double m_Is;
- nl_double m_VT;
- nl_double m_VT_inv;
-};
+ 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:
+ nl_double m_Is;
+ nl_double m_VT;
+ nl_double m_VT_inv;
+ };
-// -----------------------------------------------------------------------------
-// nld_Q - Base classes
-// -----------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------
+ // nld_Q - Base classes
+ // -----------------------------------------------------------------------------
/*! Class representing the bjt model paramers.
*
@@ -73,7 +75,7 @@ private:
* | | RBM | minimum base resistance at high currents | | RB | 10 | * |
* | | RE | emitter resistance | | 0 | 1 | * |
* | | RC | collector resistance | | 0 | 10 | * |
- * | | CJE | B-E zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | Y | CJE | B-E zero-bias depletion capacitance | F | 0 | 2pF | * |
* | | VJE | B-E built-in potential | V | 0.75 | 0.6 | |
* | | MJE | B-E junction exponential factor | - | 0.33 | 0.33 | |
* | | TF | ideal forward transit time | sec | 0 | 0.1ns | |
@@ -81,7 +83,7 @@ private:
* | | VTF | voltage describing VBC dependence of TF | V | infinite | | |
* | | ITF | high-current parameter for effect on TF | A | 0 | | * |
* | | PTF | excess phase at freq=1.0/(TF*2PI) Hz | deg | 0 | | |
- * | | CJC | B-C zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | Y | CJC | B-C zero-bias depletion capacitance | F | 0 | 2pF | * |
* | | VJC | B-C built-in potential | V | 0.75 | 0.5 | |
* | | MJC | B-C junction exponential factor | - | 0.33 | 0.5 | |
* | | XCJC | fraction of B-C depletion capacitance connected to internal base node | - | 1 | | |
@@ -95,343 +97,369 @@ private:
* | | KF | flicker-noise coefficient | - | 0 | | |
* | | AF | flicker-noise exponent | - | 1 | | |
* | | FC | coefficient for forward-bias depletion capacitance formula | - | 0.5 | | |
- * | | TNOM | Parameter measurement temperature | C | 27 | 50 | | */
+ * | | TNOM | Parameter measurement temperature | C | 27 | 50 | |
+ * */
class bjt_model_t : public param_model_t
{
public:
bjt_model_t(device_t &device, const pstring &name, const pstring &val)
: param_model_t(device, name, val)
- , m_IS(*this, "IS")
- , m_BF(*this, "BF")
- , m_NF(*this, "NF")
- , m_BR(*this, "BR")
- , m_NR(*this, "NR")
+ , m_IS (*this, "IS")
+ , m_BF (*this, "BF")
+ , m_NF (*this, "NF")
+ , m_BR (*this, "BR")
+ , m_NR (*this, "NR")
+ , m_CJE(*this, "CJE")
+ , m_CJC(*this, "CJC")
{}
- value_t m_IS; //!< transport saturation current
- value_t m_BF; //!< ideal maximum forward beta
- value_t m_NF; //!< forward current emission coefficient
- value_t m_BR; //!< ideal maximum reverse beta
- value_t m_NR; //!< reverse current emission coefficient
+ value_t m_IS; //!< transport saturation current
+ value_t m_BF; //!< ideal maximum forward beta
+ value_t m_NF; //!< forward current emission coefficient
+ value_t m_BR; //!< ideal maximum reverse beta
+ value_t m_NR; //!< reverse current emission coefficient
+ value_t m_CJE; //!< B-E zero-bias depletion capacitance
+ value_t m_CJC; //!< B-C zero-bias depletion capacitance
+
};
// Have a common start for transistors
-NETLIB_OBJECT(Q)
-{
-public:
- enum q_type {
- BJT_NPN,
- BJT_PNP
+ NETLIB_OBJECT(Q)
+ {
+ public:
+ enum q_type {
+ BJT_NPN,
+ 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)
- , m_model(*this, "MODEL", "NPN")
- , m_qtype(BJT_NPN)
+ NETLIB_OBJECT_DERIVED(QBJT, Q)
{
- }
-
- NETLIB_IS_DYNAMIC(true)
-
- //NETLIB_RESETI();
- NETLIB_UPDATEI();
+ public:
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
+ { }
- inline q_type qtype() const { return m_qtype; }
- inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
- inline void set_qtype(q_type atype) { m_qtype = atype; }
-protected:
+ protected:
- bjt_model_t m_model;
-private:
- q_type m_qtype;
-};
+ private:
+ };
-NETLIB_OBJECT_DERIVED(QBJT, Q)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
- { }
-protected:
-private:
-};
+ // -----------------------------------------------------------------------------
+ // nld_QBJT_switch
+ // -----------------------------------------------------------------------------
+ /*
+ * + - C
+ * B ----VVV----+ |
+ * | |
+ * Rb Rc
+ * Rb Rc
+ * Rb Rc
+ * | |
+ * +----+----+
+ * |
+ * E
+ */
-// -----------------------------------------------------------------------------
-// nld_QBJT_switch
-// -----------------------------------------------------------------------------
+ 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);
+ register_subalias("E", m_RB.m_N);
+ 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);
+ }
+
+ 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
+ // -----------------------------------------------------------------------------
-/*
- * + - C
- * B ----VVV----+ |
- * | |
- * Rb Rc
- * Rb Rc
- * Rb Rc
- * | |
- * +----+----+
- * |
- * E
- */
-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(NETLIST_GMIN_DEFAULT)
- , m_gC(NETLIST_GMIN_DEFAULT)
- , m_V(0.0)
- , m_state_on(*this, "m_state_on", 0)
+ NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
{
- register_subalias("B", m_RB.m_P);
- register_subalias("E", m_RB.m_N);
- register_subalias("C", m_RC.m_P);
- //register_term("_E1", m_RC.m_N);
+ 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);
+ 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<diode_e::BIPOLAR> m_gD_BC;
+ generic_diode<diode_e::BIPOLAR> 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;
+ };
- //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);
+ // ----------------------------------------------------------------------------------------
+ // nld_Q
+ // ----------------------------------------------------------------------------------------
- connect(m_RB.m_P, m_BC_dummy.m_P);
- connect(m_RC.m_P, m_BC_dummy.m_N);
+ NETLIB_UPDATE(Q)
+ {
+ // netlist().solver()->schedule1();
}
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- nld_twoterm m_RB;
- nld_twoterm m_RC;
-
- // FIXME: this is needed so we have all terminals belong to one net list
+ // ----------------------------------------------------------------------------------------
+ // nld_QBJT_switch
+ // ----------------------------------------------------------------------------------------
- nld_twoterm m_BC_dummy;
-
-protected:
+ NETLIB_RESET(QBJT_switch)
+ {
+ NETLIB_NAME(Q)::reset();
- 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;
+ m_state_on = 0;
-private:
-};
+ m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0);
+ m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0);
-// -----------------------------------------------------------------------------
-// nld_QBJT_EB
-// -----------------------------------------------------------------------------
+ m_BC_dummy.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0);
+ }
-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)
+ NETLIB_UPDATE(QBJT_switch)
{
- 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
- //register_term("_B1", m_D_CB.m_N); // Anode
-
- //register_term("_E1", m_D_EC.m_P);
- //register_term("_C1", m_D_EC.m_N);
-
- 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_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
}
-protected:
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- generic_diode m_gD_BC;
- generic_diode m_gD_BE;
-
-private:
- 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;
-
-};
-
-
-// ----------------------------------------------------------------------------------------
-// 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(netlist().gmin(), 0.0, 0.0);
- m_RC.set(netlist().gmin(), 0.0, 0.0);
-
- m_BC_dummy.set(netlist().gmin() / 10.0, 0.0, 0.0);
-
-}
+ 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);
-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
-}
+ set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+ nl_double alpha = BF / (1.0 + BF);
-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);
+ diode d(IS, NF);
- set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
+ // Assume 5mA Collector current for switch operation
- nl_double alpha = BF / (1.0 + BF);
+ m_V = d.V(0.005 / alpha);
- diode d(IS, NF);
+ /* Base current is 0.005 / beta
+ * as a rough estimate, we just scale the conductance down */
- // Assume 5mA Collector current for switch operation
+ m_gB = 1.0 / (m_V/(0.005 / BF));
- m_V = d.V(0.005 / alpha);
+ //m_gB = d.gI(0.005 / alpha);
- /* Base current is 0.005 / beta
- * as a rough estimate, we just scale the conductance down */
+ if (m_gB < exec().gmin())
+ m_gB = exec().gmin();
+ m_gC = d.gI(0.005); // very rough estimate
+ }
- m_gB = 1.0 / (m_V/(0.005 / BF));
+ 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;
+ }
+ }
- //m_gB = d.gI(0.005 / alpha);
- if (m_gB < netlist().gmin())
- m_gB = netlist().gmin();
- m_gC = d.gI(0.005); // very rough estimate
-}
+ // ----------------------------------------------------------------------------------------
+ // nld_Q - Ebers Moll
+ // ----------------------------------------------------------------------------------------
-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)
+ NETLIB_UPDATE(QBJT_EB)
{
- const nl_double gb = new_state ? m_gB : netlist().gmin();
- const nl_double gc = new_state ? m_gC : netlist().gmin();
- const nl_double v = new_state ? m_V * m : 0;
-
- m_RB.set(gb, v, 0.0);
- m_RC.set(gc, 0.0, 0.0);
- m_state_on = new_state;
+ 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);
+ }
-// ----------------------------------------------------------------------------------------
-// nld_Q - Ebers Moll
-// ----------------------------------------------------------------------------------------
+ }
+ 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);
+ m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
+
+ const nl_double gee = m_gD_BE.G();
+ const nl_double gcc = m_gD_BC.G();
+ 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,
+ 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(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();
-}
-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);
- m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
-
- const nl_double gee = m_gD_BE.G();
- const nl_double gcc = m_gD_BC.G();
- 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,
- 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)
-{
- nl_double IS = m_model.m_IS;
- nl_double BF = m_model.m_BF;
- nl_double NF = m_model.m_NF;
- nl_double BR = m_model.m_BR;
- nl_double NR = m_model.m_NR;
- //nl_double VJE = m_model.dValue("VJE", 0.75);
+ NETLIB_UPDATE_PARAM(QBJT_EB)
+ {
+ nl_double IS = m_model.m_IS;
+ nl_double BF = m_model.m_BF;
+ nl_double NF = m_model.m_NF;
+ nl_double BR = m_model.m_BR;
+ nl_double NR = m_model.m_NR;
+ //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_r = BR / (1.0 + BR);
+ m_alpha_f = BF / (1.0 + BF);
+ m_alpha_r = BR / (1.0 + BR);
- m_gD_BE.set_param(IS / m_alpha_f, NF, netlist().gmin());
- m_gD_BC.set_param(IS / m_alpha_r, NR, netlist().gmin());
-}
+ m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin(), constants::T0());
+ m_gD_BC.set_param(IS / m_alpha_r, NR, exec().gmin(), constants::T0());
+ }
- } //namespace analog
+} // namespace analog
- namespace devices {
- NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB)
- NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch)
- }
+namespace devices {
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB, "QBJT_EB", "MODEL")
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch, "QBJT_SW", "MODEL")
+} // namespace devices
} // namespace netlist