0
votes

I want to write a block, which sends all image files from selected directory.

Images are of different sizes, so output signal size should vary.

Unfortunately I was unable to find a way to change signal size at each step. There are many of undocumented features here, in examples like

block.OutputPort(1).DimensionsMode = 'Variable';

and

block.OutputPort(1).CurrentDimensions = [1 block.InputPort(1).Data];

and so on. I was unable to deduce correct way to operate all this stuff yet...

UPDATE

For example, this S-function

function Test_SF_01(block)
% Level-2 MATLAB file S-Function.

    setup(block);

function setup(block)

    % Register number of ports and parameters
    block.NumInputPorts  = 0;
    block.NumOutputPorts = 1;
    block.NumDialogPrms  = 0;

    % Setup functional port properties to dynamically inherited
    block.SetPreCompOutPortInfoToDynamic;

    % Register the properties of the output port
    block.OutputPort(1).DimensionsMode = 'Variable';
    block.OutputPort(1).SamplingMode   = 'Sample';

    % Register sample times
    %  [-1, 0] : Inherited sample time
    block.SampleTimes = [-1 0];

    % Register methods called at run-time
    block.RegBlockMethod('Outputs', @Outputs);

function Outputs(block)
    block.OutputPort(1).CurrentDimensions =  floor(rand(1,2)*10)+1;

causes an error

Invalid variable dimensions assignment for output port 1 of 'Test_01/Level-2 MATLAB S-Function'. The number of variable dimensions is 1. However, the length of the MATLAB array is 2

why?

2
Yes I cited this example.Suzan Cioc

2 Answers

2
votes

The following S-function generates variable dimension signal. They key problem was that initial set of Dimensions property defines MAXIMAL values of dimensions, which is absolutely not clear from docs, while error messages are mostly irrelevant.

function Test_SF_01(block)
% Level-2 MATLAB file S-Function.

    setup(block);

function setup(block)

    % Register number of ports and parameters
    block.NumInputPorts  = 0;
    block.NumOutputPorts = 1;
    block.NumDialogPrms  = 0;

    % Setup functional port properties to dynamically inherited
    block.SetPreCompOutPortInfoToDynamic;

    % Register the properties of the output port
    block.OutputPort(1).DimensionsMode = 'Variable';
    block.OutputPort(1).Dimensions = [10000 10000];

    block.OutputPort(1).SamplingMode   = 'Sample';

    % Register sample times
    %  [-1, 0] : Inherited sample time
    block.SampleTimes = [-1 0];

    % Register methods called at run-time
    block.RegBlockMethod('Outputs', @Outputs);

function Outputs(block)

     dims = floor(rand(1,2)*10)+1;
     block.OutputPort(1).CurrentDimensions = dims;

     data = rand(dims);
    block.OutputPort(1).Data = data;
0
votes

Have you also looked at the following code example from the doc? See Operations for Variable-Size Signals. There's a bit more in there than what you have in your code. Probably best to start from the basic template msfuntmpl_basic.m as they do in the doc.

function setup(block)
% Register the properties of the output port
block.OutputPort(1).DimensionsMode = 'Variable';
block.RegBlockMethod('SetInputPortDimensionsMode',  @SetInputDimsMode);

function DoPostPropSetup(block)
%Register dependency rules to update current output size of output port a depending on
%input ports b and c
block.AddOutputDimsDependencyRules(a, [b c], @setOutputVarDims);

%Configure output port b to have the same dimensions as input port a
block.InputPortSameDimsAsOutputPort(a,b);

%Configure DWork a to have its size reset when input size changes.
block.DWorkRequireResetForSignalSize(a,true);

function SetInputDimsMode(block, port, dm)
% Set dimension mode
block.InputPort(port).DimensionsMode = dm;
block.OutputPort(port).DimensionsMode = dm;

function setOutputVarDims(block, opIdx, inputIdx)
% Set current (run-time) dimensions of the output
outDimsAfterReset = block.InputPort(inputIdx(1)).CurrentDimensions;
block.OutputPort(opIdx).CurrentDimensions = outDimsAfterReset;