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