+++ /dev/null
-// $Id$
-/*
- * "Copyright (c) 2005 Stanford University. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose, without fee, and without written
- * agreement is hereby granted, provided that the above copyright
- * notice, the following two paragraphs and the author appear in all
- * copies of this software.
- *
- * IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
- * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY
- * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- * ENHANCEMENTS, OR MODIFICATIONS."
- */
-
-/**
- * This is a TOSSIM-specific implementation of TimerMilliC that
- * directly emulates timers rather than their underlying hardware. It
- * is intended to be a basic fill-in for microcontrollers that do not
- * have TOSSIM simulation support.
- *
- * @author Philip Levis
- * @date December 1 2005
- */
-
-#include <Timer.h>
-
-module HilTimerMilliC {
- provides interface Init;
- provides interface Timer<TMilli> as TimerMilli[uint8_t num];
-}
-implementation {
-
- enum {
- TIMER_COUNT = uniqueCount(UQ_TIMER_MILLI)
- };
-
- typedef struct tossim_timer {
- uint32_t t0;
- uint32_t dt;
- bool isPeriodic;
- bool isActive;
- sim_event_t* evt;
- } tossim_timer_t;
-
- tossim_timer_t timers[TIMER_COUNT];
- sim_time_t initTime;
-
- void initializeEvent(sim_event_t* evt, uint8_t timerID);
-
- sim_time_t clockToSim(sim_time_t clockVal) {
- return (clockVal * sim_ticks_per_sec()) / 1024;
- }
-
- sim_time_t simToClock(sim_time_t sim) {
- return (sim * 1024) / sim_ticks_per_sec();
- }
-
- command error_t Init.init() {
- memset(timers, 0, sizeof(timers));
- initTime = sim_time();
- return SUCCESS;
- }
-
- command void TimerMilli.startPeriodic[uint8_t id]( uint32_t dt ) {
- call TimerMilli.startPeriodicAt[id](call TimerMilli.getNow[id](), dt);
- }
- command void TimerMilli.startOneShot[uint8_t id]( uint32_t dt ) {
- call TimerMilli.startOneShotAt[id](call TimerMilli.getNow[id](), dt);
- }
-
- command void TimerMilli.stop[uint8_t id]() {
- timers[id].isActive = 0;
- if (timers[0].evt != NULL) {
- timers[0].evt->cancelled = 1;
- timers[0].evt->cleanup = sim_queue_cleanup_total;
- timers[0].evt = NULL;
- }
- }
-
- // extended interface
- command bool TimerMilli.isRunning[uint8_t id]() {return timers[id].isActive;}
- command bool TimerMilli.isOneShot[uint8_t id]() {return !timers[id].isActive;}
-
- command void TimerMilli.startPeriodicAt[uint8_t id]( uint32_t t0, uint32_t dt ) {
- call TimerMilli.startOneShotAt[id](t0, dt);
- timers[id].isPeriodic = 1;
- }
- command void TimerMilli.startOneShotAt[uint8_t id]( uint32_t t0, uint32_t dt ) {
- uint32_t currentTime = call TimerMilli.getNow[id]();
- sim_time_t fireTime = sim_time();
-
- call TimerMilli.stop[id]();
-
- timers[id].evt = sim_queue_allocate_event();
- initializeEvent(timers[id].evt, id);
-
- fireTime += clockToSim(dt);
-
- // Be careful about signing and casts, etc.
- if (currentTime > t0) {
- fireTime -= clockToSim(currentTime - t0);
- }
- else {
- fireTime += clockToSim(t0 - currentTime);
- }
-
- timers[id].evt->time = fireTime;
- timers[id].isPeriodic = 0;
- timers[id].isActive = 1;
- timers[id].t0 = t0;
- timers[id].dt = dt;
-
- sim_queue_insert(timers[id].evt);
- }
-
- command uint32_t TimerMilli.getNow[uint8_t id]() {
- sim_time_t nowTime = sim_time();
- nowTime -= initTime;
- nowTime = simToClock(nowTime);
- return nowTime & 0xffffffff;
- }
-
- command uint32_t TimerMilli.gett0[uint8_t id]() {
- return timers[id].t0;
- }
- command uint32_t TimerMilli.getdt[uint8_t id]() {
- return timers[id].dt;
- }
-
- void tossim_timer_handle(sim_event_t* evt) {
- uint8_t* datum = (uint8_t*)evt->data;
- uint8_t id = *datum;
- signal TimerMilli.fired[id]();
-
- // We should only re-enqueue the event if it is a follow-up firing
- // of the same timer. If the timer is stopped, it's a one shot,
- // or someone has started a new timer, don't re-enqueue it.
- if (timers[id].isActive &&
- timers[id].isPeriodic &&
- timers[id].evt == evt) {
- evt->time = evt->time += clockToSim(timers[id].dt);
- sim_queue_insert(evt);
- }
- // If we aren't enqueueing it, and nobody has done something that
- // would cause the event to have been garbage collected, then do
- // so.
- else if (timers[id].evt == evt) {
- call TimerMilli.stop[id]();
- }
- }
-
- void initializeEvent(sim_event_t* evt, uint8_t timerID) {
- uint8_t* data = (uint8_t*)malloc(sizeof(uint8_t));
- *data = timerID;
-
- evt->handle = tossim_timer_handle;
- evt->cleanup = sim_queue_cleanup_none;
- evt->data = data;
- }
-
- default event void TimerMilli.fired[uint8_t id]() {}
-}
-