[Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/cc2420_tkn154 CC2420SpiC.nc, NONE, 1.1 CC2420AsyncSplitControl.nc, 1.1, 1.2 CC2420ControlP.nc, 1.1, 1.2 CC2420ControlTransmitC.nc, 1.2, 1.3 CC2420Power.nc, 1.1, 1.2 CC2420ReceiveP.nc, 1.1, 1.2 CC2420TKN154P.nc, 1.1, 1.2 CC2420TransmitP.nc, 1.2, 1.3 CC2420Tx.nc, 1.1, 1.2 ReliableWait.nc, 1.1, 1.2

Jan-Hinrich Hauer janhauer at users.sourceforge.net
Tue Nov 25 01:35:11 PST 2008


Update of /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv21632/tos/chips/cc2420_tkn154

Modified Files:
	CC2420AsyncSplitControl.nc CC2420ControlP.nc 
	CC2420ControlTransmitC.nc CC2420Power.nc CC2420ReceiveP.nc 
	CC2420TKN154P.nc CC2420TransmitP.nc CC2420Tx.nc 
	ReliableWait.nc 
Added Files:
	CC2420SpiC.nc 
Log Message:
+ modified radio driver (PHY) interfaces: CSMA-CA algorithm is now pushed to radio driver
+ adapted CC2420 driver
+ renamed CsmaP -> FrameDispatchP
+ provided workaround for a problem with virtualized alarms (sometimes they seem to fire 2s too late)
+ updated placeholder components
+ updated debug information

--- NEW FILE: CC2420SpiC.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
 */

/**
 * Implementation of basic SPI primitives for the ChipCon CC2420 radio.
 *
 * Jan Hauer: this component currently shadows 
 * tinyos-2.x/tos/chips/cc2420/spi/CC2420SpiC.nc because the latter
 * does not (yet) provide access to the RXFIFO via the CC2420Register
 * interface. As soon as it does, this file should be removed.
 *
 * @author Jonathan Hui <jhui at archrock.com>
 * @version $Revision: 1.1 $ $Date: 2008/11/25 09:35:08 $
 */

generic configuration CC2420SpiC() {

  provides interface Resource;
  provides interface ChipSpiResource;

  // commands
  provides interface CC2420Strobe as SNOP;
  provides interface CC2420Strobe as SXOSCON;
  provides interface CC2420Strobe as STXCAL;
  provides interface CC2420Strobe as SRXON;
  provides interface CC2420Strobe as STXON;
  provides interface CC2420Strobe as STXONCCA;
  provides interface CC2420Strobe as SRFOFF;
  provides interface CC2420Strobe as SXOSCOFF;
  provides interface CC2420Strobe as SFLUSHRX;
  provides interface CC2420Strobe as SFLUSHTX;
  provides interface CC2420Strobe as SACK;
  provides interface CC2420Strobe as SACKPEND;
  provides interface CC2420Strobe as SRXDEC;
  provides interface CC2420Strobe as STXENC;
  provides interface CC2420Strobe as SAES;

  // registers
  provides interface CC2420Register as MAIN;
  provides interface CC2420Register as MDMCTRL0;
  provides interface CC2420Register as MDMCTRL1;
  provides interface CC2420Register as RSSI;
  provides interface CC2420Register as SYNCWORD;
  provides interface CC2420Register as TXCTRL;
  provides interface CC2420Register as RXCTRL0;
  provides interface CC2420Register as RXCTRL1;
  provides interface CC2420Register as FSCTRL;
  provides interface CC2420Register as SECCTRL0;
  provides interface CC2420Register as SECCTRL1;
  provides interface CC2420Register as BATTMON;
  provides interface CC2420Register as IOCFG0;
  provides interface CC2420Register as IOCFG1;
  provides interface CC2420Register as MANFIDL;
  provides interface CC2420Register as MANFIDH;
  provides interface CC2420Register as FSMTC;
  provides interface CC2420Register as MANAND;
  provides interface CC2420Register as MANOR;
  provides interface CC2420Register as AGCCTRL;
  provides interface CC2420Register as RXFIFO_REGISTER;

  // ram
  provides interface CC2420Ram as IEEEADR;
  provides interface CC2420Ram as PANID;
  provides interface CC2420Ram as SHORTADR;
  provides interface CC2420Ram as TXFIFO_RAM;

  // fifos
  provides interface CC2420Fifo as RXFIFO;
  provides interface CC2420Fifo as TXFIFO;

}

implementation {

  enum {
    CLIENT_ID = unique( "CC2420Spi.Resource" ),
  };
  
  components HplCC2420PinsC as Pins;
  components CC2420SpiWireC as Spi;
  
  ChipSpiResource = Spi.ChipSpiResource;
  Resource = Spi.Resource[ CLIENT_ID ];
  
  // commands
  SNOP = Spi.Strobe[ CC2420_SNOP ];
  SXOSCON = Spi.Strobe[ CC2420_SXOSCON ];
  STXCAL = Spi.Strobe[ CC2420_STXCAL ];
  SRXON = Spi.Strobe[ CC2420_SRXON ];
  STXON = Spi.Strobe[ CC2420_STXON ];
  STXONCCA = Spi.Strobe[ CC2420_STXONCCA ];
  SRFOFF = Spi.Strobe[ CC2420_SRFOFF ];
  SXOSCOFF = Spi.Strobe[ CC2420_SXOSCOFF ];
  SFLUSHRX = Spi.Strobe[ CC2420_SFLUSHRX ];
  SFLUSHTX = Spi.Strobe[ CC2420_SFLUSHTX ];
  SACK = Spi.Strobe[ CC2420_SACK ];
  SACKPEND = Spi.Strobe[ CC2420_SACKPEND ];
  SRXDEC = Spi.Strobe[ CC2420_SRXDEC ];
  STXENC = Spi.Strobe[ CC2420_STXENC ];
  SAES = Spi.Strobe[ CC2420_SAES ];
  
  // registers
  MAIN = Spi.Reg[ CC2420_MAIN ];
  MDMCTRL0 = Spi.Reg[ CC2420_MDMCTRL0 ];
  MDMCTRL1 = Spi.Reg[ CC2420_MDMCTRL1 ];
  RSSI = Spi.Reg[ CC2420_RSSI ];
  SYNCWORD = Spi.Reg[ CC2420_SYNCWORD ];
  TXCTRL = Spi.Reg[ CC2420_TXCTRL ];
  RXCTRL0 = Spi.Reg[ CC2420_RXCTRL0 ];
  RXCTRL1 = Spi.Reg[ CC2420_RXCTRL1 ];
  FSCTRL = Spi.Reg[ CC2420_FSCTRL ];
  SECCTRL0 = Spi.Reg[ CC2420_SECCTRL0 ];
  SECCTRL1 = Spi.Reg[ CC2420_SECCTRL1 ];
  BATTMON = Spi.Reg[ CC2420_BATTMON ];
  IOCFG0 = Spi.Reg[ CC2420_IOCFG0 ];
  IOCFG1 = Spi.Reg[ CC2420_IOCFG1 ];
  MANFIDL = Spi.Reg[ CC2420_MANFIDL ];
  MANFIDH = Spi.Reg[ CC2420_MANFIDH ];
  FSMTC = Spi.Reg[ CC2420_FSMTC ];
  MANAND = Spi.Reg[ CC2420_MANAND ];
  MANOR = Spi.Reg[ CC2420_MANOR ];
  AGCCTRL = Spi.Reg[ CC2420_AGCCTRL ];
  RXFIFO_REGISTER = Spi.Reg[ CC2420_RXFIFO ];
  
  // ram
  IEEEADR = Spi.Ram[ CC2420_RAM_IEEEADR ];
  PANID = Spi.Ram[ CC2420_RAM_PANID ];
  SHORTADR = Spi.Ram[ CC2420_RAM_SHORTADR ];
  TXFIFO_RAM = Spi.Ram[ CC2420_RAM_TXFIFO ];

  // fifos
  RXFIFO = Spi.Fifo[ CC2420_RXFIFO ];
  TXFIFO = Spi.Fifo[ CC2420_TXFIFO ];

}


Index: CC2420AsyncSplitControl.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CC2420AsyncSplitControl.nc	16 Jun 2008 18:02:40 -0000	1.1
--- CC2420AsyncSplitControl.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 74,78 ****
  
  /**
!  * An async version of the SplitControl interface.
   * @author Jan Hauer <hauer at tkn.tu-berlin.de>
   */
--- 74,78 ----
  
  /**
!  * This interface is a mixture of a SplitControl/AsyncStdControl interface.
   * @author Jan Hauer <hauer at tkn.tu-berlin.de>
   */
***************
*** 81,128 ****
  {
    /**
!    * Start this component and all of its subcomponents.  Return
!    * values of SUCCESS will always result in a <code>startDone()</code>
!    * event being signalled.
     *
!    * @return SUCCESS if the device is already in the process of 
!    *         starting or the device was off and the device is now ready to turn 
!    *         on.  After receiving this return value, you should expect a 
!    *         <code>startDone</code> event in the near future.<br>
!    *         EBUSY if the component is in the middle of powering down
!    *               i.e. a <code>stop()</code> command has been called,
!    *               and a <code>stopDone()</code> event is pending<br>
!    *         EALREADY if the device is already on <br>
     *         FAIL Otherwise
     */
    async command error_t start();
  
-   /** 
-    * Notify caller that the component has been started and is ready to
-    * receive other commands.
-    *
-    * @param <b>error</b> -- SUCCESS if the component was successfully
-    *                        turned on, FAIL otherwise
-    */
-   async event void startDone(error_t error);
- 
    /**
!    * Start this component and all of its subcomponents.  Return
!    * values of SUCCESS will always result in a <code>startDone()</code>
!    * event being signalled.
     *
!    * @return SUCCESS if the device is already in the process of 
!    *         stopping or the device was on and the device is now ready to turn 
!    *         off.  After receiving this return value, you should expect a 
!    *         <code>stopDone</code> event in the near future.<br>
!    *         EBUSY if the component is in the middle of powering up
!    *               i.e. a <code>start()</code> command has been called,
!    *               and a <code>startDone()</code> event is pending<br>
!    *         EALREADY if the device is already off <br>
!    *         FAIL Otherwise
     */
    async command error_t stop();
  
    /**
!    * Notify caller that the component has been stopped.
     *
    * @param <b>error</b> -- SUCCESS if the component was successfully
--- 81,104 ----
  {
    /**
!    * Start this component and all of its subcomponents.  
     *
!    * @return SUCCESS if the component was started successfully.<br>
     *         FAIL Otherwise
     */
    async command error_t start();
  
    /**
!    * Stop this component and all of its subcomponents - iff this command
!    * succeeds then <tt>stopDone</tt> will signal the result of the stop
!    * operation.
     *
!    * @return SUCCESS Stop operation was started, <tt>stopDone</tt> will be signalled
!    *         FAIL Otherwise (<tt>stopDone</tt> will not be signalled)
     */
    async command error_t stop();
  
    /**
!    * Notify caller that the component has been stopped. This event
!    * completes the <tt>stop()</tt> operation.
     *
    * @param <b>error</b> -- SUCCESS if the component was successfully

Index: CC2420ControlP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420ControlP.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CC2420ControlP.nc	16 Jun 2008 18:02:40 -0000	1.1
--- CC2420ControlP.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 34,38 ****
   * @author David Moss
   * @author Urs Hunkeler (ReadRssi implementation)
!  * @author Jan Hauer <hauer at tkn.tu-berlin.de> (support for promiscuous mode)
   * @version $Revision$ $Date$
   */
--- 34,38 ----
   * @author David Moss
   * @author Urs Hunkeler (ReadRssi implementation)
!  * @author Jan Hauer <hauer at tkn.tu-berlin.de>
   * @version $Revision$ $Date$
   */
***************
*** 54,57 ****
--- 54,58 ----
    uses interface GeneralIO as VREN;
    uses interface GpioInterrupt as InterruptCCA;
+   uses interface GeneralIO as FIFO;
  
    uses interface CC2420Ram as IEEEADR;
***************
*** 63,71 ****
    uses interface CC2420Register as RXCTRL1;
    uses interface CC2420Register as RSSI;
    uses interface CC2420Strobe as SRXON;
    uses interface CC2420Strobe as SRFOFF;
    uses interface CC2420Strobe as SXOSCOFF;
    uses interface CC2420Strobe as SXOSCON;
!   uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
    uses interface CC2420Register as TXCTRL;
    uses interface AMPacket;
--- 64,75 ----
    uses interface CC2420Register as RXCTRL1;
    uses interface CC2420Register as RSSI;
+   uses interface CC2420Register as RXFIFO_REGISTER;
+   uses interface CC2420Strobe as SNOP;
    uses interface CC2420Strobe as SRXON;
    uses interface CC2420Strobe as SRFOFF;
    uses interface CC2420Strobe as SXOSCOFF;
    uses interface CC2420Strobe as SXOSCON;
!   uses interface CC2420Strobe as SACKPEND;
!   uses interface CC2420Strobe as SFLUSHRX;
    uses interface CC2420Register as TXCTRL;
    uses interface AMPacket;
***************
*** 123,126 ****
--- 127,136 ----
  
    /***************** Resource Commands ****************/
+   /* This module never actively requests the SPI resource,
+    * instead the caller MUST request the SPI through this module
+    * before it calls any of the provided commands and it must
+    * release it afterwards (the caller can call multiple  
+    * commands in this module before it releases the SPI, though).
+    */ 
    async command error_t Resource.immediateRequest() {
      error_t error = call SpiResource.immediateRequest();
***************
*** 146,149 ****
--- 156,164 ----
    }
  
+   event void SpiResource.granted() {
+ /*    call CSN.clr();*/
+     signal Resource.granted();
+   }
+ 
    void switchToUnbufferedMode()
    {
***************
*** 180,184 ****
      }
      call VREN.set();
!     call StartupAlarm.start( CC2420_TIME_VREN * 2 ); // JH: a 15.4 symbol is about two 32khz ticks
      return SUCCESS;
    }
--- 195,199 ----
      }
      call VREN.set();
