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

📄 cc2420transmitp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/*
 * 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>
 * @author David Moss
 * @author Jung Il Choi Initial SACK implementation
 * @author Jan Hauer <hauer@tkn.tu-berlin.de>
 *
 * IMPORTANT: this module does not use the SPI Resource interface,
 * instead the caller must take care of the resource arbitration
 * (i.e. the caller must own the resource before calling commands
 * like CC2420Tx.loadTXFIFO())
 * Note: on TelosB there seems to be a problem if BackoffAlarm
 * is virtualized - i.e. BackoffAlarm should be a dedicated Alarm.
 *
 * @version $Revision: 1.4 $ $Date: 2009/03/04 18:31:11 $
 */

#include "CC2420.h"
#include "crc.h"
#include "message.h"

module CC2420TransmitP {

  provides interface Init;
  provides interface AsyncStdControl;
  provides interface CC2420Tx;
  uses interface Alarm<T62500hz,uint32_t> as BackoffAlarm;
  uses interface GpioCapture as CaptureSFD;
  uses interface GeneralIO as CCA;
  uses interface GeneralIO as CSN;
  uses interface GeneralIO as SFD;
  uses interface GeneralIO as FIFO;
  uses interface GeneralIO as FIFOP;

  uses interface ChipSpiResource;
  uses interface CC2420Fifo as TXFIFO;
  uses interface CC2420Ram as TXFIFO_RAM;
  uses interface CC2420Register as TXCTRL;
  uses interface CC2420Strobe as SNOP;
  uses interface CC2420Strobe as STXON;
  uses interface CC2420Strobe as STXONCCA;
  uses interface CC2420Strobe as SFLUSHTX;
  uses interface CC2420Strobe as SRXON;
  uses interface CC2420Strobe as SRFOFF;
  uses interface CC2420Strobe as SFLUSHRX;
  uses interface CC2420Strobe as SACKPEND;
  uses interface CC2420Register as MDMCTRL1;
  uses interface CaptureTime;
  uses interface ReferenceTime;

  uses interface CC2420Receive;
  uses interface Leds;
}

