]> rtime.felk.cvut.cz Git - mf624-simulink.git/blob - sfDigitalInput.c
Include license header to prepare code for publication.
[mf624-simulink.git] / sfDigitalInput.c
1 /*
2  * S-function to support digital input Humusoft MF624 card
3  *
4  * Copyright (C) 2014 Pavel Pisa <pisa@cmp.felk.cvut.cz>
5  *
6  * Department of Control Engineering
7  * Faculty of Electrical Engineering
8  * Czech Technical University in Prague (CTU)
9  *
10  * The S-Function for ERT Linux can be distributed in compliance
11  * with GNU General Public License (GPL) version 2 or later.
12  * Other licence can negotiated with CTU.
13  *
14  * Next exception is granted in addition to GPL.
15  * Instantiating or linking compiled version of this code
16  * to produce an application image/executable, does not
17  * by itself cause the resulting application image/executable
18  * to be covered by the GNU General Public License.
19  * This exception does not however invalidate any other reasons
20  * why the executable file might be covered by the GNU Public License.
21  * Publication of enhanced or derived S-function files is required
22  * although.
23  *
24  * Linux ERT code is available from
25  *    http://rtime.felk.cvut.cz/gitweb/ert_linux.git
26  * More CTU Linux target for Simulink components are available at
27  *    http://lintarget.sourceforge.net/
28  *
29  * sfuntmpl_basic.c by The MathWorks, Inc. has been used to accomplish
30  * required S-function structure.
31  */
32
33
34 /*
35  * You must specify the S_FUNCTION_NAME as the name of your S-function
36  * (i.e. replace sfuntmpl_basic with the name of your S-function).
37  */
38
39 #define S_FUNCTION_NAME  sfDigitalInput
40 #define S_FUNCTION_LEVEL 2
41
42 #define CHNL_PRM(S)     (mxGetScalar(ssGetSFcnParam(S, 0)))
43
44 /*
45  * Need to include simstruc.h for the definition of the SimStruct and
46  * its associated macro definitions.
47  */
48 #include "simstruc.h"
49 #include "mf624_SIMULINK.h"
50
51 /* Error handling
52  * --------------
53  *
54  * You should use the following technique to report errors encountered within
55  * an S-function:
56  *
57  *       ssSetErrorStatus(S,"Error encountered due to ...");
58  *       return;
59  *
60  * Note that the 2nd argument to ssSetErrorStatus must be persistent memory.
61  * It cannot be a local variable. For example the following will cause
62  * unpredictable errors:
63  *
64  *      mdlOutputs()
65  *      {
66  *         char msg[256];         {ILLEGAL: to fix use "static char msg[256];"}
67  *         sprintf(msg,"Error due to %s", string);
68  *         ssSetErrorStatus(S,msg);
69  *         return;
70  *      }
71  *
72  * See matlabroot/simulink/src/sfuntmpl_doc.c for more details.
73  */
74
75 /*====================*
76  * S-function methods *
77  *====================*/
78
79 /* Function: mdlInitializeSizes ===============================================
80  * Abstract:
81  *    The sizes information is used by Simulink to determine the S-function
82  *    block's characteristics (number of inputs, outputs, states, etc.).
83  */
84 static void mdlInitializeSizes(SimStruct *S)
85 {
86     /* See sfuntmpl_doc.c for more details on the macros below */
87
88     ssSetNumSFcnParams(S, 1);  /* Number of expected parameters */
89     if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
90         /* Return if number of expected != number of actual parameters */
91          ssSetErrorStatus(S,"Parameter count mismatch");
92         return;
93     }
94
95     ssSetNumContStates(S, 0);
96     ssSetNumDiscStates(S, 0);
97
98     if (!ssSetNumInputPorts(S, 0)) return;
99
100     if (!ssSetNumOutputPorts(S, 1)) return;
101     ssSetOutputPortWidth(S, 0, 1);
102
103     ssSetNumSampleTimes(S, 1);
104     ssSetNumRWork(S, 0);
105     ssSetNumIWork(S, 0);
106     ssSetNumPWork(S, 0);
107     ssSetNumModes(S, 0);
108     ssSetNumNonsampledZCs(S, 0);
109
110     /* Specify the sim state compliance to be same as a built-in block */
111     ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
112
113     ssSetOptions(S, 0);
114 }
115
116
117
118 /* Function: mdlInitializeSampleTimes =========================================
119  * Abstract:
120  *    This function is used to specify the sample time(s) for your
121  *    S-function. You must register the same number of sample times as
122  *    specified in ssSetNumSampleTimes.
123  */
124 static void mdlInitializeSampleTimes(SimStruct *S)
125 {
126     ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
127     ssSetOffsetTime(S, 0, FIXED_IN_MINOR_STEP_OFFSET);
128 }
129
130
131
132 #undef MDL_INITIALIZE_CONDITIONS   /* Change to #undef to remove function */
133 #if defined(MDL_INITIALIZE_CONDITIONS)
134   /* Function: mdlInitializeConditions ========================================
135    * Abstract:
136    *    In this function, you should initialize the continuous and discrete
137    *    states for your S-function block.  The initial states are placed
138    *    in the state vector, ssGetContStates(S) or ssGetRealDiscStates(S).
139    *    You can also perform any other initialization activities that your
140    *    S-function may require. Note, this routine will be called at the
141    *    start of simulation and if it is present in an enabled subsystem
142    *    configured to reset states, it will be call when the enabled subsystem
143    *    restarts execution to reset the states.
144    */
145   static void mdlInitializeConditions(SimStruct *S)
146   {
147   }
148 #endif /* MDL_INITIALIZE_CONDITIONS */
149
150
151
152 #define MDL_START  /* Change to #undef to remove function */
153 #if defined(MDL_START)
154   /* Function: mdlStart =======================================================
155    * Abstract:
156    *    This function is called once at start of model execution. If you
157    *    have states that should be initialized once, this is the place
158    *    to do it.
159    */
160   static void mdlStart(SimStruct *S)
161   {
162     if (mf624_init(NULL) != 0)
163           return;
164   }
165 #endif /*  MDL_START */
166
167
168
169 /* Function: mdlOutputs =======================================================
170  * Abstract:
171  *    In this function, you compute the outputs of your S-function
172  *    block.
173  */
174 static void mdlOutputs(SimStruct *S, int_T tid)
175 {
176     real_T *y;
177     uint16_t din;
178
179     if (mf624_check(S) != 0)
180             return;
181
182     y = (real_T *)ssGetOutputPortSignal(S, 0);
183
184     din = mf624_read16(MFST2REG(mfst, 2, DIN_reg));
185
186     *y = din & (1 << (int)(CHNL_PRM(S)-1)) ? 0.0 : 1.0;
187 }
188
189
190
191 #undef MDL_UPDATE  /* Change to #undef to remove function */
192 #if defined(MDL_UPDATE)
193   /* Function: mdlUpdate ======================================================
194    * Abstract:
195    *    This function is called once for every major integration time step.
196    *    Discrete states are typically updated here, but this function is useful
197    *    for performing any tasks that should only take place once per
198    *    integration step.
199    */
200   static void mdlUpdate(SimStruct *S, int_T tid)
201   {
202   }
203 #endif /* MDL_UPDATE */
204
205
206
207 #undef MDL_DERIVATIVES  /* Change to #undef to remove function */
208 #if defined(MDL_DERIVATIVES)
209   /* Function: mdlDerivatives =================================================
210    * Abstract:
211    *    In this function, you compute the S-function block's derivatives.
212    *    The derivatives are placed in the derivative vector, ssGetdX(S).
213    */
214   static void mdlDerivatives(SimStruct *S)
215   {
216   }
217 #endif /* MDL_DERIVATIVES */
218
219
220
221 /* Function: mdlTerminate =====================================================
222  * Abstract:
223  *    In this function, you should perform any actions that are necessary
224  *    at the termination of a simulation.  For example, if memory was
225  *    allocated in mdlStart, this is the place to free it.
226  */
227 static void mdlTerminate(SimStruct *S)
228 {
229         mf624_done();
230 }
231
232
233 /*======================================================*
234  * See sfuntmpl_doc.c for the optional S-function methods *
235  *======================================================*/
236
237 /*=============================*
238  * Required S-function trailer *
239  *=============================*/
240
241 #ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
242 #include "simulink.c"      /* MEX-file interface mechanism */
243 #else
244 #include "cg_sfun.h"       /* Code generation registration function */
245 #endif