File indexing completed on 2024-04-28 05:43:15
0001 /*************************************************************************** 0002 * Copyright (C) 2005-2006 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "jfet.h" 0012 0013 #include <cmath> 0014 using namespace std; 0015 0016 const uint JFET::PinD = 0; 0017 const uint JFET::PinG = 1; 0018 const uint JFET::PinS = 2; 0019 0020 // BEGIN class JFETSettings 0021 JFETSettings::JFETSettings() 0022 { 0023 V_Th = -2.0; 0024 beta = 1e-4; 0025 I_S = 1e-14; 0026 N = 1.0; 0027 N_R = 2.0; 0028 } 0029 // END class JFETSettings 0030 0031 // BEGIN class JFETState 0032 0033 JFETState::JFETState() 0034 { 0035 reset(); 0036 } 0037 0038 void JFETState::reset() 0039 { 0040 for (unsigned i = 0; i < 3; ++i) { 0041 for (unsigned j = 0; j < 3; ++j) 0042 A[i][j] = 0.0; 0043 0044 I[i] = 0.0; 0045 } 0046 } 0047 0048 JFETState JFETState::operator-(const JFETState &s) const 0049 { 0050 JFETState newState(*this); 0051 0052 for (unsigned i = 0; i < 3; ++i) { 0053 for (unsigned j = 0; j < 3; ++j) 0054 newState.A[i][j] -= s.A[i][j]; 0055 0056 newState.I[i] -= s.I[i]; 0057 } 0058 0059 return newState; 0060 } 0061 0062 // END class JFETState 0063 0064 // BEGIN class JFET 0065 JFET::JFET(JFET_type type) 0066 { 0067 switch (type) { 0068 case nJFET: 0069 m_pol = 1; 0070 break; 0071 0072 case pJFET: 0073 m_pol = -1; 0074 break; 0075 } 0076 0077 V_GS_prev = 0.0; 0078 V_GD_prev = 0.0; 0079 m_numCNodes = 3; 0080 updateLim(); 0081 } 0082 0083 JFET::~JFET() 0084 { 0085 } 0086 0087 void JFET::add_initial_dc() 0088 { 0089 V_GS_prev = 0.0; 0090 V_GD_prev = 0.0; 0091 m_os.reset(); 0092 update_dc(); 0093 } 0094 0095 void JFET::updateCurrents() 0096 { 0097 if (!b_status) 0098 return; 0099 0100 double V_D = p_cnode[PinD]->v; 0101 double V_G = p_cnode[PinG]->v; 0102 double V_S = p_cnode[PinS]->v; 0103 0104 double V_GS = V_G - V_S; 0105 double V_GD = V_G - V_D; 0106 double V_DS = V_D - V_S; 0107 0108 double I_GS, I_GD, I_DS, g_GS, g_GD, g_DS, g_m; 0109 0110 calcIg(V_GS, V_GD, V_DS, &I_GS, &I_GD, &I_DS, &g_GS, &g_GD, &g_DS, &g_m); 0111 0112 m_cnodeI[PinD] = I_GD - I_DS; 0113 m_cnodeI[PinS] = I_GS + I_DS; 0114 m_cnodeI[PinG] = -(m_cnodeI[PinD] + m_cnodeI[PinS]); 0115 } 0116 0117 void JFET::update_dc() 0118 { 0119 if (!b_status) 0120 return; 0121 0122 calc_eq(); 0123 0124 JFETState diff = m_ns - m_os; 0125 for (unsigned i = 0; i < 3; ++i) { 0126 for (unsigned j = 0; j < 3; ++j) 0127 A_g(i, j) += diff.A[i][j]; 0128 0129 b_i(i) += diff.I[i]; 0130 } 0131 0132 m_os = m_ns; 0133 } 0134 0135 void JFET::calc_eq() 0136 { 0137 double N = m_jfetSettings.N; 0138 0139 double V_D = p_cnode[PinD]->v; 0140 double V_G = p_cnode[PinG]->v; 0141 double V_S = p_cnode[PinS]->v; 0142 0143 // GS diode 0144 double V_GS = V_G - V_S; 0145 V_GS_prev = V_GS = diodeVoltage(V_GS, V_GS_prev, N, V_lim); 0146 0147 // GD diode 0148 double V_GD = V_G - V_D; 0149 V_GD_prev = V_GD = diodeVoltage(V_GD, V_GD_prev, N, V_lim); 0150 0151 double V_DS = V_GS - V_GD; 0152 0153 double I_GS, I_GD, I_DS, g_GS, g_GD, g_DS, g_m; 0154 0155 calcIg(V_GS, V_GD, V_DS, &I_GS, &I_GD, &I_DS, &g_GS, &g_GD, &g_DS, &g_m); 0156 0157 // current sources 0158 double IeqG = I_GS - (g_GS * V_GS); 0159 double IeqD = I_GD - (g_GD * V_GD); 0160 double IeqS = I_DS - (g_m * V_GS) - (g_DS * V_DS); 0161 0162 m_ns.A[PinG][PinG] = +g_GS + g_GD; 0163 m_ns.A[PinG][PinD] = -g_GD; 0164 m_ns.A[PinG][PinS] = -g_GS; 0165 0166 m_ns.A[PinD][PinG] = -g_GD + g_m; 0167 m_ns.A[PinD][PinD] = +g_DS + g_GD; 0168 m_ns.A[PinD][PinS] = -g_m - g_DS; 0169 0170 m_ns.A[PinS][PinG] = -g_GS - g_m; 0171 m_ns.A[PinS][PinD] = -g_DS; 0172 m_ns.A[PinS][PinS] = +g_GS + g_DS + g_m; 0173 0174 m_ns.I[PinG] = (-IeqG - IeqD) * m_pol; 0175 m_ns.I[PinD] = (+IeqD - IeqS) * m_pol; 0176 m_ns.I[PinS] = (+IeqG + IeqS) * m_pol; 0177 } 0178 0179 void JFET::calcIg(double V_GS, double V_GD, double V_DS, double *I_GS, double *I_GD, double *I_DS, double *g_GS, double *g_GD, double *g_DS, double *g_m) const 0180 { 0181 double V_Th = m_jfetSettings.V_Th; 0182 double beta = m_jfetSettings.beta; 0183 double I_S = m_jfetSettings.I_S; 0184 double N = m_jfetSettings.N; 0185 double N_R = m_jfetSettings.N_R; 0186 0187 // GS diode 0188 double g_tiny = (V_GS < (-10 * V_T * N)) ? I_S : 0; 0189 *g_GS = diodeConductance(V_GS, I_S, N) + diodeConductance(V_GS, 0, N_R) + g_tiny; 0190 *I_GS = diodeCurrent(V_GS, I_S, N) + diodeCurrent(V_GS, 0, N_R) + g_tiny * V_GS; 0191 0192 // GD diode 0193 g_tiny = (V_GD < (-10 * V_T * N)) ? I_S : 0; 0194 *g_GD = diodeConductance(V_GD, I_S, N) + diodeConductance(V_GD, 0, N_R) + g_tiny; 0195 *I_GD = diodeCurrent(V_GD, I_S, N) + diodeCurrent(V_GD, 0, N_R) + (g_tiny * V_GD); 0196 0197 double V_GST = V_GS - V_Th; 0198 double V_GDT = V_GD - V_Th; 0199 0200 *I_DS = 0; 0201 *g_m = 0; 0202 *g_DS = 0; 0203 0204 switch (getOpRegion(V_DS, V_GST, V_GDT)) { 0205 case NormalCutoff: 0206 case InverseCutoff: 0207 break; 0208 0209 case NormalSaturation: 0210 *I_DS = beta * V_GST * V_GST; 0211 *g_DS = 0; 0212 *g_m = beta * 2 * V_GST; 0213 break; 0214 0215 case NormalLinear: 0216 *I_DS = beta * V_DS * (2 * V_GST - V_DS); 0217 *g_DS = beta * 2 * (V_GST - V_DS); 0218 *g_m = beta * 2 * V_DS; 0219 break; 0220 0221 case InverseSaturation: 0222 *I_DS = -beta * V_GDT * V_GDT; 0223 *g_DS = beta * 2 * V_GDT; 0224 *g_m = -beta * 2 * V_GDT; 0225 break; 0226 0227 case InverseLinear: 0228 *I_DS = beta * V_DS * (2 * V_GDT + V_DS); 0229 *g_DS = 2 * beta * V_GDT; 0230 *g_m = beta * 2 * V_DS; 0231 break; 0232 } 0233 } 0234 0235 JFET::OpRegion JFET::getOpRegion(double V_DS, double V_GST, double V_GDT) const 0236 { 0237 if (V_DS > 0) { 0238 if (V_GST <= 0) 0239 return NormalCutoff; 0240 else if (V_GST <= V_DS) 0241 return NormalSaturation; 0242 else 0243 return NormalLinear; 0244 } else { 0245 if (V_GDT <= 0) 0246 return InverseCutoff; 0247 else if (V_GDT <= -V_DS) 0248 return InverseSaturation; 0249 else 0250 return InverseLinear; 0251 } 0252 } 0253 0254 void JFET::setJFETSettings(const JFETSettings &settings) 0255 { 0256 m_jfetSettings = settings; 0257 updateLim(); 0258 0259 if (p_eSet) 0260 p_eSet->setCacheInvalidated(); 0261 } 0262 0263 void JFET::updateLim() 0264 { 0265 double I_S = m_jfetSettings.I_S; 0266 double N = m_jfetSettings.N; 0267 V_lim = diodeLimitedVoltage(I_S, N); 0268 } 0269 0270 // END class JFET