implementation {

  typedef enum {
    S_STOPPED,
    S_STARTED,
    S_LOAD,
    S_READY_TX,
    S_SFD,
    S_EFD,
    S_ACK_WAIT,
  } cc2420_transmit_state_t;

  // This specifies how many symbols the stack should wait after a
  // TXACTIVE to receive an SFD interrupt before assuming something is
  // wrong and aborting the send. There seems to be a condition
  // on the micaZ where the SFD interrupt is never handled.
  enum {
    CC2420_ABORT_PERIOD = 320*3,
  };
  
  norace ieee154_txframe_t *m_frame;
  ieee154_timestamp_t m_timestamp;
  
  cc2420_transmit_state_t m_state = S_STOPPED;
  
  bool m_receiving = FALSE;
  
  uint16_t m_prev_time;
  
  /** Byte reception/transmission indicator */
  bool sfdHigh;
  
  /** Let the CC2420 driver keep a lock on the SPI while waiting for an ack */
  norace bool abortSpiRelease;
  
  /** The initial backoff period */
  norace uint16_t myInitialBackoff;
  
  /** The congestion backoff period */
  norace uint16_t myCongestionBackoff;
  norace uint32_t alarmStartTime;
  

  /***************** Prototypes ****************/
  void signalDone( bool ackFramePending, error_t err );
  
  /***************** Init Commands *****************/
  command error_t Init.init() {
    call CCA.makeInput();
    call CSN.makeOutput();
    call SFD.makeInput();
    return SUCCESS;
  }

  /***************** AsyncStdControl Commands ****************/
  async command error_t AsyncStdControl.start() {
    atomic {
      if (m_state == S_STARTED)
        return EALREADY;
      call CaptureSFD.captureRisingEdge();
      m_state = S_STARTED;
      m_receiving = FALSE;
    }
    return SUCCESS;
  }

  async command error_t AsyncStdControl.stop() {
    atomic {
      m_state = S_STOPPED;
      call BackoffAlarm.stop();
      call CaptureSFD.disable();
      call CSN.set();
    }
    return SUCCESS;
  }


  /**************** Load/Send Commands ****************/

  async command error_t CC2420Tx.loadTXFIFO(ieee154_txframe_t *data) 
  {
    atomic {
      if ( m_state != S_STARTED )
        return FAIL;
      m_state = S_LOAD;
      m_frame = data;
      m_frame->header->length = m_frame->headerLen + m_frame->payloadLen + 2; // 2 for CRC
      call CSN.set();
      call CSN.clr();
      call SFLUSHTX.strobe(); // flush out anything that was in TXFIFO
      call CSN.set();
      call CSN.clr();
      call TXFIFO.write( &(m_frame->header->length), 1 );
    }
    return SUCCESS;
  }   

  async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error) 
  {
    atomic {
      call CSN.set();
      if (tx_buf == &(m_frame->header->length)){
        call CSN.clr();
        call TXFIFO.write( m_frame->header->mhr, m_frame->headerLen );
        return;
      } else if (tx_buf == m_frame->header->mhr) {
        call CSN.clr();
        call TXFIFO.write( m_frame->payload, m_frame->payloadLen );
        return;
      }
    }
    m_state = S_READY_TX;
    signal CC2420Tx.loadTXFIFODone(m_frame, error);
  }

  async command error_t CC2420Tx.send(bool cca)
  {
    cc2420_status_t status;
    bool congestion = TRUE;

    atomic {
      if (m_state != S_READY_TX)
        return EOFF;
      call CSN.set();
      call CSN.clr();

      // DEBUG
      //P2OUT |= 0x40;      // P2.6 high
      status = cca ? call STXONCCA.strobe() : call STXON.strobe();
      //status = call STXON.strobe();
      //U0TXBUF = 0x04; // strobe STXON
      //while (!(IFG1 & URXIFG0));
      //status = U0RXBUF;
      //call CSN.set();

      if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) {
        status = call SNOP.strobe();
        if ( status & CC2420_STATUS_TX_ACTIVE ) {
          congestion = FALSE;
        }
      }
      
      call CSN.set();
      // DEBUG: on telosb SFD is connected to Pin P4.1
      //if (!congestion) {while (!(P4IN & 0x02)) ;  P6OUT &= ~0x80;}

      if (congestion){
        return FAIL; // channel busy
      } else {
        m_state = S_SFD;
        m_frame->metadata->timestamp = IEEE154_INVALID_TIMESTAMP; // pessimistic
        call BackoffAlarm.start(CC2420_ABORT_PERIOD); 
        return SUCCESS;
      }
    }
  }
  
  /**
   * The CaptureSFD event is actually an interrupt from the capture pin
   * which is connected to timing circuitry and timer modules.  This
   * type of interrupt allows us to see what time (being some relative value)
   * the event occurred, and lets us accurately timestamp our packets.  This
   * allows higher levels in our system to synchronize with other nodes.
   *
   * Because the SFD events can occur so quickly, and the interrupts go
   * in both directions, we set up the interrupt but check the SFD pin to
   * determine if that interrupt condition has already been met - meaning,
   * we should fall through and continue executing code where that interrupt
   * would have picked up and executed had our microcontroller been fast enough.
   */
  async event void CaptureSFD.captured( uint16_t time ) {
    //P2OUT &= ~0x40;      // debug: P2.6 low
    atomic {
      switch( m_state ) {
        
      case S_SFD:
        m_state = S_EFD;
        sfdHigh = TRUE;
        call CaptureSFD.captureFallingEdge();
        // timestamp denotes time of first bit (chip) of PPDU on the channel
        // offset: -10 for 5 bytes (preamble+SFD)
        if (call CaptureTime.convert(time, &m_timestamp, -10) == SUCCESS) 
          m_frame->metadata->timestamp = call ReferenceTime.toLocalTime(&m_timestamp);
        call BackoffAlarm.stop();
        if ( call SFD.get() ) {
          break;
        }
        /** Fall Through because the next interrupt was already received */
        
      case S_EFD:
        sfdHigh = FALSE;
        call CaptureSFD.captureRisingEdge();
        signal CC2420Tx.transmissionStarted(m_frame);
        if ( (m_frame->header->mhr)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
          // wait for the ACK
          m_state = S_ACK_WAIT;
          alarmStartTime = call BackoffAlarm.getNow();
          // we need to have *completely* received the ACK, 32+22 symbols
          // should theroretically be enough, but there can be delays in 
          // servicing the FIFOP interrupt, so we use 100 symbols here
          call BackoffAlarm.start( 100 ); 
        } else {
          signalDone(FALSE, SUCCESS);
        }
        
        if ( !call SFD.get() ) {
          break;
        }
        /** Fall Through because the next interrupt was already received */
        
      default:
        // The CC2420 is in receive mode.
        if ( !m_receiving ) {
          sfdHigh = TRUE;
          call CaptureSFD.captureFallingEdge();
          call CaptureTime.convert(time, &m_timestamp, -10);
          call CC2420Receive.sfd( &m_timestamp );
          m_receiving = TRUE;
          m_prev_time = time;
          if ( call SFD.get() ) {
            // wait for the next interrupt before moving on
            return;
          }
          // if we move on, then the timestamp will be invalid!
        }
        
        sfdHigh = FALSE;
        call CaptureSFD.captureRisingEdge();
        m_receiving = FALSE;
        if (!call CaptureTime.isValidTimestamp(m_prev_time, time))
          call CC2420Receive.sfd_dropped();
        break;
      
      }
    }
  }
   
  async command bool CC2420Tx.cca()
  {
    return call CCA.get();
  }

  async command error_t CC2420Tx.modify( uint8_t offset, uint8_t* buf, uint8_t len ) 
  {
    call CSN.set();
    call CSN.clr();
    call TXFIFO_RAM.write( offset, buf, len );
    call CSN.set();
    return SUCCESS;
  }
  
  async command void CC2420Tx.lockChipSpi()
  {
    abortSpiRelease = TRUE;
  }

  async command void CC2420Tx.unlockChipSpi()
  {
    abortSpiRelease = FALSE;
  }

  async event void ChipSpiResource.releasing() {
    if(abortSpiRelease) {
      call ChipSpiResource.abortRelease();
    }
  }
  
  
  /***************** CC2420Receive Events ****************/
  /**
   * If the packet we just received was an ack that we were expecting,
   * our send is complete.
   */
  async event void CC2420Receive.receive(  uint8_t type, message_t *ackFrame ){
    atomic {
      if ( type == IEEE154_TYPE_ACK ) {
        if (  m_state == S_ACK_WAIT && 
            m_frame->header->mhr[2] == ((ieee154_header_t*) ackFrame->header)->mhr[2] ) { // compare seqno
          call BackoffAlarm.stop();
          signalDone(( ((ieee154_header_t*) ackFrame->header)->mhr[0] & 0x10) ? TRUE: FALSE, SUCCESS);
        }
      }
    }
  }
  
  async event void BackoffAlarm.fired() {
    atomic {
      switch( m_state ) {

        case S_SFD:
        case S_EFD: // fall through
          // We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD
          // jiffies. Assume something is wrong.
          atomic {
            call CSN.set();
            call CSN.clr();
            call SFLUSHTX.strobe();
            call CSN.set();
          }
          signalDone( FALSE, ERETRY );
          break;

        case S_ACK_WAIT:
          /*        signalDone( SUCCESS );*/
          signalDone( FALSE, ENOACK );
          break;


        default:
          break;
      }
    }
  }

  void signalDone( bool ackFramePending, error_t err ) {
    ieee154_timestamp_t *txTime = &m_timestamp;
    atomic m_state = S_STARTED;
    if (m_frame->metadata->timestamp == IEEE154_INVALID_TIMESTAMP)
      txTime = NULL;
    signal CC2420Tx.sendDone( m_frame, txTime, ackFramePending, err );
    call ChipSpiResource.attemptRelease();
  }

  async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, 
      error_t error ) {
  }
}

⌨️ 快捷键说明

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