!     call StartupAlarm.start( CC2420_TIME_VREN * 2 ); // JH: changed from 32khz jiffies
      return SUCCESS;
    }
***************
*** 242,252 ****
    async command error_t CC2420Power.rxOn() {
      atomic {
!       if ( m_state != S_XOSC_STARTED ) {
          return FAIL;
-       }
        call CSN.set();
        call CSN.clr();
        call SRXON.strobe();
!       call SACKPEND.strobe();  // JH: ACKs have the pending bit set
        call CSN.set();
      }
--- 257,266 ----
    async command error_t CC2420Power.rxOn() {
      atomic {
!       if ( !call SpiResource.isOwner() )
          return FAIL;
        call CSN.set();
        call CSN.clr();
        call SRXON.strobe();
!       call SACKPEND.strobe();  // JH: ACKs need the pending bit set
        call CSN.set();
      }
***************
*** 255,265 ****
  
    async command error_t CC2420Power.rfOff() {
!     atomic {  
!       if ( m_state != S_XOSC_STARTED ) {
          return FAIL;
-       }
        call CSN.set();
        call CSN.clr();
-       call SACKPEND.strobe();  // JH: ACKs have the pending bit set
        call SRFOFF.strobe();
        call CSN.set();
--- 269,277 ----
  
    async command error_t CC2420Power.rfOff() {
!     atomic {
!       if ( !call SpiResource.isOwner() )
          return FAIL;
        call CSN.set();
        call CSN.clr();
        call SRFOFF.strobe();
        call CSN.set();
***************
*** 268,271 ****
--- 280,306 ----
    }
  
+   async command error_t CC2420Power.flushRxFifo()
+   {
+     uint16_t dummy;
+     atomic {
+       if ( !call SpiResource.isOwner() )
+         return FAIL;
+       if ( call FIFO.get() ){ // check if there is something in the RXFIFO
+         // SFLUSHRX: "Flush the RX FIFO buffer and reset the demodulator. 
+         // Always read at least one byte from the RXFIFO before 
+         // issuing the SFLUSHRX command strobe" (CC2420 Datasheet)
+         call CSN.clr();
+         call RXFIFO_REGISTER.read(&dummy); // reading 1 byte would be enough...
+         call CSN.set();
+         call CSN.clr();
+         // "SFLUSHRX command strobe should be issued twice to ensure 
+         // that the SFD pin goes back to its idle state." (CC2420 Datasheet)
+         call SFLUSHRX.strobe();
+         call SFLUSHRX.strobe();
+         call CSN.set();
+       }
+     }
+     return SUCCESS;
+   }
    
    /***************** CC2420Config Commands ****************/
***************
*** 368,378 ****
     * the microcontroller (through the CC2420Config interface) to the
     * CC2420 radio chip.
-    * ASSUMPTION: caller owns the SPI, radio will be switched off !
     */
    async command error_t CC2420Config.sync() {
      atomic {
!       if ( m_state != S_XOSC_STARTED ) {
          return FAIL;
-       }
        if (m_needsSync){
          call CSN.set();
--- 403,411 ----
     * the microcontroller (through the CC2420Config interface) to the
     * CC2420 radio chip.
     */
    async command error_t CC2420Config.sync() {
      atomic {
!       if ( !call SpiResource.isOwner() )
          return FAIL;
        if (m_needsSync){
          call CSN.set();
***************
*** 397,423 ****
    
    async command error_t CC2420Power.rssi(int8_t *rssi) {
-     // we are owner of the Spi !
      uint16_t data;
      cc2420_status_t status;
!     call CSN.clr();
!     status = call RSSI.read(&data);
!     call CSN.set();
!     if ((status & 0x02)){
!       *rssi = (data & 0x00FF);
!       return SUCCESS;
!     } else
!       return FAIL;
!   }
! 
!   event void SpiResource.granted() {
! /*    call CSN.clr();*/
!     signal Resource.granted();
    }
- 
- 
    
    /***************** StartupAlarm Events ****************/
    async event void StartupAlarm.fired() {
      if ( m_state == S_VREG_STARTING ) {
        m_state = S_VREG_STARTED;
        call RSTN.clr();
--- 430,457 ----
    
    async command error_t CC2420Power.rssi(int8_t *rssi) {
      uint16_t data;
      cc2420_status_t status;
!     atomic {
!       if ( !call SpiResource.isOwner() )
!         return FAIL;
!       call CSN.set();
!       call CSN.clr();
!       status = call RSSI.read(&data);
!       call CSN.set();
!       if ((status & 0x02)){
!         *rssi = (data & 0x00FF);
!         return SUCCESS;
!       } else
!         return FAIL;
!     }
    }
    
    /***************** StartupAlarm Events ****************/
    async event void StartupAlarm.fired() {
      if ( m_state == S_VREG_STARTING ) {
+       cc2420_status_t status;
+       do {
+        status = call SNOP.strobe();  
+       } while (!(status & CC2420_STATUS_XOSC16M_STABLE));
        m_state = S_VREG_STARTED;
        call RSTN.clr();

Index: CC2420ControlTransmitC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** CC2420ControlTransmitC.nc	18 Jun 2008 15:39:32 -0000	1.2
--- CC2420ControlTransmitC.nc	25 Nov 2008 09:35:08 -0000	1.3
***************
*** 87,90 ****
--- 87,91 ----
    CC2420ControlP.RSTN -> Pins.RSTN;
    CC2420ControlP.VREN -> Pins.VREN;
+   CC2420ControlP.FIFO -> Pins.FIFO;
  
    components HplCC2420InterruptsC as Interrupts;
***************
*** 107,111 ****
--- 108,115 ----
    CC2420ControlP.IEEEADR -> Spi.IEEEADR;
    CC2420ControlP.RXCTRL1 -> Spi.RXCTRL1;
+   CC2420ControlP.SFLUSHRX-> Spi.SFLUSHRX;
    CC2420ControlP.RSSI  -> Spi.RSSI;
+   CC2420ControlP.RXFIFO_REGISTER -> Spi.RXFIFO_REGISTER;
+   CC2420ControlP.SNOP -> Spi.SNOP;
  
    // CC2420TransmitC

Index: CC2420Power.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420Power.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CC2420Power.nc	16 Jun 2008 18:02:40 -0000	1.1
--- CC2420Power.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 103,105 ****
--- 103,113 ----
     */
    async command error_t rssi(int8_t *rssi);
+  
+   /**
+    * Flush the RXFIFO if it is not empty. 
+    * Radio SHOULD be disabled (off) when calling this command.
+    *
+    * @return SUCCESS if fifo was flushed (or it was empty), FAIL otherwise.
+    */
+   async command error_t flushRxFifo(); 
  }

Index: CC2420ReceiveP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CC2420ReceiveP.nc	16 Jun 2008 18:02:40 -0000	1.1
--- CC2420ReceiveP.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 43,47 ****
    provides interface CC2420Receive;
    provides interface CC2420Rx;
- /*  provides interface ReceiveIndicator as PacketIndicator;*/
  
    uses interface GeneralIO as CSN;
--- 43,46 ----
***************
*** 55,65 ****
    uses interface CC2420Strobe as SFLUSHRX;
    uses interface CC2420Strobe as SRXON;
!   uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
    uses interface CC2420Register as MDMCTRL1;
    uses interface ReferenceTime;
    uses interface FrameUtility;
    uses interface CC2420Config;
! /*  uses interface CC2420Packet;*/
! /*  uses interface CC2420PacketBody;*/
    
    uses interface Leds;
--- 54,63 ----
    uses interface CC2420Strobe as SFLUSHRX;
    uses interface CC2420Strobe as SRXON;
!   uses interface CC2420Strobe as SACKPEND; 
    uses interface CC2420Register as MDMCTRL1;
    uses interface ReferenceTime;
    uses interface FrameUtility;
    uses interface CC2420Config;
!   uses interface CC2420Ram as RXFIFO_RAM;
    
    uses interface Leds;
***************
*** 71,75 ****
      S_STOPPED,
      S_STARTING,
-     S_STARTING_FLUSHRX,
      S_STARTED,
      S_RX_LENGTH,
--- 69,72 ----
***************
*** 126,130 ****
    void switchToUnbufferedMode();
    void switchToBufferedMode();
-   void startingSpiReserved();
    void continueStart();
    void continueStop();
--- 123,126 ----
***************
*** 140,216 ****
    }
  
!   /***************** AsyncSplitControl ****************
!    * IMPORTANT: when AsyncSplitControl.start is called, 
!    * the radio MUST be off !
     */
    async command error_t AsyncSplitControl.start()
    {
      atomic {
        if (m_state != S_STOPPED){
          call Leds.led0On();
          return FAIL;
-       } else {
-         m_state = S_STARTING;
-         if (call SpiResource.isOwner()){ 
-           call Leds.led0On(); // internal error (debug) !
-           startingSpiReserved();
-         }
-         if (call SpiResource.immediateRequest() == SUCCESS)
-           startingSpiReserved();
-         else
-           call SpiResource.request();        
-       }
-     }
-     return SUCCESS;
-   }
- 
-   void startingSpiReserved()
-   {
-     atomic {
-       if (!call FIFOP.get() || call FIFO.get()){ // FIFOP is inverted
-         // there is something in RXFIFO: flush it out 
-         // the datasheet says at least one byte should 
-         // be read before flushing
-         m_state = S_STARTING_FLUSHRX;
-         call CSN.set();
-         call CSN.clr();
-         call RXFIFO.beginRead( &m_dummy, 1 ); // will continue in continueFlushStart()
-         return;
        }
-     }
-     continueStart();
-   }
- 
- 
-   void continueFlushStart()
-   {
-     atomic {
-       call CSN.set();
-       call CSN.clr();
-       call SFLUSHRX.strobe();
-       call SFLUSHRX.strobe();
-       call CSN.set();
-     }
-     continueStart();
-   }
-   
-   void continueStart()
-   {
-     // RXFIFO is empty
-     if (!call FIFOP.get() || call FIFO.get()){
-       call Leds.led0On();
-     }
-     atomic {
        reset_state();
        m_state = S_STARTED;
      }
!     call SpiResource.release();
!     call InterruptFIFOP.enableFallingEdge();
!     signal AsyncSplitControl.startDone(SUCCESS);
    }
  
!   /***************** AsyncSplitControl ****************
     * IMPORTANT: when AsyncSplitControl.stop is called, 
!    * the radio MUST NOT be off !
     */
    async command error_t AsyncSplitControl.stop()
--- 136,181 ----
    }
  
!   /***************** AsyncSplitControl ****************/
!   /* NOTE: AsyncSplitControl does not switch the state of the radio 
!    * hardware (i.e. it does not put the radio in Rx mode, this has to
!    * be done by the caller through a separate interface/component). 
!    */
! 
!   /** 
!    * AsyncSplitControl.start should be called before radio
!    * is switched to Rx mode (or at least early enough before
!    * a packet has been received, i.e. before FIFOP changes)
     */
    async command error_t AsyncSplitControl.start()
    {
      atomic {
+       if ( !call FIFO.get() && !call FIFOP.get() ){
+         // RXFIFO has some data (remember: FIFOP is inverted)
+         // the problem is that this messses up the timestamping
+         // so why don't we flush here ourselves? 
+         // because we don't own the SPI...
+         return FAIL; 
+       }
        if (m_state != S_STOPPED){
          call Leds.led0On();
          return FAIL;
        }
        reset_state();
        m_state = S_STARTED;
+       call InterruptFIFOP.enableFallingEdge(); // ready!
      }
!     return SUCCESS;
    }
  
!   /* AsyncSplitControl.stop:
!    *
     * IMPORTANT: when AsyncSplitControl.stop is called, 
!    * then either
!    * 1) the radio MUST still be in RxMode
!    * 2) it was never put in RxMode after  
!    *    AsyncSplitControl.start() was called
!    *
!    * => The radio may be switched off only *after* the
!    * stopDone() event was signalled.
     */
    async command error_t AsyncSplitControl.stop()
***************
*** 223,229 ****
          call InterruptFIFOP.disable();
          if (!receivingPacket)
!           continueStop();
!         // else stopContinueTask will be posted after 
!         // current Rx operation is finished, because m_stop is set
        }
      }
--- 188,194 ----
          call InterruptFIFOP.disable();
          if (!receivingPacket)
!           continueStop(); // it is safe to stop now
!         // else continueStop will be called after 
!         // current Rx operation is finished
        }
      }
***************
*** 234,237 ****
--- 199,205 ----
    {
      atomic {
+       if (!m_stop){
+         return;
+       }
        m_stop = FALSE;
        m_state = S_STOPPED;
***************
*** 242,248 ****
    task void stopContinueTask()
    {
!     if (receivingPacket){
        call Leds.led0On();
-     }
      call SpiResource.release(); // may fail
      atomic m_state = S_STOPPED;
--- 210,215 ----
    task void stopContinueTask()
    {
!     if (receivingPacket)
        call Leds.led0On();
      call SpiResource.release(); // may fail
      atomic m_state = S_STOPPED;
***************
*** 315,322 ****
        switch (m_state)
        {
!         case S_STARTING: startingSpiReserved(); break;
!         case S_STARTING_FLUSHRX: // fall through
!         case S_STOPPED: call Leds.led0On(); 
!                         call SpiResource.release(); break;
          default: receive();
        }
--- 282,289 ----
        switch (m_state)
        {
!         case S_STOPPED: // this should never happen!
!                         call Leds.led0On(); 
!                         call SpiResource.release(); 
!                         break;
          default: receive();
        }
***************
*** 472,477 ****
        break;
  
-     case S_STARTING_FLUSHRX: continueFlushStart(); break;
-       
      default:
        atomic receivingPacket = FALSE;
--- 439,442 ----
***************
*** 539,544 ****
    void beginReceive() { 
      atomic {
!       if ( m_state == S_STOPPED){
!         call Leds.led0On();
          return;
        }
--- 504,508 ----
    void beginReceive() { 
      atomic {
!       if (m_state == S_STOPPED || m_stop){
          return;
        }
***************
*** 592,600 ****
    void waitForNextPacket() {
      atomic {
-       receivingPacket = FALSE;
        if ( m_state == S_STOPPED) {
          call SpiResource.release();
          return;
        }
        if (m_stop){
          continueStop();
--- 556,564 ----
    void waitForNextPacket() {
      atomic {
        if ( m_state == S_STOPPED) {
          call SpiResource.release();
          return;
        }
+       receivingPacket = FALSE;
        if (m_stop){
          continueStop();

Index: CC2420TKN154P.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420TKN154P.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CC2420TKN154P.nc	16 Jun 2008 18:02:40 -0000	1.1
--- CC2420TKN154P.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 79,82 ****
--- 79,83 ----
      S_RESERVE_RX_SPI,
      S_RX_PREPARED,
+     S_RX_WAIT,
      S_RECEIVING,
      S_OFF_PENDING,
***************
*** 84,87 ****
--- 85,89 ----
      S_LOAD_TXFIFO,
      S_TX_LOADED,
+     S_TX_WAIT,
      S_TX_ACTIVE,
      S_TX_CANCEL,
***************
*** 90,94 ****
  
    norace m_state_t m_state = S_STOPPED;
!   norace ieee154_txframe_t *m_txdata;
    norace error_t m_txError;
    norace ieee154_reftime_t m_txReferenceTime;
--- 92,96 ----
  
    norace m_state_t m_state = S_STOPPED;
!   norace ieee154_txframe_t *m_txframe;
    norace error_t m_txError;
    norace ieee154_reftime_t m_txReferenceTime;
***************
*** 96,102 ****
    uint32_t m_edDuration;
    bool m_pibUpdated;
!   uint8_t m_numCCA;
    ieee154_reftime_t *m_t0Tx;
!   uint32_t m_dtTx;
  
    norace uint8_t m_txLockOnCCAFail;
--- 98,106 ----
    uint32_t m_edDuration;
    bool m_pibUpdated;
!   norace uint8_t m_numCCA;
    ieee154_reftime_t *m_t0Tx;
!   uint32_t m_dtMax;
!   uint32_t m_dt;
!   norace ieee154_csma_t *m_csmaParams;
  
    norace uint8_t m_txLockOnCCAFail;
***************
*** 113,144 ****
    void txSpiReserved();
    void txDoneSpiReserved();
-   void signalTxDone();
    void finishTx();
    void stopContinue();
    void offSpiReserved();
    void offStopRxDone();
!   void continueTxPrepare();
    
  
!   /******************************/
!   /* StdControl Operations      */
!   /******************************/
! 
!   /****************************************/
!   /*     TelosB Pin connection (debug)    */
!   /*                                      */
!   /* R1 = P6.6 = ADC6, R2 = P6.7 = ADC7   */
!   /* S1 = P2.3 = GIO2, S2 = P2.6 = GIO3   */
!   /* R1 is at 6pin-expansion pin 1,       */               
!   /* R2 is at 6pin-expansion pin 2,       */               
!   /****************************************/
  
    command error_t SplitControl.start()
    {
-     // debug
-     //P6SEL &= ~0xC0;     // debug PIN: 6.6, 6.7, set to I/O function
-     //P6DIR |= 0xC0;      // output
-     //P6OUT &= ~0xC0;     // low
-     
      atomic {
        if (m_state == S_RADIO_OFF)
--- 117,134 ----
    void txSpiReserved();
    void txDoneSpiReserved();
    void finishTx();
    void stopContinue();
    void offSpiReserved();
    void offStopRxDone();
!   uint16_t generateRandomBackoff(uint8_t BE);
!   void randomDelayUnslottedCsmaCa();
!   void randomDelaySlottedCsmaCa(bool resume, uint16_t remainingBackoff);
!   void sendDone(ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error);
    
  
! /* ----------------------- StdControl Operations ----------------------- */
  
    command error_t SplitControl.start()
    {
      atomic {
        if (m_state == S_RADIO_OFF)
***************
*** 167,170 ****
--- 157,161 ----
      // default configuration (addresses, etc) has been written
      call CC2420Power.rfOff();
+     call CC2420Power.flushRxFifo();
      call CC2420Tx.unlockChipSpi();
      post startDoneTask();
***************
*** 204,211 ****
      }
      if (m_state != S_STOPPING)
!       post stopTask(); // this will not happen, because the caller has switched radio off
      else 
!       if (call RxControl.stop() == EALREADY)
!         stopContinue();
    }
  
--- 195,201 ----
      }
      if (m_state != S_STOPPING)
!       post stopTask(); // spin - this should not happen, because the caller has switched radio off
      else 
!       stopContinue();
    }
  
***************
*** 220,227 ****
      atomic {
        call CC2420Power.rfOff();
!       call CC2420Tx.unlockChipSpi();
!       call TxControl.stop();
        call CC2420Power.stopOscillator(); 
        call CC2420Power.stopVReg();
        call SpiResource.release();
        m_state  = S_STOPPED;
--- 210,217 ----
      atomic {
        call CC2420Power.rfOff();
!       call CC2420Power.flushRxFifo();
        call CC2420Power.stopOscillator(); 
        call CC2420Power.stopVReg();
+       call CC2420Tx.unlockChipSpi();
        call SpiResource.release();
        m_state  = S_STOPPED;
***************
*** 230,236 ****
    }
  
!   /*********************************/
!   /*  PIB Updates                  */
!   /*********************************/
    
    // input: power in dBm, output: PA_LEVEL parameter for cc2420 TXCTRL register
--- 220,235 ----
    }
  
!   uint16_t generateRandomBackoff(uint8_t BE)
!   {
!     // return random number from [0,(2^BE) - 1] (uniform distr.)
!     uint16_t res = call Random.rand16();
!     uint16_t mask = 0xFFFF;
!     mask <<= BE;
!     mask = ~mask;
!     res &= mask;
!     return res;
!   }
! 
! /* ----------------------- PIB Updates ----------------------- */
    
    // input: power in dBm, output: PA_LEVEL parameter for cc2420 TXCTRL register
***************
*** 293,299 ****
    }
  
!   /*********************************/
!   /* Energy Detection              */
!   /*********************************/
  
    command error_t EnergyDetection.start(uint32_t duration)
--- 292,296 ----
    }
  
! /* ----------------------- Energy Detection ----------------------- */
  
    command error_t EnergyDetection.start(uint32_t duration)
***************
*** 320,324 ****
      // reading an RSSI value over SPI will usually almost
      // take as much time as 8 symbols, i.e. there's 
!     // no point using an Alarm here (but maybe a BusyWait?)
      while (!call TimeCalc.hasExpired(start, m_edDuration)){
        if (call CC2420Power.rssi(&value) != SUCCESS)
--- 317,321 ----
      // reading an RSSI value over SPI will usually almost
      // take as much time as 8 symbols, i.e. there's 
!     // no point using an Alarm here (but maybe a busy wait?)
      while (!call TimeCalc.hasExpired(start, m_edDuration)){
        if (call CC2420Power.rssi(&value) != SUCCESS)
***************
*** 332,335 ****
--- 329,333 ----
        maxEnergy -= 45; 
      call CC2420Power.rfOff();
+     call CC2420Power.flushRxFifo();
      m_state = S_RADIO_OFF;
      call SpiResource.release();
***************
*** 337,343 ****
    }
  
!   /****************************************/
!   /*     Transceiver Off                  */
!   /****************************************/
  
    async command error_t RadioOff.off()
--- 335,349 ----
    }
  
! /* ----------------------- Transceiver Off ----------------------- */
! 
!   task void spinOffTask()
!   {
!     uint8_t i;
!       call Leds.led2On(); call Leds.led1On(); 
!       for (i=0; i<65500U; i++) ;
!       call Leds.led2Off(); call Leds.led1Off(); 
!       for (i=0; i<65500U; i++) ;
!     call RadioOff.off();
!   }
  
    async command error_t RadioOff.off()
***************
*** 346,350 ****
        if (m_state == S_RADIO_OFF)
          return EALREADY;
!       else if (m_state != S_RECEIVING && m_state != S_TX_LOADED && m_state != S_RX_PREPARED)
          return FAIL;
        m_state = S_OFF_PENDING;
--- 352,359 ----
        if (m_state == S_RADIO_OFF)
          return EALREADY;
!       if (m_state == S_RX_WAIT || m_state == S_TX_WAIT){
!         post spinOffTask();
!         return SUCCESS;
!       } else if (m_state != S_RECEIVING && m_state != S_TX_LOADED && m_state != S_RX_PREPARED)
          return FAIL;
        m_state = S_OFF_PENDING;
***************
*** 368,372 ****
      call TxControl.stop();
      call CC2420Power.rfOff();
!     call CC2420Config.sync(); // put any PIB updates into operation
      call CC2420Tx.unlockChipSpi();
      call SpiResource.release();
--- 377,381 ----
      call TxControl.stop();
      call CC2420Power.rfOff();
!     call CC2420Power.flushRxFifo();
      call CC2420Tx.unlockChipSpi();
      call SpiResource.release();
***************
*** 380,386 ****
    }
  
!   /****************************************/
!   /*     Receive Operations               */
!   /****************************************/
  
    async command error_t RadioRx.prepare()
--- 389,393 ----
    }
  
! /* ----------------------- Receive Operations ----------------------- */
  
    async command error_t RadioRx.prepare()
***************
*** 393,416 ****
        m_state = S_RESERVE_RX_SPI;
      }
!     if (call RxControl.start() != SUCCESS){  // will trigger rxStartRxDone()
        m_state = S_RADIO_OFF;
        call Leds.led0On();
        return FAIL; 
      }
      return SUCCESS; 
    }
  
-   void rxStartRxDone()
-   {
-     if (call SpiResource.immediateRequest() == SUCCESS)   // will trigger rxSpiReserved()
-       rxSpiReserved();
-     else
-       call SpiResource.request();
-   }
- 
    void rxSpiReserved()
    {
      call CC2420Config.sync(); // put PIB changes into operation
!     call TxControl.start();   // for timestamping
      m_state = S_RX_PREPARED;
      signal RadioRx.prepareDone(); // keep owning the SPI
--- 400,421 ----
        m_state = S_RESERVE_RX_SPI;
      }
!     if (call RxControl.start() != SUCCESS){
        m_state = S_RADIO_OFF;
        call Leds.led0On();
        return FAIL; 
+     } else {
+       if (call SpiResource.immediateRequest() == SUCCESS)   // will trigger rxSpiReserved()
+         rxSpiReserved();
+       else
+         call SpiResource.request();
      }
      return SUCCESS; 
    }
  
    void rxSpiReserved()
    {
      call CC2420Config.sync(); // put PIB changes into operation
!     call TxControl.stop();    
!     call TxControl.start();   // for timestamping (SFD interrupt)
      m_state = S_RX_PREPARED;
      signal RadioRx.prepareDone(); // keep owning the SPI
***************
*** 429,434 ****
          return FAIL;
        }
!       if (t0 != NULL && dt)
!         call ReliableWait.waitRx(t0, dt);
        else
          signal ReliableWait.waitRxDone();
--- 434,440 ----
          return FAIL;
        }
!       m_state = S_RX_WAIT;
!       if (t0 != NULL)
!         call ReliableWait.waitRx(t0, dt); // will signal waitRxDone() in time
        else
          signal ReliableWait.waitRxDone();
***************
*** 448,457 ****
    }
  
!   event message_t* CC2420Rx.received(message_t *data, ieee154_reftime_t *timestamp) 
    {
      if (m_state == S_RECEIVING)
!       return signal RadioRx.received(data, timestamp);
      else
!       return data;
    }
  
--- 454,463 ----
    }
  
!   event message_t* CC2420Rx.received(message_t *frame, ieee154_reftime_t *timestamp) 
    {
      if (m_state == S_RECEIVING)
!       return signal RadioRx.received(frame, timestamp);
      else
!       return frame;
    }
  
***************
*** 461,491 ****
    }
  
!   /******************************/
!   /*     Transmit Operations    */
!   /******************************/
  
    async command error_t RadioTx.load(ieee154_txframe_t *frame)
    {
-     bool startRxControl;
      atomic {
        if (m_state != S_RADIO_OFF && m_state != S_TX_LOADED)
          return FAIL;
!       startRxControl = (m_state == S_RADIO_OFF);
!       m_txdata = frame;
        m_state = S_LOAD_TXFIFO;
      }
!     if (!startRxControl)
!       continueTxPrepare();
!     else if (call RxControl.start() != SUCCESS) // will trigger continueTxPrepare()
!       call Leds.led0On();
!     return SUCCESS;
!   }
! 
!   void continueTxPrepare()
!   {
!     if (call SpiResource.immediateRequest() == SUCCESS) 
        txSpiReserved();
      else
        call SpiResource.request(); // will trigger txSpiReserved()
    }
  
--- 467,485 ----
    }
  
! /* ----------------------- Transmit Operations ----------------------- */
  
    async command error_t RadioTx.load(ieee154_txframe_t *frame)
    {
      atomic {
        if (m_state != S_RADIO_OFF && m_state != S_TX_LOADED)
          return FAIL;
!       m_txframe = frame;
        m_state = S_LOAD_TXFIFO;
      }
!     if (call SpiResource.isOwner() || call SpiResource.immediateRequest() == SUCCESS) 
        txSpiReserved();
      else
        call SpiResource.request(); // will trigger txSpiReserved()
+     return SUCCESS;
    }
  
***************
*** 494,498 ****
      call CC2420Config.sync();
      call TxControl.start();
!     if (call CC2420Tx.loadTXFIFO(m_txdata) != SUCCESS)
        call Leds.led0On();
    }
--- 488,492 ----
      call CC2420Config.sync();
      call TxControl.start();
!     if (call CC2420Tx.loadTXFIFO(m_txframe) != SUCCESS)
        call Leds.led0On();
    }
***************
*** 509,586 ****
    {
      if (m_state == S_TX_LOADED)
!      return m_txdata;
      else 
        return NULL;
    }
  
!   async command error_t RadioTx.transmit(ieee154_reftime_t *t0, uint32_t dt, uint8_t numCCA, bool ackRequest)
    {
      atomic {
        if (m_state != S_TX_LOADED)
          return FAIL;
!       m_numCCA = numCCA;
!       m_t0Tx = t0;
!       m_dtTx = dt;
!       if (numCCA){
!         // for CCA we need to be in Rx mode
!         call CC2420Power.rxOn();
!         call ReliableWait.busyWait(20); // turnaround + CCA valid time
!         if (numCCA == 2){
!           // first CCA is done in software (8 symbols after backoff boundary)
!           if (t0 != NULL){
!             call ReliableWait.waitCCA(t0, dt-IEEE154_aUnitBackoffPeriod-12);
!             return SUCCESS;
!           }
          }
        }
!       signal ReliableWait.waitCCADone();
      }
      return SUCCESS;
    }
  
!   async event void ReliableWait.waitCCADone()
    {
!     bool cca = call CC2420Tx.cca();
!     if (m_numCCA == 2 && !cca){
!       // channel is busy
!       ieee154_reftime_t now;
!       call ReferenceTime.getNow(&now, IEEE154_aUnitBackoffPeriod+12);
!       memcpy(&m_txReferenceTime, &now, sizeof(ieee154_reftime_t));
!       m_ackFramePending = FALSE;
!       m_txError = EBUSY;
!       signalTxDone();
!       return;
!     } else {
!       // the second CCA (or first CCA if there's only one) is done in hardware...
!       uint16_t offset = 0;
!       if (m_numCCA)
!         offset = 12;
!       if (m_t0Tx)
!         call ReliableWait.waitTx(m_t0Tx, m_dtTx-offset);
        else
!         signal ReliableWait.waitTxDone();
      }
    }
  
!   async event void ReliableWait.waitTxDone()
    {
!     m_state = S_TX_ACTIVE;
!     call CC2420Tx.send(m_numCCA>0); // go (with or without CCA) !
    }
  
!   async event void CC2420Tx.transmissionStarted( ieee154_txframe_t *data )
    {
!     uint8_t frameType = data->header->mhr[0] & FC1_FRAMETYPE_MASK;
!     uint8_t token = data->headerLen;
!     signal Timestamp.transmissionStarted(frameType, data->handle, data->payload, token);
    }
  
!   async event void CC2420Tx.transmittedSFD(uint32_t time, ieee154_txframe_t *data)
    {
!     uint8_t frameType = data->header->mhr[0] & FC1_FRAMETYPE_MASK;
!     uint8_t token = data->headerLen;
!     signal Timestamp.transmittedSFD(time, frameType, data->handle, data->payload, token);
!     // ATTENTION: here we release the SPI, so we can receive a possible ACK
!     call SpiResource.release();
    }
  
--- 503,728 ----
    {
      if (m_state == S_TX_LOADED)
!      return m_txframe;
      else 
        return NULL;
    }
  
!   async command error_t RadioTx.transmit(ieee154_reftime_t *t0, uint32_t dt)
    {
+     // transmit without CCA
      atomic {
        if (m_state != S_TX_LOADED)
          return FAIL;
!       m_numCCA = 0;
!       m_state = S_TX_WAIT;
!       if (t0 != NULL)
!         call ReliableWait.waitTx(t0, dt); // will signal waitTxDone() in time
!       else
!         signal ReliableWait.waitTxDone();
!     }
!     return SUCCESS;
!   }
! 
!   void checkEnableRxForACK()
!   {
!     // the packet is currently being transmitted, check if we need the receive logic ready
!     bool ackRequest = (m_txframe->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST) ? TRUE : FALSE;
!     if (ackRequest){
!       // ATTENTION: here the SpiResource is released if ACK is expected
!       // (so Rx part of the driver can take over)
!       call SpiResource.release();
!       if (call RxControl.start() != SUCCESS)
!         call Leds.led0On();
!     }
!   }
! 
!   async event void ReliableWait.waitTxDone()
!   {
!     atomic {
!       m_state = S_TX_ACTIVE;
!       if (call CC2420Tx.send(FALSE) == SUCCESS) // transmit without CCA, this must succeed
!         checkEnableRxForACK();
!       else
!         call Leds.led0On();
!     }
!   }
! 
!   async command error_t RadioTx.transmitUnslottedCsmaCa(ieee154_csma_t *csmaParams)
!   {
!     // transmit with single CCA
!     atomic {
!       if (m_state != S_TX_LOADED)
!         return FAIL;
!       m_csmaParams = csmaParams;
!       m_numCCA = 1;
!       randomDelayUnslottedCsmaCa(); 
!     }
!     return SUCCESS;
!   }
! 
!   void randomDelayUnslottedCsmaCa()
!   {
!     // wait random delay (unslotted CSMA-CA)
!     uint16_t dtTx = generateRandomBackoff(m_csmaParams->BE) * 20; 
!     call ReferenceTime.getNow(m_t0Tx, 0);
!     m_state = S_TX_WAIT;
!     call ReliableWait.waitBackoff(m_t0Tx, dtTx); 
!   }
! 
!   void waitBackoffUnslottedCsmaCaDone()
!   {
!     int8_t dummy;
!     atomic {
!       // CC2420 needs to be in an Rx state for STXONCCA strobe
!       // note: the receive logic of the CC2420 driver is not yet started, 
!       // i.e. we will not (yet) receive any packets
!       call CC2420Power.rxOn();
!       m_state = S_TX_ACTIVE;
!       // wait for CC2420 Rx to calibrate + CCA valid time
!       while (call CC2420Power.rssi(&dummy) != SUCCESS)
!         ;
!       // call ReliableWait.busyWait(40);
!       // transmit with single CCA (STXONCCA strobe)
!       if (call CC2420Tx.send(TRUE) == SUCCESS){
!         checkEnableRxForACK();
!       } else {
!         // channel is busy
!         call CC2420Power.rfOff();
!         call CC2420Power.flushRxFifo(); // we might have (accidentally) caught something during CCA
!         m_state = S_TX_LOADED;
!         m_csmaParams->NB += 1;
!         if (m_csmaParams->NB > m_csmaParams->macMaxCsmaBackoffs){
!           // CSMA-CA failure, note: we keep owning the SPI, 
!           // our state is back to S_TX_LOADED, the MAC may try to retransmit
!           signal RadioTx.transmitUnslottedCsmaCaDone(m_txframe, FALSE, m_csmaParams, FAIL);
!         } else {
!           // next iteration of unslotted CSMA-CA
!           m_csmaParams->BE += 1;
!           if (m_csmaParams->BE > m_csmaParams->macMaxBE)
!             m_csmaParams->BE = m_csmaParams->macMaxBE;
!           randomDelayUnslottedCsmaCa();
          }
        }
!     }
!   }
! 
!   async command error_t RadioTx.transmitSlottedCsmaCa(ieee154_reftime_t *slot0Time, uint32_t dtMax, 
!       bool resume, uint16_t remainingBackoff, ieee154_csma_t *csmaParams)
!   {
!     // slotted CSMA-CA requires very exact timing (transmission on
!     // 320 us backoff boundary), even if we have a sufficiently precise and 
!     // accurate clock the CC2420 is not the right radio for
!     // this task because it is accessed over SPI. The code below relies on
!     // platform-specific busy-wait functions that must be adjusted
!     // (through measurements) such that they meet the timing constraints
!     atomic {
!       if (m_state != S_TX_LOADED)
!         return FAIL;
!       m_csmaParams = csmaParams;
!       m_numCCA = 2;
!       m_t0Tx = slot0Time;
!       m_dtMax = dtMax;
!       randomDelaySlottedCsmaCa(resume, remainingBackoff);
      }
      return SUCCESS;
    }
  
!   void randomDelaySlottedCsmaCa(bool resume, uint16_t remainingBackoff)
    {
!     uint16_t dtTx;
!     atomic {
!       dtTx = call TimeCalc.timeElapsed(call ReferenceTime.toLocalTime(m_t0Tx), call LocalTime.get());
!       dtTx += (20 - (dtTx % 20)); // round to backoff boundary
!       if (resume)
!         dtTx += remainingBackoff;
        else
!         dtTx = dtTx + (generateRandomBackoff(m_csmaParams->BE) * 20);
!       dtTx += 40; // two backoff periods for the two CCA, the actual tx is scheduled for = m_t0Tx + dtTx
!       if (dtTx > m_dtMax){
!         uint16_t remaining = dtTx - m_dtMax;
!         if (remaining >= 40)
!           remaining -= 40; // substract the two CCA (they don't count for the backoff)
!         else
!           remaining = 0;
!         signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, NULL, FALSE, remaining, m_csmaParams, ERETRY);
!       } else {
!         m_state = S_TX_WAIT;
!         call ReliableWait.waitBackoff(m_t0Tx, dtTx); 
!       }
      }
    }
  
!   void waitBackoffSlottedCsmaCaDone()
    {
!     bool cca;
!     uint16_t dtTx=0;
!     int8_t dummy;
!     atomic {
!       // CC2420 needs to be in an Rx state for STXONCCA strobe
!       // note: the receive logic of the CC2420 driver is not yet started, 
!       // i.e. we will not (yet) receive any packets
!       call CC2420Power.rxOn();
!       m_state = S_TX_ACTIVE;
!       // wait for CC2420 Rx to calibrate + CCA valid time
!       while (call CC2420Power.rssi(&dummy) != SUCCESS)
!         ;
!       // perform CCA on slot boundary (or rather 8 symbols after)
!       call ReliableWait.busyWaitSlotBoundaryCCA(m_t0Tx, &dtTx); // platform-specific implementation
!       cca = call CC2420Tx.cca();
!       if (cca && dtTx <= m_dtMax){
!         // Tx in following slot (STXONCCA) 
!         call ReliableWait.busyWaitSlotBoundaryTx(m_t0Tx, dtTx+20);  // platform-specific implementation
!         if (call CC2420Tx.send(TRUE) == SUCCESS){
!           checkEnableRxForACK();
!           return;
!         } else
!           cca = FALSE;
!       }
!       // did not transmit the frame
!       call CC2420Power.rfOff();
!       call CC2420Power.flushRxFifo(); // we might have (accidentally) caught something
!       m_state = S_TX_LOADED;
!       if (dtTx > m_dtMax)
!         // frame didn't fit into remaining CAP, this can only
!         // be because we couldn't meet the time-constraints 
!         // (in principle the frame should have fitted)
!         signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, NULL, FALSE, 0, m_csmaParams, ERETRY);
!       else {
!         // CCA failed
!         m_csmaParams->NB += 1;
!         if (m_csmaParams->NB > m_csmaParams->macMaxCsmaBackoffs){
!           // CSMA-CA failure, note: we keep owning the SPI
!           signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, NULL, FALSE, 0, m_csmaParams, FAIL);
!         } else {
!           // next iteration of slotted CSMA-CA
!           m_csmaParams->BE += 1;
!           if (m_csmaParams->BE > m_csmaParams->macMaxBE)
!             m_csmaParams->BE = m_csmaParams->macMaxBE;
!           randomDelaySlottedCsmaCa(FALSE, 0);
!         }
!       }
!     }
    }
  
!   async event void ReliableWait.waitBackoffDone()
    {
!     if (m_numCCA == 1)
!       waitBackoffUnslottedCsmaCaDone();
!     else
!       waitBackoffSlottedCsmaCaDone();
    }
  
!   async event void CC2420Tx.transmissionStarted( ieee154_txframe_t *frame )
    {
!     uint8_t frameType = frame->header->mhr[0] & FC1_FRAMETYPE_MASK;
!     uint8_t token = frame->headerLen;
!     signal Timestamp.transmissionStarted(frameType, frame->handle, frame->payload, token);
!   }
! 
!   async event void CC2420Tx.transmittedSFD(uint32_t time, ieee154_txframe_t *frame)
!   {
!     uint8_t frameType = frame->header->mhr[0] & FC1_FRAMETYPE_MASK;
!     uint8_t token = frame->headerLen;
!     signal Timestamp.transmittedSFD(time, frameType, frame->handle, frame->payload, token);
    }
  
***************
*** 594,606 ****
        bool ackPendingFlag, error_t error)
    {
!     memcpy(&m_txReferenceTime, referenceTime, sizeof(ieee154_reftime_t));
!     m_ackFramePending = ackPendingFlag;
!     m_txError = error;
!     if (error == EBUSY) // CCA failure, i.e. didn't transmit
!       signalTxDone();
!     else 
!       // reset radio
        if (call RxControl.stop() != SUCCESS) // will trigger txDoneRxControlStopped()
          call Leds.led0On();
    }
  
--- 736,751 ----
        bool ackPendingFlag, error_t error)
    {
!     if (!call SpiResource.isOwner()){
!       // this can only happen if an ack was requested and we gave up the SPI
!       bool wasAckRequested = (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST) ? TRUE : FALSE;
!       if (!wasAckRequested)
!         call Leds.led0On(); // internal error!
!       memcpy(&m_txReferenceTime, referenceTime, sizeof(ieee154_reftime_t));
!       m_ackFramePending = ackPendingFlag;
!       m_txError = error;
        if (call RxControl.stop() != SUCCESS) // will trigger txDoneRxControlStopped()
          call Leds.led0On();
+     } else
+       sendDone(referenceTime, ackPendingFlag, error);
    }
  
***************
*** 616,650 ****
    void txDoneSpiReserved() 
    { 
!     // switch radio off
!     call CC2420Power.rfOff(); 
!     call TxControl.stop();
!     call SpiResource.release(); // for RxControl.start to succeed
!     if (m_txError == SUCCESS)
!       signalTxDone();
!     else {
!       call TxControl.start();
!       call RxControl.start(); // will trigger txDoneRxControlStarted()
!     }
    }
  
!   void txDoneRxControlStarted()
    {
!     m_state = S_TX_DONE;
!     call SpiResource.request(); // will trigger signalTxDone()
!   }
! 
!   void signalTxDone() 
!   { 
!     // radio is off, Rx component is started, radio is loaded, we own the SPI
!     if (m_txError == SUCCESS)
        m_state = S_RADIO_OFF;
!     else
        m_state = S_TX_LOADED;
!     signal RadioTx.transmitDone(m_txdata, &m_txReferenceTime, m_ackFramePending, m_txError);
    }
  
!   /*************/
!   /* RxControl */
!   /*************/
  
    async event void RxControl.stopDone(error_t error)
--- 761,801 ----
    void txDoneSpiReserved() 
    { 
!     sendDone(&m_txReferenceTime, m_ackFramePending, m_txError);
    }
  
!   void sendDone(ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error)
    {
!     uint8_t numCCA = m_numCCA;
!     // transmission complete, we're owning the SPI, Rx logic is disabled
!     call CC2420Power.rfOff();
!     call CC2420Power.flushRxFifo();
!     switch (error)
!     {
!        case SUCCESS:
!          m_state = S_RADIO_OFF;
!          break;
!        case ENOACK:
!          m_state = S_TX_LOADED;
!          break;
!        default: 
!          call Leds.led0On(); // internal error!
!          break;
!     }
!     if (error == SUCCESS){
!       call CC2420Tx.unlockChipSpi();
!       call TxControl.stop();
!       call SpiResource.release();
        m_state = S_RADIO_OFF;
!     } else
        m_state = S_TX_LOADED;
!     if (numCCA == 0)
!       signal RadioTx.transmitDone(m_txframe, referenceTime);
!     else if (numCCA == 1)
!       signal RadioTx.transmitUnslottedCsmaCaDone(m_txframe, ackPendingFlag, m_csmaParams, error);
!     else
!       signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, referenceTime, ackPendingFlag, 0, m_csmaParams, error);
    }
  
! /* ----------------------- RxControl ----------------------- */
  
    async event void RxControl.stopDone(error_t error)
***************
*** 660,664 ****
      {
        case S_OFF_PENDING: offStopRxDone(); break;
-       case S_RX_PREPARED: rxStartRxDone(); break;
        case S_TX_ACTIVE: txDoneRxControlStopped(); break;
        case S_STOPPING: stopContinue(); break;            
--- 811,814 ----
***************
*** 668,686 ****
    }
  
!   async event void RxControl.startDone(error_t error)
!   {
!     switch (m_state)
!     {
!       case S_RESERVE_RX_SPI: rxStartRxDone(); break;
!       case S_LOAD_TXFIFO: continueTxPrepare(); break;
!       case S_TX_ACTIVE: txDoneRxControlStarted(); break;
!       default: // huh ?
!            call Leds.led0On(); break;
!     }
!   }
! 
!   /***********************/
!   /* SPI Bus Arbitration */
!   /***********************/
  
    event void SpiResource.granted() 
--- 818,822 ----
    }
  
! /* ----------------------- SPI Bus Arbitration ----------------------- */
  
    event void SpiResource.granted() 
***************
*** 694,698 ****
        case S_TX_ACTIVE: txDoneSpiReserved(); break;
        case S_STOPPING: stopReserved(); break;
-       case S_TX_DONE: signalTxDone(); break;
        case S_OFF_PENDING: offSpiReserved(); break;
        default: // huh ?
--- 830,833 ----

Index: CC2420TransmitP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420TransmitP.nc,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** CC2420TransmitP.nc	18 Jun 2008 15:39:32 -0000	1.2
--- CC2420TransmitP.nc	25 Nov 2008 09:35:08 -0000	1.3
***************
*** 35,38 ****
--- 35,46 ----
   * @author Jung Il Choi Initial SACK implementation
   * @author Jan Hauer <hauer at 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$
   */
***************
*** 46,57 ****
    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;
--- 54,58 ----
***************
*** 60,64 ****
    uses interface GeneralIO as SFD;
  
- /*  uses interface Resource as SpiResource;*/
    uses interface ChipSpiResource;
    uses interface CC2420Fifo as TXFIFO;
--- 61,64 ----
***************
*** 72,76 ****
    uses interface CC2420Strobe as SRFOFF;
    uses interface CC2420Strobe as SFLUSHRX;
!   uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
    uses interface CC2420Register as MDMCTRL1;
    uses interface CaptureTime;
--- 72,76 ----
    uses interface CC2420Strobe as SRFOFF;
    uses interface CC2420Strobe as SFLUSHRX;
!   uses interface CC2420Strobe as SACKPEND;
    uses interface CC2420Register as MDMCTRL1;
    uses interface CaptureTime;
***************
*** 87,109 ****
      S_STARTED,
      S_LOAD,
!     S_SAMPLE_CCA,
!     S_BEGIN_TRANSMIT,
      S_SFD,
      S_EFD,
      S_ACK_WAIT,
-     S_CANCEL,
    } cc2420_transmit_state_t;
  
!   // This specifies how many jiffies 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
    };
    
! /*  norace message_t *m_msg;*/
!   norace ieee154_txframe_t *m_data;
!   norace uint8_t m_txFrameLen;
    ieee154_reftime_t m_timestamp;
    
--- 87,105 ----
      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_reftime_t m_timestamp;
    
***************
*** 120,126 ****
    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;
--- 116,119 ----
***************
*** 128,144 ****
    /** The congestion backoff period */
    norace uint16_t myCongestionBackoff;
    
  
    /***************** 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 *****************/
--- 121,129 ----
    /** The congestion backoff period */
    norace uint16_t myCongestionBackoff;
+   norace uint32_t alarmStartTime;
    
  
    /***************** Prototypes ****************/
    void signalDone( bool ackFramePending, error_t err );
    
    /***************** Init Commands *****************/
***************
*** 167,171 ****
        call BackoffAlarm.stop();
        call CaptureSFD.disable();
- /*      call SpiResource.release();  // REMOVE*/
        call CSN.set();
      }
--- 152,155 ----
***************
*** 174,245 ****
  
  
!   /**************** 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)
!   {
!     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();
      return SUCCESS;
!   }
!   
!   async command void CC2420Tx.lockChipSpi()
    {
!     abortSpiRelease = TRUE;
    }
!   async command void CC2420Tx.unlockChipSpi()
    {
!     abortSpiRelease = FALSE;
!   }
  
!   /***************** Indicator Commands ****************/
! /*  command bool EnergyIndicator.isReceiving() {*/
! /*    return !(call CCA.get());*/
! /*  }*/
! /*  */
! /*  command bool ByteIndicator.isReceiving() {*/
! /*    bool high;*/
! /*    atomic high = sfdHigh;*/
! /*    return high;*/
! /*  }*/
!   
  
!   /***************** 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) {*/
! /*  }*/
!   
!   
    
    /**
--- 158,239 ----
  
  
!   /**************** 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;
!         call BackoffAlarm.start(CC2420_ABORT_PERIOD); 
!         return SUCCESS;
!       }
!     }
!   }
    
    /**
***************
*** 257,263 ****
     */
    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 ) {
--- 251,255 ----
***************
*** 266,287 ****
          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();
          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;
--- 258,266 ----
          m_state = S_EFD;
          sfdHigh = TRUE;
          call CaptureSFD.captureFallingEdge();
!         // timestamp denotes time of first bit (chip) of PPDU on the channel
!         call CaptureTime.convert(time, &m_timestamp, -10); // offset: -10 for 5 bytes (preamble+SFD)
!         m_frame->metadata->timestamp = call ReferenceTime.toLocalTime(&m_timestamp);
          call BackoffAlarm.stop();
          if ( call SFD.get() ) {
            break;
***************
*** 292,300 ****
          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 ) ) {
            m_state = S_ACK_WAIT;
!           call BackoffAlarm.start( 200 ); // we need to have *completely* received the ACK
          } else {
            signalDone(FALSE, SUCCESS);
--- 271,283 ----
          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);
***************
*** 310,315 ****
            sfdHigh = TRUE;
            call CaptureSFD.captureFallingEdge();
