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 */
00032 /* #define DEBUG_WAR_CONSOLE_ON */
00033 /* #define DEBUG_ERR_CONSOLE_ON */
00034 
00035 #include <applicfg.h>
00036 #include "timer.h"
00037 
00038 /*  ---------  The timer table --------- */
00039 s_timer_entry timers[MAX_NB_TIMER] = {{TIMER_FREE, NULL, NULL, 0, 0, 0},};
00040 
00041 TIMEVAL total_sleep_time = TIMEVAL_MAX;
00042 TIMER_HANDLE last_timer_raw = -1;
00043 
00044 #define min_val(a,b) ((a<b)?a:b)
00045 
00057 TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
00058 {
00059         /*printf("SetAlarm(UNS32 id=%d, TimerCallback_t callback=%x, TIMEVAL value=%d, TIMEVAL period=%d)\n", id, callback, value, period); */
00060         TIMER_HANDLE i;
00061         TIMER_HANDLE row_number = TIMER_NONE;
00062 
00063         /* in order to decide new timer setting we have to run over all timer rows */
00064         for(i=0; i <= last_timer_raw + 1 && i < MAX_NB_TIMER; i++)
00065         {
00066                 s_timer_entry *row = (timers+i);
00067 
00068                 if (callback &&         /* if something to store */
00069                    row->state == TIMER_FREE) /* and empty row */
00070                 {       /* just store */
00071                         row->callback = callback;
00072                         row->d = d;
00073                         row->id = id;
00074                         row->val = value;
00075                         row->interval = period;
00076                         row->state = TIMER_ARMED;
00077                         row_number = i;
00078                         break;
00079                 }
00080         }
00081         
00082         if (row_number != TIMER_NONE) /* if successfull **/
00083         {
00084                 TIMEVAL real_timer_value;
00085                 TIMEVAL elapsed_time;
00086                 
00087                 if (row_number == last_timer_raw + 1) last_timer_raw++;
00088                 
00089                 /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
00090                 real_timer_value = min_val(value, TIMEVAL_MAX);
00091                 elapsed_time = getElapsedTime();
00092 
00093                 /*printf("elapsed_time=%d real_timer_value=%d total_sleep_time=%d\n", elapsed_time, real_timer_value, total_sleep_time); */
00094                 if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
00095                 {
00096                         total_sleep_time = elapsed_time + real_timer_value;
00097                         setTimer(real_timer_value);
00098                 }
00099                 /*printf("SetAlarm() return %d\n", row_number); */
00100                 return row_number;
00101         }
00102         return TIMER_NONE;
00103 }
00104 
00112 TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
00113 {
00114         /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
00115         MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
00116         if(handle != TIMER_NONE)
00117         {
00118                 if(handle == last_timer_raw) 
00119                         last_timer_raw--;
00120                 timers[handle].state = TIMER_FREE;              
00121         }
00122         else {
00123         }
00124         return TIMER_NONE;
00125 }
00126 
00131 void TimeDispatch()
00132 {
00133         TIMER_HANDLE i;
00134         TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
00135         /* First run : change timer state depending on time */
00136         /* Get time since timer signal */
00137         TIMEVAL overrun = getElapsedTime();
00138         
00139         TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
00140         /*printf("total_sleep_time %d + overrun %d\n", total_sleep_time , overrun); */
00141 
00142         for(i=0; i <= last_timer_raw; i++)
00143         {
00144                 s_timer_entry *row = (timers+i);
00145 
00146                 if (row->state & TIMER_ARMED) /* if row is active */
00147                 {
00148                         if (row->val <= real_total_sleep_time) /* to be trigged */
00149                         {
00150                                 /*printf("row->val(%d) <= (%d)real_total_sleep_time\n", row->val, real_total_sleep_time); */
00151                                 if (!row->interval) /* if simply outdated */
00152                                 {
00153                                         row->state = TIMER_TRIG; /* ask for trig */
00154                                 }
00155                                 else /* or period have expired */
00156                                 {
00157                                         /* set val as interval, with overrun correction */
00158                                         row->val = row->interval - (overrun % row->interval);
00159                                         row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
00160                                         /* Check if this new timer value is the soonest */
00161                                         next_wakeup = min_val(row->val,next_wakeup);
00162                                 }
00163                         }
00164                         else
00165                         {
00166                                 /* Each armed timer value in decremented. */
00167                                 row->val -= real_total_sleep_time;
00168 
00169                                 /* Check if this new timer value is the soonest */
00170                                 next_wakeup = min_val(row->val,next_wakeup);
00171                         }
00172                 }
00173         }
00174         
00175         /* Remember how much time we should sleep. */
00176         total_sleep_time = next_wakeup;
00177 
00178         /* Set timer to soonest occurence */
00179         setTimer(next_wakeup);
00180 
00181         /* Then trig them or not. */
00182         for(i=0; i<=last_timer_raw; i++)
00183         {
00184                 s_timer_entry *row = (timers+i);
00185 
00186                 if (row->state & TIMER_TRIG)
00187                 {
00188                         row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
00189                         if(row->callback)
00190                                 (*row->callback)(row->d, row->id); /* trig ! */
00191                 }
00192         }
00193 }
00194 

Generated on Mon Jul 2 19:10:16 2007 for CanFestival by  doxygen 1.5.1