function varargout = FreqControlDesign(varargin)
% FREQCONTROLDESIGN M-file for FreqControlDesign.fig
%      FREQCONTROLDESIGN, by itself, creates a new FREQCONTROLDESIGN or raises the existing
%      singleton*.
%
%      H = FREQCONTROLDESIGN returns the handle to a new FREQCONTROLDESIGN or the handle to
%      the existing singleton*.
%
%      FREQCONTROLDESIGN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in FREQCONTROLDESIGN.M with the given input arguments.
%
%      FREQCONTROLDESIGN('Property','Value',...) creates a new FREQCONTROLDESIGN or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before FreqControlDesign_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to FreqControlDesign_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 FreqControlDesign

% Last Modified by GUIDE v2.5 09-Apr-2014 15:48:55

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @FreqControlDesign_OpeningFcn, ...
                   'gui_OutputFcn',  @FreqControlDesign_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(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 FreqControlDesign is made visible.
function FreqControlDesign_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to FreqControlDesign (see VARARGIN)

% Choose default command line output for FreqControlDesign
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes FreqControlDesign wait for user response (see UIRESUME)
% uiwait(handles.figure1);
setupsystem(handles)

% --- Outputs from this function are returned to the command line.
function varargout = FreqControlDesign_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;



function edit1_Callback(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit1 as text
%        str2double(get(hObject,'String')) returns contents of edit1 as a double
% what happens when user changes Student Number - nothing

% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit2_Callback(hObject, eventdata, handles)
% hObject    handle to edit2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit2 as text
%        str2double(get(hObject,'String')) returns contents of edit2 as a double
% what happens when user changes system number
setupsystem(handles);   % get info on system, using student number

% --- Executes during object creation, after setting all properties.
function edit2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on selection change in listbox1.
function listbox1_Callback(hObject, eventdata, handles)
% hObject    handle to listbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns listbox1 contents as cell array
%        contents{get(hObject,'Value')} returns selected item from listbox1
% %% Pressed to define controller
if get(handles.listbox1, 'value') == 2                  % if Phase Lead
    set(handles.text11, 'string', 'Speed up factor');   % allow user
    set(handles.text11, 'visible', 'on');               % to specify speedup
    set(handles.edit4, 'visible', 'on');
else
    set(handles.text11, 'visible', 'off');              % hide this
    set(handles.edit4, 'visible', 'off');
end

% --- Executes during object creation, after setting all properties.
function listbox1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to listbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function edit3_Callback(hObject, eventdata, handles)
% hObject    handle to edit3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit3 as text
%        str2double(get(hObject,'String')) returns contents of edit3 as a double
% what happens when user changes PM spec
%setupsystem(handles);
updatebode(handles);        % redraw line for PM on Bode plots

% --- Executes during object creation, after setting all properties.
function edit3_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


function edit4_Callback(hObject, eventdata, handles)
% hObject    handle to edit4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit4 as text
%        str2double(get(hObject,'String')) returns contents of edit4 as a double
% What happens when user changes speed up - nothing

% --- Executes during object creation, after setting all properties.
function edit4_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit5_Callback(hObject, eventdata, handles)
% hObject    handle to edit5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit5 as text
%        str2double(get(hObject,'String')) returns contents of edit5 as a double
% what happens when user changes first edit box in design panel
set(handles.text18, 'visible', 'off');      % hide help string
u = get(handles.uipanel1, 'userdata');      % find out what doing
switch u(1,1)
    case 1, pcontrolcheckw(handles, 1)      % for P design : w where PM
    case 2, pcontrolcheckw(handles, 2)      % for Phase Lead Design : same
    case 3, picontrolcheckphase(handles, 3);%PI specify phase for design
    case 4, picontrolcheckphase(handles, 4);% PID same
end

% --- Executes during object creation, after setting all properties.
function edit5_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function edit6_Callback(hObject, eventdata, handles)
% hObject    handle to edit6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit6 as text
%        str2double(get(hObject,'String')) returns contents of edit6 as a double
% what happens when user changes second edit box in design panel
set(handles.text18, 'visible', 'off');  % hide help string
u = get(handles.uipanel1, 'userdata');  % what design being done
switch u(1,1)
    case 1, pcontroldogain(handles);    % find loop gain for C*P
    case 2, phldspeedcheck(handles);    % find phase at higher freq
    case 3, picontrolcheckw(handles, 3);% find w at specified phase
    case 4, picontrolcheckw(handles, 4);% ditto
end


% --- Executes during object creation, after setting all properties.
function edit6_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


function edit7_Callback(hObject, eventdata, handles)
% hObject    handle to edit7 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit7 as text
%        str2double(get(hObject,'String')) returns contents of edit7 as a double
% what happens when user changes third edit box in design panel
set(handles.text18, 'visible', 'off');  % hide help string
u = get(handles.uipanel1, 'userdata');
switch u(1,1)
    case 1, pcontrolok(handles);        % enter C gain
    case 2, phldcontrolok(handles);     % enter phase lead
    case 3, picontrolok(handles);       % enter phase of C
    case 4, pidcontrolok(handles);      % ditto
end

% --- Executes during object creation, after setting all properties.
function edit7_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit7 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% %% Pressed to accept Controller
set(handles.text18, 'visible', 'off');      % hide help string
u = get(handles.uipanel1, 'userdata');      % find out what sort of action
controlputin(handles, u(1)>1); 
     % insert C based on numerator only if u(1)=1, otherwise num and den
updatebode(handles);                        % update Bode Plot
if u(1)>1,    % if not P design
    if get(handles.checkbox1, 'Value') > 0, doporplcontrol(handles, 1); end 
end         % done design of Te/Ti etc, auto do design gain


% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% %% Pressed to cancel Controller
set(handles.text18, 'visible', 'off');      % hide help string
set(handles.uipanel1, 'visible', 'off');    % hide panel

% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% What happens when press " Do Design" 
setupsystem(handles);                       % set system, update bode
gododesign(handles);

% --- Executes on button press in checkbox1.
function checkbox1_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox1
if get(hObject, 'Value') == 0
    set(handles.listbox1, 'String',...
       {'Find Gain', 'Find Te and Ta',...
        'Find Ti for P+I', 'Find Ti & Td for PID'});
    set(handles.pushbutton3, 'String', 'Start Design');
    set(handles.pushbutton6, 'visible', 'On');
else
    set(handles.listbox1, 'String',...
       {'P-Control', 'Phase Lead Control',...
        'P+I Control', 'PID Control'});
    set(handles.pushbutton3, 'String', 'Do Design');
    set(handles.pushbutton6, 'visible', 'Off');
end

% --- Executes on button press in pushbutton5.
function pushbutton5_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
print -dmeta


% --- Executes on button press in pushbutton6.
function pushbutton6_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
gododesign(handles);

function setupsystem (handles)
% Select system based on number in edit1; 
r = FreqSystems (2+round(str2num(get(handles.edit2, 'String'))), get(handles.edit1, 'String'));
setsys(handles, r.numstr, r.pnum, r.denstr, r.pden);    % Load data
axes(handles.axes3); cla;       % clear step graph

function gododesign(handles)
% Do the design
switch get(handles.listbox1, 'value')       % what sort of action chosen
    case 1, doporplcontrol (handles, 1);    % Start P design
    case 2, doporplcontrol (handles, 2);    % Start Ph Lead design
    case 3, dopicontrol (handles, 3);       % Start PI design
    case 4, dopicontrol (handles, 4);       % Start PID design
end
        
function setsys (handles, nstr, npoly, dstr, dpoly)
% n/d str are strings representing num/den polynomials n/d poly
% Load these into GUI's handles
set(handles.text4, 'string', nstr);     % Load Plant
set(handles.text4, 'userdata', npoly);
set(handles.text5, 'string', dstr);
set(handles.text5, 'userdata', dpoly);
set(handles.text9, 'string', '1');      % Set Controller to 1
set(handles.text9, 'userdata', 1);
set(handles.text10, 'string', '1');
set(handles.text10, 'userdata', 1);
updatebode(handles);                    % Draw Bode plot for P


function updatebode(handles)
% Draw the bode plot of C*P
[m,p,w] = getbode(handles);             % get Bode plot data
pm = str2num(get(handles.edit3, 'string')); % get PM info
axes(handles.axes1); cla;                   % Plot Gain in axes1
loglog(w, m, [min(w) max(w)], [1 1]);       % show Gain = 1 line
grid on
axes(handles.axes2); cla;                   % Plot Phase in axes2
semilogx(w, p, [min(w) max(w)], -180+[0 0], [min(w) max(w)], -180+pm+[0 0]);
grid on                                     % add -180 and -180+PM lines
pmin = 90*floor(min(p)/90);                 % Set Phase so ticks are n*90
pmax = max([0, 90*ceil(max(p)/90)]);
set(gca, 'ylim', [pmin-10, pmax+10], 'ytick', [pmin:90:pmax]);

function [m,p,w] = getbode(handles)
[num, den] = getCP(handles);    % get C*P from data in text4,5,9,10
[m, p, w] = bode(num, den);     % compute bode data

function plotstep(handles)
% Plot Step Response, of CP/1+CP imn axes 3
[num, den] = getCP(handles);    % Get C*P
[y, d, t] = step(num, polyadd(num, den));   % plot step response
axes(handles.axes3); cla;
plot(t, y, [0 0 max(t)], [0 1 1], [0 max(t)], [0, 0] + num(end)/(num(end)+den(end)));
yss = num(end)/(num(end)+den(end));
ypk = max(y);
tpk = t(y == ypk);
tset = max(t(abs(y-yss)>0.02*yss));
set(gca, 'xlim', [0 max(t)], 'xtick', sort(unique([0, tpk, tset])));
set(gca, 'ylim', [0 ypk*1.1], 'ytick', sort(unique([0, yss, ypk])));

function [num, den] = getCP(handles)
% num,den set to numerator polynomials of C * P 
pnum = get(handles.text4, 'userdata');
pden = get(handles.text5, 'userdata');
cnum = get(handles.text9, 'userdata');
cden = get(handles.text10, 'userdata');
num = conv(cnum, pnum);
den = conv(cden, pden);

function doporplcontrol(handles, mode)
% mode is 1 for P control, 2 for PhLead
setuppanel1(handles, mode);         % indicate doing P or PhLead control
set (handles.text12, 'string', 'Enter w where Phase is -180+PM');
                                    % Explain what is required
uicontrol(handles.edit5);           % Set so user enters into edit5 box

function dopicontrol(handles, mode)
%if mode is 3 is PI control, 4 is PID
setuppanel1(handles, mode);         % indicate doing PI / PID control
set (handles.text12, 'string', 'Select Phase used to choose working w');
uicontrol(handles.edit5);          % Set so user enters into edit5 box

function setuppanel1(handles, uval)
% set up the panel
set (handles.edit5, 'string', '');      % Clear all strings
set (handles.edit6, 'string', '');
set (handles.edit7, 'string', '');

set (handles.text12, 'visible', 'on');  % make text2 and edit 5 visible
set (handles.edit5, 'visible', 'on');
set (handles.text13, 'visible', 'off'); % hide rest of text/edit and buttons
set (handles.edit6, 'visible', 'off');
set (handles.text14, 'visible', 'off');
set (handles.edit7, 'visible', 'off');
set (handles.text15, 'visible', 'off');
set (handles.text16, 'visible', 'off');
set (handles.text17, 'visible', 'off');
set (handles.pushbutton1, 'visible', 'off');
set (handles.uipanel1, 'visible', 'on');
u = zeros(1,10); u(1)=uval;  u(2)=1;   % indicate which control, step 1
set(handles.uipanel1, 'userdata', u);
switch uval                             % Put Title to Panel
    case 1, set(handles.uipanel1, 'title', 'Designing Control Gain');
    case 2, set(handles.uipanel1, 'title', 'Designing Te and Ta');
    case 3, set(handles.uipanel1, 'title', 'Designing Ti for P+I');
    case 4, set(handles.uipanel1, 'title', 'Designing Ti and Td for PID');
end

function pcontrolcheckw(handles, wmode)
% called when user has entered estimate of w for Phase is -180+PM ...
% wmode is 1 if doing P control is 2 if doing Ph Lead
% first check that have good enough estimate for w 
% edit 5 has estimate, PM is in edit3
[ok, aval, eval] = gocheck(handles, str2num(get(handles.edit5, 'string')), ...
                    2, 3, -180 + str2num(get(handles.edit3, 'string')));
if wmode == 1,              % set up string for next question
   t13str = 'Enter gain at above w';
else
   t13str = ['Enter Phase at ', num2str(aval * strval(handles.edit4))];
end
p1firston (handles, ok, aval, eval, t13str);    % move to next question

function pcontroldogain(handles)
% here put check that right Gain for where Phase -180+PM
[ok, aval, eval] = gocheck(handles, str2num(get(handles.edit6, 'string')), ...
                    3, 1, str2num(get(handles.edit5, 'string')));
                    % Next move to next question
p1secondon (handles, ok, aval, eval, 'Thus controller gain is');

function pcontrolok(handles)
% Check if user entered acceptable gain for controller
eval = str2num(get(handles.edit7, 'string'));       % user estimate
aval = 1/str2num(get(handles.edit6, 'string'));     % should be 1/that in edit6
ok = (eval/aval < 1.1) & (eval/aval < 1.1);
if p1thirdon (handles, ok, aval, eval);             % if good enough
    allcontrolok (handles, num2str(aval), aval, '', 1, 'off');
                % install controller with this gain
end

function phldspeedcheck(handles)
% check whether phase in edit 6 is good estimate of phase at w=edit5*speedup
[ok, aval, eval] = gocheck(handles, strval(handles.edit6), ...
                    3, 2, strval(handles.edit5) * strval(handles.edit4));
ok = abs(eval-aval) < 10;           % ok if with 10 degrees
p1secondon (handles, ok, aval, eval, 'C needs how much phase lead');
        % Then move to next question ...

function phldcontrolok(handles)
% Check if user has identified correct phase for controller
aval = -180 + strval(handles.edit3) - strval(handles.edit6);
    % actual val = -180 + PM - phase identified and put in edit6
eval = strval(handles.edit7);   % user's estimate
if p1thirdon (handles, abs(eval-aval) < 5, aval, eval);
    g = tand(45 - strval(handles.edit7)/2);         % compute range of Leadlag
    nwx = strval(handles.edit4) * strval(handles.edit5);   % and n * wx
    te = 1 / (nwx*g);                               % hence lead time const
    ta = g / nwx;                                   % and lag tc
    allcontrolok (handles, ['(1 + s', num2str(te),')'],[te 1], ...
                           ['/(1 + s', num2str(ta), ')'], [ta 1], 'on');
end

function picontrolcheckphase(handles, wmode)
% wmode is 3 if doing PI control is 4 if doing PID 
% here put check that Phase around -90 or -180   ... allow lee way
if wmode == 3, aval = -90; else aval = -180; end   
eval = strval(handles.edit5);           % user's estimate
ok = abs(eval-aval) < 40;               % allow up to 40 deg out
p1firston (handles, ok, eval, eval, ['Estimate wx where phase is ', get(handles.edit5, 'string')]);
% note user is allowed to specify value near -90/-180 and system accepts it

function picontrolcheckw(handles, wmode)
% wmode is 3 if doing PI control is 4 if doing PID
% here put check that right w for Phase specified in edit 5
[ok, aval, eval] = gocheck(handles, str2num(get(handles.edit6, 'string')), ...
                    2, 3, strval(handles.edit5'));
p1secondon (handles, ok, aval, eval, 'Estimate Phase needed for C(s)');

function picontrolok(handles)
% check that the user has entered correct phase required for controller
% Namely -180 + PM - phase user specified in edit5
aval = -180 + strval(handles.edit3) - strval(handles.edit5);
eval = strval(handles.edit7);       %users value
if p1thirdon (handles, abs(eval-aval) < 5, aval, eval);
    wx = strval(handles.edit6);                     % wx is chosen freq
    ti = tand(strval(handles.edit7) + 90) / wx;     % compute Ti
    allcontrolok (handles, ['(1 + 1/s', num2str(ti),')'], ...
                           [1 1/ti], '', [1 0], 'off');
end

function pidcontrolok(handles)
% check if user has identified correct phase of PID controller
aval = -180 + strval(handles.edit3) - strval(handles.edit5);
eval = strval(handles.edit7);
if p1thirdon (handles, abs(eval-aval) < 5, aval, eval);
    wx = strval(handles.edit6);
    ti = 2 * cosd(aval) / (wx * (1 - sind(aval)));
    td = ti/4;
    allcontrolok (handles, ['(1 + 1/s', num2str(ti),' + s', num2str(td), ')'], ...
                           [td 1 1/ti], '', [1 0], 'off');
end

function p1firston (handles, ok, aval, eval, t13str)
% If ok, then install aval as good estimate for eval in edit5
% then setting text13 string with next question, answer to go in edit6
if ok
    set (handles.edit5, 'string', num2str(aval));   % install actual val
    set (handles.text15, 'string', [num2str(eval), ' is good estimate: actual value above']);
    set (handles.text13, 'string', t13str);         % now set up and show text13 str
    set (handles.text13, 'visible', 'on');          
    set (handles.edit6, 'visible', 'on');           % and set so user enters into edit6
    uicontrol(handles.edit6);
else
    set (handles.text15, 'string', 'Estimate too far off - try again');
end
set (handles.text15, 'visible', 'on');

function p1secondon (handles, ok, aval, eval, t14str) 
% If ok, then install aval as good estimate for eval, setting text14 string
% then setting text14 string with next question, answer to go in edit7
if ok
    set (handles.edit6, 'string', num2str(aval));   % install actual val
    set (handles.text15, 'string', [num2str(eval), ' is good estimate: actual value above']);
    set (handles.text14, 'visible', 'on');
    set (handles.edit7, 'visible', 'on');
    set (handles.text14, 'string', t14str);
    uicontrol(handles.edit7);
else
    set (handles.text15, 'string', 'Estimate too far off - try again');
end
set (handles.text15, 'visible', 'on');

function ans = p1thirdon (handles, ok, aval, eval) 
% if estimate ok, then install actual value
if ok 
    set (handles.edit7, 'string', num2str(aval));   % install actual val
    set (handles.text15, 'string', [num2str(eval), ' is good estimate: actual value above']);
else
    set (handles.text15, 'string', 'Estimate too far off - try again');
end    
ans = ok;

function allcontrolok (handles, t16str, t16ud, t17str, t17ud, t17vis)
% install Controller numerator in t16 and denominator in t17
% then make OK,ESC buttons visible
    set (handles.text16, 'string', t16str);
    set (handles.text16, 'userdata', t16ud);
    set (handles.text16, 'visible', 'on');
    set (handles.text17, 'string', t17str);
    set (handles.text17, 'userdata', t17ud);
    set (handles.text17, 'visible', t17vis);
    set (handles.pushbutton1, 'visible', 'on');

    
function controlputin(handles, doden)
% Install proposed controller in strings text9 and 10
% if doden = 0, then only do numerator
cnum = conv (get(handles.text9, 'userdata'), get(handles.text16, 'userdata'));
set(handles.text9, 'userdata', cnum);
set(handles.text9, 'string', addtocstr (handles.text9, get(handles.text16, 'string')));
if doden
    cden = conv (get(handles.text10, 'userdata'), get(handles.text17, 'userdata'));
    set(handles.text10, 'userdata', cden);
    set(handles.text10, 'string', addtocstr (handles.text10, get(handles.text17, 'string')));
end    
plotstep(handles);              % plot step response
set(handles.uipanel1, 'visible', 'off');    % hide panel

function ans = addtocstr (item, isstr)
% add isstr * to front of string in item, 
% but just make it isstr if currently string is 1
wasstr = get(item, 'string');
if wasstr == '1'
    ans = isstr;
else
    ans = [isstr, ' * ', wasstr];
end

function [ok, aval, eval] = gocheck(handles, sval, vec1, vec2, val)
% estimated value is eval, actual val found by searching [m,p or w] for val
eval = sval;
[m,p,w] = getbode(handles);
all3 = [m,p,w];
%aval = interp1(all3(:,vec1), all3(:,vec2), val, 'spline');
aval = multisearch(all3(:,vec1), all3(:,vec2), val, eval);
if vec2 == 2   % if searching linear phase
    prange = p(1)-p(end);
    ok = abs(aval - eval) < prange/20;
else
%    if vec2 == 1, range = 0.00005*m(1)/m(end); else range = 0.0002*w(end)/w(1); end
    if vec2 == 1, range = 3; else range = 1.4; end
    err = eval / aval;
    ok = (err > 1/range) & (err < range);
end

function val = multisearch (vec1, vec2, sval, eval)
% to cope with cases where vec1 is not monotonic
tv = sign(diff(vec1));
tpos = find(diff(tv)>0);            % find if vec1 starts to rise
if isempty(tpos)                    % all of vec monotonic, search it
    val = interp1(vec1, vec2, sval, 'spline');
else
    val = interp1(vec1(1:tpos(1)), vec2(1:tpos(1)), sval, 'spline');
                        % search where vec1 monotonic
    tpos2 = find(diff(tv)<0);       % look to see where starts to fall again
    if ~isempty(tpos2)
        te = length(vec1);          % find end of vec, search from tpos2 to end
        val2 = interp1(vec1(tpos2+1:te), vec2(tpos2+1:te), sval, 'spline');
                                    % now look to see which of estimates
                                    % closer to value looking for (eval)
        if abs (val - eval) > abs (val2 - eval)
            val = val2;
        end
    end
end

function ans = strval(item)
ans = str2num(get(item, 'string'));

function ans = polyadd (m1, m2)
% Returns m1 + m2, where m1 and m2 are row vectors
% But first ensures both of same size
% Dr Richard Mitchell, 3/12/99 .. 20/1/04
ldiff = length(m1) - length(m2);
if ldiff < 0, 
    m1 = [zeros(1,-ldiff) m1];  % add extra 0s to m1
elseif ldiff > 0
   m2 = [zeros(1,ldiff) m2];    % add extra 0s to m2
end;
ans = m1 + m2;          % now add m1 and m2 together


% --- Executes on button press in pushbutton4.
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
if length(get(handles.pushbutton1, 'visible')) == 2    % ie is on
    dmode = 3;
elseif length(get(handles.text14, 'visible')) == 2
    dmode = 2;
elseif length(get(handles.text13, 'visible')) == 2
    dmode = 1;
else
    dmode = 0;
end
hstr = 'unknown';
u = get(handles.uipanel1, 'userdata');
% if strcmp(get(handles.uipanel1,'Title'), 'Designing Control Gain')
%     lb = 1;
% else lb =  get(handles.listbox1, 'value')
% end
switch dmode*4 + u(1,1)
    case {1, 2}, hstr = 'Look at Phase Graph to Estimate w';
    case 3, hstr = 'For PI control this is typically -90';
    case 4, hstr = 'For PID control this is typically -180';
    case 5, hstr = ['What is gain at w = ', get(handles.edit5, 'string')];
    case 6, hstr = ['What is Phase at w = ', get(handles.edit5, 'string')];
    case {7, 8}, hstr = 'Look at Phase Graph to Estimate w';
    case 9, hstr = 'Should be 1 over gain at this w';
    case 10, hstr = ['Should be -180 + PM - ',  get(handles.edit6, 'string')];
    case {11,12}, hstr = ['Should be -180 + PM - ', get(handles.edit5, 'string')];
    case {13,14, 15, 16}, hstr = 'Press OK if C looks ok, else Cancel';
  %      else, hstr = 'Workng on it';
end
set(handles.text18, 'string', hstr);
set(handles.text18, 'visible', 'on');
