Sam Grove / Mbed 2 deprecated canopen_masternode

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers canopen_timer.c Source File

canopen_timer.c

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