MATLAB Examples

Access Signal, State, and Parameter Data During Execution

As you iteratively develop a model, you capture output signal and state data that model execution generates. You also tune parameter values during execution to observe the effect on the outputs. You can then base your design decisions upon analysis of these outputs. To access this signal, state, and parameter data in a rapid prototyping environment, you can configure the generated code to store the data in addressable memory.

By default, optimization settings make the generated code more efficient by eliminating unnecessary signal storage and inlining the numeric values of block parameters. To generate code that instead allocates addressable memory for this data, you can disable the optimizations or specify code generation settings for individual data items.

Contents

Explore Example Model

Run a script that prepares the model rtwdemo_basicsc for this example.

run(fullfile(matlabroot,'examples','simulinkcoder','main','prepare_rtwdemo_basicsc'));

Open the example model, rtwdemo_basicsc.

rtwdemo_basicsc

The model loads numeric MATLAB variables into the base workspace. The workspace variables set some block parameters in the model. However, The Gain block in the model uses the literal value 2.

Disable Optimizations

In the model, clear the model configuration parameter Signal storage reuse. When you clear this optimization and other optimizations such as Eliminate superfluous local variables (expression folding), the generated code allocates memory for signal lines. Clearing Signal storage reuse disables most of the other optimizations.

set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','off')

Set the optimization Configuration Parameters > Optimization > Signals and Parameters > Default parameter behavior to Tunable. When set to Tunable, this configuration parameter causes the generated code to allocate memory for block parameters and workspace variables.

set_param('rtwdemo_basicsc','DefaultParameterBehavior','Tunable')

Generate code from the model.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for model: rtwdemo_basicsc
### Successful completion of build procedure for model: rtwdemo_basicsc

In the code generation report, view the file rtwdemo_basicsc.h. This header file defines a structure type that contains signal data. The structure contains fields that each represent a signal line in the model. For example, the output signal of the Gain block, whose name is Gain, appears as the field Gain.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.h');
rtwdemodbtype(file,'/* Block signals (auto storage) */',...
    'B_rtwdemo_basicsc_T;',1,1)
/* Block signals (auto storage) */
typedef struct {
  real32_T Table1;                     /* '<Root>/Table1' */
  real32_T Gain;                       /* '<Root>/Gain' */
  real32_T Delay;                      /* '<Root>/Delay' */
  real32_T Table2;                     /* '<Root>/Table2' */
  boolean_T RelOp1;                    /* '<Root>/RelOp1' */
  boolean_T RelOp2;                    /* '<Root>/RelOp2' */
  boolean_T LogOp;                     /* '<Root>/LogOp' */
} B_rtwdemo_basicsc_T;

The file defines a structure type that contains block parameter data. For example, the Gain parameter of the Gain block appears as the field Gain_Gain. The other fields of the structure represent other block parameters and workspace variables from the model, including initial conditions for signals and states.

rtwdemodbtype(file,'/* Parameters (auto storage) */',...
    '/* Real-time Model Data Structure */',1,0)
/* Parameters (auto storage) */
struct P_rtwdemo_basicsc_T_ {
  real_T K2;                           /* Variable: K2
                                        * Referenced by: '<Root>/Stateflow Chart'
                                        */
  real32_T LOWER;                      /* Variable: LOWER
                                        * Referenced by: '<Root>/Constant2'
                                        */
  real32_T T1Break[11];                /* Variable: T1Break
                                        * Referenced by: '<Root>/Table1'
                                        */
  real32_T T1Data[11];                 /* Variable: T1Data
                                        * Referenced by: '<Root>/Table1'
                                        */
  real32_T T2Break[3];                 /* Variable: T2Break
                                        * Referenced by: '<Root>/Table2'
                                        */
  real32_T T2Data[9];                  /* Variable: T2Data
                                        * Referenced by: '<Root>/Table2'
                                        */
  real32_T UPPER;                      /* Variable: UPPER
                                        * Referenced by: '<Root>/Constant1'
                                        */
  real32_T Gain_Gain;                  /* Computed Parameter: Gain_Gain
                                        * Referenced by: '<Root>/Gain'
                                        */
  real32_T Delay_InitialCondition;     /* Computed Parameter: Delay_InitialCondition
                                        * Referenced by: '<Root>/Delay'
                                        */
  uint32_T Table2_maxIndex[2];         /* Computed Parameter: Table2_maxIndex
                                        * Referenced by: '<Root>/Table2'
                                        */
  boolean_T DataStoreMemory_InitialValue;/* Computed Parameter: DataStoreMemory_InitialValue
                                          * Referenced by: '<Root>/Data Store Memory'
                                          */
};

View the file rtwdemo_basicsc_data.c. This source file allocates global memory for a parameter structure and initializes the field values based on the parameter values in the model.

View the source file rtwdemo_basicsc.c. The code allocates global memory for a structure variable that contains signal data.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* Block signals (auto storage) */',...
    'B_rtwdemo_basicsc_T rtwdemo_basicsc_B;',1,1)
/* Block signals (auto storage) */
B_rtwdemo_basicsc_T rtwdemo_basicsc_B;

The code algorithm in the model step function calculates the signal values. It then assigns these values to the fields of the signal structure. To perform the calculations, the algorithm uses the parameter values from the fields of the parameter structure.

Exclude Data Items from Optimizations

When you want to select code generation optimizations such as Signal storage reuse, you can preserve individual data items from the optimizations. The generated code then allocates addressable memory for the items.

Select the optimizations that you previously cleared.

set_param('rtwdemo_basicsc','OptimizeBlockIOStorage','on')
set_param('rtwdemo_basicsc','LocalBlockOutputs','on')
set_param('rtwdemo_basicsc','DefaultParameterBehavior','Inlined')

In the model, select View > Model Data.

In the Model Data Editor, inspect the Signals tab.

Set the Change view drop-down list to Instrumentation.

In the model, select the output signal of the Gain block.

In the Model Data Editor, select the check box in the Test Point column.

portHandle = get_param('rtwdemo_basicsc/Gain','PortHandles');
portHandle = portHandle.Outport;
set_param(portHandle,'TestPoint','on')

Inspect the Parameters tab.

In the model, select the Gain block.

In the Model Data Editor, use the Value column to set the gain value to K1.

Next to K1, click the action button (with three vertical dots) and select Create.

In the Create New Data dialog box, set Value to Simulink.Parameter(2) and click Create. A Simulink.Parameter object named K1, with value 2, appears in the base workspace.

In the property dialog box for K1, apply a storage class other than Auto by using Storage class. For example, use the storage class SimulinkGlobal to represent the parameter object as a field of the global parameters structure.

set_param('rtwdemo_basicsc/Gain','Gain','K1');
K1 = Simulink.Parameter(2);
K1.StorageClass = 'SimulinkGlobal';

Generate code from the model.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for model: rtwdemo_basicsc
### Successful completion of build procedure for model: rtwdemo_basicsc

In the code generation report, view the file rtwdemo_basicsc.h. The structure that contains signal data now defines only one field, Gain, which represents the test-pointed output of the Gain block.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.h');
rtwdemodbtype(file,'/* Block signals (auto storage) */',...
    'B_rtwdemo_basicsc_T;',1,1)
/* Block signals (auto storage) */
typedef struct {
  real32_T Gain;                       /* '<Root>/Gain' */
} B_rtwdemo_basicsc_T;

The structure that contains block parameter data defines one field, K1, which represents the parameter object K1.

rtwdemodbtype(file,'/* Parameters (auto storage) */',...
    '/* Real-time Model Data Structure */',1,0)
/* Parameters (auto storage) */
struct P_rtwdemo_basicsc_T_ {
  real32_T K1;                         /* Variable: K1
                                        * Referenced by: '<Root>/Gain'
                                        */
};

Access Data Through Generated Interfaces

You can configure the generated code to contain extra code and files so that you can access model data through standardized interfaces. For example, use the C API to log signal data and tune parameters during execution.

Copy this custom source code into a file named ex_myHandCode.c in your current folder.

#include "ex_myHandHdr.h"
 
#define paramIdx 0 /* Index of the target parameter, 
determined by inspecting the array of structures generated by the C API. */
#define sigIdx 0 /* Index of the target signal, 
determined by inspecting the array of structures generated by the C API. */
 
void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr)
{
    /* Take action with the parameter value only at 
       the beginning of simulation and at the 5-second mark. */
    if (*tPtr == 0 || *tPtr == 5) {
        
        /* Local variables to store information extracted from 
           the model mapping information (mmi). */
        void** dataAddrMap;
        const rtwCAPI_DataTypeMap *dataTypeMap;
        const rtwCAPI_ModelParameters *params;
        int_T addrIdx;
        uint16_T dTypeIdx;
        uint8_T slDataType;
        
        /* Use built-in C API macros to extract information. */
        dataAddrMap = rtwCAPI_GetDataAddressMap(mmi);
        dataTypeMap = rtwCAPI_GetDataTypeMap(mmi);
        params = rtwCAPI_GetModelParameters(mmi);
        addrIdx = rtwCAPI_GetModelParameterAddrIdx(params,paramIdx);
        dTypeIdx =  rtwCAPI_GetModelParameterDataTypeIdx(params,paramIdx);
        slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx);
        
        /* Handle data types 'double' and 'int8'. */
        switch (slDataType) {
            
            case SS_DOUBLE: {
                real_T* dataAddress;
                dataAddress = dataAddrMap[addrIdx];
                /* At the 5-second mark, increment the parameter value by 1. */
                if (*tPtr == 5) {
                    (*dataAddress)++;
                }
                printf("Parameter value is %f\n", *dataAddress);
                break;
            }
            
            case SS_INT8: {
                int8_T* dataAddress;
                dataAddress = dataAddrMap[addrIdx];
                if (*tPtr == 5) {
                    (*dataAddress)++;
                }
                printf("Parameter value is %i\n", *dataAddress);
                break;
            }
        }
    }
}
 
void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr)
{
    /* Take action with the signal value only when 
       the simulation time is an integer value. */
    if (*tPtr-(int_T)*tPtr == 0) {
        
        /* Local variables to store information extracted from 
           the model mapping information (mmi). */
        void** dataAddrMap;
        const rtwCAPI_DataTypeMap *dataTypeMap;
        const rtwCAPI_Signals *sigs;
        int_T addrIdx;
        uint16_T dTypeIdx;
        uint8_T slDataType;
        
        /* Use built-in C API macros to extract information. */
        dataAddrMap = rtwCAPI_GetDataAddressMap(mmi);
        dataTypeMap = rtwCAPI_GetDataTypeMap(mmi);
        sigs = rtwCAPI_GetSignals(mmi);
        addrIdx = rtwCAPI_GetSignalAddrIdx(sigs,sigIdx);
        dTypeIdx =  rtwCAPI_GetSignalDataTypeIdx(sigs,sigIdx);
        slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx);
        
        /* Handle data types 'double' and 'single'. */
        switch (slDataType) {
            
            case SS_DOUBLE: {
                real_T* dataAddress;
                dataAddress = dataAddrMap[addrIdx];
                printf("Signal value is %f\n", *dataAddress);
                break;
            }
            
            case SS_SINGLE: {
                real32_T* dataAddress;
                dataAddress = dataAddrMap[addrIdx];
                printf("Signal value is %f\n", *dataAddress);
                break;
            }
        }
    }
}

Copy this custom header code into a file named ex_myHandHdr.h in your current folder.

#include <stdio.h>
#include <string.h>
#include <math.h>
/* Include rtw_modelmap.h for definitions of C API macros. */
#include "rtw_modelmap.h"
#include "builtin_typeid_types.h"
#include "rtwtypes.h"
void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);
void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);

These files use the C API to access signal and parameter data in the code that you generate from the example model.

In the model, set Configuration Parameters > Code Generation > Custom Code > Insert custom C code in generated > Header file to #include "ex_myHandHdr.h". In the same pane in the Configuration Parameters dialog box, set Additional Build Information > Source files to ex_myHandCode.c.

set_param('rtwdemo_basicsc','CustomHeaderCode','#include "ex_myHandHdr.h"')
set_param('rtwdemo_basicsc','CustomSource','ex_myHandCode.c')

Select Configuration Parameters > MAT-file Logging. The generated executable runs only until the simulation stop time (which you set in the model configuration parameters).

set_param('rtwdemo_basicsc','MatFileLogging','on')

Select all of the options under Configuration Parameters > Code Generation > Interface > Generate C API for.

set_param('rtwdemo_basicsc','RTWCAPIParams','on')
set_param('rtwdemo_basicsc','RTWCAPISignals','on')
set_param('rtwdemo_basicsc','RTWCAPIStates','on')
set_param('rtwdemo_basicsc','RTWCAPIRootIO','on')

Load the Custom Code block library.

custcode

Add a System Outputs block to the model.

add_block('custcode/System Outputs','rtwdemo_basicsc/System Outputs')

In the System Outputs block dialog box, set System Outputs Function Execution Code to this code:

{
rtwdemo_basicsc_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}

In the block dialog box, set System Outputs Function Exit Code to this code:

{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
}

Alternatively, to configure the System Outputs block, at the command prompt, use these commands:

temp.TLCFile = 'custcode';
temp.Location = 'System Outputs Function';
temp.Middle = sprintf(['{\nrtwdemo_basicsc_U.input2++;'...
    '\nrtwCAPI_ModelMappingInfo *MMI = '...
    '&(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);'...
    '\ntuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));\n}']);
temp.Bottom = sprintf(['{\nrtwCAPI_ModelMappingInfo *MMI = '...
    '&(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);'...
    '\nlogFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));\n}']);
set_param('rtwdemo_basicsc/System Outputs','RTWdata',temp)

Generate code from the model.

rtwbuild('rtwdemo_basicsc')
### Starting build procedure for model: rtwdemo_basicsc
### Successful completion of build procedure for model: rtwdemo_basicsc

In the code generation report, view the interface file rtwdemo_basicsc_capi.c. This file initializes the arrays of structures that you can use to interact with data items through the C API. For example, in the array of structures rtBlockSignals, the first structure (index 0) describes the test-pointed output signal of the Gain block in the model.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc_capi.c');
rtwdemodbtype(file,'/* Block output signal information */',...
    '/* Individual block tuning',1,0)
/* Block output signal information */
static const rtwCAPI_Signals rtBlockSignals[] = {
  /* addrMapIndex, sysNum, blockPath,
   * signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex
   */
  { 0, 0, TARGET_STRING("rtwdemo_basicsc/Gain"),
    TARGET_STRING(""), 0, 0, 0, 0, 0 },

  {
    0, 0, (NULL), (NULL), 0, 0, 0, 0, 0
  }
};

The fields of the structure, such as addrMapIndex, indicate indices into other arrays of structures, such as rtDataAddrMap, that describe the characteristics of the signal. These characteristics include the address of the signal data (a pointer to the data), the numeric data type, and the dimensions of the signal.

In the file rtwdemo_basicsc.c, view the code algorithm in the model step function. The algorithm first executes the code that you specified in the System Outputs block.

file = fullfile('rtwdemo_basicsc_grt_rtw','rtwdemo_basicsc.c');
rtwdemodbtype(file,'/* user code (Output function Body) */',...
    '/* Logic: ''<Root>/LogOp'' incorporates:',1,0)
  /* user code (Output function Body) */

  /* System '<Root>' */
  {
    rtwdemo_basicsc_U.input2++;
    rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
    tuneFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
  }

  /* DataStoreWrite: '<Root>/DSWrite' incorporates:
   *  Constant: '<Root>/Constant1'
   *  Constant: '<Root>/Constant2'
   *  Inport: '<Root>/In1'
   *  Logic: '<Root>/LogOp'
   *  RelationalOperator: '<Root>/RelOp1'
   *  RelationalOperator: '<Root>/RelOp2'
   */
  rtwdemo_basicsc_DW.mode = ((rtwdemo_basicsc_U.input1 > 10.0F) ||
    (rtwdemo_basicsc_U.input1 < -10.0F));

  /* Gain: '<Root>/Gain' incorporates:
   *  Inport: '<Root>/In2'
   *  Lookup_n-D: '<Root>/Table1'
   */
  rtwdemo_basicsc_B.Gain = rtwdemo_basicsc_P.K1 * look1_iflf_binlx
    (rtwdemo_basicsc_U.input2, rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U);

  /* Chart: '<Root>/Stateflow Chart' */
  /* Gateway: Stateflow Chart */
  /* During: Stateflow Chart */
  /* Entry Internal: Stateflow Chart */
  /* Transition: '<S1>:5' */
  if (rtwdemo_basicsc_DW.mode) {
    /* Transition: '<S1>:6' */
    /* Transition: '<S1>:2' */
    rtwdemo_basicsc_DW.X = rtwdemo_basicsc_B.Gain;
  } else {
    /* Transition: '<S1>:4' */
  }

  /* Outport: '<Root>/Out1' incorporates:
   *  Chart: '<Root>/Stateflow Chart'
   */
  /* Transition: '<S1>:3' */
  rtwdemo_basicsc_Y.Out1 = (real32_T)(rtwdemo_basicsc_DW.X * 3.0);

  /* Lookup_n-D: '<Root>/Table2' incorporates:
   *  Inport: '<Root>/In3'
   *  Inport: '<Root>/In4'
   */
  rtwdemo_basicsc_DW.X = look2_iflf_binlx(rtwdemo_basicsc_U.input3,
    rtwdemo_basicsc_U.input4, rtCP_Table2_bp01Data, rtCP_Table2_bp02Data,
    rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U);

  /* user code (Output function Trailer) */

  /* System '<Root>' */
  {
    rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
    logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
  }

  /* Matfile logging */
  rt_UpdateTXYLogVars(rtwdemo_basicsc_M->rtwLogInfo,
                      (&rtwdemo_basicsc_M->Timing.taskTime0));

  /* signal main to stop simulation */
  {                                    /* Sample time: [1.0s, 0.0s] */
    if ((rtmGetTFinal(rtwdemo_basicsc_M)!=-1) &&
        !((rtmGetTFinal(rtwdemo_basicsc_M)-rtwdemo_basicsc_M->Timing.taskTime0) >
          rtwdemo_basicsc_M->Timing.taskTime0 * (DBL_EPSILON))) {
      rtmSetErrorStatus(rtwdemo_basicsc_M, "Simulation finished");
    }
  }

  /* Update absolute time for base rate */
  /* The "clockTick0" counts the number of times the code of this task has
   * been executed. The absolute time is the multiplication of "clockTick0"
   * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
   * overflow during the application lifespan selected.
   * Timer of this task consists of two 32 bit unsigned integers.
   * The two integers represent the low bits Timing.clockTick0 and the high bits
   * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
   */
  if (!(++rtwdemo_basicsc_M->Timing.clockTick0)) {
    ++rtwdemo_basicsc_M->Timing.clockTickH0;
  }

  rtwdemo_basicsc_M->Timing.taskTime0 = rtwdemo_basicsc_M->Timing.clockTick0 *
    rtwdemo_basicsc_M->Timing.stepSize0 + rtwdemo_basicsc_M->Timing.clockTickH0 *
    rtwdemo_basicsc_M->Timing.stepSize0 * 4294967296.0;
}

/* Model initialize function */
void rtwdemo_basicsc_initialize(void)
{
  /* Registration code */

  /* initialize non-finites */
  rt_InitInfAndNaN(sizeof(real_T));

  /* initialize real-time model */
  (void) memset((void *)rtwdemo_basicsc_M, 0,
                sizeof(RT_MODEL_rtwdemo_basicsc_T));
  rtmSetTFinal(rtwdemo_basicsc_M, 10.0);
  rtwdemo_basicsc_M->Timing.stepSize0 = 1.0;

  /* Setup for data logging */
  {
    static RTWLogInfo rt_DataLoggingInfo;
    rt_DataLoggingInfo.loggingInterval = NULL;
    rtwdemo_basicsc_M->rtwLogInfo = &rt_DataLoggingInfo;
  }

  /* Setup for data logging */
  {
    rtliSetLogXSignalInfo(rtwdemo_basicsc_M->rtwLogInfo, (NULL));
    rtliSetLogXSignalPtrs(rtwdemo_basicsc_M->rtwLogInfo, (NULL));
    rtliSetLogT(rtwdemo_basicsc_M->rtwLogInfo, "tout");
    rtliSetLogX(rtwdemo_basicsc_M->rtwLogInfo, "");
    rtliSetLogXFinal(rtwdemo_basicsc_M->rtwLogInfo, "");
    rtliSetLogVarNameModifier(rtwdemo_basicsc_M->rtwLogInfo, "rt_");
    rtliSetLogFormat(rtwdemo_basicsc_M->rtwLogInfo, 0);
    rtliSetLogMaxRows(rtwdemo_basicsc_M->rtwLogInfo, 1000);
    rtliSetLogDecimation(rtwdemo_basicsc_M->rtwLogInfo, 1);

    /*
     * Set pointers to the data and signal info for each output
     */
    {
      static void * rt_LoggedOutputSignalPtrs[] = {
        &rtwdemo_basicsc_Y.Out1
      };

      rtliSetLogYSignalPtrs(rtwdemo_basicsc_M->rtwLogInfo, ((LogSignalPtrsType)
        rt_LoggedOutputSignalPtrs));
    }

    {
      static int_T rt_LoggedOutputWidths[] = {
        1
      };

      static int_T rt_LoggedOutputNumDimensions[] = {
        1
      };

      static int_T rt_LoggedOutputDimensions[] = {
        1
      };

      static boolean_T rt_LoggedOutputIsVarDims[] = {
        0
      };

      static void* rt_LoggedCurrentSignalDimensions[] = {
        (NULL)
      };

      static int_T rt_LoggedCurrentSignalDimensionsSize[] = {
        4
      };

      static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = {
        SS_SINGLE
      };

      static int_T rt_LoggedOutputComplexSignals[] = {
        0
      };

      static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = {
        (NULL)
      };

      static const char_T *rt_LoggedOutputLabels[] = {
        "output" };

      static const char_T *rt_LoggedOutputBlockNames[] = {
        "rtwdemo_basicsc/Out1" };

      static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = {
        { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }
      };

      static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = {
        {
          1,
          rt_LoggedOutputWidths,
          rt_LoggedOutputNumDimensions,
          rt_LoggedOutputDimensions,
          rt_LoggedOutputIsVarDims,
          rt_LoggedCurrentSignalDimensions,
          rt_LoggedCurrentSignalDimensionsSize,
          rt_LoggedOutputDataTypeIds,
          rt_LoggedOutputComplexSignals,
          (NULL),
          rt_LoggingPreprocessingFcnPtrs,

          { rt_LoggedOutputLabels },
          (NULL),
          (NULL),
          (NULL),

          { rt_LoggedOutputBlockNames },

          { (NULL) },
          (NULL),
          rt_RTWLogDataTypeConvert
        }
      };

      rtliSetLogYSignalInfo(rtwdemo_basicsc_M->rtwLogInfo,
                            rt_LoggedOutputSignalInfo);

      /* set currSigDims field */
      rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0];
    }

    rtliSetLogY(rtwdemo_basicsc_M->rtwLogInfo, "yout");
  }

  /* block I/O */
  (void) memset(((void *) &rtwdemo_basicsc_B), 0,
                sizeof(B_rtwdemo_basicsc_T));

  /* states (dwork) */
  (void) memset((void *)&rtwdemo_basicsc_DW, 0,
                sizeof(DW_rtwdemo_basicsc_T));

  /* external inputs */
  (void)memset((void *)&rtwdemo_basicsc_U, 0, sizeof(ExtU_rtwdemo_basicsc_T));

  /* external outputs */
  rtwdemo_basicsc_Y.Out1 = 0.0F;

  /* Initialize DataMapInfo substructure containing ModelMap for C API */
  rtwdemo_basicsc_InitializeDataMapInfo();

  /* Matfile logging */
  rt_StartDataLoggingWithStartTime(rtwdemo_basicsc_M->rtwLogInfo, 0.0,
    rtmGetTFinal(rtwdemo_basicsc_M), rtwdemo_basicsc_M->Timing.stepSize0,
    (&rtmGetErrorStatus(rtwdemo_basicsc_M)));

  /* Start for DataStoreMemory: '<Root>/Data Store Memory' */
  rtwdemo_basicsc_DW.mode = false;

  /* InitializeConditions for UnitDelay: '<Root>/Delay' */
  rtwdemo_basicsc_DW.X = 0.0F;
}

/* Model terminate function */
void rtwdemo_basicsc_terminate(void)
{
  /* (no terminate code required) */
}

This code first perturbs the input signal input2 by incrementing the value of the signal each time the step function executes. The code then uses the built-in macro rtmGetDataMapInfo to extract model mapping information from the model data structure rtwdemo_basicsc_M. The pointer MMI points to the extracted mapping information, which allows the functions tuneFcn and logFcn to access the information contained in the arrays of structures that the C API file rtwdemo_basicsc_capi.c defines.

View the function tuneFcn in the file ex_myHandCode.c. This function uses the C API (through the model mapping information mmi) and a pointer to the simulation time to print the value of the parameter K1 at specific times during code execution. When the simulation time reaches 5 seconds, the function changes the parameter value in memory. By using a switch case block, the function can access the parameter data whether the data type is int8 or double.

View the code algorithm in the model step function again. Near the end of the function, the algorithm executes the code that you specified in the System Outputs block. This code calls the function logFcn.

rtwdemodbtype(file,'/* user code (Output function Trailer) */',...
    '/* Matfile logging */',1,0)
  /* user code (Output function Trailer) */

  /* System '<Root>' */
  {
    rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(rtwdemo_basicsc_M).mmi);
    logFcn(MMI, rtmGetTPtr(rtwdemo_basicsc_M));
  }

View the function logFcn in the file ex_myHandCode.c. The function uses the C API to print the value of the test-pointed signal. The function can access the signal data whether the data type is single or double.

At the command prompt, run the generated executable rtwdemo_bascisc.exe.

system('rtwdemo_basicsc')

The parameter and signal values appear in the Command Window output.

For more information about data interfaces, including the C API, see docid:rtw_doccenter.bu38el2-1.