]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - src/timer.c
Inversion between Array and Record fixed
[CanFestival-3.git] / src / timer.c
1 /*
2 This file is part of CanFestival, a library implementing CanOpen Stack. 
3
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
5
6 See COPYING file for copyrights details.
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22 /*!
23 ** @file   timer.c
24 ** @author Edouard TISSERANT and Francis DUPIN
25 ** @date   Tue Jun  5 09:32:32 2007
26 **
27 ** @brief
28 **
29 **
30 */
31
32 /* #define DEBUG_WAR_CONSOLE_ON */
33 /* #define DEBUG_ERR_CONSOLE_ON */
34
35 #include <applicfg.h>
36 #include "timer.h"
37
38 /*  ---------  The timer table --------- */
39 s_timer_entry timers[MAX_NB_TIMER] = {{TIMER_FREE, NULL, NULL, 0, 0, 0},};
40
41 TIMEVAL total_sleep_time = TIMEVAL_MAX;
42 TIMER_HANDLE last_timer_raw = -1;
43
44 #define min_val(a,b) ((a<b)?a:b)
45
46 /*!                                                                                                
47 ** -------  Use this to declare a new alarm ------                                                                                                
48 **                                                                                                 
49 ** @param d                                                                                        
50 ** @param id                                                                                       
51 ** @param callback                                                                                 
52 ** @param value                                                                                    
53 ** @param period                                                                                   
54 **                                                                                                 
55 ** @return                                                                                         
56 **/   
57 TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
58 {
59         /*printf("SetAlarm(UNS32 id=%d, TimerCallback_t callback=%x, TIMEVAL value=%d, TIMEVAL period=%d)\n", id, callback, value, period); */
60         TIMER_HANDLE i;
61         TIMER_HANDLE row_number = TIMER_NONE;
62
63         /* in order to decide new timer setting we have to run over all timer rows */
64         for(i=0; i <= last_timer_raw + 1 && i < MAX_NB_TIMER; i++)
65         {
66                 s_timer_entry *row = (timers+i);
67
68                 if (callback &&         /* if something to store */
69                    row->state == TIMER_FREE) /* and empty row */
70                 {       /* just store */
71                         row->callback = callback;
72                         row->d = d;
73                         row->id = id;
74                         row->val = value;
75                         row->interval = period;
76                         row->state = TIMER_ARMED;
77                         row_number = i;
78                         break;
79                 }
80         }
81         
82         if (row_number != TIMER_NONE) /* if successfull **/
83         {
84                 TIMEVAL real_timer_value;
85                 TIMEVAL elapsed_time;
86                 
87                 if (row_number == last_timer_raw + 1) last_timer_raw++;
88                 
89                 /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
90                 real_timer_value = min_val(value, TIMEVAL_MAX);
91                 elapsed_time = getElapsedTime();
92
93                 /*printf("elapsed_time=%d real_timer_value=%d total_sleep_time=%d\n", elapsed_time, real_timer_value, total_sleep_time); */
94                 if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
95                 {
96                         total_sleep_time = elapsed_time + real_timer_value;
97                         setTimer(real_timer_value);
98                 }
99                 /*printf("SetAlarm() return %d\n", row_number); */
100                 return row_number;
101         }
102         return TIMER_NONE;
103 }
104
105 /*!                                                                                                
106 **  -----  Use this to remove an alarm ----                                                                                             
107 **                                                                                                 
108 ** @param handle                                                                                   
109 **                                                                                                 
110 ** @return                                                                                         
111 **/  
112 TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
113 {
114         /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
115         MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
116         if(handle != TIMER_NONE)
117         {
118                 if(handle == last_timer_raw) 
119                         last_timer_raw--;
120                 timers[handle].state = TIMER_FREE;              
121         }
122         else {
123         }
124         return TIMER_NONE;
125 }
126
127 /*!                                                                                                
128 ** ------  TimeDispatch is called on each timer expiration ----                                                                                                
129 **                                                                                                 
130 **/  
131 void TimeDispatch()
132 {
133         TIMER_HANDLE i;
134         TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
135         /* First run : change timer state depending on time */
136         /* Get time since timer signal */
137         TIMEVAL overrun = getElapsedTime();
138         
139         TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
140         /*printf("total_sleep_time %d + overrun %d\n", total_sleep_time , overrun); */
141
142         for(i=0; i <= last_timer_raw; i++)
143         {
144                 s_timer_entry *row = (timers+i);
145
146                 if (row->state & TIMER_ARMED) /* if row is active */
147                 {
148                         if (row->val <= real_total_sleep_time) /* to be trigged */
149                         {
150                                 /*printf("row->val(%d) <= (%d)real_total_sleep_time\n", row->val, real_total_sleep_time); */
151                                 if (!row->interval) /* if simply outdated */
152                                 {
153                                         row->state = TIMER_TRIG; /* ask for trig */
154                                 }
155                                 else /* or period have expired */
156                                 {
157                                         /* set val as interval, with overrun correction */
158                                         row->val = row->interval - (overrun % row->interval);
159                                         row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
160                                         /* Check if this new timer value is the soonest */
161                                         next_wakeup = min_val(row->val,next_wakeup);
162                                 }
163                         }
164                         else
165                         {
166                                 /* Each armed timer value in decremented. */
167                                 row->val -= real_total_sleep_time;
168
169                                 /* Check if this new timer value is the soonest */
170                                 next_wakeup = min_val(row->val,next_wakeup);
171                         }
172                 }
173         }
174         
175         /* Remember how much time we should sleep. */
176         total_sleep_time = next_wakeup;
177
178         /* Set timer to soonest occurence */
179         setTimer(next_wakeup);
180
181         /* Then trig them or not. */
182         for(i=0; i<=last_timer_raw; i++)
183         {
184                 s_timer_entry *row = (timers+i);
185
186                 if (row->state & TIMER_TRIG)
187                 {
188                         row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
189                         if(row->callback)
190                                 (*row->callback)(row->d, row->id); /* trig ! */
191                 }
192         }
193 }
194