📄 xferplot.m
字号:
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
ystem = get(block_data.hstem,'ydata');
ystem( 3*nrows*d + (0:length(u)-1)*3 + 2 ) = u;
set(block_data.hstem,'ydata',ystem);
end
if (d >= nframes-1),
% install non-init update fcn:
% Cache the appropriate line-update function:
block_data.UpdateLinesFcn = @update_lines_time_multiframe_onechan;
ud=get(block_data.hfig,'userdata');
set_param(ud.block,'userdata',block_data);
end
% ---------------------------------------------------------------
function update_lines_time_multiframe_onechan(block_data, u)
% Multiple frames per horiz span
% Single channel
[nrows,nchans] = size(u);
nframes = block_data.params.HorizSpan;
y = get(block_data.hline,'YData')';
y(1 : nrows*(nframes-1)) = y(nrows+1:nrows*nframes);
y(nrows*(nframes-1)+1 : end) = u;
set(block_data.hline, 'YData', y);
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
ystem = get(block_data.hstem,'ydata');
ystem(1 : 3*nrows*(nframes-1)) = ystem(3*nrows+1:3*nrows*nframes);
ystem( 3*nrows*(nframes-1) + (0:length(u)-1)*3 + 2 ) = u;
set(block_data.hstem,'ydata',ystem);
end
% ---------------------------------------------------------------
function init_lines_time_multiframe_multichan(block_data, u)
% Multiple frames per horiz span
% Multiple channels, multiple frames (matrix input)
[nrows,nchans] = size(u);
nframes = block_data.params.HorizSpan;
hline = block_data.hline;
% Use the frame counter to determine where we are:
% Counter starts at 0, since it is incremented after
% update_lines occurs.
d = get(block_data.hframenum(2),'userdata');
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
% ystem contains "triplets" of data
% [y1top y1bottom NaN y2top y2bottom NaN ...]
ystem = get(block_data.hstem,'ydata');
% k = indices of (d+1)th frame
k = nrows*d+1 : nrows*(d+1);
k = (k-1)*3+2;
kdn = k-1;
ystem(k) = 0;
ystem(kdn) = 0;
markerpipestr = block_data.params.LineMarkers;
for i = 1:nchans,
y = get(hline(i),'YData');
val = u(:,i)';
y(d*nrows+1 : (d+1)*nrows) = val;
set(hline(i), 'YData', y);
if strcmp(get_pipestr(markerpipestr, i,1), 'stem'),
ystem(k) = max(ystem(k), val);
ystem(kdn) = min(ystem(kdn), val);
end
end
set(block_data.hstem,'ydata',ystem);
else
for i = 1:nchans,
y = get(hline(i),'YData')';
y(d*nrows+1 : (d+1)*nrows, :) = u(:,i);
set(hline(i), 'YData', y);
end
end
if (d >= nframes-1),
% install non-init update fcn:
% Cache the appropriate line-update function:
block_data.UpdateLinesFcn = @update_lines_time_multiframe_multichan;
ud=get(block_data.hfig,'userdata');
set_param(ud.block,'userdata',block_data);
end
% ---------------------------------------------------------------
function update_lines_time_multiframe_multichan(block_data, u)
% Multiple frames per horiz span
% Multiple channels, multiple frames (matrix input)
[nrows,nchans] = size(u);
nframes = block_data.params.HorizSpan;
hline = block_data.hline;
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
% ystem contains "triplets" of data
% [y1top y1bottom NaN y2top y2bottom NaN ...]
ystem = get(block_data.hstem,'ydata');
% copy stem values from last (span-1) frames to first (span-1) frames
ystem(1 : 3*nrows*(nframes-1)) = ystem(3*nrows+1:end);
% k = indices of last frame
k = nrows*(nframes-1)+1 : nrows*nframes;
k = (k-1)*3+2;
kdn = k-1;
ystem(k) = 0;
ystem(kdn) = 0;
markerpipestr = block_data.params.LineMarkers;
for i = 1:nchans,
y = get(hline(i),'YData');
y(1 : nrows*(nframes-1)) = y(nrows+1:end);
val = u(:,i)';
y(nrows*(nframes-1)+1 : end) = val;
set(hline(i), 'YData', y);
if strcmp(get_pipestr(markerpipestr, i,1), 'stem'),
ystem(k) = max(ystem(k), val);
ystem(kdn) = min(ystem(kdn), val);
end
end
set(block_data.hstem,'ydata',ystem);
else
for i = 1:nchans,
y = get(hline(i),'YData');
y(1 : nrows*(nframes-1)) = y(nrows+1:end);
y(nrows*(nframes-1)+1 : end) = u(:,i);
set(hline(i), 'YData', y);
end
end
% ---------------------------------------------------------------
function OpenScope(blk)
% Open the scope in response to the 'OpenScopeImmediately' dialog
% checkbox being pressed.
% If scope is already open, bring it forward and return
%
block_data = get_param(blk,'UserData');
if ~isfield(block_data,'hfig'), return; end
if ~isempty(block_data.hfig),
% Scope exists
% Two options:
% 1 - Simply bring existing scope forward and return:
% figure(block_data.hfig);
% 2 - do nothing
return;
end
% Need to open/re-open scope:
status = get_param(bdroot(blk),'simulationstatus');
isRunning = ~strcmp(status,'stopped');
if isRunning,
openScopeWhileRunning(blk);
end
% ---------------------------------------------------------------
function openScopeWhileRunning(blk)
% Respond to user request to open the scope
% (eg, user pressed button in block dialog)
%
% We must open GUI; thus, we ignore "OpenScopeAtSimStart" setting in dialog
% (pass flag=1 to force GUI to open)
resetToFirstCall(blk,1);
% nothing else to do
% scope will re-open at next time step
% ---------------------------------------------------------------
function resetToFirstCall(blk, mustOpen)
% Sets up block and GUI prior to opening the scope
%
% Resets hfig handle if not present
% Sets firstcall flag to either open the gui on the next
% time step, or keep it closed, according to the block
% parameter "OpenScopeAtSimStart".
%
% If mustOpen is passed in, the decision to open a GUI
% will come from mustOpen instead of the dialog param.
block_data = get_param(blk,'UserData');
% Determine if scope should open at next time step:
if nargin>1,
block_data.firstcall = mustOpen;
else
% NOTE: This is called before params are set into block_data
block_data.firstcall = isOn(get_param(blk,'OpenScopeAtSimStart'));
% block_data.firstcall = strcmp(block_data.params.OpenScopeAtSimStart,'on');
end
% Setup empty figure handle if handle not recorded:
if ~isfield(block_data,'hfig'),
block_data.hfig = [];
end
set_param(blk,'UserData',block_data);
% ---------------------------------------------------------------
function startLineEraseMode(blk)
% Set channel lines to proper erase mode at start of simulation.
% The lines are set to 'normal' mode when a simulation terminates;
% when lines redraw over themselves in "xor" mode, dots are left at
% peaks without lines connecting to them. This can be visually misleading.
block_data = get_param(blk,'UserData');
if isOn(block_data.params.Memory),
emode='none'; % Memory mode
else
emode='xor';
end
set([block_data.hline(:) ; block_data.hstem(:)], 'EraseMode',emode);
set(block_data.hframenum, 'EraseMode','xor');
% ---------------------------------------------------------------
function terminateLineEraseMode(blk)
% Set channel line erase mode at simulation termination
block_data = get_param(blk,'UserData');
% Skip if HG window is closed:
if isempty(block_data.hfig),
return;
end
if isOn(block_data.params.Memory),
emode='none'; % Memory mode
else
emode='normal';
end
set([block_data.hline(:) ; block_data.hstem(:)], 'EraseMode',emode);
set(block_data.hframenum, 'EraseMode','normal');
% ---------------------------------------------------------------
function first_update(blk, sfcn_blk, u, params)
% FIRST_UPDATE Called the first time the update function is executed
% in a simulation run. Creates a new scope GUI if it does not exist,
% or restarts an existing scope GUI.
% blk: masked subsystem block
% sfcn_blk: name of s-function block under the masked subsystem
% u: one frame of data
% Updates block_data
block_data = get_param(blk,'UserData');
% Get dimensions of input port of scope block:
% Particularly useful for the Spectrum Scope, where
% the internal buffering and FFT blocks may change
% the signal width without our knowledge:
%
inBlk = [blk '/In1'];
dimsVect = get_param(inBlk,'CompiledPortDimensions');
block_data.inputDims = dimsVect.Outport(2:end);
% Record input frame time to the input port of the subsystem
% (and not the S-fcn itself!)
%
% NOTE: This is the per-sample time, NOT the per-frame time
%
ts = get_param(inBlk,'CompiledSampleTime');
block_data.Ts = ts(1) ./ block_data.inputDims(1); % ignore sample offset time
% Check sample time:
% - disallow continuous signals
% - allow fixed- and variable-step discrete
if ts(1)==0,
error('Continuous-time inputs are not supported.');
end
% Check input data complexity and type:
if ~isreal(u) | ~isa(u,'double'),
error('Inputs must be real, double-precision values.');
end
% Construct new scope figure window, or bring up old one:
if isfield(block_data,'hfig'),
hfig = block_data.hfig; % scope already exists
else
hfig = []; % scope was never run before
end
if isfield(block_data,'NChans') & (block_data.NChans ~= size(u,2)),
% Close the figure if the # of channels has changed
% The GUI may need to be reconfigured significantly for
% a change in channel count.
CloseFigure([],[],blk);
hfig=[];
end
[block_data.samples_per_frame, block_data.NChans] = size(u);
set_param(blk, 'UserData', block_data);
% Establish a valid scope GUI:
if ~isempty(hfig),
% Found existing scope figure window:
% Prepare to re-start with existing scope window:
fig_data = restart_scope(blk, params);
% If things did not go well during restart, say the axis
% was somehow deleted from the existing scope figure, etc.,
% then hfig is left empty, and a new scope must be created.
% Get hfig, then check if it is empty later:
hfig = fig_data.hfig;
end
if isempty(hfig),
% Initialize new figure window:
% Create the scope GUI
fig_data = create_scope(blk, params, block_data.NChans);
end
% Get line handle:
hline = fig_data.main.hline;
hstem = fig_data.main.hstem;
hgrid = fig_data.main.hgrid;
% Retain the name of the figure window for use when the
% block's name changes. Name is retained in S-fcn block's
% user-data:
block_data.firstcall = 0; % reset "new simulation" flag
block_data.hfig = fig_data.hfig;
block_data.params = params;
block_data.hcspec = fig_data.hcspec;
block_data.haxis = fig_data.main.haxis;
block_data.hline = hline;
block_data.hstem = hstem;
block_data.hgrid = hgrid;
block_data.hframenum = fig_data.main.hframenum;
block_data.autoscaling = []; % turn off any autoscaling, if in progress
if ~isfield(block_data,'hgridtext'),
block_data.hgridtext = []; % only exists in block_data, not fig_data
end
if ~isfield(block_data,'hlegend'),
block_data.hlegend = []; % ditto
end
% Cache the appropriate line-update function:
block_data.UpdateLinesFcn = select_UpdateLinesFcn(block_data);
% Set block's user data:
set_param(blk, 'UserData', block_data);
% The following block callbacks are assumed to be set
% in the library block:
%
% CopyFcn "sdspfscope2([],[],[],'BlockCopy');"
% DeleteFcn "sdspfscope2([],[],[],'BlockDelete');"
% NameChangeFcn "sdspfscope2([],[],[],'NameChange');"
SetMenuChecks(blk); % update state of menu items
setup_axes(blk); % send one frame of data for axis setup
update_lines(block_data, u); % one frame of data
% ---------------------------------------------------------------
function h = getDisableMenuHandles(blk, lineNum)
block_data = get_param(blk,'UserData');
hfig = block_data.hfig;
fig_data = get(hfig,'UserData');
h = fig_data.menu.linedisable(:,lineNum);
% ---------------------------------------------------------------
function h = getMarkerMenuHandlesFromMarker(blk, lineNum, marker)
% If marker is empty, we won't find any match
% Just return a quick empty:
if isempty(marker),
h=[]; return;
end
block_data = get_param(blk,'UserData');
hfig = block_data.hfig;
fig_data = get(hfig,'UserData');
% Get handles to just one of the options menu line style items.
% The context (and other line #) menus simply contain redundant info.
%
hmenus = fig_data.menu.linemarker; % [options;context] x [line1 line2 ...]
hmarkers = get(hmenus(:,lineNum),'child'); % marker menu items for lineNum menu, options/context
hmarkers = cat(2,hmarkers{:}); % matrix of handles: markers x [options context]
menuMarkers = get(hmarkers(:,1),'UserData'); % cell array of marker strings just for options menu
h = []; % in case no match is found
for i=1:size(hmarkers,1),
if isequal(marker, menuMarkers{i}),
% Found a matching marker entry
% Return both Options and Context menu handles for
% corresponding style entry for line number lineNum
h = hmarkers(i,:);
return;
end
end
% ---------------------------------------------------------------
function h = getStyleMenuHandlesFromStyle(blk, lineNum, style)
% If style is empty, we won't find any match
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -