|
|
Jump to this file's LXR Page |
|
|
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 |