function [sys,x0,str,ts,simStateCompliance] = tankcontrol_sfun(t,x,u,flag,inflow,outflow, ...
                                           lolim,hilim,area)

switch flag

  %%%%%%%%%%%%%%%%%%
  % Initialization %
  %%%%%%%%%%%%%%%%%%
  case 0
    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;

  %%%%%%%%%%
  % Update %
  %%%%%%%%%%
  case 2
    sys=mdlUpdate(t,x,u,inflow,outflow,lolim,hilim,area);
  
  %%%%%%%%%%%%%%%%%%%
  % Unhandled flags %
  %%%%%%%%%%%%%%%%%%%
  case { 1, 3, 4, 9 }
    sys=[];

  %%%%%%%%%%%%%%%%%%%%
  % Unexpected flags %
  %%%%%%%%%%%%%%%%%%%%
    otherwise
    SLdemo_tank_UnhandledFlag = 'Unhandled flag %d';
    error('Simulink:sldemo_tanksfun:UnhandledFlag',...
           SLdemo_tank_UnhandledFlag, flag);

end

% end sldemo_tanksfun

%
%=============================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%=============================================================================
%
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes

%
% call simsizes for a sizes structure, fill it in and convert it to a
% sizes array.
%

sizes = simsizes;

sizes.NumContStates  = 0;
sizes.NumDiscStates  = 0;
sizes.NumOutputs     = 0;
sizes.NumInputs      = 4;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;   % at least one sample time is needed

sys = simsizes(sizes);

%
% initialize the initial conditions
%
x0  = [];

%
% str is always an empty matrix
%
str = [];

%
% initialize the array of sample times
%
ts  = [0 0];

% specify that the simState for this s-function is same as the default
 simStateCompliance = 'DefaultSimState';
% end mdlInitializeSizes

%
%=============================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%=============================================================================
%
function sys=mdlUpdate(t,x,u,inflow,outflow,lolim,hilim,area) %#ok

%
% initialize the return arg
%
sys=[];

invalve=u(1);
outvalve=u(2);
stir=u(3);
tankheight=u(4);
STATE_ON = 'ON';
STATE_OFF = 'OFF';


figs = tankgui('figures');
if ~ishghandle(figs(1),'figure')
  tankgui
end

h=get(figs(1),'UserData');

ax=findobj(figs(1),'type','axes','Tag','picture');
if isempty(ax)
  tankgui
  ax=findobj(figs(1),'type','axes','Tag','picture');
end

g=get(ax,'UserData');

%
% update water height patches
%
edge=sqrt(area);
outwidth = sqrt(outflow)/pi;
inwidth = sqrt(inflow)/pi;
len=max(1,max(edge,hilim)/5);
top=1.25*max(hilim, lolim+outwidth);
tubeheight=min(tankheight,lolim+outwidth);

ref.a = (edge/2-inwidth/2);
ref.b = ref.a+inwidth;
ref.c = ref.a-len/2;
ref.d = top+2*len+inwidth;
ref.e = lolim+outwidth;
in.vert.y=[top+len top+len top+2*len+inwidth top+2*len+inwidth top+len];
bottomedge = [-len -len -len -len -len];

set([g.water.main, g.water.outh, g.water.outv g.grey.outh ... 
      g.grey.outv g.grey.main], ...
   {'Ydata'},...
   {[0 0 tankheight tankheight 0];...
    [lolim lolim tubeheight tubeheight lolim];...
    [-len -len tubeheight tubeheight -len];...
    [tubeheight tubeheight ref.e ref.e tubeheight];...
    [tubeheight tubeheight ref.e ref.e  tubeheight];...
    [tankheight tankheight top top tankheight]})

 on = {'on';'on';'off';'on';'on';'on';'on';'on'};
 off = {'off';'off';'on';'off';'off';'off';'off';'off'};
% on = {'on';'on';'on';'on';'on';'on';'on';'on'};
% off = {'off';'off';'off';'off';'off';'off';'off';'off'};

%
% if in-valve is on....
%
if invalve ~= 0
  in_valve_state = STATE_ON;
  set([g.water.inv, g.valve.in.on, g.valve.in.off, g.drip.in], ...
      {'Visible'},on)
  set(g.water.inh,'Xdata',[-len ref.a ref.a -len -len])
  set(g.grey.inv,'Ydata',bottomedge)
  set(g.water.inv,'Ydata',in.vert.y)    
else
  in_valve_state = STATE_OFF;
  set([g.water.inv, g.valve.in.on, g.valve.in.off, g.drip.in],{'Visible'},off)
  set(g.water.inh,'Xdata',[-len ref.c ref.c -len -len])
  set(g.grey.inv,'Ydata',in.vert.y)  
  set(g.water.inv,'Ydata',bottomedge)
end

%
% if out valve is on.....
%
if outvalve ~= 0
  out_valve_state = STATE_ON;
  set([g.water.outv,g.valve.out.on,g.valve.out.off,g.drip.out],{'Visible'},on)
  set(g.water.outh,'Xdata',[edge edge+len edge+len edge edge])
  set(g.grey.outh,'Xdata',[edge edge+len edge+len edge edge])    
else
  out_valve_state = STATE_OFF;
  set([g.water.outv,g.valve.out.on,g.valve.out.off,g.drip.out],{'Visible'},off)
  set(g.water.outh,'Xdata',[edge edge+len/2 edge+len/2 edge edge])
  set(g.grey.outh,'Xdata',[edge edge+len/2 edge+len/2 edge edge])
  set(g.grey.outv,'Ydata',[-len -len ref.e ref.e -len])
end

%
% update comment text
%
if outvalve ~= 0
    tank_state = 'Flusssh!';
elseif invalve ~= 0
    tank_state = 'Filling';
else
    if tankheight<=lolim
        tank_state = 'Empty';      
    elseif tankheight >=hilim
        if stir>0
            tank_state = 'Stir-Stir-Stir';
        else
            tank_state = 'Full';
        end
    else
        tank_state = 'Hold';
    end
end
txt = sprintf('Time: %3.0f, Tank: %s, In-Valve: %s, Out-Valve: %s', t,tank_state, ...
    in_valve_state, out_valve_state);
set(h.text(6), 'String', txt);
pause(0.1);

%
% that's all folks
%
drawnow

% end mdlUpdate

% LocalWords:  Ydata Xdata Flusssh
