samer@0
|
1 % arrow_sched - Instantiate arrow system to run on background timer and drop into REPL.
|
samer@0
|
2 %
|
samer@0
|
3 % arrow_sched ::
|
samer@0
|
4 % arrow({},_,_) ~'arbitrary arrow with no inputs',
|
samer@0
|
5 % nonneg ~'period of timer',
|
samer@0
|
6 % options {
|
samer@0
|
7 % sched_fig :: handle /0 ~'figure number for scheduler control UI';
|
samer@0
|
8 % draw :: boolean /false ~'do drawnow after each iteration';
|
samer@0
|
9 % exec_mode :: string / 'fixedSpacing' ~'timer execution mode'
|
samer@0
|
10 % }
|
samer@0
|
11 % -> {...}.
|
samer@0
|
12 %
|
samer@0
|
13 % This function provides a command line with access to a live
|
samer@0
|
14 % system instantiated from the given arrow. The command line
|
samer@0
|
15 % has the prompt 'with_sched>> ' to distinguish it from the normal
|
samer@0
|
16 % Matlab prompt, but in other respects, is the same. The only
|
samer@0
|
17 % commands that function differently are 'quit' and 'exit',
|
samer@0
|
18 % which are trapped and behave as 'return' does, returning control
|
samer@0
|
19 % to this function. Arbitrary values can be returned through to
|
samer@0
|
20 % the called of arrow_repl using ret, eg
|
samer@0
|
21 % unit>> ret(get_state(),45);
|
samer@0
|
22 % returns two values: the current state of the system and the
|
samer@0
|
23 % value 45.
|
samer@0
|
24 %
|
samer@0
|
25 % The environment contains the following variables of interest:
|
samer@0
|
26 % sys :: arrow(A,B,S). % the original arrow
|
samer@0
|
27 % unit :: unit(A,B,S). % the live processing unit
|
samer@0
|
28 % sched :: struct. % scheduler structure (see rsched)
|
samer@0
|
29 %
|
samer@0
|
30 % The following functions are also available:
|
samer@0
|
31 % get_state :: () -> S. % returns the state of the system
|
samer@0
|
32 % set_state :: S -> action (). % sets the state of the system
|
samer@0
|
33 % stop :: () -> action (). % stop processing in timer thread.
|
samer@0
|
34 % start :: () -> action (). % start processing in timer thread.
|
samer@0
|
35 % startat :: time -> action (). % start processing at given time (see nows).
|
samer@0
|
36 % set_period :: nonneg -> action (). % set period of timer (stops and restarts)
|
samer@0
|
37 %
|
samer@0
|
38 % While running, the background thread calls unit.process() on each
|
samer@0
|
39 % iteration, so the system must have zero inputs. It can have any
|
samer@0
|
40 % number of outputs--these are all discarded while running.
|
samer@0
|
41
|
samer@0
|
42 function varargout=arrow_sched(sys,period,varargin)
|
samer@37
|
43 opts=options('sched_fig',0,'draw',0,'exec_mode','fixedSpacing','start',0,varargin{:});
|
samer@0
|
44 [varargout{1:nargout}]=with_arrow(sys,@with_sched,{},opts,'keyboard',0);
|
samer@0
|
45
|
samer@0
|
46 function varargout=with_sched(unit)
|
samer@0
|
47 if opts.draw, stepfn=@step_draw; else stepfn=@step; end
|
samer@0
|
48
|
samer@0
|
49 returns={};
|
samer@0
|
50 uihandles=[];
|
samer@0
|
51 sched=rsched(stepfn,1,period,0,'onstart',@onstart,'onstop',@onstop,'defer',1);
|
samer@0
|
52 try
|
samer@0
|
53 set(sched.timer(),'ExecutionMode',opts.exec_mode);
|
samer@0
|
54 if opts.sched_fig>0
|
samer@0
|
55 figure(opts.sched_fig);
|
samer@0
|
56 uihandles=sched_ui(sched,12);
|
samer@0
|
57 end
|
samer@0
|
58
|
samer@0
|
59 fprintf('\n');
|
samer@0
|
60 if opts.start,
|
samer@0
|
61 fprintf('\nStarting automatically as requested.\n');
|
samer@0
|
62 start;
|
samer@0
|
63 end
|
samer@0
|
64
|
samer@0
|
65 fprintf('\nEntering REPL. Type "return","exit", or "quit" to finish.\n');
|
samer@0
|
66 fprintf('The function ret(..) sets return values.\n\n');
|
samer@0
|
67 cont=true;
|
samer@0
|
68 while cont,
|
samer@0
|
69 str=input('with_sched>> ','s');
|
samer@0
|
70 if strcmp(str,'quit') break; end
|
samer@0
|
71 if strcmp(str,'exit') break; end
|
samer@0
|
72 if strcmp(str,'return') break; end
|
samer@0
|
73 try, eval(str)
|
samer@0
|
74 catch ex
|
samer@0
|
75 fprintf('\n%s\n',getReport(ex));
|
samer@0
|
76 end
|
samer@0
|
77 end
|
samer@0
|
78 catch ex
|
samer@0
|
79 if ~isempty(uihandles), delete(uihandles); end
|
samer@0
|
80 if sched.isrunning(), sched.stop(); end
|
samer@0
|
81 sched.dispose();
|
samer@0
|
82 rethrow(ex);
|
samer@0
|
83 end
|
samer@0
|
84
|
samer@0
|
85 if ~isempty(uihandles), delete(uihandles); end
|
samer@0
|
86 if sched.isrunning(), sched.stop(); end
|
samer@0
|
87 sched.dispose();
|
samer@0
|
88 varargout=returns;
|
samer@0
|
89
|
samer@0
|
90 function step1
|
samer@0
|
91 if sched.isrunning(), error('Already running');
|
samer@0
|
92 else
|
samer@0
|
93 unit.starting();
|
samer@0
|
94 unit.process();
|
samer@0
|
95 unit.stopping();
|
samer@0
|
96 end
|
samer@0
|
97 end
|
samer@0
|
98
|
samer@0
|
99 function set_period(d)
|
samer@0
|
100 if sched.isrunning(), stop; set(sched.timer(),'Period',d); start;
|
samer@0
|
101 else set(sched.timer(),'Period',d); end
|
samer@0
|
102 end
|
samer@0
|
103
|
samer@0
|
104 function startat(t), sched.startat(t); end
|
samer@0
|
105 function start, sched.start(); end
|
samer@0
|
106 function stop, sched.stop(); end
|
samer@0
|
107 function set_state(s), unit.set_state(s); end
|
samer@0
|
108 function s=get_state, s=unit.get_state(); end
|
samer@0
|
109 function onstart(s,t,t0), unit.starting(); end
|
samer@0
|
110 function onstop(s,t), unit.stopping(); end
|
samer@0
|
111 function ret(varargin), returns=varargin; cont=false; end
|
samer@0
|
112 function run_for(its)
|
samer@0
|
113 set(sched.timer(),'TasksToExecute',its);
|
samer@0
|
114 start;
|
samer@0
|
115 end
|
samer@0
|
116
|
samer@0
|
117 function [s,t0]=step(s,per,t0,dt),
|
samer@0
|
118 unit.process();
|
samer@0
|
119 end
|
samer@0
|
120
|
samer@0
|
121 function [s,t0]=step_draw(s,per,t0,dt)
|
samer@0
|
122 unit.process();
|
samer@0
|
123 drawnow;
|
samer@0
|
124 end
|
samer@0
|
125 end
|
samer@0
|
126 end
|