Create Custom Block Libraries

When to Use MATLAB Function Block Libraries

In Simulink®, you can create your own block libraries as a way to reuse the functionality of blocks or subsystems in one or more models. If you want to reuse a set of MATLAB® algorithms in Simulink models, you can encapsulate your MATLAB code in a MATLAB Function block library.

As with other Simulink block libraries, you can specialize each instance of MATLAB Function library blocks in your model to use different data types, sample times, and other properties. Library instances that inherit the same properties can reuse generated code

How to Create Custom MATLAB Function Block Libraries

Here is a basic workflow for creating custom block libraries with MATLAB Function blocks. To work through these steps with an example, see Example: Creating a Custom Signal Processing Filter Block Library.

  1. Add polymorphic MATLAB code to MATLAB Function blocks in a Simulink model.

    Polymorphic code is code that can process data with different properties, such as type, size, and complexity.

  2. Configure the blocks to inherit the properties you want to specialize.

    For a list of properties you can specialize, see Properties You Can Specialize Across Instances of Library Blocks.

  3. Optionally, customize your library code using masking.

  4. Add instances of MATLAB Function library blocks to a Simulink model.

Note

If your MATLAB Function block library is masked, you cannot modify contents of the block with mask initialization code. The Allow library block to modify its contents option in the Mask dialog box is not supported for MATLAB Function block libraries.

Example: Creating a Custom Signal Processing Filter Block Library

What You Will Learn

This simple example takes you through the workflow described in How to Create Custom MATLAB Function Block Libraries to show you how to:

  • Create a library of signal processing filter algorithms using MATLAB Function blocks

  • Customize one of the library blocks using mask parameters

  • Convert one of the filter algorithms to source-protected P-code that you can call from a MATLAB Function library block

About the Filter Algorithms

The MATLAB filter algorithms are:

my_fft.  Performs a discrete Fourier transform on an input signal. The input can be a vector, matrix, or multidimensional array whose length is a power of 2.

my_conv.  Convolves two input vector signals. Outputs a subsection of the convolution with a size specified by a mask parameter, Shape.

my_sobel.  Convolves a 2D input matrix with a Sobel edge detection filter.

Step 1: Add the Filter Algorithms to MATLAB Function Library Blocks

  1. In Simulink, create a library model. On the Simulation tab, select New > Library

  2. Drag three MATLAB Function blocks into the model from the User-Defined Functions section of the Simulink Library Browser and name them:

    • my_fft_filter

    • my_conv_filter

    • my_sobel_filter

  3. Save the library model as my_filter_lib.

  4. Open the MATLAB Function block named my_fft_filter, replace the template code with the following code, and save the block:

    function y = my_fft(x)
    
    y = fft(x);
    

  5. Replace the template code in my_conv_filter block with the following code and save the block:

    function c = my_conv(a, b)
    
    c = conv(a, b);

  6. Replace the template code in my_sobel_filter block with the following code and save the block:

    function y = my_sobel(u)
    
    %% "my_sobel_filter" is a MATLAB function
    %%  on the  MATLAB path.
    y = my_sobel_filter(u);

    The my_sobel function acts as a wrapper that calls a MATLAB function, my_sobel_filter, on the code generation path. my_sobel_filter implements the algorithm that convolves a 2D input matrix with a Sobel edge detection filter. By calling the function rather than inlining the code directly in the MATLAB Function block, you can reuse the algorithm both as MATLAB code and in a Simulink model. You will create my_sobel_filter next.

  7. In the same folder where you created my_filter_lib, create a new MATLAB function my_sobel_filter with the following code:

    function y = my_sobel_filter(u)
    
    % Sobel edge detection filter
    h = [1     2     1;...
         0     0     0;...
        -1    -2    -1];
    
    y = abs(conv2(u, h)); 
    

    Save the file as my_sobel_filter.m.

Step 2: Configure Blocks to Inherit Properties You Want to Specialize

In this example, the data in the signal processing filter algorithms must inherit size, type, and complexity from the Simulink model. By default, data in MATLAB Function blocks inherit these properties. To explicitly configure data to inherit properties:

  1. Open a MATLAB Function block and select Edit Data.

  2. In the left pane of the Ports and Data Manager, select the data of interest.

  3. In the right pane, configure the data to inherit properties from Simulink:

    To InheritWhat to Specify
    SizeEnter -1 in Size field
    ComplexitySelect Inherited from the Complexity menu
    TypeSelect Inherit: Same as Simulink from the Type menu

For example, if you open the MATLAB Function block my_fft_filter and look at the properties of input x in the Ports and Data Manager, you see that size, type, and complexity are inherited by default.

Note

If your design has specific requirements or constraints, you can enter values for any of these properties, rather than inherit them from Simulink. For example, if your algorithm is not supposed to work with complex inputs, set Complexity to Off.

Step 3: Customize Your Library Using Masking

