/home/epimerde/documents/tc11/CanFestival-3/src/timer.c

Go to the documentation of this file.
00001 /*
00002 This file is part of CanFestival, a library implementing CanOpen Stack. 
00003 
00004 Copyright (C): Edouard TISSERANT and Francis DUPIN
00005 
00006 See COPYING file for copyrights details.
00007 
00008 This library is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU Lesser General Public
00010 License as published by the Free Software Foundation; either
00011 version 2.1 of the License, or (at your option) any later version.
00012 
00013 This library is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 Lesser General Public License for more details.
00017 
00018 You should have received a copy of the GNU Lesser General Public
00019 License along with this library; if not, write to the Free Software
00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 /* #define DEBUG_WAR_CONSOLE_ON */
00024 /* #define DEBUG_ERR_CONSOLE_ON */
00025 
00026 #include <applicfg.h>
00027 #include "timer.h"
00028 
00029 /*  ---------  The timer table --------- */
00030 s_timer_entry timers[MAX_NB_TIMER] = {{TIMER_FREE, NULL, NULL, 0, 0, 0},};
00031 
00032 TIMEVAL total_sleep_time = TIMEVAL_MAX;
00033 TIMER_HANDLE last_timer_raw = -1;
00034 
00035 #define min_val(a,b) ((a<b)?a:b)
00036 
00037 /* ---------  Use this to declare a new alarm --------- */
00038 TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
00039 {
00040         /*printf("SetAlarm(UNS32 id=%d, TimerCallback_t callback=%x, TIMEVAL value=%d, TIMEVAL period=%d)\n", id, callback, value, period); */
00041         TIMER_HANDLE i;
00042         TIMER_HANDLE row_number = TIMER_NONE;
00043 
00044         /* in order to decide new timer setting we have to run over all timer rows */
00045         for(i=0; i <= last_timer_raw + 1 && i < MAX_NB_TIMER; i++)
00046         {
00047                 s_timer_entry *row = (timers+i);
00048 
00049                 if (callback &&         /* if something to store */
00050                    row->state == TIMER_FREE) /* and empty row */
00051                 {       /* just store */
00052                         row->callback = callback;
00053                         row->d = d;
00054                         row->id = id;
00055                         row->val = value;
00056                         row->interval = period;
00057                         row->state = TIMER_ARMED;
00058                         row_number = i;
00059                         break;
00060                 }
00061         }
00062         
00063         if (row_number != TIMER_NONE) /* if successfull **/
00064         {
00065                 TIMEVAL real_timer_value;
00066                 TIMEVAL elapsed_time;
00067                 
00068                 if (row_number == last_timer_raw + 1) last_timer_raw++;
00069                 
00070                 /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
00071                 real_timer_value = min_val(value, TIMEVAL_MAX);
00072                 elapsed_time = getElapsedTime();
00073 
00074                 /*printf("elapsed_time=%d real_timer_value=%d total_sleep_time=%d\n", elapsed_time, real_timer_value, total_sleep_time); */
00075                 if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
00076                 {
00077                         total_sleep_time = elapsed_time + real_timer_value;
00078                         setTimer(real_timer_value);
00079                 }
00080                 /*printf("SetAlarm() return %d\n", row_number); */
00081                 return row_number;
00082         }
00083         return TIMER_NONE;
00084 }
00085 
00086 /* ---------  Use this to remove an alarm --------- */
00087 TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
00088 {
00089         /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
00090         MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
00091         if(handle != TIMER_NONE)
00092         {
00093                 if(handle == last_timer_raw) 
00094                         last_timer_raw--;
00095                 timers[handle].state = TIMER_FREE;              
00096         }
00097         else {
00098         }
00099         return TIMER_NONE;
00100 }
00101 
00102 
00103 /* ---------  TimeDispatch is called on each timer expiration --------- */
00104 void TimeDispatch()
00105 {
00106         TIMER_HANDLE i;
00107         TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
00108         /* First run : change timer state depending on time */
00109         /* Get time since timer signal */
00110         TIMEVAL overrun = getElapsedTime();
00111         
00112         TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
00113         /*printf("total_sleep_time %d + overrun %d\n", total_sleep_time , overrun); */
00114 
00115         for(i=0; i <= last_timer_raw; i++)
00116         {
00117                 s_timer_entry *row = (timers+i);
00118 
00119                 if (row->state & TIMER_ARMED) /* if row is active */
00120                 {
00121                         if (row->val <= real_total_sleep_time) /* to be trigged */
00122                         {
00123                                 /*printf("row->val(%d) <= (%d)real_total_sleep_time\n", row->val, real_total_sleep_time); */
00124                                 if (!row->interval) /* if simply outdated */
00125                                 {
00126                                         row->state = TIMER_TRIG; /* ask for trig */
00127                                 }
00128                                 else /* or period have expired */
00129                                 {
00130                                         /* set val as interval, with overrun correction */
00131                                         row->val = row->interval - (overrun % row->interval);
00132                                         row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
00133                                         /* Check if this new timer value is the soonest */
00134                                         next_wakeup = min_val(row->val,next_wakeup);
00135                                 }
00136                         }
00137                         else
00138                         {
00139                                 /* Each armed timer value in decremented. */
00140                                 row->val -= real_total_sleep_time;
00141 
00142                                 /* Check if this new timer value is the soonest */
00143                                 next_wakeup = min_val(row->val,next_wakeup);
00144                         }
00145                 }
00146         }
00147         
00148         /* Remember how much time we should sleep. */
00149         total_sleep_time = next_wakeup;
00150 
00151         /* Set timer to soonest occurence */
00152         setTimer(next_wakeup);
00153 
00154         /* Then trig them or not. */
00155         for(i=0; i<=last_timer_raw; i++)
00156         {
00157                 s_timer_entry *row = (timers+i);
00158 
00159                 if (row->state & TIMER_TRIG)
00160                 {
00161                         row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
00162                         if(row->callback)
00163                                 (*row->callback)(row->d, row->id); /* trig ! */
00164                 }
00165         }
00166 }
00167 

Generated on Mon Jun 4 17:09:27 2007 for CanFestival by  doxygen 1.5.1