Code covered by the BSD License  

Highlights from
Simulink bus/SimEvents entity interface blocks

Simulink bus/SimEvents entity interface blocks

by

 

This utility generates blocks which interface between Simulink bus signals and SimEvents entities.

entity2bus(BusObject)
function entity2bus(BusObject)
%% ENTITY2BUS Create entity to bus conversion block
%   ENTITY2BUS(BUSOBJECT) creates a Simulink block in a new model which can
%   be used to convert a SimEvents entity to a bus signal.  The bus will
%   have signals corresponding to the attributes in the entity.  The
%   trigger port will output a function call upon entity arrival.
%
%   This function does not currently support nested buses.
%
%   Making the generated model look non-ridiculous is left as an exercise
%   for the reader.

%% Check for valid BusObject
if ~strcmp(class(BusObject),'Simulink.Bus')
    error('Invalid bus object');
elseif isempty(BusObject.Elements)
    error('Bus contains no signals');
end

AttributeCount = length(BusObject.Elements);
BusName = inputname(1);

%% Load necessary Simulink and SimEvents librarys
load_system('simulink');
load_system('simeventsattributes2');
load_system('simeventstranslate1');
load_system('simeventsgenerators1');
load_system('simeventsportsubsys1');
load_system('simeventssink1');

%% Create top level block
MdlTop = new_system;
MdlTop = getfullname(MdlTop);
Mdl = [MdlTop,'/Entity2Bus'];
add_block('simulink/Ports & Subsystems/Subsystem',Mdl,...
    'Position',[70 48 200 117]);
% Empty subsystem
Simulink.SubSystem.deleteContents(Mdl);

%% Add GetAttribute
GetAttribute = [Mdl,'/Get Attribute'];
add_block('simeventsattributes2/Get Attribute',GetAttribute,...
    'Position',[80 160 165 295]);

%% Set GetAttribute parameters
% For Value, TreatAsVector we repeat the defaults; For From we repeat
% Signal port.  For Name we loop through the bus elements.  | is used to
% separate attributes.
AttributeName = '';
for i = 1:AttributeCount
    AttributeName = [AttributeName,BusObject.Elements(i).Name,'|'];
end
AttributeName = AttributeName(1:end-1); % Remove trailing |
    
set_param(GetAttribute,'AttributeName',AttributeName,...
	'AttributeDefaultValue',[repmat('0|',1,AttributeCount-1),'0'],...
	'AttributeMissing',[repmat('Error|',1,AttributeCount-1),'Error'],...
	'AttributeSendTiming',[repmat('After entity departure|',1,AttributeCount-1),'After entity departure'],...
    'AttributeTreatAsVector',[repmat('1|',1,AttributeCount-1),'1']);

%% Add FcnCallGenerator and FcnCallSplitter
FcnCallGenerator = [Mdl,'/FcnCallGenerator'];
add_block('simeventsgenerators1/Event Generators/Entity-Based Function-Call Event Generator',FcnCallGenerator,...
    'Position',[210 252 295 308]);
FcnCallSplitter = [Mdl,'/FcnCallSplitter'];
add_block('simeventstranslate1/Signal-Based Event to Function-Call Event',FcnCallSplitter,...
    'Position',[375 237 460 293]);

%% Set FcnCallGenerator parameters
% Defaults are acceptable

%% Set FcnCallSplitter parameters
set_param(FcnCallSplitter,'GenerateFunctionCallUpon','Function call from port fcn',...
	'EnableF2Port','on',...
	'SpecifyEventPriority','on',...
	'PriorityFunctionCall','1');

%% Add EntitySink
EntitySink = [Mdl '/Entity Sink'];
add_block('simeventssink1/Entity Sink',EntitySink,...
    'Position',[375 323 460 377]);

%% Add Subsystem
Subsystem = [Mdl,'/Subsystem'];
add_block('simulink/Ports & Subsystems/Function-Call Subsystem',Subsystem,...
    'Position',[525 157 655 233]);

%% Set Subsystem parameters
% We need to propagate execution context
set_param(Subsystem,'PropExecContextOutsideSubsystem','on')

%% Add DataTypeConversion
DataTypeConversion = {};
for i = 1:AttributeCount
    DataTypeConversion{i} = [Subsystem,'/FromDouble',num2str(i)];
    add_block('simulink/Signal Attributes/Data Type Conversion',DataTypeConversion{i},...
        'Position',[175 43+50*i 180 77+50*i]);
end

%% Add BusCreator
BusCreator = [Subsystem,'/Bus Creator'];
add_block('simulink/Signal Routing/Bus Creator',BusCreator,...
    'Position',[260 84 335 84+50*AttributeCount]);
set_param(BusCreator,'Inputs','3');

%% Add Inport
Outport = [Subsystem,'/Out1'];
set_param(Outport,'Position',[360 78+25*AttributeCount 390 92+25*AttributeCount]);
Inport = {[Subsystem,'/In1']};
for i = 2:AttributeCount
    Inport{i} = [Subsystem,'/In',num2str(i)];
    add_block('simulink/Ports & Subsystems/In1',Inport{i},...
        'Position',[110 53+50*i 140 67+50*i]);
end

%% Connect Inport, DataTypeConversion, BusCreator and Outport signal lines
delete_line(Subsystem,'In1/1','Out1/1') % Delete exisiting line
OutportPorts = get_param(Outport,'PortHandles');
BusCreatorPorts = get_param(BusCreator,'PortHandles');
add_line(Subsystem,BusCreatorPorts.Outport,OutportPorts.Inport);
for i = 1:AttributeCount
    DataTypeConversionPorts = get_param(DataTypeConversion{i},'PortHandles');
    InportPorts = get_param(Inport{i},'PortHandles');
    add_line(Subsystem,InportPorts.Outport,DataTypeConversionPorts.Inport);
    h = add_line(Subsystem,DataTypeConversionPorts.Outport,BusCreatorPorts.Inport(i));
    set_param(h,'Name',BusObject.Elements(i).Name);
end

%% Set BusCreator parameters
% , is used to separate signal names.
InputSignals = '';
for i = 1:AttributeCount
    InputSignals = [InputSignals,BusObject.Elements(i).Name,','];
end
InputSignals = InputSignals(1:end-1); % Remove trailing ,

set_param(BusCreator,'Inputs',InputSignals,...
    'BusObject',BusName,...
    'UseBusObject','on',...
    'NonVirtualBus','on');

%% Connect GetAttribute and Subsystem
GetAttributePorts = get_param(GetAttribute,'PortHandles');
SubsystemPorts = get_param(Subsystem,'PortHandles');
for i = 1:AttributeCount
    add_line(Mdl,GetAttributePorts.Outport(i),SubsystemPorts.Inport(i));
end

%% Connect GetAttribute, FcnCallGenerator, FcnCallSplitter, EntitySink, and Subsystem
FcnCallGeneratorPorts = get_param(FcnCallGenerator,'PortHandles');
FcnCallSplitterPorts = get_param(FcnCallSplitter,'PortHandles');
EntitySinkPorts = get_param(EntitySink,'PortHandles');
add_line(Mdl,GetAttributePorts.RConn,FcnCallGeneratorPorts.LConn);
add_line(Mdl,FcnCallGeneratorPorts.RConn,EntitySinkPorts.LConn);
add_line(Mdl,FcnCallGeneratorPorts.Outport,FcnCallSplitterPorts.Inport);
add_line(Mdl,FcnCallSplitterPorts.Outport(1),SubsystemPorts.Trigger);

%% Add input and output ports
EntityIn = [Mdl,'/IN'];
add_block('simeventsportsubsys1/Conn',EntityIn,...
    'Position',[25 223 55 237]);
BusOut = [Mdl,'/BusOut'];
add_block('simulink/Ports & Subsystems/Out1',BusOut,...
    'Position',[720 188 750 202]);
TriggerOut = [Mdl,'/TriggerOut'];
add_block('simulink/Ports & Subsystems/Out1',TriggerOut,...
    'Position',[570 273 600 287]);

%% Connect input and output ports to rest of system
EntityInPorts = get_param(EntityIn,'PortHandles');
BusOutPorts = get_param(BusOut,'PortHandles');
TriggerOutPorts = get_param(TriggerOut,'PortHandles');
add_line(Mdl,EntityInPorts.RConn,GetAttributePorts.LConn);
add_line(Mdl,SubsystemPorts.Outport,BusOutPorts.Inport);
add_line(Mdl,FcnCallSplitterPorts.Outport(2),TriggerOutPorts.Inport);

%% That's all folks!
set_param(Mdl,'Mask','on')
set_param(Mdl,'MaskType','Entity2Bus')
set_param(Mdl,'MaskDescription',sprintf([...
    'Entity to bus interface.  The bus will have signals corresponding ',...
    'to the attributes in the entity.  The trigger port will output a ',...
    'function call upon entity arrival.\n\nThis block was created with ',...
    'ENTITY2BUS and requires %s to be correctly defined in the ',...
    'workspace'],BusName));
open_system(MdlTop);

Contact us