Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1342 giacomo 1
#include <math.h>
2
 
3
#include "tmwtypes.h"
4
#ifdef USE_RTMODEL
5
# include "simstruc_types.h"
6
#else
7
# include "simstruc.h"
8
#endif
9
#include "rt_sim.h"
10
 
11
#ifndef RT_MALLOC /* statically declare data */
12
 
13
/*==========*
14
 * Struct's *
15
 *==========*/
16
 
17
/*
18
 * TimingData
19
 */
20
typedef struct TimingData_Tag {
21
    real_T period[NUMST];       /* Task periods in seconds                   */
22
    real_T offset[NUMST];       /* Task offsets in seconds                   */
23
    real_T clockTick[NUMST];    /* Flint task time tick counter              */
24
    int_T  taskTick[NUMST];     /* Counter for determining task hits         */
25
    int_T  nTaskTicks[NUMST];   /* Number base rate ticks for a task hit     */
26
    int_T  firstDiscIdx;        /* First discrete task index                 */
27
} TimingData;
28
 
29
/*=========================*
30
 * Data local to this file *
31
 *=========================*/
32
 
33
static TimingData td;
34
 
35
/*==================*
36
 * Visible routines *
37
 *==================*/
38
 
39
/* Function: rt_SimInitTimingEngine ============================================
40
 * Abstract:
41
 *      This function is for use with single tasking or multitasking
42
 *      real-time systems.  
43
 *
44
 *      Initializes the timing engine for a fixed-step real-time system.
45
 *      It is assumed that start time is 0.0.
46
 *
47
 * Returns:
48
 *      NULL     - success
49
 *      non-NULL - error string
50
 */
51
const char *rt_SimInitTimingEngine(int_T       rtmNumSampTimes,
52
                                   real_T      rtmStepSize,
53
                                   real_T      *rtmSampleTimePtr,
54
                                   real_T      *rtmOffsetTimePtr,
55
                                   int_T       *rtmSampleHitPtr,
56
                                   int_T       *rtmSampleTimeTaskIDPtr,
57
                                   real_T      rtmTStart,
58
                                   SimTimeStep *rtmSimTimeStepPtr,
59
                                   void        **rtmTimingDataPtr)
60
{
61
    int_T     i;
62
    int       *tsMap     = rtmSampleTimeTaskIDPtr;
63
    real_T    *period    = rtmSampleTimePtr;
64
    real_T    *offset    = rtmOffsetTimePtr;
65
    int_T     *sampleHit = rtmSampleHitPtr;
66
    real_T    stepSize   = rtmStepSize;
67
 
68
    if (rtmTStart != 0.0) {
69
        return("Start time must be zero for real-time systems");
70
    }
71
 
72
    *rtmSimTimeStepPtr = MAJOR_TIME_STEP;
73
 
74
    *rtmTimingDataPtr = (void*)&td;
75
 
76
    for (i = 0; i < NUMST; i++) {
77
        tsMap[i]         = i;
78
        td.period[i]     = period[i];
79
        td.offset[i]     = offset[i];
80
        td.nTaskTicks[i] = (int_T)floor(period[i]/stepSize + 0.5);
81
        if (td.period[i] == CONTINUOUS_SAMPLE_TIME ||
82
            td.offset[i] == 0.0) {
83
            td.taskTick[i]  = 0;
84
            td.clockTick[i] = 0.0;
85
            sampleHit[i]    = 1;
86
        } else {
87
            td.taskTick[i]  = (int_T)floor((td.period[i]-td.offset[i]) /
88
                                            stepSize+0.5);
89
            td.clockTick[i] = -1.0;
90
            sampleHit[i]    = 0;
91
        }
92
    }
93
 
94
    /* Correct first sample time if continuous task */
95
    td.period[0]     = stepSize;
96
    td.nTaskTicks[0] = 1;
97
 
98
    /* Set first discrete task index */
99
#if NUMST == 1    
100
    td.firstDiscIdx = (int_T)(period[0] == CONTINUOUS_SAMPLE_TIME);
101
#else
102
    td.firstDiscIdx = ((int_T)(period[0] == CONTINUOUS_SAMPLE_TIME) +
103
                       (int_T)(period[1] == CONTINUOUS_SAMPLE_TIME));
104
#endif
105
 
106
    return(NULL); /* success */
107
 
108
} /* end rt_SimInitTimingEngine */
109
 
110
 
111
#if !defined(MULTITASKING)
112
 
113
/*###########################################################################*/
114
/*########################### SINGLE TASKING ################################*/
115
/*###########################################################################*/
116
 
117
/* Function: rt_SimGetNextSampleHit ============================================
118
 * Abstract:
119
 *      For a single tasking real-time system, return time of next sample hit.
120
 */
121
time_T rt_SimGetNextSampleHit(void)
122
{
123
    time_T timeOfNextHit;
124
    td.clockTick[0] += 1;
125
    timeOfNextHit = td.clockTick[0] * td.period[0];
126
 
127
#   if NUMST > 1
128
    {
129
        int i;
130
        for (i = 1; i < NUMST; i++) {
131
            if (++td.taskTick[i] == td.nTaskTicks[i]) {
132
                td.taskTick[i] = 0;
133
                td.clockTick[i]++;
134
            }
135
        }
136
    }
137
#   endif
138
 
139
    return(timeOfNextHit);
140
 
141
} /* end rt_SimGetNextSampleHit */
142
 
143
 
144
 
145
/* Function: rt_SimUpdateDiscreteTaskSampleHits ================================
146
 * Abstract:
147
 *      This function is for use with single tasking real-time systems.  
148
 *      
149
 *      If the number of sample times is greater than one, then we need to
150
 *      update the discrete task sample hits for the next time step. Note,
151
 *      task 0 always has a hit since it's sample time is the fundamental
152
 *      sample time.
153
 */
154
void rt_SimUpdateDiscreteTaskSampleHits(int_T  rtmNumSampTimes,
155
                                        void   *rtmTimingData,
156
                                        int_T  *rtmSampleHitPtr,
157
                                        real_T *rtmTPtr)
158
{
159
    int_T *sampleHit = rtmSampleHitPtr;
160
    int   i;
161
 
162
    UNUSED_PARAMETER(rtmTimingData);
163
    UNUSED_PARAMETER(rtmNumSampTimes);
164
 
165
    for (i = td.firstDiscIdx; i < NUMST; i++) {
166
        int_T hit = (td.taskTick[i] == 0);
167
        if (hit) {
168
            rttiSetTaskTime(rtmTPtr, i,
169
                            td.clockTick[i]*td.period[i] + td.offset[i]);
170
        }
171
        sampleHit[i] = hit;
172
    }
173
} /* rt_SimUpdateDiscreteTaskSampleHits */
174
 
175
 
176
 
177
#else /* defined(MULTITASKING) */
178
 
179
/*###########################################################################*/
180
/*############################## MULTITASKING ###############################*/
181
/*###########################################################################*/
182
 
183
 
184
/* Function: rt_SimUpdateDiscreteEvents ========================================
185
 * Abstract:
186
 *      This function is for use with multitasking real-time systems.
187
 *
188
 *      This function updates the status of the RT_MODEL sampleHits
189
 *      flags and the perTaskSampleHits matrix which is used to determine
190
 *      when special sample hits occur.
191
 *
192
 *      The RT_MODEL contains a matrix, called perTaskSampleHits.
193
 *      This matrix is used by the ssIsSpecialSampleHit macro. The row and
194
 *      column indices are both task id's (equivalent to the root RT_MODEL
195
 *      sample time indices). This is a upper triangle matrix. This routine
196
 *      only updates the slower task hits (kept in column j) for row
197
 *      i if we have a sample hit in row i.
198
 *
199
 *                       column j
200
 *           tid   0   1   2   3   4   5  
201
 *               -------------------------
202
 *             0 |   | X | X | X | X | X |
203
 *         r     -------------------------
204
 *         o   1 |   |   | X | X | X | X |      This matrix(i,j) answers:
205
 *         w     -------------------------      If we are in task i, does
206
 *             2 |   |   |   | X | X | X |      slower task j have a hit now?
207
 *         i     -------------------------
208
 *             3 |   |   |   |   | X | X |
209
 *               -------------------------
210
 *             4 |   |   |   |   |   | X |      X = 0 or 1
211
 *               -------------------------
212
 *             5 |   |   |   |   |   |   |
213
 *               -------------------------
214
 *
215
 *      How macros index this matrix:
216
 *
217
 *          ssSetSampleHitInTask(S, j, i, X)   => matrix(i,j) = X
218
 *
219
 *          ssIsSpecialSampleHit(S, my_sti, promoted_sti, tid) =>
220
 *              (tid_for(promoted_sti) == tid && !minor_time_step &&
221
 *               matrix(tid,tid_for(my_sti))
222
 *              )
223
 *
224
 *            my_sti       = My (the block's) original sample time index.
225
 *            promoted_sti = The block's promoted sample time index resulting
226
 *                           from a transition via a ZOH from a fast to a
227
 *                           slow block or a transition via a unit delay from
228
 *                           a slow to a fast block.
229
 *
230
 *      The perTaskSampleHits array, of dimension n*n, is accessed using
231
 *      perTaskSampleHits[j + i*n] where n is the total number of sample
232
 *      times, 0 <= i < n, and 0 <= j < n.  The C language stores arrays in
233
 *      row-major order, that is, row 0 followed by row 1, etc.
234
 *
235
 */
236
time_T rt_SimUpdateDiscreteEvents(int_T  rtmNumSampTimes,
237
                                  void   *rtmTimingData,
238
                                  int_T  *rtmSampleHitPtr,
239
                                  int_T  *rtmPerTaskSampleHits)
240
{
241
    int   i, j;
242
    int_T *sampleHit = rtmSampleHitPtr;
243
 
244
    UNUSED_PARAMETER(rtmTimingData);
245
 
246
    /*
247
     * Run this loop in reverse so that we do lower priority events first.
248
     */
249
    i = NUMST;
250
    while (--i >= 0) {
251
        if (td.taskTick[i] == 0) {
252
            /*
253
             * Got a sample hit, reset the counter, and update the clock
254
             * tick counter.
255
             */
256
            sampleHit[i] = 1;
257
            td.clockTick[i]++;
258
 
259
            /*
260
             * Record the state of all "slower" events
261
             */
262
            for (j = i + 1; j < NUMST; j++) {
263
                rttiSetSampleHitInTask(rtmPerTaskSampleHits, rtmNumSampTimes,
264
                                       j, i, sampleHit[j]);
265
            }
266
        } else {
267
            /*
268
             * no sample hit, increment the counter
269
             */
270
            sampleHit[i] = 0;
271
        }
272
 
273
        if (++td.taskTick[i] == td.nTaskTicks[i]) { /* update for next time */
274
            td.taskTick[i] = 0;
275
        }
276
    }
277
 
278
    return(td.clockTick[0]*td.period[0]);
279
 
280
} /* rt_SimUpdateDiscreteEvents */
281
 
282
 
283
 
284
/* Function: rt_SimUpdateDiscreteTaskTime ======================================
285
 * Abstract:
286
 *      This function is for use with multitasking systems.
287
 *
288
 *      After a discrete task output and update has been performed, this
289
 *      function must be called to update the discrete task time for next
290
 *      time around.
291
 */
292
void rt_SimUpdateDiscreteTaskTime(real_T *rtmTPtr,
293
                                  void   *rtmTimingData,
294
                                  int    tid)
295
{
296
    UNUSED_PARAMETER(rtmTimingData);
297
    rttiSetTaskTime(rtmTPtr, tid,
298
                    td.clockTick[tid]*td.period[tid] + td.offset[tid]);
299
}
300
 
301
#endif /* MULTITASKING */
302
 
303
#else
304
 
305
#include "mrt_sim.c" /* dynamically allocate data */
306
 
307
#endif /* RT_MALLOC */
308
 
309
/*
310
 *******************************************************************************
311
 * FUNCTIONS MAINTAINED FOR BACKWARDS COMPATIBILITY WITH THE SimStruct
312
 *******************************************************************************
313
 */
314
#ifndef USE_RTMODEL
315
const char *rt_InitTimingEngine(SimStruct *S)
316
{
317
    const char_T *retVal = rt_SimInitTimingEngine(
318
        ssGetNumSampleTimes(S),
319
        ssGetStepSize(S),
320
        ssGetSampleTimePtr(S),
321
        ssGetOffsetTimePtr(S),
322
        ssGetSampleHitPtr(S),
323
        ssGetSampleTimeTaskIDPtr(S),
324
        ssGetTStart(S),
325
        &ssGetSimTimeStep(S),
326
        &ssGetTimingData(S));
327
    return(retVal);
328
}
329
 
330
# ifdef RT_MALLOC
331
void rt_DestroyTimingEngine(SimStruct *S)
332
{
333
    rt_SimDestroyTimingEngine(ssGetTimingData(S));
334
}
335
# endif
336
 
337
# if !defined(MULTITASKING)
338
void rt_UpdateDiscreteTaskSampleHits(SimStruct *S)
339
{
340
    rt_SimUpdateDiscreteTaskSampleHits(
341
        ssGetNumSampleTimes(S),
342
        ssGetTimingData(S),
343
        ssGetSampleHitPtr(S),
344
        ssGetTPtr(S));
345
}
346
 
347
#   ifndef RT_MALLOC
348
 
349
time_T rt_GetNextSampleHit(void)
350
{
351
    return(rt_SimGetNextSampleHit());
352
}
353
 
354
#   else /* !RT_MALLOC */
355
 
356
time_T rt_GetNextSampleHit(SimStruct *S)
357
{
358
    return(rt_SimGetNextSampleHit(ssGetTimingData(S),
359
                                  ssGetNumSampleTimes(S)));
360
}
361
 
362
#   endif
363
 
364
# else /* MULTITASKING */
365
 
366
time_T rt_UpdateDiscreteEvents(SimStruct *S)
367
{
368
    return(rt_SimUpdateDiscreteEvents(
369
               ssGetNumSampleTimes(S),
370
               ssGetTimingData(S),
371
               ssGetSampleHitPtr(S),
372
               ssGetPerTaskSampleHitsPtr(S)));
373
}
374
 
375
void rt_UpdateDiscreteTaskTime(SimStruct *S, int tid)
376
{
377
    rt_SimUpdateDiscreteTaskTime(ssGetTPtr(S), ssGetTimingData(S), tid);
378
}
379
 
380
#endif
381
#endif
382
 
383
/* EOF: rt_sim.c */