In this exercise you will modify the convolution filter my_conv to use a custom parameter shape that specifies what subsection of the convolution to output. To customize this algorithm for your library, place the my_conv_filter block under a masked subsystem and define shape as a mask parameter.

  1. Convert the block to a masked subsystem:

    1. Right-click the my_conv_filter block and select Subsystem & Model Reference > Create Subsystem from Selection.

      The my_conv_filter block changes to a subsystem block.

    2. Change the name of the subsystem to my_conv_filter.

    3. Right-click the my_conv_filter subsystem and select Mask > Create Mask from the context menu.

      The Mask Editor appears with the Icon & Ports tab open.

    4. Enter in the Icon drawing commands text box:

      disp('my_conv');
      port_label('output', 1, 'c');
      port_label('input', 1, 'a');
      port_label('input', 2, 'b');

    5. Select the Parameters & Dialog tab.

    6. Highlight the Parameters line item in the Dialog box pane.

    7. Add a popup-type parameter by clicking Popup under the Parameter list in the Controls pane.

      A new parameter will appear in the Dialog box pane.

    8. In the Property editor pane, set the Properties:

      PropertyValue
      Nameshape
      Valuefull
      Promptshape
      Typepopup
      Type optionsOpen the Type Options Editor and enter:
      full
      same
      valid
    9. Set the Attributes, Dialog, and Layout properties in the Property editor pane:

      Attributes, Dialog, and Layout ItemsValue
      Attributes
      • Evaluate: Checked

      • Tunable: Cleared

      • Read only: Cleared

      • Hidden: Cleared

      • Never save: Cleared

      Dialog
      • Enable: Checked

      • Visible: Checked

      • Callback: no entry

      Layout
      • Item location: Grayed out

      • Prompt location: Left

    10. Click OK.

      Your subsystem should now look like this:

  2. Set subsystem properties for code reuse:

    1. Right-click the my_conv_filter subsystem and select Block Parameters (Subsystem) from the context menu.

    2. In the subsystem parameters dialog box, select the Treat as atomic unit check box.

      The dialog box expands to display new fields.

    3. To generate a reusable function, select the Code Generation tab and in the Function packaging field, select Reusable function from the drop-down menu.

      Note

      This is an optional step, required for this example. If you leave the default setting of Auto, the code generation software uses an internal rule to determine whether to inline the function or not.

    4. Click OK.

  3. Define the shape parameter in the MATLAB Function my_conv:

    1. Right-click the my_conv_filter subsystem and select Mask > Look Under Mask from the context menu.

      The block diagram under the masked subsystem opens, containing the my_conv_filter block:

    2. Change the names of the port blocks to match the data names as follows:

      Change:To:
      In1a
      In2b
      Out1c
    3. Double-click the my_conv_filter block to open the MATLAB Function Block Editor.

    4. In the MATLAB Function Block Editor, select Edit Data.

    5. In the Ports and Data Manager, select Add > Data.

      A new data element appears selected, along with its properties dialog.

    6. Enter the following properties:

      PropertyWhat To Specify
      NameEnter shape.
      ScopeSelect Parameter.
      TunableClear the box.

    7. Leave Size, Complexity, and Type as inherited (the defaults), as described in Step 2: Configure Blocks to Inherit Properties You Want to Specialize.

    8. Click Apply, close the Ports and Data Manager, and return to the MATLAB Function Block Editor.

  4. Use the shape parameter to determine the size of the convolution to output:

    1. In the MATLAB Function Block Editor, modify the my_conv function to call conv with the right shape:

      function c = my_conv(a, b, shape)
      if shape == 1
          c = conv(a, b, 'full');
      elseif shape == 2
          c = conv(a, b, 'same');
      else
          c = conv(a, b, 'valid');
      end
    2. Save your changes and close the MATLAB Function Block Editor.

Step 4: Add Instances of MATLAB Library Blocks to a Simulink Model

In this exercise, you will add specialized instances of the my_conv_filter library block to a simple test model.

  1. Open a new Simulink model.

    For purposes of this exercise, set the following configuration parameters for simulation:

    PaneSectionWhat to Specify
    SolverSolver selection
    • Select Fixed-Step for Type

    • Select discrete (no continuous states) for Solver

    • Enter 1 for Fixed-step size

    Data Import/ExportSave optionsStructure for Format

  2. Drag two instances of the my_conv_filter block from the my_filter_lib library into the model.

  3. Add Constant, Outport, and Display blocks. Your model should look something like this:

    Both library instances share the same size, type, and complexity for inputs a and b respectively.

  4. Double-click each library instance.

    The shape parameter defaults to full for both instances.

  5. Simulate the model.

    Each library instance outputs the same result, the full 2D convolution:

  6. Specialize the second instance, my_conv_filter1 by setting the value of its shape parameter to same.

  7. Now simulate the model again.

    This time, the outputs have different sizes: my_conv_filter3 outputs the full 2D convolution, while my_conv_filter1 displays the central part of the convolution as a 1-by-2 vector, the same size as a:

  8. Now, add a third instance by copying my_conv_filter1. Specialize the new instance, my_conv_filter2, so that it does not inherit the same size inputs as the first two instances:

  9. Simulate the model again.

    This time, my_conv_filter1 and my_conv_filter2 each display the central part of the convolution, but the output sizes are different because each matches a different sized input a.

