📄 xferplot.m
字号:
function [sys, x0, str, ts] = xferplot(t,x,u,varargin)
%XFERPLOT Frame- and vector-display block for the DSP Blockset.
% The DSP Blockset provides several scopes useful for visualizing
% frame- or vector-based signals in a Simulink model.
%
% The following blocks in the "DSP Sinks" library utilize this
% scope display:
% - Vector Scope
% - FFT Frame Scope
% - Buffered FFT Frame Scope
%
% These blocks accept 2-D signals, where an MxN input matrix is
% interpreted as N channels of data, each presenting M consecutive
% time samples of data. A 1-D signal is interpreted as a single
% channel of data.
%
% Most menu options are duplicated in a context menu, accessible
% by right-clicking within the scope display. Depending upon the
% scope block, and the number of data channels entering the block,
% different options are provided.
%
% See also DSPLIB.
% This is an M-file S-Function used by the DSP Blockset that
% implements a frame- or vector-based scope display.
% Copyright 1995-2001 The MathWorks, Inc.
% $Revision: 0.1 $ $Date: 2002/01/29 14:32:45 $
% RAB, tweaked for transfer function
% Syntax:
%
% xferplot(t,x,u,flag,params);
%
% where params is a structure containing all block dialog parameters.
%
% What's in the Figure userdata:
% ------------------------------
% Main scope figure handles:
% fig_data.block block name
% fig_data.hfig handle to figure
% fig_data.hcspec handle to non-displayed line for color translation
%
% fig_data.main.haxis handle to axes
% fig_data.main.hline Nx1 vector of line handles
% fig_data.main.hstem scalar stem line handle
% fig_data.main.hgrid vector of handles to axis grid lines
% fig_data.main.axiszoom.on P/V cell-array pairs to turn on
% fig_data.main.axiszoom.off and off full-axis zoom
%
% Handles to menu items:
% - appearing only in figure menu:
% fig_data.menu.recpos record position
% fig_data.menu.axislegend (checkable)
% fig_data.menu.framenumber (checkable)
% fig_data.menu.axisgrid (checkable)
% fig_data.menu.memory (checkable)
% fig_data.menu.refresh
%
% - appearing in both figure and context menu:
% fig_data.menu.top top-level Axes and Lines in Figure
% fig_data.menu.context context menu
% fig_data.menu.linestyle 2xN, [fig;context] x [one per display line]
% fig_data.menu.linemarker 2xN (children are individual submenu options)
% fig_data.menu.linecolor 2xN
% fig_data.menu.linedisable 2x1
% fig_data.menu.axiszoom 2x1, [fig;context] (checkable)
% fig_data.menu.autoscale
%
%
% What's in the Block userdata:
% -----------------------------
% block_data.firstcall flag for first call to function
% block_data.autoscaling indicates autoscale computation in progress
% block_data.hfig handle to figure
% block_data.hcspec handle to non-displayed line for color translation
% block_data.haxis handle to axes
% block_data.hline Nx1 vector of line handles
% block_data.hstem scalar line handle
% block_data.hgrid handles to axis grid lines
% block_data.hgridtext vector of handles
% block_data.hlegend handle to legend itself
% block_data.hframenum handle to frame number text indicator
% block_data.params structure of cached block dialog parameters
% block_data.Ts updated sample time for block
% block_data.inputDims dimension vector of input to scope
% block_data.NChans Number of frames (columns) in input matrix
%
%
%
% Parameters structure fields:
% ----------------------------
% .ScopeParams
% .Domain: 1=Time, 2=Frequency, 3=User Defined
% .XLabel:
% Time, Frequency: ignored
% User: displayed
% .XUnits:
% User, Time: ignored
% Freq: 1=Hz, 2=rad/s
% .InheritXIncr: checkbox
% .XIncr: increment of x-axis samples, used for x-axis display
% Time: ignored (assumes frame-based)
% User, Freq: seconds per sample
% .XRange:
% User, Time: ignored
% Freq: 1=[0,Fn] , 2=[-Fn,Fn], 3=[0, Fs]
% (Fn=Nyquist rate, Fs=Sample rate)
% .YLabel:
% .YUnits:
% User, Time: ignored
% Freq: 1=Magnitude, 2=dB
%
% .HorizSpan: Horizontal time span (number of frames)
% Only displayed for Time and User-defined
%
% Optionally displayed in dialog:
% .AxisParams: indicates whether the Axis Settings are
% currently displayed in block dialog.
% .YMin: Minimum y-limit
% .YMax: Maximum y-limit
% .FigPos: figure position
%
% .AxisGrid: Current setting, on or off
% .AxisZoom: similar
% .FrameNumber: similar
% .AxisLegend: similar
% .Memory: checkbox
%
% .LineParams:
% .LineDisables:
% .LineColors: pipe-delimited string of colors, one per channel
% .LineStyles: similar
% .LineMarkers: similar
%
% .WindowParams: indicates whether the Scope Settings are
% currently displayed in block dialog.
% .OpenScopeAtSimStart: checkbox
% .OpenScopeImmediately: checkbox
switch(varargin{1})
case 3,
sys = []; % mdlOutput - unused
case 2,
sys = mdlUpdate(t,x,u,varargin{:});
case 0,
[sys,x0,str,ts] = mdlInitializeSizes;
case 9,
sys = mdlTerminate;
otherwise
% GUI callback:
feval(varargin{:});
sys = []; % None of these options change the state:
end
% -----------------------------------------------------------
function [sys,x0,str,ts] = mdlInitializeSizes
sfcn = gcb; % s-fcn
blk = get_param(sfcn,'parent');
parent = get_param(blk, 'parent');
sizes = simsizes;
sizes.NumInputs = -1;
sizes.NumOutputs = 0;
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
x0 = []; % states
str = ''; % state ordering strings
ts = [-1 1]; % inherited sample time, fixed in minor steps
%%% if ~syslocked(parent),
% No need to execute in a library
% (we also want to keep the block UserData empty so that
% DialogApply will not run)
%%% resetToFirstCall(blk);
%%% end
% ------------------------------------------------------------
function sys = mdlUpdate(t,x,u,flag,params)
% Faster implementation of: blk=gcb;
cs = get_param(0,'CurrentSystem');
cb = get_param(cs,'CurrentBlock');
sfcn = [cs '/' cb];
blk = get_param(sfcn,'parent');
sys = [];
block_data = get_param(blk, 'UserData');
if block_data.firstcall,
first_update(blk, sfcn, u, params);
else
update_lines(block_data, u);
end
% ---------------------------------------------------------------
function update_lines(block_data, u)
% UPDATE_LINES Update the lines in the scope display
% u: one frame of data
% Does not alter block_data
% If the user closed the figure window while the simulation
% was running, then hfig has been reset to empty.
%
% Allow the simulation to continue, do not put up a new figure
% window, and do not generate an error if window closes early.
%
if isempty(block_data.hfig), return; end
% Call update_lines function:
feval(block_data.UpdateLinesFcn, block_data, u);
% Update frame number display:
% Always update - it is invisible unless feature is enabled
%
% UpdateFramenum(block_data);
d = get(block_data.hframenum(2),'userdata');
set(block_data.hframenum(2), 'userdata', d+1, ...
'string', sprintf('%d',d+1));
% Check if autoscaling is in progress:
if ~isempty(block_data.autoscaling),
Autoscale([],[], block_data, u); % next frame of data
end
% ---------------------------------------------------------------
function fcn = select_UpdateLinesFcn(block_data)
freqDomain = (block_data.params.Domain==2);
oneFrame = (block_data.params.HorizSpan==1);
oneChan = (block_data.NChans==1);
% Use the frame counter to determine where we are:
% Counter starts at 0, since it is incremented after
% update_lines occurs.
nframes = block_data.params.HorizSpan;
d = get(block_data.hframenum(2),'userdata');
useInit = (d < nframes);
if freqDomain,
% Frequency domain:
if oneChan,
fcn = @update_lines_freq_oneframe_onechan;
else
fcn = @update_lines_freq_oneframe_multichan;
end
else
% Time domain:
if oneFrame,
if oneChan,
fcn = @update_lines_time_oneframe_onechan;
else
fcn = @update_lines_time_oneframe_multichan;
end
else
if oneChan,
if useInit,
fcn = @init_lines_time_multiframe_onechan;
else
fcn = @update_lines_time_multiframe_onechan;
end
else
if useInit,
fcn = @init_lines_time_multiframe_multichan;
else
fcn = @update_lines_time_multiframe_multichan;
end
end
end
end
% ---------------------------------------------------------------
function update_lines_freq_oneframe_onechan(block_data, u)
% Single channel
% One frame per horizontal span
[nrows,nchans] = size(u);
% Frequency domain conversions
% Convert to dB if required:
if(block_data.params.YUnits==2),
u = lin2dB(u);
end
% Rotate data if display range is [-Fn, Fn]:
if (block_data.params.XRange==2),
% rotate each channel of data:
p = nrows./2; % all FFT's are a power of 2 here
u = u([p+1:nrows 1:p],:);
end
set(block_data.hline, 'YData', u);
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
ystem = get(block_data.hstem,'ydata');
ystem((0:nrows-1)*3 + 2) = u;
set(block_data.hstem,'ydata',ystem);
end
% ---------------------------------------------------------------
function update_lines_freq_oneframe_multichan(block_data, u)
% One frame per horizontal span
% Multiple channels (matrix input)
[nrows,nchans] = size(u);
% Frequency domain conversions
% Convert to dB if required:
if(block_data.params.YUnits==2),
u = lin2dB(u);
end
% Rotate data if display range is [-Fn, Fn]:
if (block_data.params.XRange==2),
% rotate each channel of data:
p = nrows./2; % all FFT's are a power of 2 here
u = u([p+1:nrows 1:p],:);
end
hline = block_data.hline;
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
ystem = get(block_data.hstem,'ydata');
kup = (0:length(u)-1)*3 + 2; % index to top of stems
kdn = kup-1; % index to bottom of stems
ystem(kup) = 0;
ystem(kdn) = 0;
markerpipestr = block_data.params.LineMarkers;
for i = 1:nchans, % block_data.NChans
val = u(:,i)';
set(hline(i), 'YData', val);
if strcmp(get_pipestr(markerpipestr, i,1), 'stem'),
ystem(kup) = max(ystem(kup), val);
ystem(kdn) = min(ystem(kdn), val);
end
end
set(block_data.hstem,'ydata',ystem);
else
for i = 1:nchans, % block_data.NChans
set(hline(i), 'YData', u(:,i));
end
end
% ---------------------------------------------------------------
function update_lines_time_oneframe_onechan(block_data, u)
% One frame per horizontal span
% Single channel
set(block_data.hline, 'YData', u);
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
[nrows,nchans] = size(u);
ystem = get(block_data.hstem,'ydata');
ystem((0:nrows-1)*3 + 2) = u;
set(block_data.hstem,'ydata',ystem);
end
% ---------------------------------------------------------------
function update_lines_time_oneframe_multichan(block_data, u)
% One frame per horizontal span
% Multiple channels (matrix input):
[nrows,nchans] = size(u);
hline = block_data.hline;
if strcmp(get(block_data.hstem,'vis'),'on'),
% using stem plots:
ystem = get(block_data.hstem,'ydata');
kup = (0:length(u)-1)*3 + 2; % index to top of stems
kdn = kup-1; % index to bottom of stems
ystem(kup) = 0;
ystem(kdn) = 0;
markerpipestr = block_data.params.LineMarkers;
for i = 1:nchans, % block_data.NChans
val = u(:,i)';
set(hline(i), 'YData', val);
if strcmp(get_pipestr(markerpipestr, i,1), 'stem'),
ystem(kup) = max(ystem(kup), val);
ystem(kdn) = min(ystem(kdn), val);
end
end
set(block_data.hstem,'ydata',ystem);
else
for i = 1:nchans, % block_data.NChans
set(hline(i), 'YData', u(:,i));
end
end
% ---------------------------------------------------------------
function init_lines_time_multiframe_onechan(block_data, u)
% differs from update_lines_time_multiframe_onechan in that
% this begins rendering data from the LEFT side of the display.
% Used at the start (or re-start) of a simulation, and
% is only used for nframes number of input frames. After that,
% the non-init version is installed and used thereafter.
% Multiple frames per horiz span
% Single channel
[nrows,nchans] = size(u);
nframes = block_data.params.HorizSpan;
% 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');
y = get(block_data.hline,'YData')';
y(d*nrows+1 : (d+1)*nrows, :) = u;
set(block_data.hline, 'YData', y);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -