]> rtime.felk.cvut.cz Git - pes-rpp/rpp-simulink.git/blob - rpp/blocks/sfunction_lout.c
Improved S-Function blocks for DIN and LOUT. Not ready yet though.
[pes-rpp/rpp-simulink.git] / rpp / blocks / sfunction_lout.c
1 /* Copyright (C) 2013 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Carlos Jenkins <carlos@jenkins.co.cr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * File : sfunction_lout.c
20  * Abstract:
21  *     C-MEX S-function block for RPP digital output.
22  *
23  * References:
24  *     mdlCheckParameters()       : sfunctions.pdf p. 421
25  *     mdlInitializeSizes()       : sfunctions.pdf p. 441
26  *     mdlInitializeSampleTimes() : sfunctions.pdf p. 436
27  *     mdlSetWorkWidths()         : sfunctions.pdf p. 489
28  *     mdlStart()                 : sfunctions.pdf p. 492
29  *     mdlOutputs()               : sfunctions.pdf p. 447
30  *     mdlTerminate()             : sfunctions.pdf p. 493
31  *     mdlRTW()                   : sfunctions.pdf p. 458
32  *
33  *     Compile with <matlabroot>/bin/mex -v -g sfunction_lout.c
34  */
35
36
37 /*
38  * Must specify the S_FUNCTION_NAME as the name of the S-function.
39  */
40 #define S_FUNCTION_NAME                sfunction_lout
41 #define S_FUNCTION_LEVEL               2
42
43 /*
44  * Include common header and utilities
45  */
46 #include "utils.c"
47
48 #define MDL_CHECK_PARAMETERS
49 #if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE)
50
51 /* Function: mdlCheckParameters ================================================
52  * Abstract:
53  *    mdlCheckParameters verifies new parameter settings whenever parameter
54  *    change or are re-evaluated during a simulation. When a simulation is
55  *    running, changes to S-function parameters can occur at any time during
56  *    the simulation loop.
57  */
58 static void mdlCheckParameters(SimStruct *S)
59 {
60   /*
61    * Check the parameter 1
62    */
63   if EDIT_OK(S, 0) {
64     int_T dimsArray[2] = { 1, 1 };
65
66     /* Check the parameter attributes */
67     ssCheckSFcnParamValueAttribs(S, 0, "P1", DYNAMICALLY_TYPED, 2, dimsArray, 0);
68   }
69
70   /*
71    * Check the parameter 2 (sample time)
72    */
73   if EDIT_OK(S, 1) {
74     const double * sampleTime = NULL;
75     const size_t stArraySize = mxGetM(SAMPLE_TIME) * mxGetN(SAMPLE_TIME);
76
77     /* Sample time must be a real scalar value or 2 element array. */
78     if (IsRealMatrix(SAMPLE_TIME) &&
79         (stArraySize == 1 || stArraySize == 2) ) {
80       sampleTime = mxGetPr(SAMPLE_TIME);
81     } else {
82       ssSetErrorStatus(S,
83                        "Invalid sample time. Sample time must be a real scalar value or an array of two real values.");
84       return;
85     }
86
87     if (sampleTime[0] < 0.0 && sampleTime[0] != -1.0) {
88       ssSetErrorStatus(S,
89                        "Invalid sample time. Period must be non-negative or -1 (for inherited).");
90       return;
91     }
92
93     if (stArraySize == 2 && sampleTime[0] > 0.0 &&
94         sampleTime[1] >= sampleTime[0]) {
95       ssSetErrorStatus(S,
96                        "Invalid sample time. Offset must be smaller than period.");
97       return;
98     }
99
100     if (stArraySize == 2 && sampleTime[0] == -1.0 && sampleTime[1] != 0.0) {
101       ssSetErrorStatus(S,
102                        "Invalid sample time. When period is -1, offset must be 0.");
103       return;
104     }
105
106     if (stArraySize == 2 && sampleTime[0] == 0.0 &&
107         !(sampleTime[1] == 1.0)) {
108       ssSetErrorStatus(S,
109                        "Invalid sample time. When period is 0, offset must be 1.");
110       return;
111     }
112   }
113 }
114
115 #endif
116
117 /* Function: mdlInitializeSizes ================================================
118  * Abstract:
119  *    The sizes information is used by Simulink to determine the S-function
120  *    block's characteristics (number of inputs, outputs, states, etc.).
121  */
122 static void mdlInitializeSizes(SimStruct *S)
123 {
124   /* Number of expected parameters */
125   ssSetNumSFcnParams(S, 2);
126
127 #if defined(MATLAB_MEX_FILE)
128
129   if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
130     /*
131      * If the number of expected input parameters is not equal
132      * to the number of parameters entered in the dialog box return.
133      * Simulink will generate an error indicating that there is a
134      * parameter mismatch.
135      */
136     mdlCheckParameters(S);
137     if (ssGetErrorStatus(S) != NULL) {
138       return;
139     }
140   } else {
141     /* Return if number of expected != number of actual parameters */
142     return;
143   }
144
145 #endif
146
147   /* Set the parameter's tunable status */
148   ssSetSFcnParamTunable(S, 0, 1);
149   ssSetSFcnParamTunable(S, 1, 0);
150
151   ssSetNumPWork(S, 0);
152
153   if (!ssSetNumDWork(S, 0))
154     return;
155
156   /*
157    * Set the number of input ports.
158    */
159   if (!ssSetNumInputPorts(S, 1))
160     return;
161
162   /*
163    * Configure the input port 1
164    */
165   ssSetInputPortDataType(S, 0, SS_UINT8);
166   ssSetInputPortWidth(S, 0, 1);
167   ssSetInputPortComplexSignal(S, 0, COMPLEX_NO);
168   ssSetInputPortDirectFeedThrough(S, 0, 1);
169   ssSetInputPortAcceptExprInRTW(S, 0, 1);
170   ssSetInputPortOverWritable(S, 0, 1);
171   ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
172   ssSetInputPortRequiredContiguous(S, 0, 1);
173
174   /*
175    * Set the number of output ports.
176    */
177   if (!ssSetNumOutputPorts(S, 0))
178     return;
179
180   /*
181    * This S-function can be used in referenced model simulating in normal mode.
182    */
183   ssSetModelReferenceNormalModeSupport(S, MDL_START_AND_MDL_PROCESS_PARAMS_OK);
184
185   /*
186    * Set the number of sample time.
187    */
188   ssSetNumSampleTimes(S, 1);
189
190   /*
191    * All options have the form SS_OPTION_<name> and are documented in
192    * matlabroot/simulink/include/simstruc.h. The options should be
193    * combined with bitwise OR as in
194    *   ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2))
195    */
196   ssSetOptions(S,
197                SS_OPTION_USE_TLC_WITH_ACCELERATOR |
198                SS_OPTION_CAN_BE_CALLED_CONDITIONALLY |
199                SS_OPTION_EXCEPTION_FREE_CODE |
200                SS_OPTION_WORKS_WITH_CODE_REUSE |
201                SS_OPTION_SFUNCTION_INLINED_FOR_RTW |
202                SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME);
203 }
204
205 /* Function: mdlInitializeSampleTimes ==========================================
206  * Abstract:
207  *    This function is used to specify the sample time(s) for your
208  *    S-function. You must register the same number of sample times as
209  *    specified in ssSetNumSampleTimes.
210  */
211 static void mdlInitializeSampleTimes(SimStruct *S)
212 {
213   double * const sampleTime = mxGetPr(SAMPLE_TIME);
214   const  size_t stArraySize = mxGetM(SAMPLE_TIME) * mxGetN(SAMPLE_TIME);
215   ssSetSampleTime(S, 0, sampleTime[0]);
216   if (stArraySize == 1) {
217     ssSetOffsetTime(S, 0, (sampleTime[0] == CONTINUOUS_SAMPLE_TIME?
218       FIXED_IN_MINOR_STEP_OFFSET: 0.0));
219   } else {
220     ssSetOffsetTime(S, 0, sampleTime[1]);
221   }
222
223 #if defined(ssSetModelReferenceSampleTimeDefaultInheritance)
224
225   ssSetModelReferenceSampleTimeDefaultInheritance(S);
226
227 #endif
228
229 }
230
231 #define MDL_SET_WORK_WIDTHS
232 #if defined(MDL_SET_WORK_WIDTHS) && defined(MATLAB_MEX_FILE)
233
234 /* Function: mdlSetWorkWidths ==================================================
235  * Abstract:
236  *      The optional method, mdlSetWorkWidths is called after input port
237  *      width, output port width, and sample times of the S-function have
238  *      been determined to set any state and work vector sizes which are
239  *      a function of the input, output, and/or sample times.
240  *
241  *      Run-time parameters are registered in this method using methods
242  *      ssSetNumRunTimeParams, ssSetRunTimeParamInfo, and related methods.
243  */
244 static void mdlSetWorkWidths(SimStruct *S)
245 {
246   /* Set number of run-time parameters */
247   if (!ssSetNumRunTimeParams(S, 1))
248     return;
249
250   /*
251    * Register the run-time parameter 1
252    */
253   ssRegDlgParamAsRunTimeParam(S, 0, 0, "p1", ssGetDataTypeId(S, "uint8"));
254 }
255
256 #endif
257
258 #define MDL_START
259 #if defined(MDL_START)
260
261 /* Function: mdlStart ==========================================================
262  * Abstract:
263  *    This function is called once at start of model execution. If you
264  *    have states that should be initialized once, this is the place
265  *    to do it.
266  */
267 static void mdlStart(SimStruct *S)
268 {
269     UNUSED_PARAMETER(S);
270 }
271
272 #endif
273
274 /* Function: mdlOutputs ========================================================
275  * Abstract:
276  *    In this function, you compute the outputs of your S-function
277  *    block. Generally outputs are placed in the output vector(s),
278  *    ssGetOutputPortSignal.
279  */
280 static void mdlOutputs(SimStruct *S, int_T tid)
281 {
282     UNUSED_PARAMETER(S);
283     UNUSED_PARAMETER(tid);
284 }
285
286 /* Function: mdlTerminate ======================================================
287  * Abstract:
288  *    In this function, you should perform any actions that are necessary
289  *    at the termination of a simulation.
290  */
291 static void mdlTerminate(SimStruct *S)
292 {
293     UNUSED_PARAMETER(S);
294 }
295
296 #define MDL_RTW
297 #if defined(MATLAB_MEX_FILE) && defined(MDL_RTW)
298
299 /* Function: mdlRTW ============================================================
300  * Abstract:
301  *    This function is called when the Real-Time Workshop is generating
302  *    the model.rtw file.
303  */
304 static void mdlRTW(SimStruct *S)
305 {
306     UNUSED_PARAMETER(S);
307 }
308
309 #endif
310
311
312 /*
313  * Required S-function trailer
314  */
315 #ifdef MATLAB_MEX_FILE
316 # include "simulink.c"
317 #else
318 # include "cg_sfun.h"
319 #endif