! /*          signal TimeStamp.receivedSFD( time );*/
!           call CaptureTime.convert(time, &m_timestamp, -8);
            call CC2420Receive.sfd( &m_timestamp );
            m_receiving = TRUE;
--- 293,297 ----
            sfdHigh = TRUE;
            call CaptureSFD.captureFallingEdge();
!           call CaptureTime.convert(time, &m_timestamp, -10);
            call CC2420Receive.sfd( &m_timestamp );
            m_receiving = TRUE;
***************
*** 319,322 ****
--- 301,305 ----
              return;
            }
+           // if we move on, then the timestamp will be invalid!
          }
          
***************
*** 324,329 ****
          call CaptureSFD.captureRisingEdge();
          m_receiving = FALSE;
! /*        if ( time - m_prev_time < 10 ) {*/
! #ifdef PIERCEBOARD_ENABLED
          if ( time - m_prev_time < 10*30 ) {
  #else
--- 307,311 ----
          call CaptureSFD.captureRisingEdge();
          m_receiving = FALSE;
! #ifdef TKN154_PIERCEBOARD
          if ( time - m_prev_time < 10*30 ) {
  #else
***************
*** 337,342 ****
      }
    }
  
-   /***************** ChipSpiResource Events ****************/
    async event void ChipSpiResource.releasing() {
      if(abortSpiRelease) {
--- 319,347 ----
      }
    }
+    
+   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) {
***************
*** 352,380 ****
     */
    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
            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);
          }
--- 357,365 ----
     */
    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);
          }
***************
*** 382,742 ****
      }
    }
- 
-   /***************** 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();
  
!       // 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();
  
-       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);
        }
-       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 ) {
      atomic m_state = S_STARTED;
!     signal CC2420Tx.sendDone( m_data, &m_timestamp, 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 ) {*/
- /*  }*/
  
  }
  
--- 367,409 ----
      }
    }
    
    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 ) {
      atomic m_state = S_STARTED;
!     signal CC2420Tx.sendDone( m_frame, &m_timestamp, ackFramePending, err );
      call ChipSpiResource.attemptRelease();
    }
  
+   async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, 
+       error_t error ) {
+   }
  }
  

Index: CC2420Tx.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/CC2420Tx.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** CC2420Tx.nc	16 Jun 2008 18:02:40 -0000	1.1
--- CC2420Tx.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 41,45 ****
    async event void loadTXFIFODone(ieee154_txframe_t *data, error_t error );
  
!   async command void send(bool cca);
    async event void sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime, 
        bool ackPendingFlag, error_t error);
--- 41,45 ----
    async event void loadTXFIFODone(ieee154_txframe_t *data, error_t error );
  
!   async command error_t send(bool cca);
    async event void sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime, 
        bool ackPendingFlag, error_t error);

Index: ReliableWait.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154/ReliableWait.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** ReliableWait.nc	16 Jun 2008 18:02:40 -0000	1.1
--- ReliableWait.nc	25 Nov 2008 09:35:08 -0000	1.2
***************
*** 33,49 ****
  interface ReliableWait
  {
- 
    async command void busyWait(uint16_t dt);
- 
-   /*
-    * The following command/event pairs are platform-specific
-    * busy-waits. 
-    */
-   
    async command void waitRx(ieee154_reftime_t *t0, uint16_t dt);
    async event void waitRxDone();
-   async command void waitCCA(ieee154_reftime_t *t0, uint16_t dt);
-   async event void waitCCADone();
    async command void waitTx(ieee154_reftime_t *t0, uint16_t dt);
    async event void waitTxDone();
  }
--- 33,45 ----
  interface ReliableWait
  {
    async command void busyWait(uint16_t dt);
    async command void waitRx(ieee154_reftime_t *t0, uint16_t dt);
    async event void waitRxDone();
    async command void waitTx(ieee154_reftime_t *t0, uint16_t dt);
    async event void waitTxDone();
+   async command void waitBackoff(ieee154_reftime_t *t0, uint16_t dt);
+   async event void waitBackoffDone();
+ 
+   async command void busyWaitSlotBoundaryCCA(ieee154_reftime_t *t0, uint16_t *dt);
+   async command void busyWaitSlotBoundaryTx(ieee154_reftime_t *t0, uint16_t dt);
  }



More information about the Tinyos-2-commits mailing list