]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/cc2420/csma/CC2420CsmaP.nc
New CC2420 architecture in place for 2.0.2 release. See the README.txt file for...
[tinyos-2.x.git] / tos / chips / cc2420 / csma / CC2420CsmaP.nc
diff --git a/tos/chips/cc2420/csma/CC2420CsmaP.nc b/tos/chips/cc2420/csma/CC2420CsmaP.nc
new file mode 100644 (file)
index 0000000..fe49782
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+module CC2420CsmaP {
+
+  provides interface SplitControl;
+  provides interface Send;
+  provides interface RadioBackoff[am_id_t amId];
+
+  uses interface Resource;
+  uses interface CC2420Power;
+  uses interface StdControl as SubControl;
+  uses interface CC2420Transmit;
+  uses interface RadioBackoff as SubBackoff;
+  uses interface Random;
+  uses interface AMPacket;
+  uses interface Leds;
+  uses interface CC2420Packet;
+  uses interface CC2420PacketBody;
+  uses interface State as SplitControlState;
+
+}
+
+implementation {
+
+  enum {
+    S_STOPPED,
+    S_STARTING,
+    S_STARTED,
+    S_STOPPING,
+    S_TRANSMITTING,
+  };
+
+  message_t* m_msg;
+  
+  error_t sendErr = SUCCESS;
+  
+  /** TRUE if we are to use CCA when sending the current packet */
+  norace bool ccaOn;
+  
+  /****************** Prototypes ****************/
+  task void startDone_task();
+  task void startDone_task();
+  task void stopDone_task();
+  task void sendDone_task();
+  
+  void shutdown();
+
+  /***************** SplitControl Commands ****************/
+  command error_t SplitControl.start() {
+    if(call SplitControlState.requestState(S_STARTING) == SUCCESS) {
+      call CC2420Power.startVReg();
+      return SUCCESS;
+    
+    } else if(call SplitControlState.isState(S_STARTED)) {
+      return EALREADY;
+      
+    } else if(call SplitControlState.isState(S_STARTING)) {
+      return SUCCESS;
+    }
+    
+    return EBUSY;
+  }
+
+  command error_t SplitControl.stop() {
+    if (call SplitControlState.isState(S_STARTED)) {
+      call SplitControlState.forceState(S_STOPPING);
+      shutdown();
+      return SUCCESS;
+      
+    } else if(call SplitControlState.isState(S_STOPPED)) {
+      return EALREADY;
+    
+    } else if(call SplitControlState.isState(S_TRANSMITTING)) {
+      call SplitControlState.forceState(S_STOPPING);
+      // At sendDone, the radio will shut down
+      return SUCCESS;
+    
+    } else if(call SplitControlState.isState(S_STOPPING)) {
+      return SUCCESS;
+    }
+    
+    return EBUSY;
+  }
+
+  /***************** Send Commands ****************/
+  command error_t Send.cancel( message_t* p_msg ) {
+    return call CC2420Transmit.cancel();
+  }
+
+  command error_t Send.send( message_t* p_msg, uint8_t len ) {
+    
+    cc2420_header_t* header = call CC2420PacketBody.getHeader( p_msg );
+    cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( p_msg );
+
+    atomic {
+      if (!call SplitControlState.isState(S_STARTED)) {
+        return FAIL;
+      }
+      
+      call SplitControlState.forceState(S_TRANSMITTING);
+      m_msg = p_msg;
+    }
+
+    header->length = len;
+    header->fcf &= 1 << IEEE154_FCF_ACK_REQ;
+    header->fcf |= ( ( IEEE154_TYPE_DATA << IEEE154_FCF_FRAME_TYPE ) |
+                    ( 1 << IEEE154_FCF_INTRAPAN ) |
+                    ( IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE ) |
+                    ( IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE ) );
+    header->src = call AMPacket.address();
+    metadata->ack = FALSE;
+    metadata->rssi = 0;
+    metadata->lqi = 0;
+    metadata->time = 0;
+    
+    ccaOn = TRUE;
+    signal RadioBackoff.requestCca[((cc2420_header_t*)(m_msg->data - 
+        sizeof(cc2420_header_t)))->type](m_msg);
+    call CC2420Transmit.send( m_msg, ccaOn );
+    return SUCCESS;
+
+  }
+
+  command void* Send.getPayload(message_t* m) {
+    return m->data;
+  }
+
+  command uint8_t Send.maxPayloadLength() {
+    return TOSH_DATA_LENGTH;
+  }
+
+  /**************** RadioBackoff Commands ****************/
+  /**
+   * Must be called within a requestInitialBackoff event
+   * @param backoffTime the amount of time in some unspecified units to backoff
+   */
+  async command void RadioBackoff.setInitialBackoff[am_id_t amId](uint16_t backoffTime) {
+    call SubBackoff.setInitialBackoff(backoffTime);
+  }
+  
+  /**
+   * Must be called within a requestCongestionBackoff event
+   * @param backoffTime the amount of time in some unspecified units to backoff
+   */
+  async command void RadioBackoff.setCongestionBackoff[am_id_t amId](uint16_t backoffTime) {
+    call SubBackoff.setCongestionBackoff(backoffTime);
+  }
+      
+  /**
+   * Enable CCA for the outbound packet.  Must be called within a requestCca
+   * event
+   * @param ccaOn TRUE to enable CCA, which is the default.
+   */
+  async command void RadioBackoff.setCca[am_id_t amId](bool useCca) {
+    ccaOn = useCca;
+  }
+  
+
+  /**************** Events ****************/
+  async event void CC2420Transmit.sendDone( message_t* p_msg, error_t err ) {
+    atomic sendErr = err;
+    post sendDone_task();
+  }
+
+  async event void CC2420Power.startVRegDone() {
+    call Resource.request();
+  }
+  
+  event void Resource.granted() {
+    call CC2420Power.startOscillator();
+  }
+
+  async event void CC2420Power.startOscillatorDone() {
+    post startDone_task();
+  }
+  
+  /***************** SubBackoff Events ****************/
+  async event void SubBackoff.requestInitialBackoff(message_t *msg) {
+    call SubBackoff.setInitialBackoff ( call Random.rand16() 
+        % (0x1F * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF);
+        
+    signal RadioBackoff.requestInitialBackoff[((cc2420_header_t*)(msg->data - 
+        sizeof(cc2420_header_t)))->type](msg);
+  }
+
+  async event void SubBackoff.requestCongestionBackoff(message_t *msg) {
+    call SubBackoff.setCongestionBackoff( call Random.rand16() 
+        % (0x7 * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF);
+
+    signal RadioBackoff.requestCongestionBackoff[((cc2420_header_t*)(msg->data - 
+        sizeof(cc2420_header_t)))->type](msg);
+  }
+  
+  async event void SubBackoff.requestCca(message_t *msg) {
+    // Lower layers than this do not configure the CCA settings
+  }
+  
+  
+  /***************** Tasks ****************/
+  task void sendDone_task() {
+    error_t packetErr;
+    atomic packetErr = sendErr;
+    if(call SplitControlState.isState(S_STOPPING)) {
+      shutdown();
+      
+    } else {
+      call SplitControlState.forceState(S_STARTED);
+    }
+    
+    signal Send.sendDone( m_msg, packetErr );
+  }
+
+  task void startDone_task() {
+    call SubControl.start();
+    call CC2420Power.rxOn();
+    call Resource.release();
+    call SplitControlState.forceState(S_STARTED);
+    signal SplitControl.startDone( SUCCESS );
+  }
+  
+  task void stopDone_task() {
+    call SplitControlState.forceState(S_STOPPED);
+    signal SplitControl.stopDone( SUCCESS );
+  }
+  
+  
+  /***************** Functions ****************/
+  /**
+   * Shut down all sub-components and turn off the radio
+   */
+  void shutdown() {
+    call SubControl.stop();
+    call CC2420Power.stopVReg();
+    post stopDone_task();
+  }
+
+  /***************** Defaults ***************/
+  default event void SplitControl.startDone(error_t error) {
+  }
+  
+  default event void SplitControl.stopDone(error_t error) {
+  }
+  
+  
+  default async event void RadioBackoff.requestInitialBackoff[am_id_t amId](
+      message_t *msg) {
+  }
+
+  default async event void RadioBackoff.requestCongestionBackoff[am_id_t amId](
+      message_t *msg) {
+  }
+  
+  default async event void RadioBackoff.requestCca[am_id_t amId](
+      message_t *msg) {
+  }
+}
+