nico@207: nico@207: nico@215: CanFestival: src/timer.c Source File nico@207: nico@207: nico@207: nico@207: nico@207:
nico@207:
nico@207:
nico@207:
nico@215: nico@215:

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

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