%  This script runs an example of a load line analysis for a MOSFET amp
%  to find the operating point for Vgs through iteration.  A special WHILE
%  loop is used to progressivly make the interation interval smaller as
%  the final answer is approached.  The interation loop will stop once the
%  error is within some specified tolerance interval.  The quiesent values
%  of Gate voltage Vgs, Drain Source voltage Vds, and Drain current Ids are 
%  computed in the end.
%
%  The function nmos.m is needed to run this script
%
%   Written by Kevin D. Donohue (donohue@engr.uky.edu) 10/2003

%  Set Parameters:  Operating point will be set to half VDD
K=.5; vto = 1.8;  %  Nmos parameters
W=1; L=1; KP=2*K; %  Nmos parameters
VDD=15;  RS=400; RD=1e3;  %  Load line parameters
idsmax = VDD/(RD+RS);    % Maximum Load line value on Drain current axis
                         %  Operation point will be the max drain current divided by 2.
vds = [0:.05:VDD];  %  Create X-Axis

idsll = -vds/(RD+RS) + VDD/(RD+RS);  %  Generate Load Line

err = 2;   %Set initial error for quiesent point to get while loop started
toler = .05e-6;  %  Set tolerance value for stopping rule on while loop
incgs = .1;  %  Set increment for vgs to find intersection with load line.
vgs = vto;         %  Initialize vgs to threshold voltage so initial guess will below desired operating point
%  Set flag to denote when guess goes above the the operating point in
%  order to reduce interation interval.
passflag = 0;  %  If zero implies the last step is below the desired value, 1 implies last step was above

%  Set while loop to run until error is below tolerance
while err >= toler
	ids = nmos(vds,vgs,KP,W,L,vto);  % Compute characteristic curve
	[edum, inderr] = min(abs(idsll - ids));  %  Find intersection with loadline
    err =abs(idsmax/2 - idsll(inderr(1)));  %  Find error between desired current and actual

    % Check to see if we are above or below the target and make adjustments to move closer to desired operating point
	if idsmax/2>ids(inderr(1))  %  If below target value ....
        vgs = vgs + incgs   %  Still below threshold so increase
        if passflag == 1
            incgs = incgs/2;   %  If we just came from above the threshod cut increment in half for more resolution
            passflag = 0;      %  reset flag
        end
    else                   %  If above target value
        vgs = vgs - incgs   % Still above threshold so decrease 
        if passflag == 0
            incgs = incgs/2;  % If we just came from below the threshold cut increment in half for more resolution
            passflag = 1;  % reset flag
        end
	end
%   Comment out the next 4 lines to stop the while loop from being interupted by plots and pauses
    figure(1)
    plot(vds, idsmax*ones(size(vds))/2, 'c--', vds,idsll,'k:',vds,ids,'r')  %  Check plot along the way
    disp(['Iteration in progress'])
    pause(.1)
   end
vgsq = vgs;  %  Set quiesent Vgs to last result of interation
disp([' The operating point for Vgs is ' num2str(vgsq)])

%  Compute corresponding output quiesent voltage amplitude at output
ids = nmos(vds,vgsq,KP,W,L,vto);  % Compute transfer characteristic (TC) curve at quiesent
[err, inderr] = min(abs(ids - idsll));   %  Find intersection with load line and TC
vdsq = vds(inderr(1));  %  Output voltage quiesent
disp([' The operating point for Vds is ' num2str(vdsq)])
idsq = ids(inderr(1));
disp([' The operating point for Ids is ' num2str(idsq)])
