00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "bjt.h"
00012 #include "diode.h"
00013 #include "elementset.h"
00014
00015 #include <cmath>
00016 using namespace std;
00017
00018
00019 BJTSettings::BJTSettings()
00020 {
00021 I_S = 1e-16;
00022 N_F = 1.0;
00023 N_R = 1.0;
00024 B_F = 100.0;
00025 B_R = 1.0;
00026 }
00027
00028
00029
00030 BJTState::BJTState() {
00031 reset();
00032 }
00033
00034 void BJTState::reset() {
00035 for(unsigned i = 0; i < 3; ++i ) {
00036 for(unsigned j = 0; j < 3; ++j ) A[i][j] = 0.0;
00037
00038 I[i] = 0.0;
00039 }
00040 }
00041
00042 BJTState BJTState::operator-(const BJTState & s ) const {
00043 BJTState newState(*this );
00044
00045 for(unsigned i = 0; i < 3; ++i ) {
00046 for(unsigned j = 0; j < 3; ++j ) newState.A[i][j] -= s.A[i][j];
00047
00048 newState.I[i] -= s.I[i];
00049 }
00050
00051 return newState;
00052 }
00053
00054
00055
00056
00057 BJT::BJT(const bool isNPN )
00058 : NonLinear()
00059 {
00060 V_BE_prev = 0.0;
00061 V_BC_prev = 0.0;
00062 m_pol = isNPN ? 1 : -1;
00063 m_numCNodes = 3;
00064 }
00065
00066 BJT::~BJT()
00067 {
00068 }
00069
00070 void BJT::add_map()
00071 {
00072 if(!b_status) return;
00073
00074 if(!p_cnode[0]->isGround ) {
00075 p_A->setUse(p_cnode[0]->n(), p_cnode[0]->n(), Map::et_unstable, false );
00076 }
00077
00078 if(!p_cnode[1]->isGround ) {
00079 p_A->setUse(p_cnode[1]->n(), p_cnode[1]->n(), Map::et_unstable, false );
00080 }
00081
00082 if(!p_cnode[2]->isGround ) {
00083 p_A->setUse(p_cnode[2]->n(), p_cnode[2]->n(), Map::et_unstable, false );
00084 }
00085
00086 if(!p_cnode[0]->isGround && !p_cnode[2]->isGround ) {
00087 p_A->setUse(p_cnode[0]->n(), p_cnode[2]->n(), Map::et_unstable, false );
00088 p_A->setUse(p_cnode[2]->n(), p_cnode[0]->n(), Map::et_unstable, false );
00089 }
00090
00091 if(!p_cnode[1]->isGround && !p_cnode[2]->isGround ) {
00092 p_A->setUse(p_cnode[2]->n(), p_cnode[1]->n(), Map::et_unstable, false );
00093 p_A->setUse(p_cnode[1]->n(), p_cnode[2]->n(), Map::et_unstable, false );
00094 }
00095 }
00096
00097 void BJT::add_initial_dc()
00098 {
00099 V_BE_prev = 0.0;
00100 V_BC_prev = 0.0;
00101 m_os.reset();
00102 update_dc();
00103 }
00104
00105 void BJT::updateCurrents()
00106 {
00107 if(!b_status) return;
00108
00109 double V_B = p_cnode[0]->v;
00110 double V_C = p_cnode[1]->v;
00111 double V_E = p_cnode[2]->v;
00112
00113 double V_BE = (V_B - V_E) * m_pol;
00114 double V_BC = (V_B - V_C) * m_pol;
00115
00116 double I_BE, I_BC, I_T, g_BE, g_BC, g_IF, g_IR;
00117 calcIg(V_BE, V_BC, & I_BE, &I_BC, &I_T, &g_BE, &g_BC, &g_IF, &g_IR );
00118
00119 m_cnodeI[1] = I_BC - I_T;
00120 m_cnodeI[2] = I_BE + I_T;
00121 m_cnodeI[0] = -(m_cnodeI[1] + m_cnodeI[2]);
00122 }
00123
00124
00125 void BJT::update_dc()
00126 {
00127 if(!b_status) return;
00128
00129 calc_eq();
00130
00131 BJTState diff = m_ns - m_os;
00132 for(unsigned i = 0; i < 3; ++i ) {
00133 for(unsigned j = 0 ; j < 3; ++j ) A_g(i, j ) += diff.A[i][j];
00134
00135 b_i(i ) += diff.I[i];
00136 }
00137
00138 m_os = m_ns;
00139 }
00140
00141
00142 void BJT::calc_eq()
00143 {
00144 double V_B = p_cnode[0]->v;
00145 double V_C = p_cnode[1]->v;
00146 double V_E = p_cnode[2]->v;
00147
00148 double V_BE = (V_B - V_E) * m_pol;
00149 double V_BC = (V_B - V_C) * m_pol;
00150
00151 double I_S = m_bjtSettings.I_S;
00152 double N_F = m_bjtSettings.N_F;
00153 double N_R = m_bjtSettings.N_R;
00154
00155
00156 double V_BEcrit = diodeCriticalVoltage(I_S, N_F * V_T );
00157 double V_BCcrit = diodeCriticalVoltage(I_S, N_R * V_T );
00158 V_BE_prev = V_BE = diodeVoltage(V_BE, V_BE_prev, V_T * N_F, V_BEcrit );
00159 V_BC_prev = V_BC = diodeVoltage(V_BC, V_BC_prev, V_T * N_R, V_BCcrit );
00160
00161 double I_BE, I_BC, I_T, g_BE, g_BC, g_IF, g_IR;
00162 calcIg(V_BE, V_BC, & I_BE, & I_BC, & I_T, & g_BE, & g_BC, & g_IF, & g_IR );
00163
00164 double I_eq_B = I_BE - V_BE * g_BE;
00165 double I_eq_C = I_BC - V_BC * g_BC;
00166 double I_eq_E = I_T - V_BE * g_IF + V_BC * g_IR;
00167
00168 m_ns.A[0][0] = g_BC + g_BE;
00169 m_ns.A[0][1] = -g_BC;
00170 m_ns.A[0][2] = -g_BE;
00171
00172 m_ns.A[1][0] = -g_BC + (g_IF - g_IR);
00173 m_ns.A[1][1] = g_IR + g_BC;
00174 m_ns.A[1][2] = -g_IF;
00175
00176 m_ns.A[2][0] = -g_BE - (g_IF - g_IR);
00177 m_ns.A[2][1] = -g_IR;
00178 m_ns.A[2][2] = g_BE + g_IF;
00179
00180 m_ns.I[0] = (-I_eq_B - I_eq_C) * m_pol;
00181 m_ns.I[1] = (+I_eq_C - I_eq_E) * m_pol;
00182 m_ns.I[2] = (+I_eq_B + I_eq_E) * m_pol;
00183 }
00184
00185 void BJT::calcIg(double V_BE, double V_BC, double *I_BE, double *I_BC, double *I_T, double *g_BE, double *g_BC, double *g_IF, double *g_IR )
00186 {
00187 double I_S = m_bjtSettings.I_S;
00188 double N_F = m_bjtSettings.N_F;
00189 double N_R = m_bjtSettings.N_R;
00190 double B_F = m_bjtSettings.B_F;
00191 double B_R = m_bjtSettings.B_R;
00192
00193
00194 double g_tiny = (V_BE < (-10 * V_T * N_F)) ? I_S : 0;
00195
00196 double I_F;
00197 diodeJunction(V_BE, I_S, V_T * N_F, & I_F, g_IF );
00198
00199 double I_BEI = I_F / B_F;
00200 double g_BEI = *g_IF / B_F;
00201 double I_BEN = g_tiny * V_BE;
00202 double g_BEN = g_tiny;
00203 *I_BE = I_BEI + I_BEN;
00204 *g_BE = g_BEI + g_BEN;
00205
00206
00207 g_tiny = (V_BC < (-10 * V_T * N_R)) ? I_S : 0;
00208
00209 double I_R;
00210 diodeJunction(V_BC, I_S, V_T * N_R, & I_R, g_IR );
00211
00212 double I_BCI = I_R / B_R;
00213 double g_BCI = *g_IR / B_R;
00214 double I_BCN = g_tiny * V_BC;
00215 double g_BCN = g_tiny;
00216 *I_BC = I_BCI + I_BCN;
00217 *g_BC = g_BCI + g_BCN;
00218
00219 *I_T = I_F - I_R;
00220 }
00221
00222 void BJT::setBJTSettings(const BJTSettings & settings )
00223 {
00224 m_bjtSettings = settings;
00225
00226 if(p_eSet) p_eSet->setCacheInvalidated();
00227 }
00228
00229
00230
00231