diff -r 000000000000 -r 4472ee7c6c3e drivers/ecos_lpc2138_sja1000/time_slicer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/ecos_lpc2138_sja1000/time_slicer.c Wed May 10 16:59:40 2006 +0200 @@ -0,0 +1,219 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + + Author: Christian Fortin (canfestival@canopencanada.ca) + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include +#include + +#include +#include + +#include "applicfg.h" + +#include + + +#define max(a,b) a>b?a:b +#define min(a,b) astate & TIMER_ARMED) // if row is active + { + if (row->val <= real_total_sleep_time) // to be trigged + { + if (!row->interval) // if simply outdated + { + row->state = TIMER_TRIG; // ask for trig + } + else // or period have expired + { + // set val as interval, with overrun correction + row->val = row->interval - (overrun % row->interval); + row->state = TIMER_TRIG_PERIOD; // ask for trig, periodic + // Check if this new timer value is the soonest + next_wakeup = min(row->val,next_wakeup); + } + } + else + { + // Each armed timer value in decremented. + row->val -= real_total_sleep_time; + + // Check if this new timer value is the soonest + next_wakeup = min(row->val,next_wakeup); + } + } + } + + // Remember how much time we should sleep. + total_sleep_time = next_wakeup; + + // Set timer to soonest occurence + setTimer(next_wakeup); + + // Then trig them or not. + for(i=0; i<=last_timer_raw; i++) + { + s_timer_entry *row = (timers+i); + + if (row->state & TIMER_TRIG) + { + row->state &= ~TIMER_TRIG; // reset trig state (will be free if not periodic) + (*row->callback)(row->d, row->id); // trig ! + } + } +} + + + + +TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period) +{ + int i; + TIMER_HANDLE row_number = TIMER_NONE; + + if (callback == NULL) // nothing to store + return TIMER_NONE; + + // in order to decide new timer setting we have to run over all timer rows + + for(i=0; i <= last_timer_raw + 1 && i < MAX_NB_TIMER; i++) + { + s_timer_entry *row = (timers+i); + + if (row->state == TIMER_FREE) // an empty row + { // just store + row->callback = callback; + row->d = d; + row->id = id; + row->val = value; + row->interval = period; + row->state = TIMER_ARMED; + + row_number = i; + break; + } + } + + if (row_number != TIMER_NONE) // if successfull + { + if (row_number == last_timer_raw + 1) last_timer_raw++; + + // set next wakeup alarm if new entry is sooner than others, or if it is alone + unsigned int real_timer_value = min(value, TIMEVAL_MAX); + unsigned int elapsed_time = getElapsedTime(); + + if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value) + { + total_sleep_time = elapsed_time + real_timer_value; + setTimer(real_timer_value); + } + + return row_number; + } + + return TIMER_NONE; +} + +// --------- Use this to remove an alarm --------- +TIMER_HANDLE DelAlarm(TIMER_HANDLE handle) +{ + if (handle != TIMER_NONE) + { + if (handle == last_timer_raw) + last_timer_raw--; + timers[handle].state = TIMER_FREE; + } + else + { + } + + return TIMER_NONE; +}