Code covered by the BSD License  

Highlights from
Analog Filter Design Toolbox

image thumbnail
from Analog Filter Design Toolbox by James Squire
GUI to design and simulate active (opamp) LP and HP Bessel, Butter, Cheby, and Elliptic filters.

BuildCircuit_LastStage(strCircuit)
function strCircuit = BuildCircuit_LastStage(strCircuit)
% BuildCircuit_LastStage is a subfile of the AnalogFilter GUI collection
%
% James C. Squire, 2002
% Assistant Professor, Virginia Military Institute
% ver 1.0

% BuildCircuit_LastStage takes a strFilterObject with precomputed biquads
% and if necessary builds a final first OR zero order stage to meet the 
% specified poles, zeros, gain, and polarity

% constants
CLOSE_ENOUGH = 0.05;  % if gain is within CLOSE_ENOUGH then omit final gain stage (e.g. .05 = 5%)
DEBUG = 1;            % print out helpful information to aid in debugging

% setup
nStages = strCircuit.nStages;
nBiquads = strCircuit.nBiquads;
bFirstOrderStage = strCircuit.bFirstOrderStage;
bGainStage = strCircuit.bGainStage; 
sPolarity = strCircuit.sPolarity; % may be i, n, or d
nRTol = strCircuit.nRTol;
nCTol = strCircuit.nCTol;
sPurpose = strCircuit.sPurpose; % may be LP, HP, or Notch
vStage = strCircuit.vStage;

% find kRequired, the amount of gain required in a last stage to fix undesired gain in the biquads
kSoFar = 1;
for i=1:nBiquads
    k1=strCircuit.vStage(i).k1;
    p1=strCircuit.vStage(i).p1;
    z1=strCircuit.vStage(i).z1;
    k=strCircuit.vStage(i).k;
    p=strCircuit.vStage(i).p;
    z=strCircuit.vStage(i).z;
    if prod(z)*prod(z1)==0 % if a HP
        kSoFar = kSoFar * k1;
    else
        kSoFar = kSoFar * k1 * prod(-z1) / prod(-p1) / prod(-z) * prod(-p);
    end
end
kRequired = strCircuit.k/kSoFar;
switch sPolarity
    case 'd'    % if we don't care about the polarity, make it so if close to +/-1 we don't use the last stage
        kRequired = abs(kRequired);
    case 'n'    % if non-inverting do nothing
    case 'i'    % if inverting passband, then invert kRequired
        kRequired = -kRequired;
    otherwise
        error('unknown sPolarity')
end
if kRequired > 1-CLOSE_ENOUGH && kRequired < 1+CLOSE_ENOUGH
    kRequired = 1;
end

% determine each stage's name
if ~bFirstOrderStage   % no first order stage
    if kRequired < 0
        bGainStage = 1;
        nStages = nBiquads + bFirstOrderStage + bGainStage;
        vStage(nStages).k = kRequired;
        vStage(nStages).k1 = kRequired;
        vStage(nStages).schName = 'ZO_I';
        vStage(nStages).schTitle = 'Inverting gain';
    elseif kRequired>0 && kRequired < 1
        bGainStage = 1;
        nStages = nBiquads + bFirstOrderStage + bGainStage;
        vStage(nStages).k = kRequired;
        vStage(nStages).k1 = kRequired;
        vStage(nStages).schName = 'ZO_N_KLE1';
        vStage(nStages).schTitle = 'Non-inverting gain';
    elseif kRequired==1
        % no final stage needed
        bGainStage = 0;
        nStages = nBiquads + bFirstOrderStage + bGainStage;
    elseif kRequired>1
        bGainStage = 1;
        nStages = nBiquads + bFirstOrderStage + bGainStage;
        vStage(nStages).k = kRequired;
        vStage(nStages).k1 = kRequired;
        vStage(nStages).schName = 'ZO_N_KGT1';
        vStage(nStages).schTitle = 'Non-inverting gain';
    end
else                % requires a first order stage
    vStage(nStages).k = kRequired;
    vStage(nStages).k1 = kRequired;
    if isempty(vStage(nStages).z)   % LP
        vStage(nStages).schTitle = 'First order lowpass';
        % kDC = k / abs(p) for 1st order LP or k otherwise - important because 
        % LP_SK uses a different configuration for kDC <=1 and >1 
        kDC = kRequired/abs(vStage(nStages).p(1));
        if kDC < 0
            vStage(nStages).schName = 'SO_LP_I';
        elseif kDC>0 && kDC <= 1
            vStage(nStages).schName = 'SO_LP_N_KLE1';
        elseif kDC>1
            vStage(nStages).schName = 'SO_LP_N_KGT1';
        end
    else                            % HP 
        vStage(nStages).schTitle = 'First order highpass';
        if kRequired < 0
            vStage(nStages).schName = 'SO_HP_I';
        elseif kRequired>0 && kRequired <= 1
            vStage(nStages).schName = 'SO_HP_N_KLE1';
        elseif kRequired>1
            vStage(nStages).schName = 'SO_HP_N_KGT1';
        end
    end
end

% make the recommended name/title the same as the current schematic name/title if a last stage
if bFirstOrderStage || bGainStage
    vStage(nStages).recName  = vStage(nStages).schName;
    vStage(nStages).recTitle = vStage(nStages).schTitle;
end

% fill up the output structure
strCircuit.bGainStage = bGainStage;
strCircuit.nStages = nStages;
strCircuit.vStage = vStage;
 
% select components for the last stage (if any)
if bFirstOrderStage || bGainStage
    strCircuit.vStage(nStages) = ...
        BuildCircuit_UpdateComponents(strCircuit.vStage(nStages),nRTol,nCTol);
end

Contact us