nico@207: nico@207:
nico@215: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: