(file) Return to TimerHeapM.nc CVS log (file) Jump to this file's LXR Page (dir) Up to [CENS] / tos-contrib / oldTimerHeap

File: [CENS] / tos-contrib / oldTimerHeap / TimerHeapM.nc (download) / (as text)
Revision: 1.1, Fri May 16 01:46:50 2003 UTC (6 years, 6 months ago) by moshe
Branch: MAIN
CVS Tags: scale_radio_channel, rdd_alpha_version_1, pregeonet, nims-lab-Sep07-2004, nims-jr-Sep05-04, lessgps_release, kiss_release, bp_scale_radio_channel, acoustic-05-18-06, PRE_TOSNIC_FIX, PRE_NOMEGA_MOTENIC, PRE_MOTENIC_CLEANUP, PRE_CEILING_FIX, PRE_64BIT, MOTENIC_PRE_BUGFIX_20050415, LESSGPS_1_00, LAURA_CALIBRATION_EXPERIMENTS, KISS_1_0, HOSTMOTE_V_6_EXPERIMENTAL, HOSTMOTE_PROTOCOL_VERSION_7, HOSTMOTE_PROTOCOL_VERSION_6_WITH_HOSTMOAP, HOSTMOTE_PROTOCOL_VERSION_5_WITH_HOSTMOAP, HOSTMOTE_PROTOCOL_VERSION_5, HOSTMOTE_PROTOCOL_VERSION_4, HOSTMOTE_PROTOCOL_VERSION_3, HEAD, ESS_RELEASE_3_5, ESS_RELEASE_3_4, ESS_RELEASE_3_3, ESS_RELEASE_3_2, ESS_RELEASE_3_1, ESS_RELEASE_3_0, ESS_RELEASE_2_0, ESS_CONNECTIVITY, ESS_CENTROUTE_TESTING, ESS2-CMS-V1_5_pretest, ESS2-CMS-V1_4cMergeSympathy_2, ESS2-CMS-V1_4c, ESS2-CMS-V1_4b, ESS2-CMS-V1_4a, ESS2-CMS-V1_3, ESS2-CMS-V1_2, ESS2-CMS-V1_1, ESS2-CMS-V1_0, EMSTAR_RELEASE_2_5, EMSTAR_RELEASE_2_1_BRANCH, EMSTAR_RELEASE_2_1, EMSTAR_RELEASE_2_0, EMSTAR_PRE_HTML, CYCLOPS_RELEASE_CANDIDATE_2_0, CYCLOPS_PRERELEASE_STABLE, CENTROUTE_EMSTAR_SOCKETS, BG_1_0, BANGLADESH_ARSENIC_1_2, BANGLADESH_ARSENIC_1_1, AMARSS_JR_DEPLOYMENT_6_05_07
Timer Heap




/* 
	Module File for Timer Heap
   	
*/

includes timer;

module TimerHeapM {

  provides {
    interface HeapTimers;
 
  }


} // End Interfaces 



implementation {

// ==============     Includes   ==================== 

#include <inttypes.h>
#include "hardware_ucla.h"

    // #include "timer.h"      
    // #include "timerHeap.c"

    // Temp +++ move to header file later

#define HEAP_SIZE 15
#define PARENT(i) (((i) - 1) / 2)
#define CHILD1(i) ((i) * 2 + 1)
#define CHILD2(i) ((i) * 2 + 2)
#define TIME(i) heap[i]->abstime

#define CLOCK_INTERVAL 15625*4


// ============= Local Variable - State ================


  Timer *heap[HEAP_SIZE];
  Timer *st; /* saved timer */
  uint8_t num_timers;
  uint8_t heap_size;
  uint32_t clock,counter;
  uint8_t heap_p,check_p,fire_p, check_m;
  int test,test1;
  uint8_t mutex;

// =============== Function Prototypes ===============

task void reset_heap_task();
task void timer_fire_task();



// =============== Helper Functions ===================

// ===================== Mutex =======================

/* Clear mutex */

static inline void v() { mutex = 0; }

/* Test and set mutex (need to rewrite in assembly)*/

static inline uint8_t p() {
  cli();
  if ( mutex ) {sei();return 0;} 
  else { mutex = 1;sei();return 1;}
}

// ================= Clock Init =====================

void clock_init()
{
    cbi(TIMSK, OCIE_ITC_16A);    // Disable CNT1 output compare interrupt
    cbi(TIMSK, OCIE_ITC_16B);    // Disable CNT1 output compare interrupt
    cbi(TIMSK, TICIE_ITC_16);    // Disable CNT1 input capture interrupt
    cbi(TIMSK, TOIE_ITC_16);     // Disable CNT1 overflow interrupt

    outp(0x0A, TCCR_ITC_16B);    // Prescaling the timer clk/8
    outp(0x00, TCCR_ITC_16A);

    __outw(0, OCR_ITC_16BL);    

    // set comp registers
    outp(((uint16_t)CLOCK_INTERVAL >> 8)&0xFF, OCR_ITC_16AH);
    outp((uint16_t)CLOCK_INTERVAL & 0xFF, OCR_ITC_16AL);

    __outw(0, TCNT_ITC_16L); 
    sbi(TIMSK, OCIE_ITC_16A);      // enable timer1 interupt
    sei();
}



void clock_get_time()
{
  clock = counter;
  cli();
  /* get clock value */
  clock += __inw(TCNT_ITC_16L);
  /* if the interrupt is pending, adjust clock forward */
  if (inp(TIFR) & OCF_ITC_16A) clock += __inw(OCR_ITC_16AL);
  sei();
}

// ================= Reset Heap  ======================

void reset_heap(Timer *t) {
    int pos, min;

    /* Free the timer, saving its heap position. */
    pos = getHeapPos(t);
    
    if (pos != num_timers - 1) {
        /* Replace the timer with the last timer in the heap and
         * restore the heap, propagating the timer either up or
         * down, depending on which way it violates the heap
         * property to insert the last timer in place of the
         * deleted timer. */
        if (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))) {
            do {
                heap[pos] = heap[PARENT(pos)];
                setHeapPos(heap[pos],pos);
                pos = PARENT(pos);
            } while (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos)));
            heap[pos] = heap[num_timers - 1];
            setHeapPos(heap[pos],pos);
        } else {
            while (CHILD2(pos) < num_timers) {
                min = num_timers - 1;
                if (TIME(CHILD1(pos)) < TIME(min))
                    min = CHILD1(pos);
                if (TIME(CHILD2(pos)) < TIME(min))
                    min = CHILD2(pos);
                heap[pos] = heap[min];
                setHeapPos(heap[pos],pos);
                pos = min;
            }
            if (pos != num_timers - 1) {
                heap[pos] = heap[num_timers - 1];
                setHeapPos(heap[pos],pos);
            }
        }
    }
    num_timers--;
} // end reset timer


// ================= Timer Fire ======================

void timer_fire() {
  Timer *t;
  void (*f) ();

  /* Remove the first timer from the heap, remembering its
   * function and argument. */
  t = heap[0];

  f = t->f;

  st = t;

  post reset_heap_task();

  /* Run the function. */
  f();
} // end timer fire


// ================= check timer ======================

/*
Compare Current value of Clock with Timeout of top of heap.
If less than CLOCK granularity, set timeout for delta on 
timer compareb (OCIE1B)
*/
void check_timer() {
  int32_t temp;

  if (num_timers == 0) return;

  clock_get_time();
  temp = heap[0]->abstime - clock;
  if (temp > (int32_t)CLOCK_INTERVAL) return;
  else {
    if (temp < 0) {
      /* CRITICAL SECTION: Lock while operation on state variables */
      if (!p()) return;
      if (!heap_p && !fire_p) {
          post timer_fire_task(); 
	fire_p = 1;
	heap_p = 1;
      }
      v();
      /* END CRITICAL SECTION */
    } else {
      outp((temp >> 8)&0xFF, OCR_ITC_16BH);
      outp(temp & 0xFF, OCR_ITC_16BL);    
      sbi(TIMSK, OCIE_ITC_16B);      // enable timer1b interupt for remaining delta
    }
  }
} // end


// ===================== Tasks =========================

/* check_timer() is called after all operations on heap have completed
   in each task. This is so that interrupts dont fire while heap re-organization
   is in progress
*/

  task void check_timer_task()
  {
       check_timer();
       check_p = 0;

  } // end check_timer_task

  task void timer_fire_task()
  {
      timer_fire();
      fire_p = 0;
  } // end timer_fire_task

  task void add_timer_absolute_task()
  {
  
      int pos;

      pos = num_timers;
      while (pos > 0 && st->abstime < TIME(PARENT(pos))) {
          heap[pos] = heap[PARENT(pos)];
          setHeapPos(heap[pos],pos);
          pos = PARENT(pos);
      }
      heap[pos] = st;
      setHeapPos(heap[pos],pos);
      num_timers++;
      st = NULL;

      if (!check_p) {
          post check_timer_task();
          check_p = 1;
      }
      heap_p = 0;
  } // end add_timer absolute task


task void reset_heap_task() {

  /* Consistency Check: Check if timer exists in heap. Is this check necc?? */
  if ( st != heap[getHeapPos(st)]) return;

  reset_heap(st);

  if (isPeriodic(st) && !getDeleteFlag(st)) {
    st->abstime += st->periodic_offset;
    post add_timer_absolute_task(); 
  } else {
    setFree(st); /* Free the timer to be reused by app */
    resetDeleteFlag(st);
    heap_p = 0;
    st = NULL;

    /* check heap */
    if (!check_p) {
      post check_timer_task(); 
      check_p = 1;
    }
  }
}



// ============== Interface timerHeap =================

command  char HeapTimers.TIMER_INIT()
{

  dbg(DBG_PROG, ("Timer Initialized\n"));
  num_timers = 0;
  heap_size = 0;

  v();

  clock_init();

  return 1;

}

command  char HeapTimers.ADD_TIMER_RELATIVE(Timer* t, uint32_t trel)
{ 
  if ( heap_p || !isFree(t)) return 0;

  clock_get_time();
  t->abstime = clock + trel;

  return call  HeapTimers.ADD_TIMER_ABSOLUTE(t) ;
  
}

command  char HeapTimers.ADD_TIMER_ABSOLUTE( Timer * t )
{
    uint8_t ret = 0;
  
  /* Insert the Timer *into the heap. */
  dbg(DBG_PROG, ("ADD_TIMER %l\n", t->abstime));

  /* CRITICAL SECTION: Lock while operation on state variables */

  if (!p()) return 0;
   if ( heap_p || !isFree(t)) {
    ret=0;
    if (!check_p) {
      post check_timer_task();
      check_p = 1;
    }
  } else {
    ret=1;
    heap_p = 1;
    setUsed(t);
    st = t;
    post add_timer_absolute_task();
  }
  v();
  /* END CRITICAL SECTION */

  // TODO - CHECK pos?  dbg(DBG_PROG, ("ADD_TIMER %l at position:%d\n", t->abstime,pos));
  return ret;
   
}
command  char HeapTimers.DELETE_TIMER( Timer * t )
{
    uint8_t ret=0;

  /* CRITICAL SECTION: Lock while operation on state variables */
  if (!p()) return 0;
  /* reject request if either
        reset pending
	the passed timer does not exist on the heap
	the passed timer has been fucked with by the app
  */
  if ( heap_p || isFree(t) || (t!= heap[getHeapPos(t)])) {
    ret=0;
    if (!check_p) {
      post check_timer_task();
      check_p = 1;
    }
  } else {
    ret=1;
    heap_p = 1;
    st = t;
    setDeleteFlag(t);
    post reset_heap_task();
  }
  v();
  /* END CRITICAL SECTION */

  return ret;
  
}

// ============ Interups Handler ===================



TOSH_INTERRUPT(SIG_OUTPUT_COMPARE1A) 
{
  // Count the elapsed ticks
  counter += __inw_atomic(OCR_ITC_16AL);

  if (!check_p) {
    post check_timer_task();
    check_p = 1;
  }
} // end clock init


TOSH_INTERRUPT(SIG_OUTPUT_COMPARE1B) {
  cbi(TIMSK, OCIE1B);      // disable timer1b interupt
  if (p()) {
    if (!heap_p && !fire_p) {
      post timer_fire_task();
      fire_p = 1;
      heap_p = 1;
    }
    v();
  }
}


} // end implementation




/*
USES{
        char GET_TIME(uint32_t* );
};


*/

CENS CVS Mailing List
Powered by
ViewCVS 0.9.2