📄 scsb_sfun.c~
字号:
there is no reset signal. Note that the sampled-data clock input is now the first input port after the discrete-location inputs. */ if (use_reset) reset_port = sd_port + 1; else reset_port = -1; ninput = (nu > 0) + use_sd + use_reset; if (!ssSetNumInputPorts(S,ninput)) return; /* Initialize size and direct feedthrough status for u port. */ if (u_port != -1) { ssSetInputPortWidth(S,u_port,nu); ssSetInputPortDirectFeedThrough(S,u_port,0); } /* Initialize size and direct feedthrough status for sampled-data clock input port. */ if (use_sd) { ssSetInputPortWidth(S,sd_port,1); ssSetInputPortDirectFeedThrough(S,sd_port,0); } /* Initialize size, type, and direct feedthrough status for reset port. */ if (reset_port != -1) { ssSetInputPortWidth(S,reset_port,1); ssSetInputPortDirectFeedThrough(S,reset_port,0); ssSetInputPortDataType(S,reset_port,DYNAMICALLY_TYPED); } /* Compute port index for the state output port x. Port index is -1 if the output x is not available. */ if ((nx > 0)||(nz>0)) x_port = 0; else x_port = -1; noutput = (nx > 0)||(nz > 0); if (!ssSetNumOutputPorts(S,noutput)) return; /* Initialize the size for the x port. If sampled-data analysis is used, then make the output the continuous-time state, the controller output, and the discrete-time controller state.*/ if (x_port != -1) { if (use_sd) ssSetOutputPortWidth(S,x_port,nx+nz); else ssSetOutputPortWidth(S,x_port,nx); } ssSetNumSampleTimes(S,1); ssSetNumRWork(S,0); ssSetNumDWork(S,0); ssSetNumIWork(S,NIWORK); ssSetNumPWork(S,NPWORK); zero_crossings = 0; if (use_reset) { /* Declare that we will track one zero crossing signal, namely the reset signal. */ zero_crossings = 1; } if (use_sd) { zero_crossings++; } ssSetNumNonsampledZCs(S,zero_crossings); }/* Function: mdlInitializeSampleTimes ========================================= * Abstract: * * This function is used to specify the sample time(s) for your S-function. * You must register the same number of sample times as specified in * ssSetNumSampleTimes. If you specify that you have no sample times, then * the S-function is assumed to have one inherited sample time. * * The sample times are specified as pairs "[sample_time, offset_time]" * via the following macros: * ssSetSampleTime(S, sampleTimePairIndex, sample_time) * ssSetOffsetTime(S, offsetTimePairIndex, offset_time) * Where sampleTimePairIndex starts at 0. * * The valid sample time pairs are (upper case 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] * * The following guidelines may help aid in specifying sample times: * * o A continuous function that changes during minor integration steps * should register the [CONTINUOUS_SAMPLE_TIME, 0.0] sample time. * o A continuous function that does not change during minor integration * steps should register the * [CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET] * sample time. * o 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 * o A discrete function that changes at a variable rate should * register the variable step discrete [VARIABLE_SAMPLE_TIME, 0.0] * sample time. The mdlGetTimeOfNextVarHit function is called to get * the time of the next sample hit for the variable step discrete task. * Note, the VARIABLE_SAMPLE_TIME can be used with variable step * solvers only. * o Discrete blocks which can operate in triggered subsystems. For your * block to operate correctly in a triggered subsystem or a periodic * system it must register [INHERITED_SAMPLE_TIME, 0.0]. In a triggered * subsystem after sample times have been propagated throughout the * block diagram, the assigned sample time to the block will be * [INHERITED_SAMPLE_TIME, INHERITED_SAMPLE_TIME]. Typically discrete * blocks which can be periodic or reside within triggered subsystems * need to register the inherited sample time and the option * SS_DISALLOW_CONSTANT_SAMPLE_TIME. Then in mdlSetWorkWidths, they * need to verify that they were assigned a discrete or triggered * sample time. To do this: * mdlSetWorkWidths: * if (ssGetSampleTime(S, 0) == CONTINUOUS_SAMPLE_TIME) { * ssSetErrorStatus(S, "This block cannot be assigned a " * "continuous sample time"); * } * * If your function has no intrinsic sample time, then you should indicate * that your sample time is inherited according to the following guidelines: * * o A function that changes as its input changes, even during minor * integration steps should register the [INHERITED_SAMPLE_TIME, 0.0] * sample time. * o A function that changes as its input changes, but doesn't change * during minor integration steps (i.e., 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), * you should use the ssIsSampleHit or ssIsContinuousTask macros. * For example, if your first sample time is continuous, then you * used the following code-fragment to check for a sample hit. Note, * you would get incorrect results if you used ssIsSampleHit(S,0,tid). * if (ssIsContinuousTask(S,tid)) { * } * If say, you wanted to determine if the third (discrete) task has a hit, * then you would use the following code-fragment: * if (ssIsSampleHit(S,2,tid) { * } * */static void mdlInitializeSampleTimes(SimStruct *S){ /* Specify that we have a continuous sample time. */ ssSetSampleTime(S,0,CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S,0,0.0);}#define MDL_START /* Change to #undef to remove function *//* Function: mdlStart ======================================================= * Abstract: * This function is called once at start of model execution. If you * have states that should be initialized once, this is the place * to do it. */static void mdlStart(SimStruct *S){ int_T nx,nu,nz,nup,use_reset,u_port,reset_port,use_param,use_sd,sd_port; real_T *z_and_u,*temp,zero,*cont_states; /* Assume that all parameters have been checked previously. */ use_reset = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_RESET)); use_param = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_PARAM)); use_sd = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_SD)); nx = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NX)); if (use_sd) { nup = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NUP)); nz = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NZ)); } nu = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NU)); /* Compute port index for the input u. Port index is -1 if there is no input signal u. */ if ((nu > 0)) u_port = 0; else u_port = -1; /* Compute port index for the SD clock input.*/ if (use_sd) sd_port = u_port + 1; else sd_port = u_port; /* Compute port index for the reset signal. Port index is -1 if there is no reset signal. Note that the sampled-data clock input is now the first input port after the discrete-location inputs. */ if (use_reset) reset_port = sd_port + 1; else reset_port = -1; /* Store port indices in the integer work vector so that we don't have to compute them again. */ ssSetIWorkValue(S,IWORK_U_PORT,u_port); ssSetIWorkValue(S,IWORK_RESET_PORT,reset_port); ssSetIWorkValue(S,IWORK_USE_RESET,use_reset); ssSetIWorkValue(S,IWORK_USE_PARAM,use_param); ssSetIWorkValue(S,IWORK_USE_SD,use_sd); ssSetIWorkValue(S,IWORK_SD_PORT,sd_port); /* Initialize pointer work vector and allocate some mxArrays to store arguments for the SCSB wrapper function. */ ssSetPWorkValue(S,PWORK_X_DOT,calloc((nx+1),sizeof(real_T))); ssSetPWorkValue(S,PWORK_X_RESET,calloc(nx,sizeof(real_T))); if (use_sd){ ssSetPWorkValue(S,PWORK_Z,calloc(nz,sizeof(real_T))); ssSetPWorkValue(S,PWORK_U_OUT,calloc(nup,sizeof(real_T))); } /* Initialize the continuous state vector to initial values specified in S-function parameter. */ if (nx>0){ nx = ssGetNumContStates(S); memcpy(ssGetContStates(S),mxGetPr(ssGetSFcnParam(S,PARAM_X0)), (nx-1)*sizeof(real_T)); zero=0; cont_states = ssGetContStates(S); memcpy(&cont_states[nx-1],&zero, sizeof(real_T)); } /* If sampled-data analysis is used, put the initial controller states in the first part of the discrete-state vector. Then compute the output of the controller and put those values in the second part of the discrete-state vector.*/ if (use_sd) { temp = mxGetPr(ssGetSFcnParam(S,PARAM_X0)); if (nx>0){ memcpy(ssGetDiscStates(S),&temp[nx-1], (nz)*sizeof(real_T)); } else { memcpy(ssGetDiscStates(S),temp, (nz)*sizeof(real_T)); } computeDerivativeAndReset(S); z_and_u = ssGetDiscStates(S); if (nup>0){ memcpy(&z_and_u[nz],ssGetPWorkValue(S,PWORK_U_OUT),nup*sizeof(real_T)); } } }/* Function: mdlOutputs ======================================================= * Abstract: * In this function, you compute the outputs of your S-function * block. Generally outputs are placed in the output vector(s), * ssGetOutputPortSignal. */static void mdlOutputs(SimStruct *S,int_T tid){ real_T *cont_out,*disc_out,use_sd; int_T nx,nz; use_sd = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_USE_SD)); nx = ssGetNumContStates(S); if (use_sd){ nz = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NZ)); } /* y = x, copy state vector x to output vector y. */ cont_out = ssGetOutputPortRealSignal(S,0); memcpy(cont_out,ssGetContStates(S), (ssGetNumContStates(S)-1)*sizeof(real_T)); if (use_sd){ disc_out = &cont_out[nx-1]; memcpy(disc_out,ssGetDiscStates(S), nz*sizeof(real_T)); }}#define MDL_UPDATE /* Change to #undef to remove function */#if defined(MDL_UPDATE)/* Function: mdlUpdate ====================================================== * Abstract: * This function is called once for every major integration time step. * Discrete states are typically updated here, but this function is useful * for performing any tasks that should only take place once per * integration step. */static void mdlUpdate(SimStruct *S,int_T tid){ int_T i,j,nx,nz,nup,use_reset,reset_value,use_sd,sd_port,reset_port,clock_value,nAR; real_T prod_i; real_T *x,*CI,*dI,*z_and_u; mxArray *mxCI; InputPtrsType u; DTypeId test; nx = ssGetNumContStates(S); x = ssGetContStates(S); /* Check if state reset should be applied. */ use_reset = ssGetIWorkValue(S,IWORK_USE_RESET); if (use_reset) { reset_port = ssGetIWorkValue(S,IWORK_RESET_PORT); /* This code was added by JPK 2/2004. The purpose is to * determine what the data type of the reset input is and * to handle it accordingly.*/ test= ssGetInputPortDataType(S,reset_port); if (test==8) { /* Boolean data type case */ u = ssGetInputPortSignalPtrs(S,reset_port); if((**(InputBooleanPtrsType) u)==1){ reset_value=1; }else{ reset_value=0; } } else { /* Double data type case */ if(**ssGetInputPortRealSignalPtrs(S,reset_port)==1){ reset_value=1; }else{ reset_value=0; } } if (ssGetIWorkValue(S,IWORK_LAST_RESET) != reset_value) { /* If the reset signal changes, record the new reset signal value. */ ssSetIWorkValue(S,IWORK_LAST_RESET,reset_value); /* Apply state reset. */ computeDerivativeAndReset(S); memcpy(x,ssGetPWorkValue(S,PWORK_X_RESET),(nx-1)*sizeof(real_T)); /* Update block output since state has changed. */ mdlOutputs(S,tid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -