function notchdemo
%NOTCHDEMO  Discretization of a notch filter demo.

%   Author(s): P. Gahinet
%   Copyright 1986-2000 The MathWorks, Inc.
%   $Revision: 1.6 $  $Date: 2000/09/15 19:28:17 $

% Data structure
nf = tf([1 0.5 100],[1 5 100]);
ds = struct(...
	'Notch',ss(nf),...
	'Ts',0.1,...
	'Method','zoh',...
	'BodeMag',[],...
	'BodePhase',[],...
	'Sim',[],...
	'Status',[],...
	'Tf',6,...
	'FreqLims',[0.06 17]);
	
% Main figure
Prefs = cstprefs.tbxprefs;
fig = figure(...
    'Units','character', ...
    'Visible','off',...
    'DoubleBuffer','on', ...
    'IntegerHandle','off',...
    'Name',xlate('Notch Filter Discretization Demo'), ...
    'NumberTitle','off', ...
    'DefaultUIControlFontSize',Prefs.UIFontSize,...
    'DefaultAxesFontSize',Prefs.AxesFontSize,...
    'DefaultTextFontSize',Prefs.AxesFontSize);
figgray = get(fig,'Color');

% Frame and buttons
hBorder = 0.01;
vBorder = 0.01;
axes('parent',fig,...
    'units','norm',...
    'Color',figgray, ...
    'Position',[hBorder .06+2*vBorder 1-2*hBorder .94-4*vBorder],... 
    'Box','on',...
    'Xcolor',[0.5 0.5 0.5],...
    'Ycolor',[0.5 0.5 0.5],...
    'XTick',[], ...
    'YTick',[]);
ds.Status = uicontrol('style','text',...
    'parent',fig,...
    'horiz','left',...
    'units','norm',...
    'backgroundcolor',figgray,...
    'position',[hBorder 0.003 .9 .06],...
    'string','Try a different method or sampling rate...');
uicontrol('style','pushbutton',...
    'parent',fig,...
    'units','norm',...
    'position',[1-2*(.12+hBorder) vBorder .12 .06],...
    'callback','notchdemo_sls',...
    'string','Details');
uicontrol('style','pushbutton',...
    'parent',fig,...
    'units','norm',...
    'position',[1-(.12+hBorder) vBorder .12 .06],...
    'string','Close',...
    'callback','close(gcbf)');


% Bode mag axis
MagPos = [0.1 0.56 0.38 0.35];
hmag = axes('parent',fig,...
    'position',MagPos,...
    'xscale','log',...
    'box','on',...
    'DrawMode','fast', ...
    'XColor',Prefs.AxesForegroundColor,...
    'YColor',Prefs.AxesForegroundColor,...
    'Xtick',[.1 1 10],...
    'XtickLabel',[], ...
    'xlim',ds.FreqLims,...
    'ylim',[-20 5]);
set(get(hmag,'Title'),'String','Bode Diagram of Notch Filter',...
    'FontSize',Prefs.TitleFontSize);
set(get(hmag,'Ylabel'),'String','Magnitude (dB)',...
    'FontSize',Prefs.TitleFontSize,'Color',[0 0 0]);
line(ds.FreqLims,[0 0],'Color',Prefs.AxesForegroundColor,...
    'LineStyle',':','Parent',hmag,'Handlevis','off');
    
% Bode phase axis
PhasePos = [0.1 0.18 0.38 0.35];
hphase = axes('parent',fig,...
    'position',PhasePos,...
    'xscale','log',...
    'box','on',...
    'DrawMode','fast', ...
    'XColor',Prefs.AxesForegroundColor,...
    'YColor',Prefs.AxesForegroundColor,...
    'Xtick',[.1 1 10],...
    'Ytick',[-90,-45,0,45,90],...
    'xlim',ds.FreqLims,...
    'ylim',[-90 90]);
set(get(hphase,'Xlabel'),'String','Frequency (Hz)',...
    'FontSize',Prefs.TitleFontSize,'Color',[0 0 0]);
set(get(hphase,'Ylabel'),'String','Phase (deg)',...
    'FontSize',Prefs.TitleFontSize,'Color',[0 0 0]);
line(ds.FreqLims,[0 0],'Color',Prefs.AxesForegroundColor,...
    'LineStyle',':','Parent',hphase,'Handlevis','off');

% Simulation
StepPos = [0.58 0.56 0.39 0.35];
hstep = axes('parent',fig,...
    'position',StepPos,...
    'box','on',...
    'DrawMode','fast', ...
    'XColor',Prefs.AxesForegroundColor,...
    'YColor',Prefs.AxesForegroundColor,...
    'xlim',[0 ds.Tf],...
    'ylim',[-1 1]);
set(get(hstep,'Title'),'String','Filtered Sine Wave at Notch Frequency',...
    'FontSize',Prefs.TitleFontSize);
set(get(hstep,'Xlabel'),'String','Time (sec)',...
    'FontSize',Prefs.TitleFontSize,'Color',[0 0 0]);
set(get(hstep,'Ylabel'),'String','Amplitude',...
    'FontSize',Prefs.TitleFontSize,'Color',[0 0 0]);
line(get(hstep,'xlim'),[0 0],'Color',Prefs.AxesForegroundColor,...
    'LineStyle',':','Parent',hstep);

% Text
x0 = 0.59;
x1 = 0.95;
uicontrol('style','text',...
    'parent',fig,...
    'units','norm',...
    'string','Method:',...
    'horiz','left',...
    'backgroundcolor',figgray,...
    'position',[x0 .35 .11 .05]);
uicontrol('style','popupmenu',...
    'parent',fig,...
    'units','norm',...
    'string',{'Zero-order hold','Tustin','Prewarped Tustin','Matched pole/zero'},...
    'horiz','left',...
    'value',1,...
    'callback',@LocalSetMethod,...
    'position',[x0+.12 .355 x1-x0-.12 .05]);
uicontrol('style','text',...
    'parent',fig,...
    'units','norm',...
    'string','Sample Time:',...
    'horiz','left',...
    'backgroundcolor',figgray,...
    'position',[x0 .27 x1-x0 .05]);

% Gain slider
BDF = {@LocalSlider 'init'};
BUF = {@LocalSlider 'finish'};
BMF = {@LocalSlider 'update'};
rtslider('Position',[x0+0.02 .2 x1-x0-.02 .05],'Range',[0.03 0.30],...
    'FontSize',8+isunix,'parent',fig,'Value',ds.Ts,...
    'ButtonDownFcn',BDF,'Callback',BMF,'ButtonUpFcn',BUF);
    
% Response of continuous filter
[mag,phase,w] = bode(ds.Notch,{.1 100});
f = unitconv(w,'rad/sec','hz');
line(f,20*log10(mag(:)),'parent',hmag,'linewidth',2,'color','b')
line(f,phase(:),'parent',hphase,'linewidth',2,'color','b')
t = 0:0.01:ds.Tf;
y = lsim(nf,sin(10*t),t);
line(t,y,'parent',hstep,'linewidth',2,'color','b')
line(t,sin(10*t),'parent',hstep,'color',[.8 .8 .8])

% Mag plot
ds.BodeMag.Plot = line(NaN,NaN,...
	'parent',hmag,...
	'linewidth',2,...
	'color','r');
ds.BodeMag.NyquistLine = line([NaN,NaN],[-20 5],...
	'parent',hmag,...
	'color',[0 0 0]);

% Phase plot
ds.BodePhase.Plot = line(NaN,NaN,...
	'parent',hphase,...
	'linewidth',2,...
	'color','r');
ds.BodePhase.NyquistLine = line([NaN,NaN],[-90 90],...
	'parent',hphase,...
	'color',[0 0 0]);

% Sim plot
ds.Sim.Plot = line(NaN,NaN,...
	'parent',hstep,...
	'linewidth',2,...
	'color','r');

% Initialize plots
LocalUpdate(ds);
legend(hmag,'Continuous','Discretized',3)

% Make figure visible
set(fig,'Visible','on','UserData',ds,'HandleVisibility','callback');


%--------------------- Local functions ------------------------------


function LocalSlider(hSrc,Value,event)
% Manages the slider dynamic update

ds = get(gcbf,'UserData');

switch event
case 'init'
    set([ds.BodeMag.Plot,ds.BodeMag.NyquistLine,...
        ds.BodePhase.Plot,ds.BodePhase.NyquistLine,...
        ds.Sim.Plot],'erasemode','xor');
case 'update'
    ds.Ts = Value;
    LocalUpdate(ds)
case 'finish'
    set([ds.BodeMag.Plot,ds.BodeMag.NyquistLine,...
        ds.BodePhase.Plot,ds.BodePhase.NyquistLine,...
        ds.Sim.Plot],'erasemode','normal');
	LocalUpdate(ds)
    set(gcbf,'UserData',ds)
	set(ds.Status,'String','Click on Details for more info...')
end

%%%%%%%%%%%%

function LocalSetMethod(hPopup,EventData)
% Dynamic plot update
fig = gcbf;
ds = get(fig,'UserData');
Methods = get(hPopup,'String');
pval = get(hPopup,'Value');
ds.Method = Methods{pval};
LocalUpdate(ds);
switch pval
case 1
   set(ds.Status,'String','Discretization method:  Zero-order hold')
case 2
   set(ds.Status,'String','Discretization method:  Tustin (bilinear) approximation')
case 3
   set(ds.Status,'String','Discretization method:  Tustin approximation, prewarped at notch frequency')
case 4
   set(ds.Status,'String','Discretization method:  Matched pole-zero')
end
set(fig,'UserData',ds)

%%%%%%%%%%%%

function LocalUpdate(ds)
% Dynamic plot update

% Discretization
Notch_d = c2d(ds.Notch,ds.Ts,ds.Method,10);

% Update Bode plot
nf = pi/ds.Ts;  % rad/sec
[mag,phase,w] = bode(Notch_d,{0.1 nf});
nf = 1/2/ds.Ts; % Hz
f = unitconv(w,'rad/sec','hz');
set(ds.BodeMag.Plot,'Xdata',f,'Ydata',20*log10(mag(:)))
set(ds.BodePhase.Plot,'Xdata',f,'Ydata',phase(:))
set([ds.BodeMag.NyquistLine,ds.BodePhase.NyquistLine],'Xdata',[nf nf])

% Update simulation
t = 0:ds.Ts:ds.Tf;
y = lsim(Notch_d,sin(10*t));
[t,y] = stairs(t,y);
set(ds.Sim.Plot,'Xdata',t,'Ydata',y)
