cc1000csmap.nc

来自「tinyos-2.0源代码!转载而已!要的尽管拿!」· NC 代码 · 共 550 行

NC
550
字号
// $Id: CC1000CsmaP.nc,v 1.1.2.13 2006/06/21 16:58:03 idgay Exp $/*									tab:4 * "Copyright (c) 2000-2005 The Regents of the University  of California.   * 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 THE UNIVERSITY OF CALIFORNIA 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 THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * THE UNIVERSITY OF CALIFORNIA 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 THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2005 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE      * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,  * 94704.  Attention:  Intel License Inquiry. */#include "message.h"#include "crc.h"#include "CC1000Const.h"#include "Timer.h"/** * A rewrite of the low-power-listening CC1000 radio stack. * This file contains the CSMA and low-power listening logic. Actual * packet transmission and reception is in SendReceive. * <p> * This code has some degree of platform-independence, via the * CC1000Control, RSSIADC and SpiByteFifo interfaces which must be provided * by the platform. However, these interfaces may still reflect some * particularities of the mica2 hardware implementation. * * @author Philip Buonadonna * @author Jaein Jeong * @author Joe Polastre * @author David Gay */  module CC1000CsmaP {  provides {    interface Init;    interface SplitControl;    interface CsmaControl;    interface CsmaBackoff;    interface LowPowerListening;  }  uses {    interface Init as ByteRadioInit;    interface StdControl as ByteRadioControl;    interface ByteRadio;    //interface PowerManagement;    interface CC1000Control;    interface CC1000Squelch;    interface Random;    interface Timer<TMilli> as WakeupTimer;    interface BusyWait<TMicro, uint16_t>;    interface ReadNow<uint16_t> as RssiNoiseFloor;    interface ReadNow<uint16_t> as RssiCheckChannel;    interface ReadNow<uint16_t> as RssiPulseCheck;    async command void cancelRssi();  }}implementation {  enum {    DISABLED_STATE,    IDLE_STATE,    RX_STATE,    TX_STATE,    POWERDOWN_STATE,    PULSECHECK_STATE  };  enum {    TIME_AFTER_CHECK =  30,  };  uint8_t radioState = DISABLED_STATE;  struct {    uint8_t ccaOff : 1;    uint8_t txPending : 1;  } f; // f for flags  uint8_t count;  uint8_t clearCount;  int16_t macDelay;  uint8_t lplTxPower, lplRxPower;  uint16_t sleepTime;  uint16_t rssiForSquelch;  task void setWakeupTask();  void enterIdleState() {    call cancelRssi();    radioState = IDLE_STATE;  }  void enterIdleStateSetWakeup() {    enterIdleState();    post setWakeupTask();  }  void enterDisabledState() {    call cancelRssi();    radioState = DISABLED_STATE;  }  void enterPowerDownState() {    call cancelRssi();    radioState = POWERDOWN_STATE;  }  void enterPulseCheckState() {    radioState = PULSECHECK_STATE;    count = 0;  }  void enterRxState() {    call cancelRssi();    radioState = RX_STATE;  }  void enterTxState() {    radioState = TX_STATE;  }  /* Basic radio power control */  void radioOn() {    call CC1000Control.coreOn();    call BusyWait.wait(2000);    call CC1000Control.biasOn();    call BusyWait.wait(200);    atomic call ByteRadio.listen();  }  void radioOff() {    call ByteRadio.off();    call CC1000Control.off();  }  /* LPL preamble length and sleep time computation */  void setPreambleLength() {    uint16_t len =      (uint16_t)read_uint8_t(&CC1K_LPL_PreambleLength[lplTxPower * 2]) << 8      | read_uint8_t(&CC1K_LPL_PreambleLength[lplTxPower * 2 + 1]);    call ByteRadio.setPreambleLength(len);  }  void setSleepTime() {    sleepTime =      (uint16_t)read_uint8_t(&CC1K_LPL_SleepTime[lplRxPower *2 ]) << 8 |      read_uint8_t(&CC1K_LPL_SleepTime[lplRxPower * 2 + 1]);  }  /* Initialisation, startup and stopping */  /*--------------------------------------*/  command error_t Init.init() {    call ByteRadioInit.init();    call CC1000Control.init();    return SUCCESS;  }  task void startStopDone() {    uint8_t s;    // Save a byte of RAM by sharing start/stopDone task    atomic s = radioState;    if (s == DISABLED_STATE)      signal SplitControl.stopDone(SUCCESS);    else      signal SplitControl.startDone(SUCCESS);  }  command error_t SplitControl.start() {    atomic       if (radioState == DISABLED_STATE)	{	  call ByteRadioControl.start();	  enterIdleStateSetWakeup();	  f.txPending = FALSE;	  setPreambleLength();	  setSleepTime();	}      else	return SUCCESS;    radioOn();    post startStopDone();    return SUCCESS;  }  command error_t SplitControl.stop() {    atomic       {	call ByteRadioControl.stop();	enterDisabledState();	radioOff();      }    call WakeupTimer.stop();    post startStopDone();    return SUCCESS;  }  /* Wakeup timer */  /*-------------*/  /* All timer setting code is placed in setWakeup, for consistency. */  void setWakeup() {    switch (radioState)      {      case IDLE_STATE:	/* Timer already running means that we have a noise floor	   measurement scheduled. */	if (!call WakeupTimer.isRunning())	  if (call CC1000Squelch.settled())	    {	      if (lplRxPower == 0 || f.txPending)		call WakeupTimer.startOneShot(CC1K_SquelchIntervalSlow);	      else		// timeout for receiving a message after an lpl check		// indicates channel activity.		call WakeupTimer.startOneShot(TIME_AFTER_CHECK);	    }	  else	    call WakeupTimer.startOneShot(CC1K_SquelchIntervalFast);	break;      case PULSECHECK_STATE:	// Radio warm-up time.	call WakeupTimer.startOneShot(1);	break;      case POWERDOWN_STATE:	// low-power listening check interval	call WakeupTimer.startOneShot(sleepTime);	break;      }  }  task void setWakeupTask() {    atomic setWakeup();  }  event void WakeupTimer.fired() {    atomic       {	switch (radioState)	  {	  case IDLE_STATE:	    /* If we appear to be receiving a packet we don't check the	       noise floor. For LPL, this means that going to sleep will	       be delayed by another TIME_AFTER_CHECK ms. */	    if (!call ByteRadio.syncing())	      {		call cancelRssi();		call RssiNoiseFloor.read();	      }	    break;	  case POWERDOWN_STATE:	    // Turn radio on, wait for 1ms	    enterPulseCheckState();	    call CC1000Control.biasOn();	    break;	  case PULSECHECK_STATE:	    // Switch to RX mode and get RSSI output	    call CC1000Control.rxMode();	    call RssiPulseCheck.read();	    call BusyWait.wait(80);	    return; // don't set wakeup timer	  }	setWakeup();      }  }  /* Low-power listening stuff */  /*---------------------------*/  /* Should we go to sleep, or turn the radio fully on? */  task void sleepCheck() {    bool turnOn = FALSE;    atomic      if (f.txPending)	{	  if (radioState == PULSECHECK_STATE || radioState == POWERDOWN_STATE)	    {	      enterIdleStateSetWakeup();	      turnOn = TRUE;	    }	}      else if (lplRxPower > 0 && call CC1000Squelch.settled() &&	       !call ByteRadio.syncing())	{	  radioOff();	  enterPowerDownState();	  setWakeup();	}    if (turnOn)      radioOn();  }  task void adjustSquelch();  async event void RssiPulseCheck.readDone(error_t result, uint16_t data) {    if (result != SUCCESS)      {	/* Just give up on this interval. */	post sleepCheck();	return;      }    /* We got some RSSI data for our LPL check. Decide whether to:       - go back to sleep (quiet)       - wake up (channel active)       - get more RSSI data    */    if (data > call CC1000Squelch.get() - (call CC1000Squelch.get() >> 2))      {	// don't be too agressive (ignore really quiet thresholds).	if (data < call CC1000Squelch.get() + (call CC1000Squelch.get() >> 3))	  {	    // adjust the noise floor level, go back to sleep.	    rssiForSquelch = data;	    post adjustSquelch();	  }	post sleepCheck();      }    else if (count++ > 5)      {	//go to the idle state since no outliers were found	enterIdleStateSetWakeup();	call ByteRadio.listen();      }    else      {	call RssiPulseCheck.read();	call BusyWait.wait(80);      }  }  /* CSMA */  /*------*/  event void ByteRadio.rts() {    atomic      {	f.txPending = TRUE;	if (radioState == POWERDOWN_STATE)	  post sleepCheck();	if (!f.ccaOff)	  macDelay = signal CsmaBackoff.initial(call ByteRadio.getTxMessage());	else	  macDelay = 1;      }  }  async event void ByteRadio.sendDone() {    f.txPending = FALSE;    enterIdleStateSetWakeup();  }  void congestion() {    macDelay = signal CsmaBackoff.congestion(call ByteRadio.getTxMessage());  }  async event void ByteRadio.idleByte(bool preamble) {    if (f.txPending)      {	if (!f.ccaOff && preamble)	  congestion();	else if (macDelay && !--macDelay)	  {	    call cancelRssi();	    count = 0;	    call RssiCheckChannel.read();	  }      }  }  async event void RssiCheckChannel.readDone(error_t result, uint16_t data) {    if (result != SUCCESS)      {	/* We'll retry the transmission at the next SPI event. */	atomic macDelay = 1;	return;      }    count++;    if (data > call CC1000Squelch.get() + CC1K_SquelchBuffer)      clearCount++;    else      clearCount = 0;    // if the channel is clear or CCA is disabled, GO GO GO!    if (clearCount >= 1 || f.ccaOff)      {	enterTxState();	call ByteRadio.cts();      }    else if (count == CC1K_MaxRSSISamples)      congestion();    else       call RssiCheckChannel.read();  }  /* Message being received. We basically just go inactive. */  /*--------------------------------------------------------*/  async event void ByteRadio.rx() {    enterRxState();  }  async event void ByteRadio.rxDone() {    if (radioState == RX_STATE)      enterIdleStateSetWakeup();  }  /* Noise floor */  /*-------------*/  task void adjustSquelch() {    uint16_t squelchData;    atomic squelchData = rssiForSquelch;    call CC1000Squelch.adjust(squelchData);  }  async event void RssiNoiseFloor.readDone(error_t result, uint16_t data) {    if (result != SUCCESS)      {	/* We just ignore failed noise floor measurements */	post sleepCheck();	return;      }    rssiForSquelch = data;    post adjustSquelch();    post sleepCheck();  }  /* Options */  /*---------*/  async command error_t CsmaControl.enableCca() {    atomic f.ccaOff = FALSE;    return SUCCESS;  }  async command error_t CsmaControl.disableCca() {    atomic f.ccaOff = TRUE;    return SUCCESS;  }  async command error_t LowPowerListening.setListeningMode(uint8_t power) {    if (power >= CC1K_LPL_STATES)      return FAIL;    atomic      {	if (radioState != DISABLED_STATE)	  return FAIL;	lplTxPower = power;	lplRxPower = power;      }    return SUCCESS;  }  async command uint8_t LowPowerListening.getListeningMode() {    atomic return lplRxPower;  }  async command error_t LowPowerListening.setTransmitMode(uint8_t power) {    if (power >= CC1K_LPL_STATES)      return FAIL;    atomic      {	lplTxPower = power;	setPreambleLength();      }    return SUCCESS;  }  async command uint8_t LowPowerListening.getTransmitMode() {    atomic return lplTxPower;  }  async command error_t LowPowerListening.setPreambleLength(uint16_t bytes) {    call ByteRadio.setPreambleLength(bytes);    return SUCCESS;  }  async command uint16_t LowPowerListening.getPreambleLength() {    return call ByteRadio.getPreambleLength();  }  async command error_t LowPowerListening.setCheckInterval(uint16_t ms) {    atomic       {	if (lplRxPower == 0)	  return FAIL;	sleepTime = ms;      }    return SUCCESS;  }  async command uint16_t LowPowerListening.getCheckInterval() {    atomic return sleepTime;  }  /* Default MAC backoff parameters */  /*--------------------------------*/  default async event uint16_t CsmaBackoff.initial(message_t *m) {     // initially back off [1,32] bytes (approx 2/3 packet)    return (call Random.rand16() & 0x1F) + 1;  }  default async event uint16_t CsmaBackoff.congestion(message_t *m) {     return (call Random.rand16() & 0xF) + 1;  }}

⌨️ 快捷键说明

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