forked from lordnathan0/MagicSimNode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
msfun_realtime_pacer.m
115 lines (98 loc) · 3.88 KB
/
msfun_realtime_pacer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
function msfun_realtime_pacer(block)
% Help for Writing Level-2 M-File S-Functions:
% web([docroot '/toolbox/simulink/sfg/f7-67622.html']
% http://www.mathworks.com/access/helpdesk/help/toolbox/simulink/sfg/f7-67622.html
% Copyright 2009, The MathWorks, Inc.
% instance variables
mySimTimePerRealTime = 1;
myRealTimeBaseline = 0;
mySimulationTimeBaseline = 0;
myResetBaseline = true;
myTotalBurnedTime = 0;
myNumUpdates = 0;
setup(block);
%% ---------------------------------------------------
function setup(block)
% Register the number of ports.
block.NumInputPorts = 0;
block.NumOutputPorts = 0;
% Set up the states
block.NumContStates = 0;
block.NumDworks = 0;
% Register the parameters.
block.NumDialogPrms = 1; % scale factor
block.DialogPrmsTunable = {'Nontunable'};
% Block is fixed in minor time step, i.e., it is only executed on major
% time steps. With a fixed-step solver, the block runs at the fastest
% discrete rate.
block.SampleTimes = [0 1];
block.SetAccelRunOnTLC(false); % run block in interpreted mode even w/ Acceleration
% methods called during update diagram/compilation.
block.RegBlockMethod('CheckParameters', @CheckPrms);
% methods called at run-time
block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Update', @Update);
block.RegBlockMethod('SimStatusChange', @SimStatusChange);
block.RegBlockMethod('Terminate', @Terminate);
end
%%
function CheckPrms(block)
try
validateattributes(block.DialogPrm(1).Data, {'double'},{'real', 'scalar', '>', 0});
catch %#ok<CTCH>
throw(MSLException(block.BlockHandle, ...
'Simulink:Parameters:BlkParamUndefined', ...
'Enter a number greater than 0'));
end
end
%%
function Start(block)
mySimTimePerRealTime = block.DialogPrm(1).Data;
myTotalBurnedTime = 0;
myNumUpdates = 0;
myResetBaseline = true;
if strcmp(pause('query'),'off')
fprintf('%s: Enabling MATLAB PAUSE command\n', getfullname(block.BlockHandle));
pause('on');
end
end
%%
function Update(block)
if myResetBaseline
myRealTimeBaseline = tic;
mySimulationTimeBaseline = block.CurrentTime;
myResetBaseline = false;
else
if isinf(mySimTimePerRealTime)
return;
end
elapsedRealTime = toc(myRealTimeBaseline);
differenceInSeconds = ((block.CurrentTime - mySimulationTimeBaseline) / mySimTimePerRealTime) - elapsedRealTime;
if differenceInSeconds >= 0
pause(differenceInSeconds);
myTotalBurnedTime = myTotalBurnedTime + differenceInSeconds;
myNumUpdates = myNumUpdates + 1;
end
end
end
%%
function SimStatusChange(block, status)
if status == 0,
% simulation paused
fprintf('%s: Pausing real time execution of the model (simulation time = %g sec)\n', ...
getfullname(block.BlockHandle), block.CurrentTime);
elseif status == 1
% Simulation resumed
fprintf('%s: Continuing real time execution of the model\n', ...
getfullname(block.BlockHandle));
myResetBaseline = true;
end
end
%%
function Terminate(block)
if myNumUpdates > 0
fprintf('%s: Average idle real time per major time step = %g sec\n', ...
getfullname(block.BlockHandle), myTotalBurnedTime / myNumUpdates);
end
end
end