Code Reuse with Library Blocks

When instances of MATLAB Function library blocks inherit the same properties, they can reuse generated code, as illustrated by an example based on Step 4: Add Instances of MATLAB Library Blocks to a Simulink Model:

In this model, the library instances my_conv_filter and my_conv_filter1 inherit the same size, type, and complexity for each respective input. For each instance, input a is a 1-by-2 vector and input b is a 1-by-5 vector. By comparison, the inputs of my_conv_filter2 inherit different respective sizes; both are 1-by-3 vectors.

In addition, each library instance has a mask parameter called shape that determines what subsection of the convolution to output. Assume that the value of shape is the same for each instance.

To generate code for this example, follow these steps:

  1. Enable code reuse for the library block:

    1. In the library, right-click the MATLAB Function block my_conv_filter and select Block Parameters (Subsystem) from the context menu.

    2. In the Function Block Parameters dialog box, set these parameters:

      • Select the Treat as atomic unit check box.

      • In the Function packaging field, select Reusable function from the drop-down menu.

  2. Configure the model for code generation.

    For purposes of this exercise, set the following configuration parameters:

    PaneSectionWhat to Specify
    Code GenerationTarget selectionEnter ert.tlc for System target file
    Code Generation > Report Select Create code generation report check box.
  3. Build the model.

    If you build this model, the generated C code reuses logic for the my_conv_filter and my_conv_filter1 library instances because they inherit the same input properties:

    /*
     * Output and update for atomic system:
     *    '<Root>/my_conv_filter'
     *    '<Root>/my_conv_filter1'
     */
    void sp_algorithm_tes_my_conv_filter(const real32_T rtu_a[2], const real32_T
      rtu_b[5], rtB_my_conv_filter_sp_algorithm *localB)
    {
      int32_T jA;
      int32_T jA_0;
      real32_T s;
      int32_T jC;
    
      /* MATLAB Function Block: '<S1>/my_conv_filter' */
      /* MATLAB Function 'my_conv_filter/my_conv_filter': '<S4>:1' */
      /* '<S4>:1:4' */
      for (jC = 0; jC < 6; jC++) {
        if (5 < jC + 2) {
          jA = jC - 4;
        } else {
          jA = 0;
        }
    
        if (2 < jC + 1) {
          jA_0 = 2;
        } else {
          jA_0 = jC + 1;
        }
    
        s = 0.0F;
        while (jA + 1 <= jA_0) {
          s += rtu_b[jC - jA] * rtu_a[jA];
          jA++;
        }
    
        localB->c[jC] = s;
      }
    
      /* end of MATLAB Function Block: '<S1>/my_conv_filter' */
    }

    However, a separate function is generated for my_conv_filter2:

    /* Output and update for atomic system: '<Root>/my_conv_filter2' */
    void sp_algorithm_te_my_conv_filter2(const real_T rtu_a[3], const real_T rtu_b[3],
      rtB_my_conv_filter_sp_algorit_h *localB)
    {
      int32_T jA;
      int32_T jA_0;
      real_T s;
      int32_T jC;
    
      /* MATLAB Function Block: '<S3>/my_conv_filter' */
      /* MATLAB Function 'my_conv_filter/my_conv_filter': '<S6>:1' */
      /* '<S6>:1:4' */
      for (jC = 0; jC < 5; jC++) {
        if (3 < jC + 2) {
          jA = jC - 2;
        } else {
          jA = 0;
        }
    
        if (3 < jC + 1) {
          jA_0 = 3;
        } else {
          jA_0 = jC + 1;
        }
    
        s = 0.0;
        while (jA + 1 <= jA_0) {
          s += rtu_b[jC - jA] * rtu_a[jA];
          jA++;
        }
    
        localB->c[jC] = s;
      }
    
      /* end of MATLAB Function Block: '<S3>/my_conv_filter' */
    }
    

Note

Generating C code for this model requires a Simulink Coder™ or Embedded Coder® license.

Debugging MATLAB Function Library Blocks

You debug MATLAB Function library blocks the same way you debug any MATLAB Function block. However, when you add a breakpoint in a library block, the breakpoint is shared by all instances. As you continue execution, the debugger stops at the breakpoint in each instance.

Properties You Can Specialize Across Instances of Library Blocks

You can specialize instances of MATLAB Function library blocks by allowing them to inherit any of the following properties from Simulink:

PropertyInherits by Default?How to Specify Inheritance
TypeYesSet data type property to Inherit: Same as Simulink.
SizeYesSet data size property to -1.
ComplexityYesSet data complexity property to Inherited.
Limit rangeNoSpecify minimum and maximum values as Simulink parameters.
For example, if minimum value = aParam and maximum value = aParam + 3, different instances of a MATLAB Function library block can resolve to different aParam parameters defined in their parent mask subsystems.
Sampling mode (input)YesMATLAB Function block input ports always inherit sampling mode
Data type override mode for fixed-point dataYesSet data type override property to Inherit.
Sample time (block)YesSet block sample time property to -1.

Related Topics