📄 s0_usertel_txd.c
字号:
/******************************************************************************/
/* */
/* Name: s0_userTel_txd.c - S-Function for the communication using the */
/* asynchronous serial interface S0 */
/* */
/******************************************************************************/
// =============================================================================
// FW-01-03
//
// level 2 s-function
//
// To recompile this s-function into a Windows DLL use: 'recompile(name_of_the_mod_to_be_comp)'
// (==> <toolbox>\C167\MC\recomp.m)
//
// error numbers: 34 -> 39
// =============================================================================
#define S_FUNCTION_NAME s0_userTel_txd
#define S_FUNCTION_LEVEL 2
/* undefine VERBOSE to run this DLL in silent mode */
//#define VERBOSE
#include <string.h> /* memcpy, memcmp */
#include <simstruc.h>
#ifdef MATLAB_MEX_FILE
#define abort_LED(x) return
#else
#include "reg167_sfr.h" /* adapted for GCC-166 (HighTec), C167CR, FW-06-01 */
#include "reg167_sbit.h" /* adapted for GCC-166 (HighTec), C167CR, FW-06-01 */
#include "mc_signal.h" /* abort_LED, etc. */
#endif
// -------------------------------------------------------------------------------
// Number of S-function Parameters and macros to access from the SimStruct
// -------------------------------------------------------------------------------
#define SAMPLE_TIME_ARG ssGetSFcnParam(S,0) /* Sample time in seconds */
#define CHANNEL_NO_ARG ssGetSFcnParam(S,1) /* communication channel number (up to MAX_UCOM_CHANNELS) */
#define NUM_ELEMENTS_ARG ssGetSFcnParam(S,2) /* block output width -> # of elements */
#define DATA_TYPE_ARG ssGetSFcnParam(S,3) /* data type to be expected at block input */
#define NUMBER_OF_ARG 4 /* Number of input arguments */
// -------------------------------------------------------------------------------
// Macros to access the S-function parameter values
// -------------------------------------------------------------------------------
#define SAMPLE_TIME ((real_T) mxGetPr (SAMPLE_TIME_ARG)[0])
#define CHANNEL_NO ((uint_T) mxGetPr (CHANNEL_NO_ARG)[0])
#define NUM_ELEMENTS ((uint_T) mxGetPr (NUM_ELEMENTS_ARG)[0])
#define DATA_TYPE ((int_T) mxGetPr (DATA_TYPE_ARG)[0])
// ----------------------------------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------------------------------
// input signals may have the following bytes per element
const int_T BuiltInDTypeSize[8] = {
4, /* real32_T */
1, /* int8_T */
1, /* uint8_T */
2, /* int16_T */
2, /* uint16_T */
4, /* int32_T */
4, /* uint32_T */
2 /* boolean_T */
};
// ----------------------------------------------------------------------------------------------------
// local methods
// ----------------------------------------------------------------------------------------------------
// declaration of global user communication admin variables (only relevant for the target module, defined in ext_srv.h)
#include "s0_usertel.h"
/* allocate and initialise the communication variables associated with a particular channel (buffer, admin, ... ) */
static myUsrBuf *AllocateUserBuffer(uint_T channel, uint_T bufsize, uint8_T data_type_len) {
uint8_T *buf;
static myUsrBuf *admin = NULL;
/* allocate memory for admin structure of this instance's data buffer */
if((admin = (myUsrBuf *)calloc(1, sizeof(myUsrBuf))) == NULL) return NULL;
/* allocate memory for the buffer itself (buf_size '+ 4' -> telegram size, channel number, '0 0' [reserved]) */
/* the additional '+3' has been introduced to allow safe byte-swapping -- required on the 9S12... fw-03-05 */
/* (the order of every group of 4 bytes gets reversed -> uint8_T transmissions might just end up on '+1' -> '+3' makes it dword aligned) */
if((buf = (uint8_T *)calloc(bufsize + 4 + 3, sizeof(uint8_T))) == NULL) return NULL;
/* store pointer to buf in the admin structure */
admin->buf = buf;
/* store size of the actual data buffer */
admin->buf_size = bufsize;
/* initialise the access_count field */
admin->access_count = 1;
/* initialise the buffer_full flag */
admin->buffer_full = 0;
/* initialise buffer */
/* set first field of the buffer to the number of bytes per user telegram (remains invariant)... */
buf[0] = (uint8_T)(bufsize + 4);
/* set second field of the buffer to the channel number (remains invariant)... */
buf[1] = (uint8_T)channel;
/* set third field of the buffer to the channel data type length: 1, 2, 4) (remains invariant)... */
buf[2] = data_type_len;
//mexPrintf("Setting channel %d data type length to: %d\n", channel, data_type_len);
/* ... and clear the reserved byte (buf[3]) as well as the local data buffer */
memset(&buf[3], 0, bufsize + 1);
/* return access pointer */
return admin;
}
// ----------------------------------------------------------------------------------------------------
// S-Function methods
// ----------------------------------------------------------------------------------------------------
/* Function: mdlCheckParameters ===============================================
*
*/
#define MDL_CHECK_PARAMETERS
#if defined(MDL_CHECK_PARAMETERS)
static void mdlCheckParameters(SimStruct *S)
{
// check parameter: SAMPLE_TIME
if (mxGetNumberOfElements(SAMPLE_TIME_ARG) != 1) abort_LED(36); // parameter must be a scalar
if ((SAMPLE_TIME < 0) && (SAMPLE_TIME != INHERITED_SAMPLE_TIME)) abort_LED(36); // invalid negative sample time
// check parameter: CHANNEL_NO
if (mxGetNumberOfElements(CHANNEL_NO_ARG) != 1) abort_LED(37); // parameter must be a scalar
if ((CHANNEL_NO < 0) || (CHANNEL_NO >= MAX_UCOM_CHANNELS)) abort_LED(37); // invalid channel number
// check parameter: NUM_ELEMENTS
if (mxGetNumberOfElements(NUM_ELEMENTS_ARG) != 1) abort_LED(38); // parameter must be a scalar
if ((NUM_ELEMENTS < 1) ||
(BuiltInDTypeSize[DATA_TYPE-1] * NUM_ELEMENTS > MAX_BUF_SIZE)) abort_LED(38); // inadmissible buffer size
}
#endif /* MDL_CHECK_PARAMETERS */
/* Function: mdlInitializeSizes ===============================================
*
*/
static void mdlInitializeSizes (SimStruct *S)
{
int_T i;
ssSetNumSFcnParams(S, NUMBER_OF_ARG); // expected number of parameters
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) abort_LED(35); // incorrect number of parameters
else {
#ifdef MDL_CHECK_PARAMETERS
mdlCheckParameters(S); // check all parameters
#endif
}
/* setup sizes of both work vectors and state vectors */
//ssSetNumIWork (S, 0); // no instance-local integer values
//ssSetNumRWork (S, 0); // no instance-local real values
ssSetNumPWork (S, 1); // instance-local pointer: access to this channel's buffer structure
//ssSetNumDWork (S, 0); // no instance-local user data types used
//ssSetNumContStates (S, 0); // width of the instance-local vector of continuous states
//ssSetNumDiscStates (S, 0); // width of the instance-local vector of discrete states
/* define number of sample times used by this s-function */
ssSetNumSampleTimes (S, 1); // only 'one' sampletime in this S-Function
// None of this s-functions's parameters are tunable during simulation (sample time, channel, buffer size, data type)
for (i=0; i<NUMBER_OF_ARG; i++) ssSetSFcnParamNotTunable(S, i);
if(!ssSetNumInputPorts(S, 1)) abort_LED(39); // block has a single input...
if(!ssSetNumOutputPorts(S, 0)) abort_LED(39); // ... and no output (-> sink)
ssSetInputPortWidth(S, 0, NUM_ELEMENTS); // input width: number of elements
//mexPrintf("Data type: %d\n", DATA_TYPE);
ssSetInputPortDataType(S, 0, DATA_TYPE); // block initialization code (mbc_userteltxd.m) adjusts this to '1' ... (no '0' = 'double')
ssSetInputPortDirectFeedThrough(S, 0, 1); // direct feedthrough (only executs after update of inputs)
ssSetInputPortRequiredContiguous(S, 0, 1); // ports to be stored contiguously in memory
}
/* Function: mdlInitializeSampleTimes =========================================
*
*/
static void mdlInitializeSampleTimes (SimStruct *S)
{
ssSetSampleTime(S, 0, SAMPLE_TIME); // this S-Function only has 'one' sampletime -> index '0'
ssSetOffsetTime(S, 0, 0.0);
}
/* Function: mdlStart =========================================================
*
*/
#define MDL_START
static void mdlStart(SimStruct *S)
{
void **PWork = ssGetPWork(S);
uint8_T data_type = BuiltInDTypeSize[DATA_TYPE-1]; // first possible 'DATA_TYPE' is '1' ('sinle') -> map this to '0' (beginning of array)
uint_T buf_size = data_type * NUM_ELEMENTS;
#ifdef MATLAB_MEX_FILE
/* host S-Function (DLL) */
{
mxArray *BufferAdminVar;
myUsrBuf *admin, **myPtr;
int_T i;
/* all admin variables associated with a buffer are communicated via the workspace variable 'BufferAdminVar' */
//mexPrintf("s0_usertel_txd: mdlStart.\n");
/* check if variable 'BufferAdminVar' exists in the base workspace */
if((BufferAdminVar = mexGetVariable("base", "BufferAdminVar")) == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -