]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/cc2420_tkn154/CC2420TransmitP.nc
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / tos / chips / cc2420_tkn154 / CC2420TransmitP.nc
index d746c854098e781a7849e1e647be7672e588ff94..4e4c955437f39e60a400e08cc6fc93e850071164 100644 (file)
  * @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$ $Date$
  */
 
@@ -45,21 +53,15 @@ module CC2420TransmitP {
 
   provides interface Init;
   provides interface AsyncStdControl;
-/*    interface CC2420Transmit;*/
   provides interface CC2420Tx;
-/*  provides interface RadioBackoff;*/
-/*  provides interface RadioTimeStamping as TimeStamp;*/
-/*  provides interface ReceiveIndicator as EnergyIndicator;*/
-/*  provides interface ReceiveIndicator as ByteIndicator;*/
-  
-/*  uses interface Alarm<T32khz,uint32_t> as BackoffAlarm;*/
   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 Resource as SpiResource;*/
   uses interface ChipSpiResource;
   uses interface CC2420Fifo as TXFIFO;
   uses interface CC2420Ram as TXFIFO_RAM;
@@ -71,7 +73,7 @@ module CC2420TransmitP {
   uses interface CC2420Strobe as SRXON;
   uses interface CC2420Strobe as SRFOFF;
   uses interface CC2420Strobe as SFLUSHRX;
-  uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
+  uses interface CC2420Strobe as SACKPEND;
   uses interface CC2420Register as MDMCTRL1;
   uses interface CaptureTime;
   uses interface ReferenceTime;
@@ -86,26 +88,22 @@ implementation {
     S_STOPPED,
     S_STARTED,
     S_LOAD,
-    S_SAMPLE_CCA,
-    S_BEGIN_TRANSMIT,
+    S_READY_TX,
     S_SFD,
     S_EFD,
     S_ACK_WAIT,
-    S_CANCEL,
   } cc2420_transmit_state_t;
 
-  // This specifies how many jiffies the stack should wait after a
+  // 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
+    CC2420_ABORT_PERIOD = 320*3,
   };
   
-/*  norace message_t *m_msg;*/
-  norace ieee154_txframe_t *m_data;
-  norace uint8_t m_txFrameLen;
-  ieee154_reftime_t m_timestamp;
+  norace ieee154_txframe_t *m_frame;
+  ieee154_timestamp_t m_timestamp;
   
   cc2420_transmit_state_t m_state = S_STOPPED;
   
@@ -119,27 +117,16 @@ implementation {
   /** Let the CC2420 driver keep a lock on the SPI while waiting for an ack */
   norace bool abortSpiRelease;
   
-  /** Total CCA checks that showed no activity before the NoAck LPL send */
-  norace int8_t totalCcaChecks;
-  
   /** The initial backoff period */
   norace uint16_t myInitialBackoff;
   
   /** The congestion backoff period */
   norace uint16_t myCongestionBackoff;
+  norace uint32_t alarmStartTime;
   
 
   /***************** Prototypes ****************/
-  error_t load( ieee154_txframe_t *data );
-  error_t resend( bool cca );
-  void loadTXFIFO();
-  void attemptSend(bool cca);
-  void congestionBackoff();
-  error_t acquireSpiResource();
-  error_t releaseSpiResource();
-/*  void signalDone( error_t err );*/
   void signalDone( bool ackFramePending, error_t err );
-/*  void cancelTx();*/
   
   /***************** Init Commands *****************/
   command error_t Init.init() {
@@ -166,81 +153,91 @@ implementation {
       m_state = S_STOPPED;
       call BackoffAlarm.stop();
       call CaptureSFD.disable();
-/*      call SpiResource.release();  // REMOVE*/
       call CSN.set();
     }
     return SUCCESS;
   }
 
 
-  /**************** Send Commands ****************/
+  /**************** Load/Send Commands ****************/
 
-/*  async command error_t Send.send( message_t* p_msg, bool useCca ) {*/
-  async command error_t CC2420Tx.loadTXFIFO(ieee154_txframe_t *data) {
-    return load( data);
-  }
-
-  async command void CC2420Tx.send(bool cca)
+  async command error_t CC2420Tx.loadTXFIFO(ieee154_txframe_t *data) 
   {
-    attemptSend(cca);
-  }
-  
-  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();
+    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 command void CC2420Tx.lockChipSpi()
+  }   
+
+  async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error) 
   {
-    abortSpiRelease = TRUE;
+    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 void CC2420Tx.unlockChipSpi()
+
+  async command error_t CC2420Tx.send(bool cca)
   {
-    abortSpiRelease = FALSE;
-  }
+    cc2420_status_t status;
+    bool congestion = TRUE;
 
-  /***************** Indicator Commands ****************/
-/*  command bool EnergyIndicator.isReceiving() {*/
-/*    return !(call CCA.get());*/
-/*  }*/
-/*  */
-/*  command bool ByteIndicator.isReceiving() {*/
-/*    bool high;*/
-/*    atomic high = sfdHigh;*/
-/*    return high;*/
-/*  }*/
-  
+    atomic {
+      if (m_state != S_READY_TX)
+        return EOFF;
+      call CSN.set();
+      call CSN.clr();
 
-  /***************** 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(uint16_t backoffTime) {*/
-/*    myInitialBackoff = backoffTime + 1;*/
-/*  }*/
-  
-  /**
-   * Must be called within a requestCongestionBackoff event
-   * @param backoffTime the amount of time in some unspecified units to backoff
-   */
-/*  async command void RadioBackoff.setCongestionBackoff(uint16_t backoffTime) {*/
-/*    myCongestionBackoff = backoffTime + 1;*/
-/*  }*/
-  
-/*  async command void RadioBackoff.setCca(bool useCca) {*/
-/*  }*/
-  
-  
+      // 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
@@ -256,33 +253,19 @@ implementation {
    * would have picked up and executed had our microcontroller been fast enough.
    */
   async event void CaptureSFD.captured( uint16_t time ) {
-    // "time" is from TimerB capture, which is sourced by SMCLK (1MHz)
     //P2OUT &= ~0x40;      // debug: P2.6 low
-    uint32_t localTime;
     atomic {
       switch( m_state ) {
         
       case S_SFD:
         m_state = S_EFD;
         sfdHigh = TRUE;
-        call CaptureTime.convert(time, &m_timestamp, -8); // -8 for the preamble
         call CaptureSFD.captureFallingEdge();
-/*        signal TimeStamp.transmittedSFD( time, m_msg );*/
-        localTime = call ReferenceTime.toLocalTime(&m_timestamp);
-        signal CC2420Tx.transmittedSFD(localTime, m_data );
-        //if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
-        //if ( (m_data->header)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
-          // This is an ack packet, don't release the chip's SPI bus lock.
-        //}
-        releaseSpiResource();
+        // 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();
-        m_data->metadata->timestamp = localTime;
-
-        
-/*        if ( ( ( (call CC2420PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) {*/
-/*          (call CC2420PacketBody.getMetadata( m_msg ))->time = time;*/
-/*        }*/
-        
         if ( call SFD.get() ) {
           break;
         }
@@ -291,11 +274,15 @@ implementation {
       case S_EFD:
         sfdHigh = FALSE;
         call CaptureSFD.captureRisingEdge();
-        
-/*        if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {*/
-        if ( (m_data->header->mhr)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
+        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;
-          call BackoffAlarm.start( 200 ); // we need to have *completely* received the ACK
+          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);
         }
@@ -306,11 +293,11 @@ implementation {
         /** Fall Through because the next interrupt was already received */
         
       default:
+        // The CC2420 is in receive mode.
         if ( !m_receiving ) {
           sfdHigh = TRUE;
           call CaptureSFD.captureFallingEdge();
-/*          signal TimeStamp.receivedSFD( time );*/
-          call CaptureTime.convert(time, &m_timestamp, -8);
+          call CaptureTime.convert(time, &m_timestamp, -10);
           call CC2420Receive.sfd( &m_timestamp );
           m_receiving = TRUE;
           m_prev_time = time;
@@ -318,26 +305,44 @@ implementation {
             // 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 ( time - m_prev_time < 10 ) {*/
-#ifdef PIERCEBOARD_ENABLED
-        if ( time - m_prev_time < 10*30 ) {
-#else
-        if ( time - m_prev_time < 10 ) {
-#endif
+        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;
+  }
 
-  /***************** ChipSpiResource Events ****************/
   async event void ChipSpiResource.releasing() {
     if(abortSpiRelease) {
       call ChipSpiResource.abortRelease();
@@ -351,392 +356,57 @@ implementation {
    * our send is complete.
    */
   async event void CC2420Receive.receive(  uint8_t type, message_t *ackFrame ){
-/*  async event void CC2420Receive.receive( uint8_t type, message_t* ack_msg ) {*/
-/*    cc2420_header_t* ack_header;*/
-/*    cc2420_header_t* msg_header;*/
-/*    cc2420_metadata_t* msg_metadata;*/
-/*    uint8_t* ack_buf;*/
-/*    uint8_t length;*/
-
     atomic {
       if ( type == IEEE154_TYPE_ACK ) {
-
-        /*      ack_header = call CC2420PacketBody.getHeader( ack_msg );*/
-        /*      msg_header = call CC2420PacketBody.getHeader( m_msg );*/
-
-        /*      if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) {*/
         if (  m_state == S_ACK_WAIT && 
-            m_data->header->mhr[2] == ((ieee154_header_t*) ackFrame->header)->mhr[2] ) { // compare seqno
+            m_frame->header->mhr[2] == ((ieee154_header_t*) ackFrame->header)->mhr[2] ) { // compare seqno
           call BackoffAlarm.stop();
-
-          /*        msg_metadata = call CC2420PacketBody.getMetadata( m_msg );*/
-          /*        ack_buf = (uint8_t *) ack_header;*/
-          /*        length = ack_header->length;*/
-          /*        */
-          /*        msg_metadata->ack = TRUE;*/
-          /*        msg_metadata->rssi = ack_buf[ length - 1 ];*/
-          /*        msg_metadata->lqi = ack_buf[ length ] & 0x7f;*/
           signalDone(( ((ieee154_header_t*) ackFrame->header)->mhr[0] & 0x10) ? TRUE: FALSE, SUCCESS);
         }
       }
     }
   }
-
-  /***************** SpiResource Events ****************/
-    /*
-  event void SpiResource.granted() {
-    uint8_t cur_state;
-
-    atomic {
-      cur_state = m_state;
-    }
-
-    switch( cur_state ) {
-    case S_LOAD:
-      loadTXFIFO();
-      break;
-      
-    case S_BEGIN_TRANSMIT:
-      attemptSend();
-      break;
-      
-    case S_CANCEL:
-      cancelTx();
-      break;
-      
-    default:
-      releaseSpiResource();
-      break;
-    }
-  }
-  */
-  
-  /***************** TXFIFO Events ****************/
-  /**
-   * The TXFIFO is used to load packets into the transmit buffer on the
-   * chip
-   */
-  async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len,
-                                     error_t error ) {
-
-    call CSN.set();
-    
-    if (tx_buf == &m_txFrameLen){
-      // until here: 1.65 ms
-      call CSN.clr();
-      call TXFIFO.write( m_data->header->mhr, m_data->headerLen );
-      return;
-    } else if (tx_buf == m_data->header->mhr) {
-      // until here: 2.2 ms
-      call CSN.clr();
-      call TXFIFO.write( m_data->payload, m_data->payloadLen );
-      return;
-    }
-    // until here: 4.6 ms (no DMA on USART0)
-    // until here: 3.3 ms (with DMA on USART0)
-    // P2OUT &= ~0x40;      // P2.1 low 
-    
-/*    if ( m_state == S_CANCEL ) {*/
-/*      atomic {*/
-/*        call CSN.clr();*/
-/*        call SFLUSHTX.strobe();*/
-/*        call CSN.set();*/
-/*      }*/
-/*      releaseSpiResource();*/
-/*      m_state = S_STARTED;*/
-            
-/*    } else if ( !m_cca ) {*/
-/*    } else  {*/
-      m_state = S_BEGIN_TRANSMIT;
-      releaseSpiResource();
-      signal CC2420Tx.loadTXFIFODone(m_data, error);
-/*      attemptSend();*/
-/*    }*/
-
-/*    } else {*/
-/*      releaseSpiResource();*/
-/*      atomic {*/
-/*        if (m_state == S_LOAD_CANCEL) {*/
-/*          m_state = S_CCA_CANCEL;*/
-/*        } else {*/
-/*          m_state = S_SAMPLE_CCA;*/
-/*        }*/
-/*      }*/
-/*      signal CC2420Tx.loadTXFIFODone(m_data, error);*/
-      
-/*      signal RadioBackoff.requestInitialBackoff(m_msg);*/
-/*      call BackoffAlarm.start(myInitialBackoff);*/
-/*    }*/
-  }
-
-  
-  async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, 
-      error_t error ) {
-  }
   
-  
-  /***************** Timer Events ****************/
-  /**
-   * The backoff timer is mainly used to wait for a moment before trying
-   * to send a packet again. But we also use it to timeout the wait for
-   * an acknowledgement, and timeout the wait for an SFD interrupt when
-   * we should have gotten one.
-   */
   async event void BackoffAlarm.fired() {
     atomic {
       switch( m_state ) {
-        
-      case S_SAMPLE_CCA : 
-        // sample CCA and wait a little longer if free, just in case we
-        // sampled during the ack turn-around window
-        if ( call CCA.get() ) {
-          m_state = S_BEGIN_TRANSMIT;
-          call BackoffAlarm.start( CC2420_TIME_ACK_TURNAROUND );
-          
-        } else {
-          congestionBackoff();
-        }
-        break;
-        
-      case S_BEGIN_TRANSMIT:
-      case S_CANCEL:
-        // should never happen
-        call Leds.led0On();
-/*        if ( acquireSpiResource() == SUCCESS ) {*/
-/*          attemptSend();*/
-/*        }*/
-        break;
-        
-      case S_ACK_WAIT:
-/*        signalDone( SUCCESS );*/
-        signalDone( FALSE, FAIL );
-        break;
-
-      case S_SFD:
-        // 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 );
-        releaseSpiResource();
-        //call CaptureSFD.captureRisingEdge();
-        break;
-
-      default:
-        break;
-      }
-    }
-  }
 
-  /***************** Functions ****************/
-  /**
-   * Set up a message to be sent. First load it into the outbound tx buffer
-   * on the chip, then attempt to send it.
-   * @param *p_msg Pointer to the message that needs to be sent
-   * @param cca TRUE if this transmit should use clear channel assessment
-   */
-  error_t load( ieee154_txframe_t *data) {
-    atomic {
-      if (m_state == S_CANCEL) {
-        return ECANCEL;
-      }
-      
-      if ( m_state != S_STARTED ) {
-        return FAIL;
-      }
-      
-      m_state = S_LOAD;
-/*      m_msg = p_msg;*/
-      m_data = data;
-      totalCcaChecks = 0;
-    }
-    
-    if ( acquireSpiResource() == SUCCESS ) {
-      loadTXFIFO();
-    }
-
-    return SUCCESS;
-  }
-  
-  /**
-   * Resend a packet that already exists in the outbound tx buffer on the
-   * chip
-   * @param cca TRUE if this transmit should use clear channel assessment
-   */
-/*  error_t resend( bool cca ) {*/
-
-/*    atomic {*/
-/*      if (m_state == S_LOAD_CANCEL*/
-/*          || m_state == S_CCA_CANCEL*/
-/*          || m_state == S_TX_CANCEL) {*/
-/*        return ECANCEL;*/
-/*      }*/
-/*      */
-/*      if ( m_state != S_STARTED ) {*/
-/*        return FAIL;*/
-/*      }*/
-/*      */
-/*      m_cca = cca;*/
-/*      m_state = cca ? S_SAMPLE_CCA : S_BEGIN_TRANSMIT;*/
-/*      totalCcaChecks = 0;*/
-/*    }*/
-/*    */
-/*    if(m_cca) {*/
-/*      signal RadioBackoff.requestInitialBackoff(m_msg);*/
-/*      call BackoffAlarm.start( myInitialBackoff );*/
-/*      */
-/*    } else if ( acquireSpiResource() == SUCCESS ) {*/
-/*      attemptSend();*/
-/*    }*/
-/*    */
-/*    return SUCCESS;*/
-/*  }*/
-  
-  /**
-   * Attempt to send the packet we have loaded into the tx buffer on 
-   * the radio chip.  The STXONCCA will send the packet immediately if
-   * the channel is clear.  If we're not concerned about whether or not
-   * the channel is clear (i.e. m_cca == FALSE), then STXON will send the
-   * packet without checking for a clear channel.
-   *
-   * If the packet didn't get sent, then congestion == TRUE.  In that case,
-   * we reset the backoff timer and try again in a moment.
-   *
-   * If the packet got sent, we should expect an SFD interrupt to take
-   * over, signifying the packet is getting sent.
-   */
-  void attemptSend(bool cca) {
-    uint8_t status;
-    bool congestion = TRUE;
-
-    atomic {
-      call CSN.set();
-      call CSN.clr();
+        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;
 
-      // STXONCCA costs about ? symbols, i.e. attemptSend should be called
-      // ? symbols, before the actual CCA
-      //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();
+        case S_ACK_WAIT:
+          /*        signalDone( SUCCESS );*/
+          signalDone( FALSE, ENOACK );
+          break;
 
-      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){
-        call ReferenceTime.getNow(&m_timestamp, 0);
-        m_state = S_BEGIN_TRANSMIT; // don't use a state S_SAMPLE_CCA
-        releaseSpiResource();
-        signal CC2420Tx.sendDone(m_data, &m_timestamp, FALSE, EBUSY); // waiting for the next send()
-      } else {
-        m_state = S_SFD; // wait for an ACK
-        signal CC2420Tx.transmissionStarted(m_data);
-        call BackoffAlarm.start(CC2420_ABORT_PERIOD*3);
+        default:
+          break;
       }
-      return; // we still own the SPI, either we wait for an ACK or resend is going to be called soon
     }
-    
-/*    if ( congestion ) {*/
-/*      totalCcaChecks = 0;*/
-/*      releaseSpiResource();*/
-/*      congestionBackoff();*/
-/*    } else {*/
-/*      call BackoffAlarm.start(CC2420_ABORT_PERIOD);*/
-/*    }*/
   }
-  
-  /**  
-   * Congestion Backoff
-   */
-  void congestionBackoff() {
-    atomic {
-/*      signal RadioBackoff.requestCongestionBackoff(m_msg);*/
-      call BackoffAlarm.start(myCongestionBackoff);
-    }
-  }
-  
-  error_t acquireSpiResource() {
-    return SUCCESS;
-    /*
-    error_t error = call SpiResource.immediateRequest();
-    if ( error != SUCCESS ) {
-      call SpiResource.request();
-    }
-    return error;
-    */
-  }
-
-  error_t releaseSpiResource() {
-    //call SpiResource.release();
-    return SUCCESS;
-  }
-
-
-  /** 
-   * Setup the packet transmission power and load the tx fifo buffer on
-   * the chip with our outbound packet.  
-   *
-   * Warning: the tx_power metadata might not be initialized and
-   * could be a value other than 0 on boot.  Verification is needed here
-   * to make sure the value won't overstep its bounds in the TXCTRL register
-   * and is transmitting at max power by default.
-   *
-   * It should be possible to manually calculate the packet's CRC here and
-   * tack it onto the end of the header + payload when loading into the TXFIFO,
-   * so the continuous modulation low power listening strategy will continually
-   * deliver valid packets.  This would increase receive reliability for
-   * mobile nodes and lossy connections.  The crcByte() function should use
-   * the same CRC polynomial as the CC2420's AUTOCRC functionality.
-   */
-  void loadTXFIFO() {
-/*    cc2420_header_t* header = call CC2420PacketBody.getHeader( m_msg );*/
-/*    uint8_t tx_power = (call CC2420PacketBody.getMetadata( m_msg ))->tx_power;*/
-    m_txFrameLen = m_data->headerLen + m_data->payloadLen + 2;
 
-/*    if ( !tx_power ) {*/
-/*      tx_power = CC2420_DEF_RFPOWER;*/
-/*    }*/
-    call CSN.set();
-    call CSN.clr();
-    call SFLUSHTX.strobe(); // flush out anything that was in there
-    call CSN.set();
-    call CSN.clr();
-    
-/*    call TXFIFO.write( (uint8_t*)header, header->length - 1);*/
-    call TXFIFO.write( &m_txFrameLen, 1 );
-
-  }
-  
   void signalDone( bool ackFramePending, error_t err ) {
+    ieee154_timestamp_t *txTime = &m_timestamp;
     atomic m_state = S_STARTED;
-    signal CC2420Tx.sendDone( m_data, &m_timestamp, ackFramePending, err );
+    if (m_frame->metadata->timestamp == IEEE154_INVALID_TIMESTAMP)
+      txTime = NULL;
+    signal CC2420Tx.sendDone( m_frame, txTime, ackFramePending, err );
     call ChipSpiResource.attemptRelease();
-/*    signal Send.sendDone( m_msg, err );*/
   }
-  
-  /***************** Tasks ****************/
-
-  /***************** Defaults ****************/
-/*  default async event void TimeStamp.transmittedSFD( uint16_t time, message_t* p_msg ) {*/
-/*  }*/
-  
-/*  default async event void TimeStamp.receivedSFD( uint16_t time ) {*/
-/*  }*/
 
+  async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, 
+      error_t error ) {
+  }
 }