⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hplatm128timer0asyncp.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 2 页
字号:
/*
 * "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."
 */

/**
 * The TOSSIM implementation of the Atm128 Timer0 counter. It handles
 * overflow, scaling, and phase considerations.
 *
 * @date November 22 2005
 *
 * @author Philip Levis <pal@cs.stanford.edu>
 * @author Martin Turon <mturon@xbow.com>
 * @author David Gay <dgay@intel-research.net>
 */

// $Id: HplAtm128Timer0AsyncP.nc,v 1.1 2008/06/12 14:02:20 klueska Exp $/// $Id: HplAtm128Timer2C.nc,

#include <Atm128Timer.h>
#include <hardware.h>

module HplAtm128Timer0AsyncP {
  provides {
    interface HplAtm128Timer<uint8_t>   as Timer0;
    interface HplAtm128TimerCtrl8       as Timer0Ctrl;
    interface HplAtm128Compare<uint8_t> as Compare;
    interface HplAtm128TimerAsync       as TimerAsync;
  }
  uses interface ThreadScheduler;
}
implementation {
  bool inOverflow = 0;
  uint8_t savedCounter = 0;

  void adjust_zero(uint8_t currentCounter);

  void cancel_overflow();
  sim_event_t* allocate_overflow();
  void configure_overflow(sim_event_t* e);
  void schedule_new_overflow();

  sim_time_t clock_to_sim(sim_time_t t);
  sim_time_t sim_to_clock(sim_time_t t);
  uint16_t shiftFromScale();

  /* lastZero keeps track of the phase of the clock. It denotes the sim
   * time at which the underlying clock started, which is needed to
   * calculate when compares will occur. */
  sim_time_t lastZero = 0;

  /** This variable is needed to keep track of when the underlying
   *  timer starts, in order to reset lastZero. When oldScale is
   *  AVR_CLOCK_OFF and the scale is set to something else, the
   *  clock starts ticking. */
  uint8_t oldScale = AVR_CLOCK_OFF;
  
  void adjust_zero(uint8_t currentCounter);
  
  void cancel_compare();
  sim_event_t* allocate_compare();
  void configure_compare(sim_event_t* e);
  void schedule_new_compare();

  sim_time_t clock_to_sim(sim_time_t t);
  sim_time_t sim_to_clock(sim_time_t t);
  uint16_t shiftFromScale();

  default async event void Compare.fired() { }
  AVR_ATOMIC_HANDLER(SIG_OUTPUT_COMPARE0) {
    //stabiliseTimer0();
    signal Compare.fired();
    call ThreadScheduler.interruptPostAmble();
  }
 
  default async event void Timer0.overflow() { }
  AVR_ATOMIC_HANDLER(SIG_OVERFLOW0) {
    inOverflow = TRUE;
    signal Timer0.overflow();
    inOverflow = FALSE;
    call ThreadScheduler.interruptPostAmble();
  }


  
  sim_time_t last_zero() {
    if (lastZero == 0) {
      lastZero = sim_mote_start_time(sim_node());
    }
    return lastZero;
  }


  void notify_changed() {
    uint8_t newScale = call Timer0.getScale();
    if (newScale != AVR_CLOCK_OFF &&
	oldScale == AVR_CLOCK_OFF) {
      lastZero = sim_time();
    }
    oldScale = newScale;
    
    schedule_new_compare();
  }

  sim_time_t notify_clockTicksPerSec() {
    return ATM128_TIMER0_TICKSPPS;
  }
  
  /**
   * If the clock was stopped and has restarted, then
   * we need to move the time when the clock was last
   * zero to a time that reflects the current settings.
   * For example, if the clock was stopped when the counter
   * was 52 and then later restarted, then <tt>lastZero</tt>
   * needs to be moved forward in time so that the 52
   * reflects the current time.
   */ 
  void adjust_zero(uint8_t currentCounter) {
    sim_time_t now = sim_time();
    sim_time_t adjust = currentCounter;
    adjust = adjust << shiftFromScale();
    adjust = clock_to_sim(adjust);
    lastZero = now - adjust;
  }
  
  sim_time_t clock_to_sim(sim_time_t t) {
    t *= sim_ticks_per_sec();
    t /= notify_clockTicksPerSec();
    return t;
  }

  sim_time_t sim_to_clock(sim_time_t t) {
    t *= notify_clockTicksPerSec();
    t /= sim_ticks_per_sec();
    return t;
  }
  
  uint16_t shiftFromScale() {
    uint8_t scale = call Timer0.getScale();
    switch (scale) {
    case 0:
      return 0;
    case 1:
      return 0;
    case 2:
      return 3;
    case 3:
      return 5;
    case 4:
      return 6;
    case 5:
      return 7;
    case 6:
      return 8;
    case 7:
      return 10;
    default:
      return 255;
    }
    
  }

  sim_event_t* compare;

  void timer0_compare_handle(sim_event_t* evt) {
    dbg("HplAtm128Timer0AsyncP", "Beginning compare 0x%p at %s\n", evt, sim_time_string());
    if (evt->cancelled) {
      return;
    }
    else {
      char timeStr[128];
      sim_print_now(timeStr, 128);
      dbg("HplAtm128Timer0AsyncP", "Handling compare at 0x%p @ %s\n", evt, sim_time_string());
      
      if (READ_BIT(ATM128_TCCR0, WGM01) && !READ_BIT(ATM128_TCCR0, WGM00)) {
	dbg("HplAtm128Timer0AsyncP", "%s: CTC is set, clear timer.\n", __FUNCTION__);
	call Timer0.set(0);
      }
      else {
	dbg("HplAtm128Timer0AsyncP", "%s: TCCR is 0x%hhx, %i, %i\n", __FUNCTION__, TCCR0, (int)READ_BIT(ATM128_TCCR0, WGM01), (int)READ_BIT(ATM128_TCCR0, WGM00));
      }
      
      if (READ_BIT(ATM128_TIMSK, OCIE0)) {
	dbg("HplAtm128Timer0AsyncP", "TIFR is %hhx\n", TIFR);
	CLR_BIT(ATM128_TIFR, OCF0);
	dbg("HplAtm128Timer0AsyncP", "TIFR is %hhx\n", TIFR);
	dbg("HplAtm128Timer0AsyncP", "Compare interrupt @ %s\n", timeStr);
	SIG_OUTPUT_COMPARE0();
      }
      else {
	SET_BIT(ATM128_TIFR, OCF0);
      }
      // If we haven't been cancelled
      if (!evt->cancelled) {
	configure_compare(evt);
	sim_queue_insert(evt);
      }
    }
  }

  sim_event_t* allocate_compare() {
    sim_event_t* newEvent = sim_queue_allocate_event();
    dbg("HplAtm128Timer0AsyncP", "Allocated compare at 0x%p\n", newEvent);
    newEvent->handle = timer0_compare_handle;
    newEvent->cleanup = sim_queue_cleanup_none;
    return newEvent;
  }
  
  void configure_compare(sim_event_t* evt) {
    sim_time_t compareTime = 0;
    sim_time_t phaseOffset = 0;
    uint8_t timerVal = call Timer0.get();
    uint8_t compareVal = call Compare.get();

    // Calculate how many counter increments until timer
    // hits compare, considering wraparound, and special
    // case of complete wraparound.
    compareTime = ((compareVal - timerVal) & 0xff);
    if (compareTime == 0) {
      compareTime = 256;
    }

    // Now convert the compare time from counter increments
    // to simulation ticks, considering the fact that the
    // increment actually has a phase offset.
    // The +1 is from the timer behavior: if you set OCR0 to be X,
    // it will actually fire when TCNT is X+1
    compareTime = (compareTime + 1) << shiftFromScale();
    compareTime = clock_to_sim(compareTime);
    compareTime += sim_time();

    // How long into a timer tick was the clock actually reset?
    // This covers the case when the compare is set midway between
    // a tick, so it will go off a little early
    phaseOffset = sim_time();
    phaseOffset -= last_zero();
    phaseOffset %= clock_to_sim(1 << shiftFromScale());
    compareTime -= phaseOffset;
      
    dbg("HplAtm128Timer0AsyncP", "Configuring new compare of %i for %i at time %llu  (@ %llu)\n", (int)compareVal, sim_node(), compareTime, sim_time());
    
    evt->time = compareTime;    
  }
  
  void schedule_new_compare() {
    if (compare != NULL) {
      cancel_compare();
    }
    if (call Timer0.getScale() != AVR_CLOCK_OFF) {
      sim_event_t* newEvent = allocate_compare();
      configure_compare(newEvent);

      compare = newEvent;
      sim_queue_insert(newEvent);
    }
  }

  
  //=== Read the current timer value. ===================================
  async command uint8_t  Timer0.get() {
    uint8_t rval;
    sim_time_t elapsed = sim_time() - last_zero();
    elapsed = sim_to_clock(elapsed);
    elapsed = elapsed >> shiftFromScale();
    rval = (uint8_t)(elapsed & 0xff);
    dbg("HplAtm128Timer0AsyncP", "HplAtm128Timer0AsyncP: Getting timer: %hhu\n", rval);
    return rval;
  }

  //=== Set/clear the current timer value. ==============================
  /**
   * Set/clear the current timer value.
   *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -