Atom Tab for Programmable Super Block
Define the Atom tab of the Block Builder for a programmable super block.
_block = vssAddNewObject('SubSystem', _diagram);
_diagr = vssCreateObject('Diagram');
The code continues to populate _diagr with blocks and links, constructing a diagram.
To define a block in the diagram requires the following steps:
- Define the block parameters using an OML struct.
- Load the block from the corresponding library.
- Instantiate the block.
_params = struct();
_params.init_cond = z0;
_params.typ = 'double';
_params.externalActivation = 0;
vssLoadBlock('system', 'Dynamical', 'DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagr, 'DiscreteDelay', _params);
In this example, the initial condition is set to z0, which must be a parameter of the programmable super block. Links between blocks are established using the OML function vssAdd_Link. For instance, the following instruction connects the first output of the Input block to the first output of the DiscreteDelay block via a regular link:
vssAdd_Link(_diagram, 'Input', 'DiscreteDelay', 1, 1, 0, 1, 1);
When the Block Builder is invoked with a masked super block, the SetParameters function of the block is automatically generated. This function contains the code responsible for constructing the diagram in the Super Block. In this case, the diagram is fixed.
A fixed-diagram programmable super block might not be useful because it can also be implemented with a standard masked super block. However, it can serve as a useful starting point for defining the SetParameters function of a more general programmable super block. This approach is illustrated through the following example.
Example
nout=3
), the diagram is as
follows:After the super block is masked, click Block Builder with the super block selected. The Block Builder interface now contains a good starting point for defining a new block.
nout=3
. No graphical properties are used at this point. The
code generated by Block Builder for the fixed diagram is as
follows:function _setdiagram_1 (_diagram, _label, __fenv__)
_curdiagram=_diagram;
_curlabel=_label;
importenv(__fenv__);
_diagram=_curdiagram;
_label=_curlabel;
clear _curdiagram;
clear _curlabel;
global _vss;
global __OBJ_ERR_;
_parent = __OBJ_ERR_.('block');
__OBJ_ERR_.('type')='context';
if isscalar(z0) z0=z0*ones(nout,1);end
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'Output_2');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.portNumber=3;
_params.insize=[-1;-2];
_params.intyp='inherit';
vssLoadBlock('system','Ports','Output');
_vss._palettes.('_system').('Ports').('Output').setparams(_diagram,'Output_2',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'DiscreteDelay_2');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.init_cond=z0(3);
_params.typ='double';
_params.externalActivation=0;
vssLoadBlock('system','Dynamical','DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagram,'DiscreteDelay_2',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'Output_1');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.portNumber=2;
_params.insize=[-1;-2];
_params.intyp='inherit';
vssLoadBlock('system','Ports','Output');
_vss._palettes.('_system').('Ports').('Output').setparams(_diagram,'Output_1',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'Output');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.portNumber=1;
_params.insize=[-1;-2];
_params.intyp='inherit';
vssLoadBlock('system','Ports','Output');
_vss._palettes.('_system').('Ports').('Output').setparams(_diagram,'Output',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'Input');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.portNumber=1;
_params.outsize=[-1;-2];
_params.outtyp='inherit';
_params.dept=0;
vssLoadBlock('system','Ports','Input');
_vss._palettes.('_system').('Ports').('Input').setparams(_diagram,'Input',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'Block');
__OBJ_ERR_.('type')='parameters';
_params=struct();
vssLoadBlock('system','Links','Split');
_vss._palettes.('_system').('Links').('Split').setparams(_diagram,'Block',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'DiscreteDelay_1');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.init_cond=z0(2);
_params.typ='double';
_params.externalActivation=0;
vssLoadBlock('system','Dynamical','DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagram,'DiscreteDelay_1',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'Split');
__OBJ_ERR_.('type')='parameters';
_params=struct();
vssLoadBlock('system','Links','Split');
_vss._palettes.('_system').('Links').('Split').setparams(_diagram,'Split',_params);
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'DiscreteDelay');
__OBJ_ERR_.('type')='parameters';
_params=struct();
_params.init_cond=z0(1);
_params.typ='double';
_params.externalActivation=0;
vssLoadBlock('system','Dynamical','DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagram,'DiscreteDelay',_params);
vssAdd_Link(_diagram,'Output_2','DiscreteDelay_2',1,1,1,0,1);
vssAdd_Link(_diagram,'DiscreteDelay_1','Block',1,1,0,1,1);
vssAdd_Link(_diagram,'Block','Output_1',1,1,0,1,1);
vssAdd_Link(_diagram,'DiscreteDelay_2','Block',1,2,1,0,1);
vssAdd_Link(_diagram,'Input','DiscreteDelay',1,1,0,1,1);
vssAdd_Link(_diagram,'DiscreteDelay','Split',1,1,0,1,1);
vssAdd_Link(_diagram,'Split','DiscreteDelay_1',1,1,0,1,1);
vssAdd_Link(_diagram,'Split','Output',2,1,0,1,1);
end
_block = vssAddNewObject('SubSystem',_diagram);
_diagr= vssCreateObject('Diagram');
_setdiagram_1(_diagr,_label,getcurrentenv());
vssSet_SubSystem(_block,1,3,0,0,0,_label,_diagr);
The variable __OBJ_ERR_ is used to anchor the error locations for generating precise error messages. In the case of programmable super blocks, this is not very useful and it is better to reference all error message to the parent block, the programmable super block. In general, users do not know about the content of this block.
function shiftreg_setdiagram_1 (_diagram, _label, __fenv__)
_curdiagram=_diagram;
_curlabel=_label;
importenv(__fenv__);
_diagram=_curdiagram;
_label=_curlabel;
clear _curdiagram;
clear _curlabel;
global _vss;
global __OBJ_ERR_;
_parent = __OBJ_ERR_.('block');
__OBJ_ERR_.('type')='context';
if isscalar(z0) z0=z0*ones(nout,1); elseif length(z0)~=nout error('size of z0 must match nb of outputs.');end
__OBJ_ERR_.('block')=vssConstructBlockFullName(_parent,'DiscreteDelay');
_params=struct();
_params.init_cond=z0(1);
_params.typ='double';
_params.externalActivation=0;
vssLoadBlock('system','Dynamical','DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagram,'DiscreteDelay',_params);
_params=struct();
vssLoadBlock('system','Links','Split');
_vss._palettes.('_system').('Links').('Split').setparams(_diagram,'Split_1',_params);
_params=struct();
_params.portNumber=1;
_params.outsize=[-1;-2];
_params.outtyp='inherit';
_params.dept=0;
vssLoadBlock('system','Ports','Input');
_vss._palettes.('_system').('Ports').('Input').setparams(_diagram,'Input',_params);
_params=struct();
_params.portNumber=1;
_params.insize=[-1;-2];
_params.intyp='inherit';
vssLoadBlock('system','Ports','Output');
_vss._palettes.('_system').('Ports').('Output').setparams(_diagram,'Output',_params);
vssAdd_Link(_diagram,'Input','DiscreteDelay',1,1,0,1,1);
vssAdd_Link(_diagram,'DiscreteDelay','Split_1',1,1,0,1,1);
vssAdd_Link(_diagram,'Split_1','Output',2,1,0,1,1);
for i=2:nout-1
_params=struct();
_params.init_cond=z0(i);
_params.typ='double';
_params.externalActivation=0;
vssLoadBlock('system','Dynamical','DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagram,['DiscreteDelay_',...
num2str(i-1)],_params);
_params=struct();
_params.portNumber=i;
_params.insize=[-1;-2];
_params.intyp='inherit';
vssLoadBlock('system','Ports','Output');
_vss._palettes.('_system').('Ports').('Output').setparams(_diagram,['Output_',num2str(i-1)],_params);
_params=struct();
vssLoadBlock('system','Links','Split');
_vss._palettes.('_system').('Links').('Split').setparams(_diagram,['Split_',num2str(i)],_params);
vssAdd_Link(_diagram,['Split_',num2str(i-1)],['DiscreteDelay_',num2str(i-1)],1,1,0,1,1);
vssAdd_Link(_diagram,['DiscreteDelay_',num2str(i-1)],['Split_',num2str(i)],1,1,0,1,1);
vssAdd_Link(_diagram,['Split_',num2str(i)],['Output_',num2str(i-1)],2,1,0,1,1);
end
_params=struct();
_params.init_cond=z0(nout);
_params.typ='double';
_params.externalActivation=0;
vssLoadBlock('system','Dynamical','DiscreteDelay');
_vss._palettes.('_system').('Dynamical').('DiscreteDelay').setparams(_diagram,['DiscreteDelay_',...
num2str(nout-1)],_params);
_params=struct();
_params.portNumber=nout;
_params.insize=[-1;-2];
_params.intyp='inherit';
vssLoadBlock('system','Ports','Output');
_vss._palettes.('_system').('Ports').('Output').setparams(_diagram,['Output_',num2str(nout-1)],_params);
vssAdd_Link(_diagram,['DiscreteDelay_',num2str(nout-1)],['Output_',num2str(nout-1)],1,1,0,1,1);
vssAdd_Link(_diagram,['Split_',num2str(nout-1)],['DiscreteDelay_',num2str(nout-1)],1,1,0,1,1);
end
_block = vssAddNewObject('SubSystem',_diagram);
_diagr= vssCreateObject('Diagram');
shiftreg_setdiagram_1(_diagr,_label,getcurrentenv());
vssSet_SubSystem(_block,1,nout,0,0,0,_label,_diagr);
Examining the new script, the new repeated blocks are named by extensions
_2
, _3
, up to nout. This is
not needed for links, which are not named.
After creating the first layer of blocks, the repeated structure is created within the following for loop:
for i=2:nout-1
....
end
The final layer is created after the for loop. Another change needs to be made in the code to change the number of outputs of the new block:
vssSet_SubSystem(_block,1,3,0,0,0,_label,_diagr);
is replaced by:
vssSet_SubSystem(_block,1,nout,0,0,0,_label,_diagr);
indicating that the block has nout outputs instead of 3.
You can move the new block to another model and set its paramters to the desired values and test it.