| Contents | Index |
| On this page… |
|---|
The following files in matlabroot/toolbox/simulink/fixedandfloat/fxpdemos/ are examples of S-functions written with the API for user-written fixed-point S-functions:
sfun_user_fxp_asr.c
sfun_user_fxp_BiasProbe.c
sfun_user_fxp_const.c
sfun_user_fxp_ContainWordLenProbe.c
sfun_user_fxp_dtprop.c
sfun_user_fxp_FixedExponentProbe.c
sfun_user_fxp_FracLengthProbe.c
sfun_user_fxp_FracSlopeProbe.c
sfun_user_fxp_IsFixedPointProbe.c
sfun_user_fxp_IsFloatingPointProbe.c
sfun_user_fxp_IsFxpFltApiCompatProbe.c
sfun_user_fxp_IsScalingPow2Probe.c
sfun_user_fxp_IsScalingTrivialProbe.c
sfun_user_fxp_IsSignedProbe.c
sfun_user_fxp_prodsum.c
sfun_user_fxp_StorageContainCatProbe.c
sfun_user_fxp_StorageContainSizeProbe.c
sfun_user_fxp_TotalSlopeProbe.c
sfun_user_fxp_U32BitRegion.c
sfun_user_fxp_WordLengthProbe.c
The sections that follow present smaller portions of code that focus on specific kinds of tasks you might want to perform within your S-function.
Within your S-function, you might need to know the data types of different ports, run-time parameters, and DWorks. In each case, you will need to get the data type ID of the data type, and then use functions from this API to extract information about the data type.
For example, suppose you need to know the data type of your input port. To do this,
Use ssGetInputPortDataType. The data type ID of the input port is returned.
Use API functions to extract information about the data type.
The following lines of example code are from sfun_user_fxp_dtprop.c.
In lines 191 and 192, ssGetInputPortDataType is used to get the data type ID for the two input ports of the S-function:
dataTypeIdU0 = ssGetInputPortDataType( S, 0 ); dataTypeIdU1 = ssGetInputPortDataType( S, 1 );
Further on in the file, the data type IDs are used with API functions to get information about the input port data types. In lines 205 through 226, a check is made to see whether the input port data types are single or double:
storageContainerU0 = ssGetDataTypeStorageContainCat( S,
dataTypeIdU0 );
storageContainerU1 = ssGetDataTypeStorageContainCat( S,
dataTypeIdU1 );
if ( storageContainerU0 == FXP_STORAGE_DOUBLE ||
storageContainerU1 == FXP_STORAGE_DOUBLE )
{
/* Doubles take priority over all other rules.
* If either of first two inputs is double,
* then third input is set to double.
*/
dataTypeIdU2Desired = SS_DOUBLE;
}
else if ( storageContainerU0 == FXP_STORAGE_SINGLE ||
storageContainerU1 == FXP_STORAGE_SINGLE )
{
/* Singles take priority over all other rules,
* except doubles.
* If either of first two inputs is single
* then third input is set to single.
*/
dataTypeIdU2Desired = SS_SINGLE;
}
elseIn lines 227 through 244, additional API functions are used to get information about the data types if they are neither single nor double:
{
isSignedU0 = ssGetDataTypeFxpIsSigned( S, dataTypeIdU0 );
isSignedU1 = ssGetDataTypeFxpIsSigned( S, dataTypeIdU1 );
wordLengthU0 = ssGetDataTypeFxpWordLength( S, dataTypeIdU0 );
wordLengthU1 = ssGetDataTypeFxpWordLength( S, dataTypeIdU1 );
fracSlopeU0 = ssGetDataTypeFracSlope( S, dataTypeIdU0 );
fracSlopeU1 = ssGetDataTypeFracSlope( S, dataTypeIdU1 );
fixedExponentU0 = ssGetDataTypeFixedExponent( S,dataTypeIdU0 );
fixedExponentU1 = ssGetDataTypeFixedExponent( S,dataTypeIdU1 );
totalSlopeU0 = ssGetDataTypeTotalSlope( S, dataTypeIdU0 );
totalSlopeU1 = ssGetDataTypeTotalSlope( S, dataTypeIdU1 );
biasU0 = ssGetDataTypeBias( S, dataTypeIdU0 );
biasU1 = ssGetDataTypeBias( S, dataTypeIdU1 );
}The functions used above return whether the data types are signed or unsigned, as well as their word lengths, fractional slopes, exponents, total slopes, and biases. Together, these quantities give full information about the fixed-point data types of the input ports.
You may want to set the data type of various ports, run-time parameters, or DWorks in your S-function.
For example, suppose you want to set the output port data type of your S-function. To do this,
Register a data type by using one of the functions listed in the table Data Type Registration Functions. A data type ID is returned.
Alternately, you can use one of the predefined data type IDs of the Simulink built-in data types.
Use ssSetOutputPortDataType with the data type ID from Step 1 to set the output port to the desired data type.
In the example below from lines 336 - 352 of sfun_user_fxp_const.c, ssRegisterDataTypeFxpBinaryPoint is used to register the data type. ssSetOutputPortDataType then sets the output data type either to the given data type ID, or to be dynamically typed:
/* Register data type
*/
if ( notSizesOnlyCall )
{
DTypeId DataTypeId = ssRegisterDataTypeFxpBinaryPoint(
S,
V_ISSIGNED,
V_WORDLENGTH,
V_FRACTIONLENGTH,
1 /* true means obey data type override setting for
this subsystem */ );
ssSetOutputPortDataType( S, 0, DataTypeId );
}
else
{
ssSetOutputPortDataType( S, 0, DYNAMICALLY_TYPED );
}Suppose you need to get the value of the signal on your input port to use in your S-function. You should write your code so that the pointer to the input value is properly typed, so that the values read from the input port are interpreted correctly. To do this, you can use these steps, which are shown in the example code below:
Get the data type ID of the input port using ssGetInputPortDataType.
Use the data type ID to get the storage container type of the input.
Have a case for each input storage container type you want to handle. Within each case, you will need to perform the following in some way:
Create a pointer of the correct type according to the storage container, and cast the original void pointer into the new fully typed pointer (see a and c).
You can now store and use the value by dereferencing the new, fully typed pointer (see b and d).
For example,
static void mdlOutputs(SimStruct *S, int_T tid)
{
const void *pVoidIn =
(const void *)ssGetInputPortSignal( S, 0 ); (1)
DTypeId dataTypeIdU0 = ssGetInputPortDataType( S, 0 ); (2)
fxpStorageContainerCategory storageContainerU0 =
ssGetDataTypeStorageContainCat( S, dataTypeIdU0 ); (3)
switch ( storageContainerU0 )
{
case FXP_STORAGE_UINT8: (4)
{
const uint8_T *pU8_Properly_Typed_Pointer_To_U0; (a)
uint8_T u8_Stored_Integer_U0; (b)
pU8_Properly_Typed_Pointer_To_U0 =
(const uint8_T *)pVoidIn; (c)
u8_Stored_Integer_U0 =
*pU8_Properly_Typed_Pointer_To_U0; (d)
<snip: code that uses input when it's in a uint8_T>
}
break;
case FXP_STORAGE_INT8: (4)
{
const int8_T *pS8_Properly_Typed_Pointer_To_U0; (a)
int8_T s8_Stored_Integer_U0; (b)
pS8_Properly_Typed_Pointer_To_U0 =
(const int8_T *)pVoidIn; (c)
s8_Stored_Integer_U0 =
*pS8_Properly_Typed_Pointer_To_U0; (d)
<snip: code that uses input when it's in a int8_T>
}
break;Suppose you need to write the value of the output signal to the output port in your S-function. You should write your code so that the pointer to the output value is properly typed. To do this, you can use these steps, which are followed in the example code below:
Get the data type ID of the output port using ssGetOutputPortDataType.
Use the data type ID to get the storage container type of the output.
Have a case for each output storage container type you want to handle. Within each case, you will need to perform the following in some way:
Create a pointer of the correct type according to the storage container, and cast the original void pointer into the new fully typed pointer (see a and c).
You can now write the value by dereferencing the new, fully typed pointer (see b and d).
For example,
static void mdlOutputs(SimStruct *S, int_T tid)
{
<snip>
void *pVoidOut = ssGetOutputPortSignal( S, 0 ); (1)
DTypeId dataTypeIdY0 = ssGetOutputPortDataType( S, 0 ); (2)
fxpStorageContainerCategory storageContainerY0 =
ssGetDataTypeStorageContainCat( S,
dataTypeIdY0 ); (3)
switch ( storageContainerY0 )
{
case FXP_STORAGE_UINT8: (4)
{
const uint8_T *pU8_Properly_Typed_Pointer_To_Y0; (a)
uint8_T u8_Stored_Integer_Y0; (b)
<snip: code that puts the desired output stored integer
value in to temporary variable u8_Stored_Integer_Y0>
pU8_Properly_Typed_Pointer_To_Y0 =
(const uint8_T *)pVoidOut; (c)
*pU8_Properly_Typed_Pointer_To_Y0 =
u8_Stored_Integer_Y0; (d)
}
break;
case FXP_STORAGE_INT8: (4)
{
const int8_T *pS8_Properly_Typed_Pointer_To_Y0; (a)
int8_T s8_Stored_Integer_Y0; (b)
<snip: code that puts the desired output stored integer
value in to temporary variable s8_Stored_Integer_Y0>
pS8_Properly_Typed_Pointer_To_Y0 =
(const int8_T *)pVoidY0; (c)
*pS8_Properly_Typed_Pointer_To_Y0 =
s8_Stored_Integer_Y0; (d)
}
break;
<snip>The following sample code from lines 243 through 261 of sfun_user_fxp_asr.c gives an example of using the data type of the input to your S-function to calculate the output data type. Notice that in this code
The output is signed or unsigned to match the input (a).
The output is the same word length as the input (b).
The fraction length of the output depends on the input fraction length and the number of shifts (c).
#define MDL_SET_INPUT_PORT_DATA_TYPE
static void mdlSetInputPortDataType(SimStruct *S, int port,
DTypeId dataTypeIdInput)
{
if ( isDataTypeSupported( S, dataTypeIdInput ) )
{
DTypeId dataTypeIdOutput;
ssSetInputPortDataType( S, port, dataTypeIdInput );
dataTypeIdOutput = ssRegisterDataTypeFxpBinaryPoint(
S,
ssGetDataTypeFxpIsSigned( S, dataTypeIdInput ), (a)
ssGetDataTypeFxpWordLength( S, dataTypeIdInput ), (b)
ssGetDataTypeFractionLength( S, dataTypeIdInput )
- V_NUM_BITS_TO_SHIFT_RGHT, (c)
0 /* false means do NOT obey data type override
setting for this subsystem */ );
ssSetOutputPortDataType( S, 0, dataTypeIdOutput );
}
}![]() | Create MEX-Files | API Function Reference | ![]() |

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