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