samer@0: % arrow_sched - Instantiate arrow system to run on background timer and drop into REPL. samer@0: % samer@0: % arrow_sched :: samer@0: % arrow({},_,_) ~'arbitrary arrow with no inputs', samer@0: % nonneg ~'period of timer', samer@0: % options { samer@0: % sched_fig :: handle /0 ~'figure number for scheduler control UI'; samer@0: % draw :: boolean /false ~'do drawnow after each iteration'; samer@0: % exec_mode :: string / 'fixedSpacing' ~'timer execution mode' samer@0: % } samer@0: % -> {...}. samer@0: % samer@0: % This function provides a command line with access to a live samer@0: % system instantiated from the given arrow. The command line samer@0: % has the prompt 'with_sched>> ' to distinguish it from the normal samer@0: % Matlab prompt, but in other respects, is the same. The only samer@0: % commands that function differently are 'quit' and 'exit', samer@0: % which are trapped and behave as 'return' does, returning control samer@0: % to this function. Arbitrary values can be returned through to samer@0: % the called of arrow_repl using ret, eg samer@0: % unit>> ret(get_state(),45); samer@0: % returns two values: the current state of the system and the samer@0: % value 45. samer@0: % samer@0: % The environment contains the following variables of interest: samer@0: % sys :: arrow(A,B,S). % the original arrow samer@0: % unit :: unit(A,B,S). % the live processing unit samer@0: % sched :: struct. % scheduler structure (see rsched) samer@0: % samer@0: % The following functions are also available: samer@0: % get_state :: () -> S. % returns the state of the system samer@0: % set_state :: S -> action (). % sets the state of the system samer@0: % stop :: () -> action (). % stop processing in timer thread. samer@0: % start :: () -> action (). % start processing in timer thread. samer@0: % startat :: time -> action (). % start processing at given time (see nows). samer@0: % set_period :: nonneg -> action (). % set period of timer (stops and restarts) samer@0: % samer@0: % While running, the background thread calls unit.process() on each samer@0: % iteration, so the system must have zero inputs. It can have any samer@0: % number of outputs--these are all discarded while running. samer@0: samer@0: function varargout=arrow_sched(sys,period,varargin) samer@37: opts=options('sched_fig',0,'draw',0,'exec_mode','fixedSpacing','start',0,varargin{:}); samer@0: [varargout{1:nargout}]=with_arrow(sys,@with_sched,{},opts,'keyboard',0); samer@0: samer@0: function varargout=with_sched(unit) samer@0: if opts.draw, stepfn=@step_draw; else stepfn=@step; end samer@0: samer@0: returns={}; samer@0: uihandles=[]; samer@0: sched=rsched(stepfn,1,period,0,'onstart',@onstart,'onstop',@onstop,'defer',1); samer@0: try samer@0: set(sched.timer(),'ExecutionMode',opts.exec_mode); samer@0: if opts.sched_fig>0 samer@0: figure(opts.sched_fig); samer@0: uihandles=sched_ui(sched,12); samer@0: end samer@0: samer@0: fprintf('\n'); samer@0: if opts.start, samer@0: fprintf('\nStarting automatically as requested.\n'); samer@0: start; samer@0: end samer@0: samer@0: fprintf('\nEntering REPL. Type "return","exit", or "quit" to finish.\n'); samer@0: fprintf('The function ret(..) sets return values.\n\n'); samer@0: cont=true; samer@0: while cont, samer@0: str=input('with_sched>> ','s'); samer@0: if strcmp(str,'quit') break; end samer@0: if strcmp(str,'exit') break; end samer@0: if strcmp(str,'return') break; end samer@0: try, eval(str) samer@0: catch ex samer@0: fprintf('\n%s\n',getReport(ex)); samer@0: end samer@0: end samer@0: catch ex samer@0: if ~isempty(uihandles), delete(uihandles); end samer@0: if sched.isrunning(), sched.stop(); end samer@0: sched.dispose(); samer@0: rethrow(ex); samer@0: end samer@0: samer@0: if ~isempty(uihandles), delete(uihandles); end samer@0: if sched.isrunning(), sched.stop(); end samer@0: sched.dispose(); samer@0: varargout=returns; samer@0: samer@0: function step1 samer@0: if sched.isrunning(), error('Already running'); samer@0: else samer@0: unit.starting(); samer@0: unit.process(); samer@0: unit.stopping(); samer@0: end samer@0: end samer@0: samer@0: function set_period(d) samer@0: if sched.isrunning(), stop; set(sched.timer(),'Period',d); start; samer@0: else set(sched.timer(),'Period',d); end samer@0: end samer@0: samer@0: function startat(t), sched.startat(t); end samer@0: function start, sched.start(); end samer@0: function stop, sched.stop(); end samer@0: function set_state(s), unit.set_state(s); end samer@0: function s=get_state, s=unit.get_state(); end samer@0: function onstart(s,t,t0), unit.starting(); end samer@0: function onstop(s,t), unit.stopping(); end samer@0: function ret(varargin), returns=varargin; cont=false; end samer@0: function run_for(its) samer@0: set(sched.timer(),'TasksToExecute',its); samer@0: start; samer@0: end samer@0: samer@0: function [s,t0]=step(s,per,t0,dt), samer@0: unit.process(); samer@0: end samer@0: samer@0: function [s,t0]=step_draw(s,per,t0,dt) samer@0: unit.process(); samer@0: drawnow; samer@0: end samer@0: end samer@0: end