/** * @file controller.c * @author Xiao Lifan (xiaolf6@midea.com) * @brief 仿真s-function主文件 * @version 0.1 * @date 2022-04-08 * * @copyright Copyright (c) 2022 * */ /* * You must specify the S_FUNCTION_NAME as the name of your S-function * (i.e. replace sfuntmpl_basic with the name of your S-function). */ #define S_FUNCTION_NAME sim_board #define S_FUNCTION_LEVEL 2 /* * Need to include simstruc.h for the definition of the SimStruct and * its associated macro definitions. */ #include "simstruc.h" #include "sfun_wrapper.h" int injection_dtype_id; /* Function: mdlInitializeSizes =============================================== * Abstract: * The sizes information is used by Simulink to determine the S-function * block's characteristics (number of inputs, outputs, states, etc.). */ static void mdlInitializeSizes(SimStruct *S) { /* Register Simulink Bus Data Types */ ssRegisterTypeFromNamedObject(S, "sfunc_injection", &injection_dtype_id); /* One expected parameters which is sample time */ ssSetNumSFcnParams(S, 1); if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { /* Return if number of expected != number of actual parameters */ return; } /* Set the first parameter non-tunable */ ssSetSFcnParamTunable(S, 0, 0); /* Set no continuous and discrete state */ ssSetNumContStates(S, 0); ssSetNumDiscStates(S, 0); /* Set 2 input port, 1 for analog input, 1 for digital input*/ if (!ssSetNumInputPorts(S, 3)) return; /* Analog input port width 8 */ ssSetInputPortWidth(S, 0, 16); /*direct input signal access*/ ssSetInputPortRequiredContiguous(S, 0, true); ssSetInputPortDirectFeedThrough(S, 0, 1); /* Digital input port width 8 */ ssSetInputPortWidth(S, 1, 8); /* Digital input port data type INT32*/ ssSetInputPortDataType(S, 1, SS_INT32); /*direct input signal access*/ ssSetInputPortRequiredContiguous(S, 1, true); ssSetInputPortDirectFeedThrough(S, 1, 1); /* Injection input port width 8 */ ssSetInputPortWidth(S, 2, 8); /* Injection control port data type INT32 */ ssSetInputPortDataType(S, 2, injection_dtype_id); /*direct input signal access*/ ssSetInputPortRequiredContiguous(S, 2, true); ssSetInputPortDirectFeedThrough(S, 2, 1); ///* Injection data input port width 8 */ // ssSetInputPortWidth(S, 3, 8); ///*direct input signal access*/ // ssSetInputPortRequiredContiguous(S, 3, true); // ssSetInputPortDirectFeedThrough(S, 3, 1); /* Set 2 output port, 1 for analog output, 1 for digital input */ if (!ssSetNumOutputPorts(S, 3)) return; /* Analog output port width 8 */ ssSetOutputPortWidth(S, 0, 8); /* Digital output port width 16 */ ssSetOutputPortWidth(S, 1, 16); /* Digital input port data type INT32*/ ssSetOutputPortDataType(S, 1, SS_INT32); /* Test point data output port width 32 */ ssSetOutputPortWidth(S, 2, 32); ssSetNumSampleTimes(S, 1); ssSetNumRWork(S, 0); ssSetNumIWork(S, 0); ssSetNumPWork(S, 0); ssSetNumModes(S, 0); ssSetNumNonsampledZCs(S, 0); /* Specify the operating point save/restore compliance to be same as a * built-in block */ ssSetOperatingPointCompliance(S, USE_DEFAULT_OPERATING_POINT); ssSetOptions(S, 0); } /* 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. */ static void mdlInitializeSampleTimes(SimStruct *S) { const real_T *ts = mxGetPr(ssGetSFcnParam(S, 0)); ssSetSampleTime(S, 0, ts[0]); ssSetOffsetTime(S, 0, 0.0); } #define MDL_START /* Change to #undef to remove function */ #if defined(MDL_START) /* 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) { McuInit(ssGetSampleTime(S, 0)); } #endif /* MDL_START */ /* Function: mdlOutputs ======================================================= * Abstract: * In this function, you compute the outputs of your S-function * block. */ static void mdlOutputs(SimStruct *S, int_T tid) { const real_T *ain = (const real_T *)ssGetInputPortSignal(S, 0); const int32_T *din = (const int32_T *)ssGetInputPortSignal(S, 1); const injection_dtype *ctrl = (const injection_dtype *)ssGetInputPortSignal(S, 2); // const real_T* data = (const real_T*)ssGetInputPortSignal(S, 3); real_T *aout = ssGetOutputPortSignal(S, 0); int32_T *dout = ssGetOutputPortSignal(S, 1); real_T *wout = ssGetOutputPortSignal(S, 2); McuRun(ain, din, ctrl, aout, dout, wout); } #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) {} #endif /* MDL_UPDATE */ /* Function: mdlTerminate ===================================================== * Abstract: * In this function, you should perform any actions that are necessary * at the termination of a simulation. For example, if memory was * allocated in mdlStart, this is the place to free it. */ static void mdlTerminate(SimStruct *S) {} /*=============================* * Required S-function trailer * *=============================*/ #ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif