| Products & Services | Solutions | Academia | Support | User Community | Company |
| Download Product Updates | | | Get Pricing | | | Trial Software |
| Documentation → Simulink |
| Contents | Index |
| Learn more about Simulink |
| On this page… |
|---|
Specifying Port-Based Sample Times Hybrid Block-Based and Port-Based Sample Times Multirate S-Functions and Sample Time Hit Calculations |
You can specify the sample-time behavior of your S-functions in mdlInitializeSampleTimes. Your S-function can inherit its rates from the blocks that drive it or define its own rates.
You can specify your S-function's rates (i.e., sample times) as
Block-based sample times
Port-based sample times
Hybrid block-based and port-based sample times
With block-based sample times, the S-function specifies a set of operating rates for the block as a whole during the initialization phase of the simulation. With port-based sample times, the S-function specifies a sample time for each input and output port individually during initialization. During the simulation phase, with block-based sample times, the S-function processes all inputs and outputs each time a sample hit occurs for the block. By contrast, with port-based sample times, the block processes a particular port only when a sample hit occurs for that port.
For example, consider two sample rates, 0.5 and 0.25 seconds, respectively:
In the block-based method, selecting 0.5 and 0.25 would direct the block to execute inputs and outputs at 0.25 second increments.
In the port-based method, you could set the input port to 0.5 and the output port to 0.25, and the block would process inputs at 2 Hz and outputs at 4 Hz.
You should use port-based sample times if your application requires unequal sample rates for input and output execution or if you do not want the overhead associated with running input and output ports at the highest sample rate of your block.
In some applications, an S-Function block might need to operate internally at one or more sample rates while inputting or outputting signals at other rates. The hybrid block- and port-based method of specifying sample rates allows you to create such blocks.
In typical applications, you specify only one block-based sample time. Advanced S-functions might require the specification of port-based or multiple block sample times.
Level-2 M-file S-functions specify block-based sample times in their setup method. Use the line
block.SampleTimes = [sampleTime offsetTime];
to specify the sample time. Use a value of [-1 0] to indicate an inherited sample time. See How to Specify the Sample Time in Using Simulink for a complete list of valid sample times.
C MEX S-functions specify block-based sample time information in
The next two sections discuss how to specify block-based sample times for C MEX S-functions. A third section presents a simple example that shows how to specify sample times in mdlInitializeSampleTimes. For a detailed example, see mixedm.c.
To configure your S-function for block-based sample times, use
ssSetNumSampleTimes(S,numSampleTimes);
where numSampleTimes > 0. This tells the Simulink engine that your S-function has block-based sample times. the engine calls mdlInitializeSampleTimes, which in turn sets the sample times.
mdlInitializeSampleTimes specifies two pieces of execution information:
Sample and offset times — In mdlInitializeSampleTimes, you must specify the sampling period and offset for each sample time using ssSetSampleTime and ssSetOffsetTime. If applicable, you can calculate the appropriate sampling period and offset prior to setting them, for example, by computing the best sample time for the block based on the S-function's dialog parameters obtained using ssGetSFcnParam.
Function calls — In mdlInitializeSampleTimes, use ssSetCallSystemOutput to specify the output elements that are performing function calls. Seesfun_fcncall.c for an example and Function-Call Subsystems for an explanation of this S-function.
You specify the sample times as pairs [sample_time, offset_time], using these macros
ssSetSampleTime(S, sampleTimePairIndex, sample_time) ssSetOffsetTime(S, offsetTimePairIndex, offset_time)
where sampleTimePairIndex and offsetTimePairIndex starts at 0.
The valid sample time pairs are (uppercase values are macros defined in simstruc.h):
[CONTINUOUS_SAMPLE_TIME, 0.0 ] [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] [discrete_sample_period, offset ] [VARIABLE_SAMPLE_TIME , 0.0 ]
Alternatively, you can specify that the sample time is inherited from the driving block, in which case the S-function can have only one sample time pair,
[INHERITED_SAMPLE_TIME, 0.0 ]
or
[INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]
Note If your S-function inherits its sample time, you should specify whether it is safe to use the S-function in a submodel, i.e., a model referenced by another model. See Specifying Model Reference Sample Time Inheritance for more information. |
The following guidelines might help in specifying sample times:
A continuous function that changes during minor integration steps should register the [CONTINUOUS_SAMPLE_TIME, 0.0] sample time.
A continuous function that does not change during minor integration steps should register the [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] sample time.
A discrete function that changes at a specified rate should register the discrete sample time pair
[discrete_sample_period, offset]
where
discrete_sample_period > 0.0
and
0.0 <= offset < discrete_sample_period
A discrete function that changes at a variable rate should register the variable-step discrete [VARIABLE_SAMPLE_TIME, 0.0] sample time. In C MEX S-functions, the mdlGetTimeOfNextVarHit function is called to get the time of the next sample hit for the variable-step discrete task. The VARIABLE_SAMPLE_TIME can be used with variable-step solvers only.
If your function has no intrinsic sample time, you must indicate that it is inherited according to the following guidelines:
A function that changes as its input changes, even during minor integration steps, should register the [INHERITED_SAMPLE_TIME, 0.0] sample time.
A function that changes as its input changes, but doesn't change during minor integration steps (that is, is held during minor steps), should register the [INHERITED_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] sample time.
To check for a sample hit during execution (in mdlOutputs or mdlUpdate), use the ssIsSampleHit or ssIsContinuousTask macro. For example, use the following code fragment to check for a continuous sample hit:
if (ssIsContinuousTask(S,tid)) { }
To determine whether the third (discrete) task has a hit, use the following code fragment:
if (ssIsSampleHit(S,2,tid) { }
The Simulink engine always assigns an index of 0 to the continuous sample rate, if it exists, however you get incorrect results if you use ssIsSampleHit(S,0,tid).
This example specifies that there are two discrete sample times with periods of 0.01 and 0.5 seconds.
static void mdlInitializeSampleTimes(SimStruct *S) { ssSetSampleTime(S, 0, 0.01); ssSetOffsetTime(S, 0, 0.0); ssSetSampleTime(S, 1, 0.5); ssSetOffsetTime(S, 1, 0.0); } /* End of mdlInitializeSampleTimes. */
Port-based sample times cannot be used with S-functions that have neither input ports nor output ports. If an S-function uses port-based sample times and has no ports, the S-function produces errors when the Simulink model is updated or run. If the number of input or output ports on an S-function is variable, extra protection should be added into the S-function to ensure the total number of ports does not go to zero.
To use port-based sample times in a Level-2 M-file S-function:
Specify the sample and offset times for each S-function port in the setup method. For example:
block.InputPort(1).SampleTime = [-1 0]; block.OutputPort(1).SampleTime = [-1 0];
The setup method should not specify a sample time for the block when using port-based sample times.
Provide SetInputPortSampleTime and SetOutputPortSampleTime methods, even if your S-function does not inherit its port-based sample times.
To use port-based sample times in your C MEX S-function, you must specify the number of sample times as port-based in the S-function's mdlInitializeSizes method:
ssSetNumSampleTimes(S, PORT_BASED_SAMPLE_TIMES)
You must also specify the sample time of each input and output port in the S-function's mdlInitializeSizes method, using the following macros
ssSetInputPortSampleTime(S, idx, period) ssSetInputPortOffsetTime(S, idx, offset) ssSetOutputPortSampleTime(S, idx, period) ssSetOutputPortOffsetTime(S, idx, offset)
Note mdlInitializeSizes should not contain any ssSetSampleTime or ssSetOffsetTime calls when you use port-based sample times. |
The call to ssSetNumSampleTimes can be placed before or after the port-based sample times are actually specified in mdlInitializeSizes. However, if ssSetNumSampleTimes does not configure the S-function to use port-based sample times, any sample times set on the ports will be ignored.
For any given port, you can specify
A specific sample time and period
For example, the following code sets the sample time of the S-function's first input port to 0.1 and the offset time to 0.
ssSetInputPortSampleTime(S, 0, 0.1); ssSetInputPortOffsetTime(S, 0, 0);
Inherited sample time, i.e., the port inherits its sample time from the port to which it is connected (see Specifying Inherited Sample Time for a Port)
Constant sample time, i.e., the port's input or output never changes (see Specifying Constant Sample Time for a Port)
Note To be usable in a triggered subsystem, all of your S-function's ports must have either inherited or constant sample time (see Configuring Port-Based Sample Times for Use in Triggered Subsystems). |
In a Level-2 M-file S-function, use a value of [-1 0] for the SampleTime property of each port to specify that the port inherits its sample time.
To specify that a port's sample time is inherited in a C MEX S-function, the mdlInitializeSizes method should set its period to -1 and its offset to 0. For example, the following code specifies inherited sample time for a C MEX S-function's first input port:
ssSetInputPortSampleTime(S, 0, -1); ssSetInputPortOffsetTime(S, 0, 0);
When you specify port-based sample times, the Simulink engine calls mdlSetInputPortSampleTime and mdlSetOutputPortSampleTime to determine the rates of inherited signals.
Once all rates have been determined, the engine calls mdlInitializeSampleTimes. Even though there is no need to initialize port-based sample times at this point, the engine invokes this method to give your S-function an opportunity to configure function-call connections. Your S-function must thus provide an implementation for this method regardless of whether it uses port-based sample times or function-call connections. Although you can provide an empty implementation, you might want to use it to check the appropriateness of the sample times that the block inherited during sample time propagation. Use ssGetInputPortSampleTime and ssGetOutputPortSampleTime in mdlInitializeSampleTimes to obtain the values of the inherited sample times. For example, the following code in mdlInitializeSampleTimes checks if the S-function's first input inherited a continuous sample time.
if (!ssGetInputPortSampleTime(S,0) {
ssSetErrorStatus(S,"Cannot inherit a continuous sample time.");
}Note If you specify that your S-function's ports inherit their sample time, you should also specify whether it is safe to use the S-function in a submodel, i.e., a model referenced by another model. See Specifying Model Reference Sample Time Inheritance for more information. |
If your S-function uses port-based sample times, it can specify that any of its ports has a constant sample time. This means that the signal entering or leaving the port never changes from its initial value at the start of the simulation.
In a Level-2 M-file S-function, use the following line of code to specify a constant port-based sample time:
block.OutputPort(1).SampleTime = [inf 0];
The Simulink engine determines if a constant sample time is valid during sample-time propagation.
For C MEX S-functions, before specifying a constant sample time for an output port whose output depends on the S-function's parameters, the S-function should use ssGetInlineParameters to check whether the Inline parameters option on the Optimization pane of the Configuration parameters dialog box is on. If this option is not selected, you can change the values the S-function's parameters and hence its outputs during the simulation. In this case, the S-function can not specify a constant sample time for any ports whose outputs depend on the S-function's parameters.
To specify constant sample time for a port, the S-function must perform the following tasks
Use ssSetOptions to tell the Simulink engine that it supports constant port sample times in its mdlInitializeSizes method:
ssSetOptions(S, SS_OPTION_ALLOW_CONSTANT_PORT_SAMPLE_TIME);
Note By setting this option, your S-function is telling the engine that all of its ports support a constant sample time, including ports that inherit their sample times from other blocks. If any of the S-function's inherited sample time ports cannot have a constant sample time, your S-function's mdlSetInputPortSampleTime and mdlSetOutputPortSampleTime methods must check whether that port has inherited a constant sample time. If the port has inherited a constant sample time, your S-function should throw an error. |
Set the port's period to inf and its offset to 0, e.g.,
ssSetInputPortSampleTime(S, 0, mxGetInf()); ssSetInputPortOffsetTime(S, 0, 0);
Check in mdlOutputs whether the method's tid argument equals CONSTANT_TID and if so, set the value of the port's output if it is an output port.
See sfun_port_constant.c, the source file for the sfcndemo_port_constant demo, for an example of how to create ports with a constant sample time.
Level-2 M-file S-functions with port-based sample times cannot be placed in a triggered subsystem. You must modify your S-function to use block-based sample times if you need to include it in a triggered subsystem.
To use a C MEX S-function in a triggered subsystem, your port-based sample time S-function must perform the following tasks.
Use ssSetOptions in the mdlInitializeSizes method to indicate the S-function can run in a triggered subsystem:
ssSetOptions(S, SS_OPTION_ALLOW_PORT_SAMPLE_TIME_IN_TRIGSS);
Set all of its ports to have either inherited or constant sample time in its mdlInitializeSizes method.
Handle inheritance of a triggered sample time in mdlSetInputPortSampleTime and mdlSetOutputPortSampleTime methods as follows.
Since the S-function's ports inherit their sample times, the Simulink engine invokes either mdlSetInputPortSampleTime or mdlSetOutputPortSampleTime during sample time propagation. The macro ssSampleAndOffsetAreTriggered can be used in these methods to determine if the S-function resides in a triggered subsystem. If the S-function does reside in a triggered subsystem, whichever method is called must set the sample time and offset of the port for which it is called to INHERITED_SAMPLE_TIME (-1).
Setting a port's sample time and offset both to INHERITED_SAMPLE_TIME indicates that the sample time of the port is triggered, i.e., it produces an output or accepts an input only when the subsystem in which it resides is triggered. The method must then also set the sample times and offsets of all of the S-function's other input and output ports to have either triggered or constant sample time, whichever is appropriate, e.g.,
static void mdlSetInputPortSampleTime(SimStruct *S,
int_T portIdx,
real_T sampleTime
real_T offsetTime)
{
/* If the S-function resides in a triggered subsystem,
the sample time and offset passed to this method
are both equal to INHERITED_SAMPLE_TIME. Therefore,
if triggered, the following lines set the sample time
and offset of the input port to INHERITED_SAMPLE_TIME.*/
ssSetInputPortSampleTime(S, portIdx, sampleTime);
ssSetInputPortOffsetTime(S, portIdx, offsetTime);
/* If triggered, set the output port to inherited, as well */
if (ssSampleAndOffsetAreTriggered(sampleTime,offsetTime)) {
ssSetOutputPortSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOutputPortOffsetTime(S, 0, INHERITED_SAMPLE_TIME);
/* Note, if there are additional input and output ports
on this S-function, they should be set to either
inherited or constant at this point, as well. */
}
}There is no way for an S-function residing in a triggered subsystem to predict whether the Simulink engine will call mdlSetInputPortSampleTime or mdlSetOutputPortSampleTime to set its port sample times. For this reason, both methods must be able to set the sample times of all ports correctly so the engine has to call only one of the methods a single time.
In mdlUpdate and mdlOutputs, use ssGetPortBasedSampleTimeBlockIsTriggered to check whether the S-function resides in a triggered subsystem and if so, use appropriate algorithms for computing its states and outputs.
See sfun_port_triggered.c, the source file for the sfcndemo_port_triggered.mdl demo model, for an example of how to create an S-function that can be used in a triggered subsystem.
The hybrid method of assigning sample times combines the block-based and port-based methods. You first specify, in mdlInitializeSizes, the total number of rates at which your block operates, including both block and input and output rates, using ssSetNumSampleTimes.
You then set the SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED option, using ssSetOptions, to tell the simulation engine that you are going to use the port-based method to specify the rates of the input and output ports individually. Next, as in the block-based method, you specify the periods and offsets of all of the block's rates, both internal and external, using
ssSetSampleTime ssSetOffsetTime
Finally, as in the port-based method, you specify the rates for each port, using
ssSetInputPortSampleTime(S, idx, period) ssSetInputPortOffsetTime(S, idx, offset) ssSetOutputPortSampleTime(S, idx, period) ssSetOutputPortOffsetTime(S, idx, offset)
Note that each of the assigned port rates must be the same as one of the previously declared block rates. For an example S-function, see mixedm.c.
Note If you use the SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED option, your S-function cannot inherit sample times. Instead, you must specify the rate at which each input and output port runs. |
Level-2 M-file S-functions do not support hybrid block-based and port-based sample times.
In a multirate S-Function block, you can encapsulate the code that defines each behavior in the mdlOutputs and mdlUpdate functions with a statement that determines whether a sample hit has occurred. In a C MEX S-function, the ssIsSampleHit macro determines whether the current time is a sample hit for a specified sample time. The macro has this syntax:
ssIsSampleHit(S, st_index, tid)
where S is the SimStruct, st_index identifies a specific sample time index, and tid is the task ID (tid is an argument to the mdlOutputs and mdlUpdate functions).
For example, these statements in a C MEX S-function specify three sample times: one for continuous behavior and two for discrete behavior.
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetSampleTime(S, 1, 0.75); ssSetSampleTime(S, 2, 1.0);
In the mdlUpdate function, the following statement encapsulates the code that defines the behavior for the sample time of 0.75 second.
if (ssIsSampleHit(S, 1, tid)) {
}
The second argument, 1, corresponds to the second sample time, 0.75 second.
Use the following lines to encapsulate the code that defines the behavior for the continuous sample hit:
if (ssIsContinuousTask(S,tid)) { }
In a Level-2 M-file S-function, use the IsSampleHit method to determine whether the current simulation time is one at which a task handled by this block is active.
This example defines a sample time for a block that is continuous.
/* Initialize the sample time and offset. */
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
You must add this statement to the mdlInitializeSizes function.
ssSetNumSampleTimes(S, 1);
This example defines sample times for a hybrid S-Function block.
/* Initialize the sample time and offset. */
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Continuous state sample time and offset. */
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
/* Discrete state sample time and offset. */
ssSetSampleTime(S, 1, 0.1);
ssSetOffsetTime(S, 1, 0.025);
}
In the second sample time, the offset causes the Simulink engine to call the mdlUpdate function at these times: 0.025 second, 0.125 second, 0.225 second, and so on, in increments of 0.1 second.
The following statement, which indicates how many sample times are defined, also appears in the mdlInitializeSizes function.
ssSetNumSampleTimes(S, 2);
For fixed-step solvers, Simulink uses integer arithmetic, rather than floating-point arithmetic, to calculate the sample time hits. Consequently, task times are integer multiples of their corresponding sample time periods.
This calculation method becomes important if you consider performing Boolean logic based upon task times in multirate S-functions. For example, consider an S-function that has two sample times. The fact that (ssIsSampleHit(S, idx1) == true && ssIsSampleHit(S,idx2) == true, does not guarantee that ssGetTaskTime(S, idx1) == ssGetTaskTime(S, idx2).
If tasks running at different rates need to share data, you must ensure that data generated by one task is valid when accessed by another task running at a different rate. You can use the ssIsSpecialSampleHit macro in the mdlUpdate or mdlOutputs routine of a multirate S-function to ensure that the shared data is valid. This macro returns true if a sample hit has occurred at one rate and a sample hit has also occurred at another rate in the same time step. It thus permits a higher rate task to provide data needed by a slower rate task at a rate the slower task can accommodate.
Suppose, for example, that your model has an input port operating at one rate (with a sample time index of 0) and an output port operating at a slower rate (with a sample time index of 1). Further, suppose that you want the output port to output the value currently on the input. The following example illustrates usage of this macro.
if (ssIsSampleHit(S, 0, tid) {
if (ssIsSpecialSampleHit(S, 0, 1, tid) {
/* Transfer input to output memory. */
...
}
}
if (ssIsSampleHit(S, 1, tid) {
/* Emit output. */
...
}
In this example, the first block runs when a sample hit occurs at the input rate. If the hit also occurs at the output rate, the block transfers the input to the output memory. The second block runs when a sample hit occurs at the output rate. It transfers the output in its memory area to the block's output.
Note that higher-rate tasks always run before slower-rate tasks. Thus, the input task in the preceding example always runs before the output task, ensuring that valid data is always present at the output port.
In a Level-2 M-file S-function, use the IsSpecialSampleHit method to determine whether the current simulation time is one at which multiple tasks implemented by this block are active.
If your C MEX S-function inherits its sample times from the blocks that drive it, it should specify whether submodels containing your S-function can inherit sample times from their parent model. If the S-function's output does not depend on its inherited sample time, use the ssSetModelReferenceSampleTimeInheritanceRule macro to set the S-function's sample time inheritance rule to USE_DEFAULT_FOR_DISCRETE_INHERITANCE. Otherwise, set the rule to DISALLOW_SAMPLE_TIME_INHERITANCE to disallow sample-time inheritance for submodels that include S-functions whose outputs depend on their inherited sample time and thereby avoid inadvertent simulation errors.
Note If your S-function does not set this flag, the Simulink engine assumes that it does not preclude a submodel containing it from inheriting a sample time. However, the engine optionally warns you that the submodel contains S-functions that do not specify a sample-time inheritance rule (see Blocks Whose Outputs Depend on Inherited Sample Time in Using Simulink). |
If you are uncertain whether an existing S-function's output depends on its inherited sample time, check whether it invokes any of the following C macros:
ssGetSampleTime
ssGetInputPortSampleTime
ssGetOutputPortSampleTime
ssGetInputPortOffsetTime
ssGetOutputPortOffsetTime
ssGetSampleTimePtr
ssGetInputPortSampleTimeIndex
ssGetOutputPortSampleTimeIndex
ssGetSampleTimeTaskID
ssGetSampleTimeTaskIDPtr
or TLC functions:
LibBlockSampleTime
CompiledModel.SampleTime
LibBlockInputSignalSampleTime
LibBlockInputSignalOffsetTime
LibBlockOutputSignalSampleTime
LibBlockOutputSignalOffsetTime
If your S-function does not invoke any of these macros or functions, its output does not depend on its inherited sample time and hence it is safe to use in submodels that inherit their sample time.
As an example of an S-function that precludes a submodel from inheriting its sample time, consider an S-function that has the following mdlOutputs method:
static void mdlOutputs(SimStruct *S, int_T tid) {
const real_T *u = (const real_T*)
ssGetInputPortSignal(S,0);
real_T *y = ssGetOutputPortSignal(S,0);
y[0] = ssGetSampleTime(S,tid) * u[0];
}
The output of this S-function is its inherited sample time, hence its output depends on its inherited sample time, and hence it is unsafe to use in a submodel. For this reason, this S-function should specify its model reference inheritance rule as follows:
ssSetModelReferenceSampleTimeInheritanceRule (S, DISALLOW_SAMPLE_TIME_INHERITANCE);
![]() | Custom Data Types | Zero Crossings | ![]() |

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.
| © 1984-2009- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |