nico@207: nico@207: nico@207: CanFestival: /home/epimerde/documents/tc11/CanFestival-3/src/timer.c Source File nico@207: nico@207: nico@207: nico@207: nico@207:
nico@207:
nico@207:
nico@207:
nico@207:

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

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

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