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.

GuiPlotFrequencyResponse(varargin)
function varargout = GuiPlotFrequencyResponse(varargin)
% GUIPLOTFREQUENCYRESPONSE M-file for GuiPlotFrequencyResponse.fig
%      GUIPLOTFREQUENCYRESPONSE, by itself, creates a new GUIPLOTFREQUENCYRESPONSE or raises the existing
%      singleton*.
%
%      H = GUIPLOTFREQUENCYRESPONSE returns the handle to a new GUIPLOTFREQUENCYRESPONSE or the handle to
%      the existing singleton*.
%
%      GUIPLOTFREQUENCYRESPONSE('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in GUIPLOTFREQUENCYRESPONSE.M with the given input arguments.
%
%      GUIPLOTFREQUENCYRESPONSE('Property','Value',...) creates a new GUIPLOTFREQUENCYRESPONSE or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before GuiPlotFrequencyResponse_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to GuiPlotFrequencyResponse_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help GuiPlotFrequencyResponse

% Last Modified by GUIDE v2.5 19-Jan-2012 00:18:55

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @GuiPlotFrequencyResponse_OpeningFcn, ...
                   'gui_OutputFcn',  @GuiPlotFrequencyResponse_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin & isstr(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before GuiPlotFrequencyResponse is made visible.
function GuiPlotFrequencyResponse_OpeningFcn(hObject, eventdata, handles, varargin)
% Choose default command line output for GuiPlotFrequencyResponse
handles.output = hObject;

global strFilterObject

% Load data
if isempty(strFilterObject)
   temp=load('matlab');
   disp([mfilename ' called in debug mode using matlab.mat datafile'])
   strFilterObject = temp.strFilterObject;
else
    strFilterObject=Utility_zpk(strFilterObject); % find poles, zeros
end
set(handles.uiFigure,'Name',strFilterObject.sTitle)

% determine and save FMin, FMax
FMin = floor(log10(strFilterObject.fFc))-2;
FMax = ceil(log10(strFilterObject.fFc))+2;
handles.FMin = FMin;
handles.FMax = FMax;
% set the query frequency to the critical frequency
if strFilterObject.fFc >= 1e6
    set(handles.uipmFc,'Value',4)
    set(handles.uitxFc, 'String', num2str(strFilterObject.fFc/1e6))
elseif strFilterObject.fFc >= 1000
    set(handles.uipmFc,'Value',3)
    set(handles.uitxFc, 'String', num2str(strFilterObject.fFc/1e3))
elseif strFilterObject.fFc >= 1
    set(handles.uipmFc,'Value',2)
    set(handles.uitxFc, 'String', num2str(strFilterObject.fFc))
elseif strFilterObject > 0
    set(handles.uipmFc,'Value',1)
    set(handles.uitxFc, 'String', num2str(strFilterObject.fFc*1000))
else
    error('Fc in strFilterObject is negative')
end
% enable/disable the "plot using standard values" button
if isempty(strFilterObject.fK1)
    handles.DrawStandard = 0;
    set(handles.uitxStandard,'Enable','off')
    set(handles.uicbStandard,'Enable','off')
    set(handles.uifrBox,'BackgroundColor',[.9 .9 .9]);
else
    handles.DrawStandard = 1;
    set(handles.uitxStandard,'Enable','on')
    set(handles.uicbStandard,'Enable','on')
    set(handles.uifrBox,'BackgroundColor',[0 0 .75])
    set(handles.uicbStandard,'Value',1)
end
% initialize variables
set(handles.uitxStandard,'Value',0)
handles.IsdB = get(handles.uirbdB,'Value');
handles.IsDeg = get(handles.uirbDeg,'Value');
handles.IsFLog = get(handles.uirbFLog,'Value');
handles.fExact = strFilterObject.fFc;

% Calculate y and plot it
guidata(hObject, handles);
Recalculate(handles);
Replot(handles);

function varargout = GuiPlotFrequencyResponse_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output; % default output

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     Limit Callbacks   
%                    uitxFMin, uitxFMax
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function uitxFMin_Callback(hObject, eventdata, handles)
global strFilterObject
sFMin = get(hObject,'String');
if findstr('default',lower(sFMin))
    FMin = floor(log10(strFilterObject.fFc))-2;
    handles.FMin = FMin;
    sFMin = num2str(FMin);
    set(hObject,'String','default ')
    % check to see if maximum frequency must be increased
    if FMin>=handles.FMax
        handles.FMax=FMin+1;
        set(handles.uitxFMax,'String',num2str(handles.FMax))
    end
end
FMin = str2num(sFMin);
if isempty(FMin)
    errordlg('Enter the power of 10 of the lowest frequency to plot (e.g. 3 for 1kHz), or "default"','Error')
    set(hObject,'String',num2str(handles.FMin))
elseif FMin >= handles.FMax
    errordlg('Minimum frequency to plot must be less than the maximum frequency to plot','Error')
    set(hObject,'String',num2str(handles.FMin));
else
    handles.FMin = FMin;
    guidata(hObject, handles);
    Replot(handles)
end

function uitxFMax_Callback(hObject, eventdata, handles)
global strFilterObject
sFMax = get(hObject,'String');
if findstr('default',lower(sFMax)) 
    FMax = ceil(log10(strFilterObject.fFc))+2;
    handles.FMax = FMax;
    sFMax = num2str(FMax);
    set(hObject,'String','default ')
    % check to see if minimum frequency must be decreased
    if FMax<=handles.FMin
        handles.FMin=FMax-1;
        set(handles.uitxFMin,'String',num2str(handles.FMin))
    end
end
FMax = str2num(sFMax);
if isempty(FMax)
    errordlg('Enter the power of 10 of the highest frequency to plot (e.g. 6 for 1MHz), or "default"','Error')
    set(hObject,'String',num2str(handles.FMax))
elseif FMax <= handles.FMin
    errordlg('Maximum frequency to plot must be greater the minimum frequency to plot','Error')
    set(hObject,'String',num2str(handles.FMax));
else
    handles.FMax = FMax;
    guidata(hObject, handles);
    Replot(handles)
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      Options Callbacks   
%                      uirbLinear, uirbdB
%                      uirbRad, uirbDeg
%                     uirbFLin, uirbFLog
%                        uicbStandard
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function uirbLinear_Callback(hObject, eventdata, handles)
if get(hObject,'Value') == 1
    set(handles.uirbdB, 'Value', 0);
    set(handles.uitxGainTitle,'String','Gain')
    handles.IsdB = 0;
    guidata(hObject, handles);
    Replot(handles)
else
    set(hObject,'Value',1)
end

function uirbdB_Callback(hObject, eventdata, handles)
if get(hObject,'Value') == 1
    set(handles.uirbLinear, 'Value', 0);
    set(handles.uitxGainTitle,'String','Gain (dB)')
    handles.IsdB = 1;
    guidata(hObject, handles);
    Replot(handles)
else
    set(hObject,'Value',1)
end

function uirbRad_Callback(hObject, eventdata, handles)
if get(hObject,'Value') == 1
    set(handles.uirbDeg, 'Value', 0);
    set(handles.uitxPhaseTitle,'String','Phase (rad)')
    handles.IsDeg = 0;
    guidata(hObject, handles);
    Replot(handles)
else
    set(hObject,'Value',1)
end

function uirbDeg_Callback(hObject, eventdata, handles)
if get(hObject,'Value') == 1
    set(handles.uirbRad, 'Value', 0);
    set(handles.uitxPhaseTitle,'String','Phase (deg)')
    handles.IsDeg =1;
    guidata(hObject, handles);
    Replot(handles)
else
    set(hObject,'Value',1)
end

function uirbFLin_Callback(hObject, eventdata, handles)
if get(hObject,'Value') == 1
    set(handles.uirbFLog, 'Value', 0);
    handles.IsFLog = 0;
    guidata(hObject, handles);
    Replot(handles)
else
    set(hObject,'Value',1)
end

function uiFLog_Callback(hObject, eventdata, handles)
if get(hObject,'Value') == 1
    set(handles.uirbFLin, 'Value', 0);
    handles.IsFLog = 1;
    guidata(hObject, handles);
    Replot(handles)
else
    set(hObject,'Value',1)
end

function uicbStandard_Callback(hObject, eventdata, handles)
handles.DrawStandard = get(hObject,'Value');
guidata(hObject, handles);
Replot(handles)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     Analyze Callbacks   
%                      uitxFc, uipmFc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function uitxFc_Callback(hObject, eventdata, handles)
num=str2double(get(hObject,'String'));
if isnan(num)
    errordlg('Enter a numeric freqnency at which to examine the filter''s response','Error')
    set(hObject,'String',sprintf('%g',handles.fExact))
elseif num < 0
    errordlg('The frequency must be postive','Error')
    set(hObject,'String',sprintf('%g',handles.fExact))
else
    set(hObject,'String',sprintf('%g',num))
    handles.fExact = str2num(get(handles.uitxFc,'String'))*10^((get(handles.uipmFc,'Value')-2)*3);
end
guidata(hObject, handles);
Recalculate(handles)
Replot(handles)

function uipmFc_Callback(hObject, eventdata, handles)
handles.fExact = str2num(get(handles.uitxFc,'String'))*10^((get(handles.uipmFc,'Value')-2)*3);
guidata(hObject, handles);
Recalculate(handles)
Replot(handles)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                        Helper functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function Recalculate(handles)
global strFilterObject
% setup
z = strFilterObject.vZeros; 
p = strFilterObject.vPoles; 
k = strFilterObject.fK; 
f = str2num(get(handles.uitxFc,'String'))*10^((get(handles.uipmFc,'Value')-2)*3);
% do the calculations
w=f*2*pi;
H = k*prod(j*w-z)/prod(j*w-p);
magH = abs(H);
dBH  = 20*log10(magH);
radH = angle(H);
degH = radH*180/pi;
% post the data
set(handles.uitxGain,'String',sprintf('%4.4g',magH))
set(handles.uitxGaindB,'String',sprintf('%4.4g',dBH))
set(handles.uitxPhaseDeg,'String',sprintf('%4.4g',degH))
set(handles.uitxPhaseRad,'String',sprintf('%4.4g',radH))


function Replot(handles)
% ------------------------setup----------------------------
global strFilterObject
z = strFilterObject.vZeros; 
p = strFilterObject.vPoles; 
k = strFilterObject.fK; 
f = logspace(handles.FMin, handles.FMax, 500);
w = 2*pi*f;
Fc = strFilterObject.fFc;
if handles.DrawStandard
    z1 = strFilterObject.vZeros1; 
    p1 = strFilterObject.vPoles1; 
    k1 = strFilterObject.fK1;    
end
% -------------------do the calculations--------------------
H=f;
for ind=1:length(w)
    wcur=w(ind);
    H(ind)= k*prod(j*wcur-z)/prod(j*wcur-p);
end
gain = abs(H);
if handles.IsdB
    gain = 20*log10(gain);
end
phase = unwrap(angle(H));
if handles.IsDeg
    phase = 180/pi*phase;
end
if handles.DrawStandard
    H1=f;
    for ind=1:length(w)
        wcur=w(ind);
        H1(ind)= k1*prod(j*wcur-z1)/prod(j*wcur-p1);
    end
    gain1 = abs(H1);
    if handles.IsdB
        gain1 = 20*log10(gain1);
    end
    phase1 = unwrap(angle(H1));
    if handles.IsDeg
        phase1 = 180/pi*phase1;
    end
    % due to weird rounding errors sometimes a 2pi diff b/n phase and phase1 occurs.
    % Stop it here.
    if handles.IsDeg
        for ind=1:length(w) 
            if abs(phase1(ind)-(phase(ind)+360)) < 10
                phase1(ind:end) = phase1(ind:end)-360;
            end
            if abs(phase1(ind)-(phase(ind)-360)) < 10
                phase1(ind:end) = phase1(ind:end)+360;
            end
        end
    else
        for ind=1:length(w) 
            if abs(phase1(ind)-(phase(ind)+2*pi)) < .1
                phase1(ind:end) = phase1(ind:end)-2*pi;
            end
            if abs(phase1(ind)-(phase(ind)-2*pi)) < .1
                phase1(ind:end) = phase1(ind:end)+2*pi;
            end
        end
    end
end
    % ----------------------plot the gain-------------------------
axes(handles.uiaxGain)
if handles.IsFLog
    semilogx(f,gain,'k-')
else
    plot(f,gain,'k-')
end
hold on
% plot standardized RC values
if handles.DrawStandard
    if handles.IsFLog
        semilogx(f,gain1,'b-')
    else
        plot(f,gain1,'b-')
    end
end
% plot the vertical line
axlimits=axis;
ymin = axlimits(3);
ymax = axlimits(4);
if handles.fExact>10^handles.FMin && handles.fExact<10^handles.FMax
    vx = [handles.fExact handles.fExact]; 
    vy = [ymin ymax];
    if handles.IsFLog
        semilogx(vx,vy,'r-')
    else
        plot(vx,vy,'r-')
    end
end
axis(axlimits)
hold off
% ----------------------plot the phase-------------------------
% plot ideal phase
axes(handles.uiaxPhase)
if handles.IsFLog
    semilogx(f,phase,'k-')
else
    plot(f,phase,'k-')
end
hold on
% plot standardized RC values
if handles.DrawStandard
    if handles.IsFLog
        semilogx(f,phase1,'b-')
    else
        plot(f,phase,'k-')
    end 
end
% plot the vertical line
axlimits=axis;
ymin = axlimits(3);
ymax = axlimits(4);
if handles.fExact>10^handles.FMin && handles.fExact<10^handles.FMax
    vx = [handles.fExact handles.fExact]; 
    vy = [ymin ymax];
    if handles.IsFLog
        semilogx(vx,vy,'r-')
    else
        plot(f,phase,'k-')
    end
end
axis(axlimits)
hold off

Contact us at files@mathworks.com