]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - src/timer.c
*** empty log message ***
[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         s_timer_entry *row;
63
64         /* in order to decide new timer setting we have to run over all timer rows */
65         for(i=0, row=timers; i <= last_timer_raw + 1 && i < MAX_NB_TIMER; i++, row++)
66         {
67                 if (callback &&         /* if something to store */
68                    row->state == TIMER_FREE) /* and empty row */
69                 {       /* just store */
70                         row->callback = callback;
71                         row->d = d;
72                         row->id = id;
73                         row->val = value;
74                         row->interval = period;
75                         row->state = TIMER_ARMED;
76                         row_number = i;
77                         break;
78                 }
79         }
80         
81         if (row_number != TIMER_NONE) /* if successfull **/
82         {
83                 TIMEVAL real_timer_value;
84                 TIMEVAL elapsed_time;
85                 
86                 if (row_number == last_timer_raw + 1) last_timer_raw++;
87                 
88                 /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
89                 real_timer_value = min_val(value, TIMEVAL_MAX);
90                 elapsed_time = getElapsedTime();
91
92                 /*printf("elapsed_time=%d real_timer_value=%d total_sleep_time=%d\n", elapsed_time, real_timer_value, total_sleep_time); */
93                 if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
94                 {
95                         total_sleep_time = elapsed_time + real_timer_value;
96                         setTimer(real_timer_value);
97                 }
98                 /*printf("SetAlarm() return %d\n", row_number); */
99                 return row_number;
100         }
101         return TIMER_NONE;
102 }
103
104 /*!                                                                                                
105 **  -----  Use this to remove an alarm ----                                                                                             
106 **                                                                                                 
107 ** @param handle                                                                                   
108 **                                                                                                 
109 ** @return                                                                                         
110 **/  
111 TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
112 {
113         /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
114         MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
115         if(handle != TIMER_NONE)
116         {
117                 if(handle == last_timer_raw) 
118                         last_timer_raw--;
119                 timers[handle].state = TIMER_FREE;              
120         }
121         return TIMER_NONE;
122 }
123
124 /*!                                                                                                
125 ** ------  TimeDispatch is called on each timer expiration ----                                                                                                
126 **                                                                                                 
127 **/  
128 void TimeDispatch(void)
129 {
130         TIMER_HANDLE i;
131         TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
132         /* First run : change timer state depending on time */
133         /* Get time since timer signal */
134         TIMEVAL overrun = getElapsedTime();
135         
136         TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
137         /*printf("total_sleep_time %d + overrun %d\n", total_sleep_time , overrun); */
138
139         s_timer_entry *row;
140
141         for(i=0, row = timers; i <= last_timer_raw; i++, row++)
142         {
143                 if (row->state & TIMER_ARMED) /* if row is active */
144                 {
145                         if (row->val <= real_total_sleep_time) /* to be trigged */
146                         {
147                                 /*printf("row->val(%d) <= (%d)real_total_sleep_time\n", row->val, real_total_sleep_time); */
148                                 if (!row->interval) /* if simply outdated */
149                                 {
150                                         row->state = TIMER_TRIG; /* ask for trig */
151                                 }
152                                 else /* or period have expired */
153                                 {
154                                         /* set val as interval, with overrun correction */
155                                         row->val = row->interval - (overrun % row->interval);
156                                         row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
157                                         /* Check if this new timer value is the soonest */
158                                         if(row->val < next_wakeup)
159                                                 next_wakeup = row->val;   
160                                 }
161                         }
162                         else
163                         {
164                                 /* Each armed timer value in decremented. */
165                                 row->val -= real_total_sleep_time;
166
167                                 /* Check if this new timer value is the soonest */
168                                 if(row->val < next_wakeup)
169                                         next_wakeup = row->val;   
170                         }
171                 }
172         }
173         
174         /* Remember how much time we should sleep. */
175         total_sleep_time = next_wakeup;
176
177         /* Set timer to soonest occurence */
178         setTimer(next_wakeup);
179
180         /* Then trig them or not. */
181         for(i=0, row = timers; i<=last_timer_raw; i++, row++)
182         {
183                 if (row->state & TIMER_TRIG)
184                 {
185                         row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
186                         if(row->callback)
187                                 (*row->callback)(row->d, row->id); /* trig ! */
188                 }
189         }
190 }