www.gusucode.com > 利用MATLAB GUI设计滤波器界面,可以设计IIR滤波器 > AFD/BuildCircuit_LastStage.m

    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