]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/cc2420_lpl/CC2420LowPowerListeningP.nc
Removal - this stack has become the default.
[tinyos-2.x.git] / tos / chips / cc2420_lpl / CC2420LowPowerListeningP.nc
diff --git a/tos/chips/cc2420_lpl/CC2420LowPowerListeningP.nc b/tos/chips/cc2420_lpl/CC2420LowPowerListeningP.nc
deleted file mode 100644 (file)
index 51b405e..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-/*\r
- * Copyright (c) 2005-2006 Rincon Research Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- *   notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- *   notice, this list of conditions and the following disclaimer in the\r
- *   documentation and/or other materials provided with the\r
- *   distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- *   its contributors may be used to endorse or promote products derived\r
- *   from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
-\r
-/**\r
- * Low Power Listening for the CC2420\r
- *\r
- * @author David Moss\r
- */\r
-\r
-#include "CC2420LowPowerListening.h"\r
-\r
-module CC2420LowPowerListeningP {\r
-  provides {\r
-    interface Init;\r
-    interface LowPowerListening;\r
-    interface Send;\r
-    interface Receive;\r
-  }\r
-  \r
-  uses {\r
-    interface Leds;\r
-    interface Send as SubSend;\r
-    interface CC2420Transmit as Resend;\r
-    interface Receive as SubReceive;\r
-    interface AMPacket;\r
-    interface SplitControl as SubControl;\r
-    interface CC2420DutyCycle;\r
-    interface PacketAcknowledgements;\r
-    interface State as SendState;\r
-    interface State as RadioState;\r
-    interface State as SplitControlState;\r
-    interface Random;\r
-    interface Timer<TMilli> as OffTimer;\r
-    interface Timer<TMilli> as SendDoneTimer;\r
-  }\r
-}\r
-\r
-implementation {\r
-  \r
-  /** The message currently being sent */\r
-  message_t *currentSendMsg;\r
-  \r
-  /** The length of the current send message */\r
-  uint8_t currentSendLen;\r
-  \r
-  /** TRUE if the radio is duty cycling and not always on */\r
-  bool dutyCycling;\r
\r
-  /** Tx DSN to ensure multiple transmitted messages get across only once */ \r
-  uint8_t txDsn;\r
-  \r
-  /** The last received broadcast DSN. TODO is this the best way? */\r
-  uint8_t lastRxDsn;\r
-\r
-  /**\r
-   * Radio State\r
-   */\r
-  enum {\r
-    S_OFF,\r
-    S_ON,\r
-  };\r
-  \r
-  /**\r
-   * Send States\r
-   */\r
-  enum {\r
-    S_IDLE,\r
-    S_SENDING,\r
-  };\r
-  \r
-  \r
-  /***************** Prototypes ***************/\r
-  task void send();\r
-  task void resend();\r
-  task void startRadio();\r
-  task void stopRadio();\r
-  \r
-  void startOffTimer();\r
-  cc2420_header_t *getHeader(message_t *msg);\r
-  cc2420_metadata_t *getMetadata(message_t* msg);\r
-  uint16_t getActualDutyCycle(uint16_t dutyCycle);\r
-  void signalDone(error_t error);\r
-  \r
-  /***************** Init Commands ***************/\r
-  command error_t Init.init() {\r
-    txDsn = call Random.rand16();\r
-    dutyCycling = FALSE;\r
-    return SUCCESS;\r
-  }\r
-  \r
-  /***************** LowPowerListening Commands ***************/\r
-  /**\r
-   * Set this this node's radio sleep interval, in milliseconds.\r
-   * Once every interval, the node will sleep and perform an Rx check \r
-   * on the radio.  Setting the sleep interval to 0 will keep the radio\r
-   * always on.\r
-   *\r
-   * This is the equivalent of setting the local duty cycle rate.\r
-   *\r
-   * @param sleepIntervalMs the length of this node's Rx check interval, in [ms]\r
-   */\r
-  command void LowPowerListening.setLocalSleepInterval(\r
-      uint16_t sleepIntervalMs) {\r
-    call CC2420DutyCycle.setSleepInterval(sleepIntervalMs);\r
-  }\r
-  \r
-  /**\r
-   * @return the local node's sleep interval, in [ms]\r
-   */\r
-  command uint16_t LowPowerListening.getLocalSleepInterval() {\r
-    return call CC2420DutyCycle.getSleepInterval();\r
-  }\r
-  \r
-  /**\r
-   * Set this node's radio duty cycle rate, in units of [percentage*100].\r
-   * For example, to get a 0.05% duty cycle,\r
-   * <code>\r
-   *   call LowPowerListening.setDutyCycle(5);  // or equivalently...\r
-   *   call LowPowerListening.setDutyCycle(00005);  // for better readability?\r
-   * </code>\r
-   *\r
-   * For a 100% duty cycle (always on),\r
-   * <code>\r
-   *   call LowPowerListening.setDutyCycle(10000);\r
-   * </code>\r
-   *\r
-   * This is the equivalent of setting the local sleep interval explicitly.\r
-   * \r
-   * @param dutyCycle The duty cycle percentage, in units of [percentage*100]\r
-   */\r
-  command void LowPowerListening.setLocalDutyCycle(uint16_t dutyCycle) {\r
-    call CC2420DutyCycle.setSleepInterval(\r
-        call LowPowerListening.dutyCycleToSleepInterval(dutyCycle));\r
-  }\r
-  \r
-  /**\r
-   * @return this node's radio duty cycle rate, in units of [percentage*100]\r
-   */\r
-  command uint16_t LowPowerListening.getLocalDutyCycle() {\r
-    return call LowPowerListening.sleepIntervalToDutyCycle(\r
-        call CC2420DutyCycle.getSleepInterval());\r
-  }\r
-  \r
-  \r
-  /**\r
-   * Configure this outgoing message so it can be transmitted to a neighbor mote\r
-   * with the specified Rx sleep interval.\r
-   * @param msg Pointer to the message that will be sent\r
-   * @param sleepInterval The receiving node's sleep interval, in [ms]\r
-   */\r
-  command void LowPowerListening.setRxSleepInterval(message_t *msg, \r
-      uint16_t sleepIntervalMs) {\r
-    getMetadata(msg)->rxInterval = sleepIntervalMs;\r
-  }\r
-  \r
-  /**\r
-   * @return the destination node's sleep interval configured in this message\r
-   */\r
-  command uint16_t LowPowerListening.getRxSleepInterval(message_t *msg) {\r
-    return getMetadata(msg)->rxInterval;\r
-  }\r
-  \r
-  /**\r
-   * Configure this outgoing message so it can be transmitted to a neighbor mote\r
-   * with the specified Rx duty cycle rate.\r
-   * Duty cycle is in units of [percentage*100], i.e. 0.25% duty cycle = 25.\r
-   * \r
-   * @param msg Pointer to the message that will be sent\r
-   * @param dutyCycle The duty cycle of the receiving mote, in units of \r
-   *     [percentage*100]\r
-   */\r
-  command void LowPowerListening.setRxDutyCycle(message_t *msg, \r
-      uint16_t dutyCycle) {\r
-    getMetadata(msg)->rxInterval =\r
-        call LowPowerListening.dutyCycleToSleepInterval(dutyCycle);\r
-  }\r
-  \r
-    \r
-  /**\r
-   * @return the destination node's duty cycle configured in this message\r
-   *     in units of [percentage*100]\r
-   */\r
-  command uint16_t LowPowerListening.getRxDutyCycle(message_t *msg) {\r
-    return call LowPowerListening.sleepIntervalToDutyCycle(\r
-        getMetadata(msg)->rxInterval);\r
-  }\r
-  \r
-  /**\r
-   * Convert a duty cycle, in units of [percentage*100], to\r
-   * the sleep interval of the mote in milliseconds\r
-   * @param dutyCycle The duty cycle in units of [percentage*100]\r
-   * @return The equivalent sleep interval, in units of [ms]\r
-   */\r
-  command uint16_t LowPowerListening.dutyCycleToSleepInterval(\r
-      uint16_t dutyCycle) {\r
-    dutyCycle = getActualDutyCycle(dutyCycle);\r
-    \r
-    if(dutyCycle == 10000) {\r
-      return 0;\r
-    }\r
-    \r
-    return (DUTY_ON_TIME * (10000 - dutyCycle)) / dutyCycle;\r
-  }\r
-  \r
-  /**\r
-   * Convert a sleep interval, in units of [ms], to a duty cycle\r
-   * in units of [percentage*100]\r
-   * @param sleepInterval The sleep interval in units of [ms]\r
-   * @return The duty cycle in units of [percentage*100]\r
-   */\r
-  command uint16_t LowPowerListening.sleepIntervalToDutyCycle(\r
-      uint16_t sleepInterval) {\r
-    if(sleepInterval == 0) {\r
-      return 10000;\r
-    }\r
-    \r
-    return getActualDutyCycle((DUTY_ON_TIME * 10000) \r
-        / (sleepInterval + DUTY_ON_TIME));\r
-  }\r
-\r
-  \r
-  /***************** Send Commands ***************/\r
-  /**\r
-   * Each call to this send command gives the message a single\r
-   * DSN that does not change for every copy of the message\r
-   * sent out.  For messages that are not acknowledged, such as\r
-   * a broadcast address message, the receiving end does not\r
-   * signal receive() more than once for that message.\r
-   */\r
-  command error_t Send.send(message_t *msg, uint8_t len) {\r
-    if(call SplitControlState.getState() == S_OFF) {\r
-      // Everything is off right now, start SplitControl and try again\r
-      return EOFF;\r
-    }\r
-    \r
-    if(call SendState.requestState(S_SENDING) == SUCCESS) {\r
-      currentSendMsg = msg;\r
-      currentSendLen = len;\r
-      (getHeader(msg))->dsn = ++txDsn;\r
-      \r
-      // In case our off timer is running...\r
-      call OffTimer.stop();\r
-      \r
-      if(call RadioState.getState() == S_ON) {\r
-        if(call LowPowerListening.getRxSleepInterval(currentSendMsg) \r
-            > ONE_MESSAGE) {\r
-          // Send it repetitively within our transmit window\r
-          call PacketAcknowledgements.requestAck(currentSendMsg);\r
-          call SendDoneTimer.startOneShot(\r
-              call LowPowerListening.getRxSleepInterval(currentSendMsg) * 2);\r
-        }\r
-        \r
-        post send();\r
-    \r
-      } else {\r
-        post startRadio();\r
-      }\r
-      \r
-      return SUCCESS;\r
-    }\r
-    \r
-    return FAIL;\r
-  }\r
-\r
-  command error_t Send.cancel(message_t *msg) {\r
-    if(currentSendMsg == msg) {\r
-      call SendState.toIdle();\r
-      return SUCCESS;\r
-    }\r
-    \r
-    return FAIL;\r
-  }\r
-  \r
-  \r
-  command uint8_t Send.maxPayloadLength() {\r
-    return call SubSend.maxPayloadLength();\r
-  }\r
-\r
-  command void *Send.getPayload(message_t* msg) {\r
-    return call SubSend.getPayload(msg);\r
-  }\r
-  \r
-  /***************** Receive Commands ***************/\r
-  command void *Receive.getPayload(message_t* msg, uint8_t* len) {\r
-    return call SubReceive.getPayload(msg, len);\r
-  }\r
-\r
-  command uint8_t Receive.payloadLength(message_t* msg) {\r
-    return call SubReceive.payloadLength(msg);\r
-  }\r
-\r
-\r
-  /***************** DutyCycle Events ***************/\r
-  /**\r
-   * A transmitter was detected.  You must now take action to\r
-   * turn the radio off when the transaction is complete.\r
-   */\r
-  event void CC2420DutyCycle.detected() {\r
-    // At this point, the duty cycling has been disabled temporary\r
-    // and it will be this component's job to turn the radio back off\r
-   \r
-    startOffTimer();\r
-  }\r
-  \r
-  \r
-  /***************** SubControl Events ***************/\r
-  event void SubControl.startDone(error_t error) {\r
-    if(!error) {\r
-      call RadioState.forceState(S_ON);\r
-      \r
-      if(call SendState.getState() == S_SENDING) {\r
-        if(call LowPowerListening.getRxSleepInterval(currentSendMsg) \r
-            > ONE_MESSAGE) {\r
-          // Send it repetitively within our transmit window\r
-          call PacketAcknowledgements.requestAck(currentSendMsg);\r
-          call SendDoneTimer.startOneShot(\r
-              call LowPowerListening.getRxSleepInterval(currentSendMsg) * 2);\r
-        }\r
-        \r
-        post send();\r
-      }\r
-    }\r
-  }\r
-    \r
-  event void SubControl.stopDone(error_t error) {\r
-    if(!error) {\r
-      call RadioState.forceState(S_OFF);\r
-\r
-      if(call SendState.getState() == S_SENDING) {\r
-        // We're in the middle of sending a message; start the radio back up\r
-        post startRadio();\r
-      }\r
-    }\r
-  }\r
-  \r
-  /***************** SubSend Events ***************/\r
-  event void SubSend.sendDone(message_t* msg, error_t error) {\r
-    if(call SendState.getState() == S_SENDING  \r
-        && call SendDoneTimer.isRunning()) {\r
-      if(call PacketAcknowledgements.wasAcked(msg)) {\r
-        signalDone(error);\r
-        \r
-      } else {\r
-        post resend();\r
-      }\r
-      \r
-      return;\r
-    }\r
-    \r
-    signalDone(error);\r
-  }\r
-  \r
-  /***************** SubReceive Events ***************/\r
-  /**\r
-   * If the received message is new, we signal the receive event and\r
-   * start the off timer.  If the last message we received had the same\r
-   * DSN as this message, then the chances are pretty good\r
-   * that this message should be ignored, especially if the destination address\r
-   * as the broadcast address\r
-   *\r
-   * TODO\r
-   * What happens if a unicast Tx doesn't get Rx's ack, and resends that\r
-   * message?\r
-   */\r
-  event message_t *SubReceive.receive(message_t* msg, void* payload, \r
-      uint8_t len) {\r
-    \r
-    if((getHeader(msg))->dsn == lastRxDsn \r
-        && call AMPacket.destination(msg) == AM_BROADCAST_ADDR) {\r
-      // Already got this broadcast message.\r
-      // TODO should we do something similar with unicast messages?\r
-      return msg;\r
-\r
-    } else {\r
-      lastRxDsn = (getHeader(msg))->dsn;\r
-      startOffTimer();\r
-      return signal Receive.receive(msg, payload, len);\r
-    }\r
-  }\r
-  \r
-  /***************** Timer Events ****************/\r
-  event void OffTimer.fired() {\r
-    /*\r
-     * Only stop the radio if the radio is supposed to be off permanently\r
-     * or if the duty cycle is on and our sleep interval is not 0\r
-     */\r
-    if(call SplitControlState.getState() == S_OFF\r
-        || (call CC2420DutyCycle.getSleepInterval() > 0\r
-            && call SplitControlState.getState() == S_ON)) { \r
-      post stopRadio();\r
-    }\r
-  }\r
-  \r
-  /**\r
-   * When this timer is running, that means we're sending repeating messages\r
-   * to a node that is receive check duty cycling.\r
-   */\r
-  event void SendDoneTimer.fired() {\r
-    if(call SendState.getState() == S_SENDING) {\r
-      // The next time SubSend.sendDone is signaled, send is complete.\r
-      call SendState.toIdle();\r
-    }\r
-  }\r
-  \r
-  /***************** Resend Events ****************/\r
-  /**\r
-   * Signal that a message has been sent\r
-   *\r
-   * @param p_msg message to send.\r
-   * @param error notifaction of how the operation went.\r
-   */\r
-  async event void Resend.sendDone( message_t* p_msg, error_t error ) {\r
-    // This is actually caught by SubSend.sendDone\r
-  }\r
-  \r
-  \r
-  /***************** Tasks ***************/\r
-  task void send() {\r
-    if(call SubSend.send(currentSendMsg, currentSendLen) != SUCCESS) {\r
-      post send();\r
-    }\r
-  }\r
-  \r
-  task void resend() {\r
-    // Resend the last message without CCA checks.\r
-    if(call Resend.resend() != SUCCESS) {\r
-      post resend();\r
-    }\r
-  }\r
-  \r
-  task void startRadio() {\r
-    if(call SubControl.start() != SUCCESS) {\r
-      post startRadio();\r
-    }\r
-  }\r
-  \r
-  task void stopRadio() {\r
-    if(call SubControl.stop() != SUCCESS) {\r
-      post stopRadio();\r
-    }\r
-  }\r
-  \r
-  /***************** Functions ***************/\r
-  void startOffTimer() {\r
-    call OffTimer.startOneShot(DELAY_AFTER_RECEIVE);\r
-  }\r
-  \r
-  /**\r
-   * Check the bounds on a given duty cycle\r
-   * We're never over 100%, and we're never at 0%\r
-   */\r
-  uint16_t getActualDutyCycle(uint16_t dutyCycle) {\r
-    if(dutyCycle > 10000) {\r
-      return 10000;\r
-    } else if(dutyCycle == 0) {\r
-      return 1;\r
-    }\r
-    \r
-    return dutyCycle;\r
-  }\r
-  \r
-  cc2420_header_t *getHeader(message_t *msg) {\r
-    return (cc2420_header_t *)(msg->data - sizeof( cc2420_header_t ));\r
-  }\r
-  \r
-  cc2420_metadata_t *getMetadata(message_t* msg) {\r
-    return (cc2420_metadata_t*)msg->metadata;\r
-  }\r
-  \r
-  void signalDone(error_t error) {\r
-    call SendState.toIdle();\r
-    startOffTimer();\r
-    signal Send.sendDone(currentSendMsg, error);\r
-    currentSendMsg = NULL;\r
-  }\r
-}\r
-\r