]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Initial version of a CC2420 driver for TKN15.4 (see tinyos-2.x/tos/lib/mac/tkn154...
authorjanhauer <janhauer>
Mon, 16 Jun 2008 18:02:40 +0000 (18:02 +0000)
committerjanhauer <janhauer>
Mon, 16 Jun 2008 18:02:40 +0000 (18:02 +0000)
18 files changed:
tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420Config.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420ControlP.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420Power.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420Receive.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420ReceiveC.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420ReceiveP.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420Rx.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420TKN154C.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420TKN154P.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420TransmitP.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CC2420Tx.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/CaptureTime.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/ReferenceTime.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/ReliableWait.nc [new file with mode: 0644]
tos/chips/cc2420_tkn154/TKN154_PHY.h [new file with mode: 0644]
tos/chips/cc2420_tkn154/Timestamp.nc [new file with mode: 0644]

diff --git a/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc b/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc
new file mode 100644 (file)
index 0000000..7688a55
--- /dev/null
@@ -0,0 +1,133 @@
+/* 
+ * Copyright (c) 2008, Technische Universitaet Berlin 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
+ * Technische Universitaet Berlin 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 COPYRIGHT OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$ $Date$ 
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+/*
+ * "Copyright (c) 2005 Washington University in St. Louis.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS BE LIABLE TO ANY PARTY 
+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING 
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF WASHINGTON 
+ * UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * WASHINGTON UNIVERSITY IN ST. LOUIS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS."
+ */
+/*
+ * "Copyright (c) 2000-2005 The Regents of the University  of California.  
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ */
+
+/**
+ * An async version of the SplitControl interface.
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ */
+
+interface CC2420AsyncSplitControl
+{
+  /**
+   * 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
+  *                        turned off, FAIL otherwise
+   */
+  async event void stopDone(error_t error);
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420Config.nc b/tos/chips/cc2420_tkn154/CC2420Config.nc
new file mode 100644 (file)
index 0000000..c1e07de
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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
+ */
+
+/**
+ * An HAL abstraction of the ChipCon CC2420 radio. This abstraction
+ * deals specifically with radio configurations. All get() and set()
+ * commands are single-phase. After setting some values, a call to
+ * sync() is required for the changes to propagate to the cc2420
+ * hardware chip. This interface allows setting multiple parameters
+ * before calling sync().
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de> (added some commands)
+ * @version $Revision$ $Date$
+ */
+
+interface CC2420Config {
+
+  /**
+   * Sync configuration changes with the radio hardware. This only
+   * applies to set commands below.
+   *
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */
+  async command error_t sync();
+
+  /**
+   * Whether changes have been made that should be sync-ed.
+   *
+   * @return TRUE if changes have been made, FALSE otherwise.
+   */
+  async command bool needsSync();
+
+  /**
+   * Change the channel of the radio, between 11 and 26
+   */
+  command uint8_t getChannel();
+  command void setChannel( uint8_t channel );
+
+  /**
+   * Change the short address of the radio.
+   */
+  async command uint16_t getShortAddr();
+  command void setShortAddr( uint16_t address );
+
+  /**
+   * Change the PAN address of the radio.
+   */
+  async command uint16_t getPanAddr();
+  command void setPanAddr( uint16_t address );
+
+  /**
+   * Change the PAN address of the radio.
+   */
+  async command bool getPanCoordinator();
+  command void setPanCoordinator( bool pcoord );  
+
+  /**
+   * Change to promiscuous mode.
+   */
+  command void setPromiscuousMode(bool on);
+  async command bool isPromiscuousModeEnabled();
+
+  /**
+   * Change the CCA mode.
+   */
+  async command uint8_t getCCAMode();
+  command void setCCAMode(uint8_t mode);
+
+  /**
+   * Change the transmission power.
+   */
+  async command uint8_t getTxPower();
+  command void setTxPower(uint8_t txPower);
+  
+}
diff --git a/tos/chips/cc2420_tkn154/CC2420ControlP.nc b/tos/chips/cc2420_tkn154/CC2420ControlP.nc
new file mode 100644 (file)
index 0000000..64e4adf
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author David Moss
+ * @author Urs Hunkeler (ReadRssi implementation)
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de> (support for promiscuous mode)
+ * @version $Revision$ $Date$
+ */
+
+#include "Timer.h"
+#include "AM.h"
+#include "TKN154_PIB.h"
+
+module CC2420ControlP {
+
+  provides interface Init;
+  provides interface Resource;
+  provides interface CC2420Config;
+  provides interface CC2420Power;
+
+  uses interface Alarm<T62500hz,uint32_t> as StartupAlarm;
+  uses interface GeneralIO as CSN;
+  uses interface GeneralIO as RSTN;
+  uses interface GeneralIO as VREN;
+  uses interface GpioInterrupt as InterruptCCA;
+
+  uses interface CC2420Ram as IEEEADR;
+  uses interface CC2420Register as FSCTRL;
+  uses interface CC2420Register as IOCFG0;
+  uses interface CC2420Register as IOCFG1;
+  uses interface CC2420Register as MDMCTRL0;
+  uses interface CC2420Register as MDMCTRL1;
+  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;
+  
+  uses interface Resource as SpiResource;
+
+  uses interface Leds;
+  uses interface FrameUtility;
+}
+
+implementation {
+
+  typedef enum {
+    S_VREG_STOPPED,
+    S_VREG_STARTING,
+    S_VREG_STARTED,
+    S_XOSC_STARTING,
+    S_XOSC_STARTED,
+  } cc2420_control_state_t;
+
+  uint8_t m_channel;
+  uint16_t m_pan;
+  uint16_t m_short_addr;
+  bool autoAckEnabled;
+  bool hwAutoAckDefault;
+  bool addressRecognition;
+  bool acceptReservedFrames;
+  bool m_isPanCoord;
+  uint8_t m_CCAMode;
+  uint8_t m_txPower;
+
+  bool m_needsSync;
+
+  norace cc2420_control_state_t m_state = S_VREG_STOPPED;
+  
+  /***************** Prototypes ****************/
+
+  void writeFsctrl();
+  void writeMdmctrl0();
+  void writeId();
+  void writeTxPower();
+
+  /***************** Init Commands ****************/
+  command error_t Init.init() {
+    call CSN.makeOutput();
+    call RSTN.makeOutput();
+    call VREN.makeOutput();
+    autoAckEnabled = TRUE;
+    hwAutoAckDefault = TRUE;
+    addressRecognition = TRUE;
+    acceptReservedFrames = FALSE;
+    m_needsSync = FALSE;
+    return SUCCESS;
+  }
+
+  /***************** Resource Commands ****************/
+  async command error_t Resource.immediateRequest() {
+    error_t error = call SpiResource.immediateRequest();
+    if ( error == SUCCESS ) {
+/*      call CSN.clr();*/
+    }
+    return error;
+  }
+
+  async command error_t Resource.request() {
+    return call SpiResource.request();
+  }
+
+  async command uint8_t Resource.isOwner() {
+    return call SpiResource.isOwner();
+  }
+
+  async command error_t Resource.release() {
+    atomic {
+/*      call CSN.set();*/
+      return call SpiResource.release();
+    }
+  }
+
+  void switchToUnbufferedMode()
+  {
+    uint16_t mdmctrol1;
+    call CSN.set();
+    call CSN.clr();
+    call MDMCTRL1.read(&mdmctrol1);
+    call CSN.set();
+    mdmctrol1 &= ~0x0003;
+    mdmctrol1 |= 0x0000;
+    call CSN.clr();
+    call MDMCTRL1.write(mdmctrol1);
+    call CSN.set();
+  }
+
+  void switchToBufferedMode()
+  {
+    uint16_t mdmctrol1;
+    call CSN.set();
+    call CSN.clr();
+    call MDMCTRL1.read(&mdmctrol1);
+    mdmctrol1 &= ~0x03;
+    call MDMCTRL1.write(mdmctrol1);
+    call CSN.set();
+  }
+
+  /***************** CC2420Power Commands ****************/
+  async command error_t CC2420Power.startVReg() {
+    atomic {
+      if ( m_state != S_VREG_STOPPED ) {
+        return FAIL;
+      }
+      m_state = S_VREG_STARTING;
+    }
+    call VREN.set();
+    call StartupAlarm.start( CC2420_TIME_VREN * 2 ); // JH: a 15.4 symbol is about two 32khz ticks
+    return SUCCESS;
+  }
+
+  async command error_t CC2420Power.stopVReg() {
+    m_state = S_VREG_STOPPED;
+    call RSTN.clr();
+    call VREN.clr();
+    call RSTN.set();
+    return SUCCESS;
+  }
+
+  async command error_t CC2420Power.startOscillator() {
+    atomic {
+      if ( m_state != S_VREG_STARTED ) {
+        return FAIL;
+      }
+        
+      m_state = S_XOSC_STARTING;
+      call CSN.set();
+      call CSN.clr();
+      call IOCFG1.write( CC2420_SFDMUX_XOSC16M_STABLE << 
+                         CC2420_IOCFG1_CCAMUX );
+                         
+      call InterruptCCA.enableRisingEdge();
+      call SXOSCON.strobe();
+      
+      call IOCFG0.write( ( 1 << CC2420_IOCFG0_FIFOP_POLARITY ) |
+          ( 127 << CC2420_IOCFG0_FIFOP_THR ) );
+                         
+      writeFsctrl();
+      writeMdmctrl0();
+  
+      call RXCTRL1.write( ( 1 << CC2420_RXCTRL1_RXBPF_LOCUR ) |
+          ( 1 << CC2420_RXCTRL1_LOW_LOWGAIN ) |
+          ( 1 << CC2420_RXCTRL1_HIGH_HGM ) |
+          ( 1 << CC2420_RXCTRL1_LNA_CAP_ARRAY ) |
+          ( 1 << CC2420_RXCTRL1_RXMIX_TAIL ) |
+          ( 1 << CC2420_RXCTRL1_RXMIX_VCM ) |
+          ( 2 << CC2420_RXCTRL1_RXMIX_CURRENT ) );
+      call CSN.set();
+    }
+    return SUCCESS;
+  }
+
+
+  async command error_t CC2420Power.stopOscillator() {
+    atomic {
+      if ( m_state != S_XOSC_STARTED ) {
+        return FAIL;
+      }
+      m_state = S_VREG_STARTED;
+      call CSN.set();
+      call CSN.clr();
+      call SXOSCOFF.strobe();
+      call CSN.set();
+    }
+    return SUCCESS;
+  }
+
+  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();
+    }
+    return SUCCESS;
+  }
+
+  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();
+    }
+    return SUCCESS;
+  }
+
+  
+  /***************** CC2420Config Commands ****************/
+  command uint8_t CC2420Config.getChannel() {
+    atomic return m_channel;
+  }
+
+  command void CC2420Config.setChannel( uint8_t channel ) {
+    atomic {
+      m_needsSync = TRUE;
+      m_channel = channel;
+    }
+  }
+
+  async command uint16_t CC2420Config.getShortAddr() {
+    atomic return m_short_addr;
+  }
+
+  command void CC2420Config.setShortAddr( uint16_t addr ) {
+    atomic {
+      m_needsSync = TRUE;
+      m_short_addr = addr;
+    }
+  }
+
+  async command uint16_t CC2420Config.getPanAddr() {
+    atomic return m_pan;
+  }
+
+  command void CC2420Config.setPanAddr( uint16_t pan ) {
+    atomic {
+      m_needsSync = TRUE;
+      m_pan = pan;
+    }
+  }
+
+  async command bool CC2420Config.getPanCoordinator() {
+    atomic return m_isPanCoord;
+  }
+
+  command void CC2420Config.setPanCoordinator( bool pCoord ) {
+    atomic {
+      m_needsSync = TRUE;
+      m_isPanCoord = pCoord;
+    }
+  }
+
+  command void CC2420Config.setPromiscuousMode(bool on)
+  {
+    atomic {
+      m_needsSync = TRUE;
+      if (on){
+        addressRecognition = FALSE;
+        acceptReservedFrames = TRUE;
+        autoAckEnabled = FALSE;
+      } else {
+        addressRecognition = TRUE;
+        acceptReservedFrames = FALSE;
+        autoAckEnabled = TRUE;
+      }
+    }
+  }
+
+  async command bool CC2420Config.isPromiscuousModeEnabled()
+  {
+    return acceptReservedFrames;
+  }
+
+  async command uint8_t CC2420Config.getCCAMode()
+  {
+    atomic return m_CCAMode;
+  }
+
+  command void CC2420Config.setCCAMode(uint8_t mode)
+  {
+    atomic {
+      m_needsSync = TRUE;
+      m_CCAMode = mode;
+    }
+  }
+
+  async command uint8_t CC2420Config.getTxPower()
+  {
+    atomic return m_txPower;
+  }
+
+  command void CC2420Config.setTxPower(uint8_t txPower)
+  {
+    atomic {
+      m_needsSync = TRUE;
+      m_txPower = txPower;
+    }
+  }
+
+  async command bool CC2420Config.needsSync(){
+    atomic return m_needsSync;
+  }
+  /**
+   * Sync must be called to commit software parameters configured on
+   * 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();
+        call CSN.clr();
+        call SRFOFF.strobe();
+        call CSN.set();
+        call CSN.clr();
+        writeFsctrl();
+        writeMdmctrl0();
+        writeTxPower();
+        call CSN.set();
+        call CSN.clr();
+        writeId();
+        call CSN.set();
+        m_needsSync = FALSE;
+      }
+    }
+    return SUCCESS;
+  }
+
+  /***************** ReadRssi Commands ****************/
+  
+  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();
+      call RSTN.set();
+      signal CC2420Power.startVRegDone();
+    }
+  }
+
+  /***************** InterruptCCA Events ****************/
+  async event void InterruptCCA.fired() {
+    m_state = S_XOSC_STARTED;
+    call InterruptCCA.disable();
+    call CSN.set();
+    call CSN.clr();
+    call IOCFG1.write( 0 );
+    writeId();
+    call CSN.set();
+    signal CC2420Power.startOscillatorDone();
+  }
+  
+  /***************** Functions ****************/
+  /**
+   * Write teh FSCTRL register
+   */
+  void writeFsctrl() {
+    uint8_t channel;
+    
+    atomic {
+      channel = m_channel;
+    }
+    
+    call FSCTRL.write( ( 1 << CC2420_FSCTRL_LOCK_THR ) |
+          ( ( (channel - 11)*5+357 ) << CC2420_FSCTRL_FREQ ) );
+  }
+
+  /**
+   * Write the MDMCTRL0 register
+   */
+  void writeMdmctrl0() {
+    atomic {
+      uint8_t _acceptReservedFrames = (acceptReservedFrames ? 1: 0);
+      uint8_t _panCoord = (m_isPanCoord ? 1: 0);
+      uint8_t _addressRecognition = (addressRecognition ? 1: 0);
+      uint8_t _autoAck = ((autoAckEnabled && hwAutoAckDefault) ? 1 : 0);
+      call MDMCTRL0.write( ( _acceptReservedFrames << CC2420_MDMCTRL0_RESERVED_FRAME_MODE ) |
+          ( _panCoord << CC2420_MDMCTRL0_PAN_COORDINATOR ) | 
+          ( _addressRecognition << CC2420_MDMCTRL0_ADR_DECODE ) |
+          ( 2 << CC2420_MDMCTRL0_CCA_HYST ) |
+          ( m_CCAMode << CC2420_MDMCTRL0_CCA_MOD ) |
+          ( 1 << CC2420_MDMCTRL0_AUTOCRC ) |
+          ( _autoAck << CC2420_MDMCTRL0_AUTOACK ) |
+          ( 2 << CC2420_MDMCTRL0_PREAMBLE_LENGTH ) );
+    }
+    // Jon Green:
+    // MDMCTRL1.CORR_THR is defaulted to 20 instead of 0 like the datasheet says
+    // If we add in changes to MDMCTRL1, be sure to include this fix.
+  }
+  
+  /**
+   * Write the IEEEADR register
+   */
+  void writeId() {
+    uint16_t bcnAccept = 0;
+    nxle_uint16_t id[ 6 ];
+
+    atomic {
+      call FrameUtility.copyLocalExtendedAddressLE((uint8_t*) &id);
+      id[ 4 ] = m_pan;
+      id[ 5 ] = m_short_addr;
+    }
+    if (m_pan == 0xFFFF)
+      bcnAccept = 1;
+    
+    
+    call IOCFG0.write( (bcnAccept << CC2420_IOCFG0_BCN_ACCEPT) |
+        ( 1 << CC2420_IOCFG0_FIFOP_POLARITY ) |
+          ( 127 << CC2420_IOCFG0_FIFOP_THR ) );
+    // ext.adr, PANID and short adr are located at consecutive addresses in RAM
+    call IEEEADR.write(0, (uint8_t*)&id, sizeof(id));
+  }
+
+  void writeTxPower(){
+    call TXCTRL.write( 
+        ( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) |
+        ( 3 << CC2420_TXCTRL_PA_CURRENT ) |
+        ( 1 << CC2420_TXCTRL_RESERVED ) |
+      ( (m_txPower & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) );
+  }
+}
diff --git a/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc b/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc
new file mode 100644 (file)
index 0000000..97637d8
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2008, Technische Universitaet Berlin
+ * 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 Technische Universitaet Berlin 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 COPYRIGHT 
+ * OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+/**
+ * This configuration combines CC2420ControlC and CC2420TransmitC
+ * and uses only one instance of CC2420SpiC.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author Jan-Hinrich Hauer
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+
+configuration CC2420ControlTransmitC {
+
+  provides {
+    // CC2420ControlC
+    interface Resource;
+    interface CC2420Config;
+    interface CC2420Power;
+
+    // CC2420TransmitC
+    interface AsyncStdControl as TxControl;
+    interface CC2420Tx;
+  } uses {
+    // CC2420ControlC
+    interface Alarm<T62500hz,uint32_t> as StartupAlarm;
+    interface FrameUtility;
+
+    // CC2420TransmitC
+    interface Alarm<T62500hz,uint32_t> as AckAlarm;
+    interface CaptureTime;
+    interface ReferenceTime;
+    interface Leds;
+  }
+}
+
+implementation {
+  
+  // CC2420ControlC
+  components CC2420ControlP;
+  Resource = CC2420ControlP;
+  CC2420Config = CC2420ControlP;
+  CC2420Power = CC2420ControlP;
+  FrameUtility = CC2420ControlP;
+  CC2420ControlP.Leds = Leds;
+
+  components MainC;
+  MainC.SoftwareInit -> CC2420ControlP;
+  CC2420ControlP.StartupAlarm = StartupAlarm;
+
+  components HplCC2420PinsC as Pins;
+  CC2420ControlP.CSN -> Pins.CSN;
+  CC2420ControlP.RSTN -> Pins.RSTN;
+  CC2420ControlP.VREN -> Pins.VREN;
+
+  components HplCC2420InterruptsC as Interrupts;
+  CC2420ControlP.InterruptCCA -> Interrupts.InterruptCCA;
+
+  components new CC2420SpiC() as Spi;
+  CC2420ControlP.SpiResource -> Spi;
+  CC2420ControlP.SRXON -> Spi.SRXON;
+  CC2420ControlP.SACKPEND -> Spi.SACKPEND;
+  CC2420ControlP.SRFOFF -> Spi.SRFOFF;
+  CC2420ControlP.SXOSCON -> Spi.SXOSCON;
+  CC2420ControlP.SXOSCOFF -> Spi.SXOSCOFF;
+  CC2420ControlP.FSCTRL -> Spi.FSCTRL;
+  CC2420ControlP.IOCFG0 -> Spi.IOCFG0;
+  CC2420ControlP.IOCFG1 -> Spi.IOCFG1;
+  CC2420ControlP.MDMCTRL0 -> Spi.MDMCTRL0;
+  CC2420ControlP.MDMCTRL1 -> Spi.MDMCTRL1;
+/*  CC2420ControlP.PANID -> Spi.PANID;*/
+  CC2420ControlP.TXCTRL      -> Spi.TXCTRL;
+  CC2420ControlP.IEEEADR -> Spi.IEEEADR;
+  CC2420ControlP.RXCTRL1 -> Spi.RXCTRL1;
+  CC2420ControlP.RSSI  -> Spi.RSSI;
+
+  // CC2420TransmitC
+  components CC2420TransmitP;
+  TxControl = CC2420TransmitP;
+  CC2420Tx = CC2420TransmitP;
+  AckAlarm = CC2420TransmitP;
+  CaptureTime = CC2420TransmitP;
+  ReferenceTime = CC2420TransmitP;
+  CC2420TransmitP.Leds = Leds;
+
+  MainC.SoftwareInit -> CC2420TransmitP;
+  CC2420TransmitP.CCA -> Pins.CCA;
+  CC2420TransmitP.CSN -> Pins.CSN;
+  CC2420TransmitP.SFD -> Pins.SFD;
+  CC2420TransmitP.CaptureSFD -> Interrupts.CaptureSFD;
+
+  CC2420TransmitP.ChipSpiResource -> Spi;
+  CC2420TransmitP.SNOP        -> Spi.SNOP;
+  CC2420TransmitP.STXON       -> Spi.STXON;
+  CC2420TransmitP.STXONCCA    -> Spi.STXONCCA;
+  CC2420TransmitP.SFLUSHTX    -> Spi.SFLUSHTX;
+  CC2420TransmitP.TXCTRL      -> Spi.TXCTRL;
+  CC2420TransmitP.TXFIFO      -> Spi.TXFIFO;
+  CC2420TransmitP.TXFIFO_RAM  -> Spi.TXFIFO_RAM;
+  CC2420TransmitP.MDMCTRL1    -> Spi.MDMCTRL1;
+  CC2420TransmitP.SRXON -> Spi.SRXON;
+  CC2420TransmitP.SRFOFF -> Spi.SRFOFF;
+  CC2420TransmitP.SFLUSHRX-> Spi.SFLUSHRX;
+  CC2420TransmitP.SACKPEND -> Spi.SACKPEND;
+  
+  components CC2420ReceiveC;
+  CC2420TransmitP.CC2420Receive -> CC2420ReceiveC;
+  
+  components CC2420PacketC;
+  CC2420TransmitP.CC2420Packet -> CC2420PacketC;
+  CC2420TransmitP.CC2420PacketBody -> CC2420PacketC;
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420Power.nc b/tos/chips/cc2420_tkn154/CC2420Power.nc
new file mode 100644 (file)
index 0000000..a213f31
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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
+ */
+
+/**
+ * An HAL abstraction of the ChipCon CC2420 radio. This abstraction
+ * deals specifically with radio power operations (e.g. voltage
+ * regulator, oscillator, etc). However, it does not include
+ * transmission power, see the CC2420Config interface.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+interface CC2420Power {
+
+  /**
+   * Start the voltage regulator on the CC2420. On SUCCESS,
+   * <code>startVReg()</code> will be signalled when the voltage
+   * regulator is fully on.
+   *
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */
+  async command error_t startVReg();
+
+  /**
+   * Signals that the voltage regulator has been started.
+   */
+  async event void startVRegDone();
+  
+  /**
+   * Stop the voltage regulator immediately.
+   *
+   * @return SUCCESS always
+   */
+  async command error_t stopVReg();
+
+  /**
+   * Start the oscillator. On SUCCESS, <code>startOscillator</code>
+   * will be signalled when the oscillator has been started.
+   *
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */
+  async command error_t startOscillator();
+
+  /**
+   * Signals that the oscillator has been started.
+   */
+  async event void startOscillatorDone();
+
+  /**
+   * Stop the oscillator.
+   *
+   * @return SUCCESS if the oscillator was stopped, FAIL otherwise.
+   */
+  async command error_t stopOscillator();
+
+  /**
+   * Enable RX.
+   *
+   * @return SUCCESS if receive mode has been enabled, FAIL otherwise.
+   */
+  async command error_t rxOn();
+
+  /**
+   * Disable RX.
+   *
+   * @return SUCCESS if receive mode has been disabled, FAIL otherwise.
+   */
+  async command error_t rfOff();
+
+  /**
+   * Read RSSI from the radio. 
+   * @return SUCCESS if RSSI was read successfulyy, FAIL otherwise.
+   */
+  async command error_t rssi(int8_t *rssi);
+}
diff --git a/tos/chips/cc2420_tkn154/CC2420Receive.nc b/tos/chips/cc2420_tkn154/CC2420Receive.nc
new file mode 100644 (file)
index 0000000..1ba224e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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
+ */
+
+/**
+ * Low-level abstraction of the receive path implementation for the
+ * ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+interface CC2420Receive {
+
+  /**
+   * Notification that an SFD capture has occured.
+   *
+   * @param time at which the capture happened.
+   */
+  async command void sfd( ieee154_reftime_t *time );
+
+  /**
+   * Notification that the packet has been dropped by the radio
+   * (e.g. due to address rejection).
+   */
+  async command void sfd_dropped();
+
+  /**
+   * Signals that a message has been received.
+   *
+   * @param type of the message received.
+   * @param message pointer to message received.
+   */
+  async event void receive( uint8_t type, message_t* message );
+
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420ReceiveC.nc b/tos/chips/cc2420_tkn154/CC2420ReceiveC.nc
new file mode 100644 (file)
index 0000000..f838182
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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 the receive path for the ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+configuration CC2420ReceiveC {
+
+  provides interface CC2420AsyncSplitControl;
+  provides interface CC2420Receive; // to CC2420TransmitP for ACK
+  provides interface CC2420Rx;      // to the driver
+  uses interface ReferenceTime;
+  uses interface Leds;
+  uses interface FrameUtility;
+  uses interface CC2420Config;
+}
+
+implementation {
+  components MainC;
+  components CC2420ReceiveP;
+  components new CC2420SpiC() as Spi;
+  
+  components HplCC2420PinsC as Pins;
+  components HplCC2420InterruptsC as InterruptsC;
+
+  CC2420ReceiveP.Leds = Leds;
+  CC2420AsyncSplitControl = CC2420ReceiveP;
+  CC2420Receive = CC2420ReceiveP;
+  CC2420Rx = CC2420ReceiveP;
+  ReferenceTime = CC2420ReceiveP;
+  FrameUtility = CC2420ReceiveP;
+  CC2420Config = CC2420ReceiveP;
+
+  MainC.SoftwareInit -> CC2420ReceiveP;
+  
+  CC2420ReceiveP.CSN -> Pins.CSN;
+  CC2420ReceiveP.FIFO -> Pins.FIFO;
+  CC2420ReceiveP.FIFOP -> Pins.FIFOP;
+  CC2420ReceiveP.InterruptFIFOP -> InterruptsC.InterruptFIFOP;
+  CC2420ReceiveP.SpiResource -> Spi;
+  CC2420ReceiveP.RXFIFO -> Spi.RXFIFO;
+  CC2420ReceiveP.SFLUSHRX -> Spi.SFLUSHRX;
+  CC2420ReceiveP.SACK -> Spi.SACK;
+  CC2420ReceiveP.SACKPEND -> Spi.SACKPEND;
+  CC2420ReceiveP.SRXON -> Spi.SRXON;
+  CC2420ReceiveP.MDMCTRL1 -> Spi.MDMCTRL1;
+
+}
diff --git a/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc b/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc
new file mode 100644 (file)
index 0000000..0486092
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author David Moss
+ * @author Jung Il Choi
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+module CC2420ReceiveP {
+
+  provides interface Init;
+  provides interface CC2420AsyncSplitControl as AsyncSplitControl; 
+  provides interface CC2420Receive;
+  provides interface CC2420Rx;
+/*  provides interface ReceiveIndicator as PacketIndicator;*/
+
+  uses interface GeneralIO as CSN;
+  uses interface GeneralIO as FIFO;
+  uses interface GeneralIO as FIFOP;
+  uses interface GpioInterrupt as InterruptFIFOP;
+
+  uses interface Resource as SpiResource;
+  uses interface CC2420Fifo as RXFIFO;
+  uses interface CC2420Strobe as SACK;
+  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;
+}
+
+implementation {
+
+  typedef enum {
+    S_STOPPED,
+    S_STARTING,
+    S_STARTING_FLUSHRX,
+    S_STARTED,
+    S_RX_LENGTH,
+    S_RX_FCF,
+    S_RX_HEADER,
+    S_RX_PAYLOAD,
+  } cc2420_receive_state_t;
+
+  enum {
+    RXFIFO_SIZE = 128,
+    TIMESTAMP_QUEUE_SIZE = 8,
+    //SACK_HEADER_LENGTH = 7,
+    SACK_HEADER_LENGTH = 3,
+  };
+
+  ieee154_reftime_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];
+  ieee154_reftime_t m_timestamp;
+  norace bool m_timestampValid;
+  
+  uint8_t m_timestamp_head;
+  
+  uint8_t m_timestamp_size;
+  
+  /** Number of packets we missed because we were doing something else */
+  uint8_t m_missed_packets;
+  
+  /** TRUE if we are receiving a valid packet into the stack */
+  norace bool receivingPacket;
+  
+  /** The length of the frame we're currently receiving */
+  norace uint8_t rxFrameLength;
+  
+  norace uint8_t m_bytes_left;
+
+  // norace message_t* m_p_rx_buf;
+
+  // message_t m_rx_buf;
+  
+  cc2420_receive_state_t m_state;
+  
+  // new packet format:
+  message_t m_frame;
+  norace message_t *m_rxFramePtr;
+  norace uint8_t m_mhrLen;
+  uint8_t m_dummy;
+  norace bool m_stop;
+  
+  /***************** Prototypes ****************/
+  void reset_state();
+  void beginReceive();
+  void receive();
+  void waitForNextPacket();
+  void flush();
+  void switchToUnbufferedMode();
+  void switchToBufferedMode();
+  void startingSpiReserved();
+  void continueStart();
+  void continueStop();
+  task void stopContinueTask();
+  
+  task void receiveDone_task();
+  
+  /***************** Init Commands ****************/
+  command error_t Init.init() {
+    m_rxFramePtr = &m_frame;
+    atomic m_state = S_STOPPED;
+    return SUCCESS;
+  }
+
+  /***************** 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()
+  {
+    atomic {
+      if (m_state == S_STOPPED)
+        return EALREADY;
+      else {
+        m_stop = TRUE;
+        call InterruptFIFOP.disable();
+        if (!receivingPacket)
+          continueStop();
+        // else stopContinueTask will be posted after 
+        // current Rx operation is finished, because m_stop is set
+      }
+    }
+    return SUCCESS;
+  }
+
+  void continueStop()
+  {
+    atomic {
+      m_stop = FALSE;
+      m_state = S_STOPPED;
+    }
+    post stopContinueTask();
+  }
+
+  task void stopContinueTask()
+  {
+    if (receivingPacket){
+      call Leds.led0On();
+    }
+    call SpiResource.release(); // may fail
+    atomic m_state = S_STOPPED;
+    signal AsyncSplitControl.stopDone(SUCCESS);
+  }
+
+  void switchToUnbufferedMode()
+  {
+    uint16_t mdmctrol1;
+    call CSN.set();
+    call CSN.clr();
+    call MDMCTRL1.read(&mdmctrol1);
+    mdmctrol1 &= ~0x03;
+    mdmctrol1 |= 0x01;
+    call MDMCTRL1.write(mdmctrol1);
+    call CSN.set();
+  }
+
+  void switchToBufferedMode()
+  {
+    uint16_t mdmctrol1;
+    call CSN.set();
+    call CSN.clr();
+    call MDMCTRL1.read(&mdmctrol1);
+    mdmctrol1 &= ~0x03;
+    call MDMCTRL1.write(mdmctrol1);
+    call CSN.set();
+  }
+
+  /***************** CC2420Receive Commands ****************/
+  /**
+   * Start frame delimiter signifies the beginning/end of a packet
+   * See the CC2420 datasheet for details.
+   */
+  async command void CC2420Receive.sfd( ieee154_reftime_t *time ) {
+    if (m_state == S_STOPPED)
+      return;
+    if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) {
+      uint8_t tail =  ( ( m_timestamp_head + m_timestamp_size ) % 
+                        TIMESTAMP_QUEUE_SIZE );
+      memcpy(&m_timestamp_queue[ tail ], time, sizeof(ieee154_reftime_t) );
+      m_timestamp_size++;
+    }
+  }
+
+  async command void CC2420Receive.sfd_dropped() {
+    if (m_state == S_STOPPED)
+      return;    
+    if ( m_timestamp_size ) {
+      m_timestamp_size--;
+    }
+  }
+  
+  /***************** InterruptFIFOP Events ****************/
+  async event void InterruptFIFOP.fired() {
+    atomic {
+      if ( m_state == S_STARTED ) {
+        beginReceive();
+
+      } else {
+        m_missed_packets++;
+      }
+    }
+  }
+  
+  
+  /***************** SpiResource Events ****************/
+  event void SpiResource.granted() {
+    atomic {
+      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();
+      }
+    }
+  }
+  
+  uint8_t mhrLength(uint8_t *fcf)
+  {
+    uint8_t idCompression;
+    uint8_t len = MHR_INDEX_ADDRESS;
+    if (fcf[MHR_INDEX_FC1] & FC1_SECURITY_ENABLED)
+      return 0xFF; // not supported 
+    idCompression = (fcf[0] & FC1_PAN_ID_COMPRESSION);
+    if (fcf[MHR_INDEX_FC2] & 0x08){ // short or ext. address
+      len += 4; // pan id + short address
+      if (fcf[MHR_INDEX_FC2] & 0x04) // ext. address
+        len += 6; // diff to short address
+    }
+    if (fcf[MHR_INDEX_FC2] & 0x80){ // short or ext. address
+      len += 2;
+      if (!idCompression)
+        len += 2;
+      if (fcf[MHR_INDEX_FC2] & 0x40) // ext. address
+        len += 6; // diff to short address
+    }
+    return len;
+  }
+    
+  
+  /***************** RXFIFO Events ****************/
+  /**
+   * We received some bytes from the SPI bus.  Process them in the context
+   * of the state we're in.  Remember the length byte is not part of the length
+   */
+  async event void RXFIFO.readDone( uint8_t* rx_buf, uint8_t rx_len,
+                                    error_t error ) {
+    uint8_t* buf;
+
+   atomic {
+    buf = (uint8_t*) &((ieee154_header_t*) m_rxFramePtr->header)->length; 
+    rxFrameLength = ((ieee154_header_t*) m_rxFramePtr->header)->length;
+
+     switch( m_state ) {
+
+    case S_RX_LENGTH:
+      m_state = S_RX_FCF;
+      if ( rxFrameLength + 1 > m_bytes_left ) {
+        // Length of this packet is bigger than the RXFIFO, flush it out.
+        flush();
+        
+      } else {
+        if ( !call FIFO.get() && !call FIFOP.get() ) {
+          //m_bytes_left -= rxFrameLength + 1;
+          flush(); 
+        }
+        
+        //if(rxFrameLength <= MAC_PACKET_SIZE) {
+        if(rxFrameLength <= (sizeof(ieee154_header_t) - 1 + TOSH_DATA_LENGTH + 2)){
+          if(rxFrameLength > 0) {
+            if(rxFrameLength > SACK_HEADER_LENGTH) {
+              // This packet has an FCF byte plus at least one more byte to read
+              call RXFIFO.continueRead(buf + 1, SACK_HEADER_LENGTH);
+              
+            } else {
+              // This is really a bad packet, skip FCF and get it out of here.
+              flush(); 
+              //m_state = S_RX_PAYLOAD;
+              //call RXFIFO.continueRead(buf + 1, rxFrameLength);
+            }
+                            
+          } else {
+            // Length == 0; start reading the next packet
+            flush();  
+/*            atomic receivingPacket = FALSE;*/
+/*            call CSN.set();*/
+/*            call SpiResource.release();*/
+/*            waitForNextPacket();*/
+          }
+          
+        } else {
+          // Length is too large; we have to flush the entire Rx FIFO
+          flush();
+        }
+      }
+      break;
+      
+    case S_RX_FCF:
+      if (call FrameUtility.getMHRLength(buf[1], buf[2], &m_mhrLen) != SUCCESS ||
+          m_mhrLen > rxFrameLength - 2) {
+        // header size incorrect
+        flush();
+        break;
+      } else if (m_mhrLen > SACK_HEADER_LENGTH) {
+        m_state = S_RX_HEADER;
+        call RXFIFO.continueRead(buf + 1 + SACK_HEADER_LENGTH, 
+          m_mhrLen - SACK_HEADER_LENGTH);
+        break;
+      } else {
+        // complete header has been read: fall through
+      }
+      // fall through
+
+    case S_RX_HEADER:
+      // JH: we are either using HW ACKs (normal receive mode) or don't ACK any
+      // packets (promiscuous mode)
+      // Didn't flip CSn, we're ok to continue reading.
+      if ((rxFrameLength - m_mhrLen - 2) > TOSH_DATA_LENGTH) // 2 for CRC
+        flush();
+      else {
+        m_state = S_RX_PAYLOAD;
+        call RXFIFO.continueRead((uint8_t*) m_rxFramePtr->data, rxFrameLength - m_mhrLen);
+      }
+      break;
+    
+    case S_RX_PAYLOAD:
+      call CSN.set();
+      
+      if(!m_missed_packets) {
+        // Release the SPI only if there are no more frames to download
+        call SpiResource.release();
+      }
+      
+      if ( m_timestamp_size ) {
+        if ( rxFrameLength > 10 ) {
+          //((ieee154_metadata_t*) m_rxFramePtr->metadata)->timestamp = m_timestamp_queue[ m_timestamp_head ];
+          memcpy(&m_timestamp, &m_timestamp_queue[ m_timestamp_head ], sizeof(ieee154_reftime_t) );
+          m_timestampValid = TRUE;
+          m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;
+          m_timestamp_size--;
+        }
+      } else {
+/*        metadata->time = 0xffff;*/
+        m_timestampValid = FALSE;
+        //((ieee154_metadata_t*) m_rxFramePtr->metadata)->timestamp = IEEE154_INVALID_TIMESTAMP;
+      }
+      
+      // We may have received an ack that should be processed by Transmit
+      // buf[rxFrameLength] >> 7 checks the CRC
+      if ( ( m_rxFramePtr->data[ rxFrameLength - m_mhrLen - 1 ] >> 7 ) && rx_buf ) {
+        uint8_t type = ((ieee154_header_t*) m_rxFramePtr->header)->mhr[0] & 0x07;
+/*        signal CC2420Receive.receive( type, m_p_rx_buf );*/
+        signal CC2420Receive.receive( type, m_rxFramePtr );
+/*        if ( type == IEEE154_TYPE_DATA ) {*/
+        if ( (type != IEEE154_TYPE_ACK || call CC2420Config.isPromiscuousModeEnabled())
+            && !m_stop) { 
+          post receiveDone_task();
+          return;
+        }
+      }
+      
+      waitForNextPacket();
+      break;
+
+    case S_STARTING_FLUSHRX: continueFlushStart(); break;
+      
+    default:
+      atomic receivingPacket = FALSE;
+      call CSN.set();
+      call SpiResource.release();
+      if (m_stop){
+        continueStop();
+        return;
+      }
+      break;
+      
+    }
+    }
+    
+  }
+
+  async event void RXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error ) {
+  }  
+  
+  /***************** Tasks *****************/
+  /**
+   * Fill in metadata details, pass the packet up the stack, and
+   * get the next packet.
+   */
+  task void receiveDone_task() {
+    uint8_t payloadLen = ((ieee154_header_t*) m_rxFramePtr->header)->length - m_mhrLen - 2;
+    ieee154_metadata_t *metadata = (ieee154_metadata_t*) m_rxFramePtr->metadata;
+
+    atomic {
+      if (m_state == S_STOPPED){
+        call Leds.led0On();
+        return;
+      }
+    }
+    ((ieee154_header_t*) m_rxFramePtr->header)->length = m_rxFramePtr->data[payloadLen+1] & 0x7f; // temp. LQI
+    metadata->rssi = m_rxFramePtr->data[payloadLen];
+    metadata->linkQuality = ((ieee154_header_t*) m_rxFramePtr->header)->length; // copy back
+    ((ieee154_header_t*) m_rxFramePtr->header)->length = payloadLen;
+    if (m_timestampValid)
+      metadata->timestamp = call ReferenceTime.toLocalTime(&m_timestamp);
+    else
+      metadata->timestamp = IEEE154_INVALID_TIMESTAMP;
+    m_rxFramePtr = signal CC2420Rx.received(m_rxFramePtr, &m_timestamp);
+
+/*    cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf );*/
+/*    uint8_t* buf = (uint8_t*) call CC2420PacketBody.getHeader( m_p_rx_buf );;*/
+/*    */
+/*    metadata->crc = buf[ rxFrameLength ] >> 7;*/
+/*    metadata->rssi = buf[ rxFrameLength - 1 ];*/
+/*    metadata->lqi = buf[ rxFrameLength ] & 0x7f;*/
+    // async event message_t* receiveDone( message_t *data );
+
+/*    m_p_rx_buf = signal Receive.receive( m_rxFramePtrm_p_rx_buf, m_p_rx_buf->data, */
+/*                                         rxFrameLength );*/
+
+    atomic receivingPacket = FALSE;
+    waitForNextPacket();
+  }
+  
+  
+  /****************** Functions ****************/
+  /**
+   * Attempt to acquire the SPI bus to receive a packet.
+   */
+  void beginReceive() { 
+    atomic {
+      if ( m_state == S_STOPPED){
+        call Leds.led0On();
+        return;
+      }
+      m_state = S_RX_LENGTH;
+      receivingPacket = TRUE;
+    
+      if(call SpiResource.isOwner()) {
+        receive();
+
+      } else if (call SpiResource.immediateRequest() == SUCCESS) {
+        receive();
+
+      } else {
+        call SpiResource.request();
+      }
+    }
+  }
+  
+  /**
+   * Flush out the Rx FIFO
+   */
+  void flush() {
+    reset_state();
+    call CSN.set();
+    call CSN.clr();
+    call SFLUSHRX.strobe();
+    call SFLUSHRX.strobe();
+    call CSN.set();
+    call SpiResource.release();
+    waitForNextPacket();
+  }
+  
+  /**
+   * The first byte of each packet is the length byte.  Read in that single
+   * byte, and then read in the rest of the packet.  The CC2420 could contain
+   * multiple packets that have been buffered up, so if something goes wrong, 
+   * we necessarily want to flush out the FIFO unless we have to.
+   */
+  void receive() {
+    call CSN.set();
+    call CSN.clr();
+    //call RXFIFO.beginRead( (uint8_t*)(call CC2420PacketBody.getHeader( m_p_rx_buf )), 1 );
+    call RXFIFO.beginRead( &((ieee154_header_t*) m_rxFramePtr->header)->length, 1 );
+  }
+
+
+  /**
+   * Determine if there's a packet ready to go, or if we should do nothing
+   * until the next packet arrives
+   */
+  void waitForNextPacket() {
+    atomic {
+      receivingPacket = FALSE;
+      if ( m_state == S_STOPPED) {
+        call SpiResource.release();
+        return;
+      }
+      if (m_stop){
+        continueStop();
+        return;
+      }
+      
+      if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() ) {
+        // A new packet is buffered up and ready to go
+        if ( m_missed_packets ) {
+          m_missed_packets--;
+        }
+        
+        beginReceive();
+        
+      } else {
+        // Wait for the next packet to arrive
+        m_state = S_STARTED;
+        m_missed_packets = 0;
+        call SpiResource.release();
+      }
+    }
+  }
+  
+  /**
+   * Reset this component
+   */
+  void reset_state() {
+    m_bytes_left = RXFIFO_SIZE;
+    atomic receivingPacket = FALSE;
+    m_timestamp_head = 0;
+    m_timestamp_size = 0;
+    m_missed_packets = 0;
+  }
+
+}
diff --git a/tos/chips/cc2420_tkn154/CC2420Rx.nc b/tos/chips/cc2420_tkn154/CC2420Rx.nc
new file mode 100644 (file)
index 0000000..1f1abf2
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008, Technische Universitaet Berlin
+ * 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 Technische Universitaet Berlin 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 COPYRIGHT
+ * OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+#include "TKN154_MAC.h"
+#include "TKN154_platform.h"
+
+interface CC2420Rx {
+
+  /**
+   * Receive a packet buffer, returning a buffer for the signaling
+   * component to use for the next reception. 
+   */
+  event message_t* received(message_t *data, ieee154_reftime_t *timestamp);
+
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420TKN154C.nc b/tos/chips/cc2420_tkn154/CC2420TKN154C.nc
new file mode 100644 (file)
index 0000000..18da878
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2008, Technische Universitaet Berlin
+ * 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 Technische Universitaet Berlin 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 COPYRIGHT
+ * OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+#include "Timer62500hz.h"
+configuration CC2420TKN154C
+{
+  provides
+  {
+    interface SplitControl;
+    interface RadioRx;
+    interface RadioTx;
+    interface EnergyDetection;
+    interface RadioOff;
+    interface Set<bool> as RadioPromiscuousMode;
+    interface Timestamp;
+  } uses {
+    interface Notify<const void*> as PIBUpdate[uint8_t attributeID];
+    interface LocalTime<T62500hz>;
+    interface Alarm<T62500hz,uint32_t> as Alarm1;
+    interface Alarm<T62500hz,uint32_t> as Alarm2;
+    interface FrameUtility;
+    interface CaptureTime;
+    interface ReferenceTime;
+    interface ReliableWait;
+    interface TimeCalc;
+    interface Leds;
+    interface Random;
+  }
+} implementation {
+
+  components MainC, CC2420TKN154P as PHY;
+
+  SplitControl = PHY;
+  RadioRx = PHY;
+  RadioTx = PHY;
+  RadioOff = PHY;
+  EnergyDetection = PHY;
+  PIBUpdate = PHY;
+  RadioPromiscuousMode = PHY;
+  Timestamp = PHY;
+  LocalTime = PHY;
+  ReliableWait = PHY;
+  ReferenceTime = PHY;
+  TimeCalc = PHY;
+
+  PHY.Random = Random;
+  Leds = PHY.Leds;
+
+  components CC2420ControlTransmitC;
+  PHY.SpiResource -> CC2420ControlTransmitC;
+  PHY.CC2420Power -> CC2420ControlTransmitC;
+  PHY.CC2420Config -> CC2420ControlTransmitC;
+  CC2420ControlTransmitC.StartupAlarm = Alarm2;
+  FrameUtility = CC2420ControlTransmitC;
+  Leds = CC2420ControlTransmitC;
+
+  PHY.TxControl -> CC2420ControlTransmitC;
+  PHY.CC2420Tx -> CC2420ControlTransmitC;
+  CC2420ControlTransmitC.AckAlarm = Alarm1;
+  CC2420ControlTransmitC.CaptureTime = CaptureTime;
+  CC2420ControlTransmitC.ReferenceTime = ReferenceTime;
+
+  components CC2420ReceiveC;
+  PHY.RxControl -> CC2420ReceiveC;
+  PHY.CC2420Rx -> CC2420ReceiveC.CC2420Rx;
+  ReferenceTime = CC2420ReceiveC;
+  Leds = CC2420ReceiveC;
+  FrameUtility = CC2420ReceiveC;
+  CC2420ReceiveC.CC2420Config -> CC2420ControlTransmitC;
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420TKN154P.nc b/tos/chips/cc2420_tkn154/CC2420TKN154P.nc
new file mode 100644 (file)
index 0000000..2546253
--- /dev/null
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2008, Technische Universitaet Berlin
+ * 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 Technische Universitaet Berlin 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 COPYRIGHT
+ * OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+#include "TKN154_MAC.h"
+#include "TKN154_PHY.h"
+#include <CC2420.h>
+#include "Timer62500hz.h"
+
+module CC2420TKN154P 
+{
+
+  provides {
+    interface SplitControl;
+    interface RadioRx;
+    interface RadioTx;
+    interface RadioOff;
+    interface EnergyDetection;
+    interface Set<bool> as RadioPromiscuousMode;
+    interface Timestamp;
+  } uses {
+    interface Notify<const void*> as PIBUpdate[uint8_t attributeID];
+    interface LocalTime<T62500hz> as LocalTime;
+    interface Resource as SpiResource;
+    interface AsyncStdControl as TxControl;        
+    interface CC2420AsyncSplitControl as RxControl; 
+    interface CC2420Power;
+    interface CC2420Config;
+    interface CC2420Rx;
+    interface CC2420Tx;
+    interface Random;
+    interface Leds;
+    interface ReliableWait;
+    interface ReferenceTime;
+    interface TimeCalc;
+  }
+
+} implementation {
+
+  typedef enum {
+    S_STOPPED,
+    S_STOPPING,
+    S_STARTING,
+
+    S_RADIO_OFF,
+    S_ED,
+
+    S_RESERVE_RX_SPI,
+    S_RX_PREPARED,
+    S_RECEIVING,
+    S_OFF_PENDING,
+
+    S_LOAD_TXFIFO,
+    S_TX_LOADED,
+    S_TX_ACTIVE,
+    S_TX_CANCEL,
+    S_TX_DONE,
+  } m_state_t;
+
+  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;
+  norace bool m_ackFramePending;
+  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;
+  norace bool m_rxAfterTx = FALSE;
+  norace bool m_stop = FALSE;
+
+  task void startDoneTask();
+  task void rxControlStopDoneTask();
+  task void stopTask();
+
+  uint8_t dBmToPA_LEVEL(int dbm);
+  void txDoneRxControlStopped();
+  void rxSpiReserved();
+  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)
+        return EALREADY;
+      else {
+        if (m_state != S_STOPPED)
+          return FAIL;
+        m_state = S_STARTING;
+      }
+    }
+    return call SpiResource.request();
+  }
+
+  void startReserved()
+  {
+    call CC2420Power.startVReg();
+  }
+
+  async event void CC2420Power.startVRegDone() 
+  {
+    call CC2420Power.startOscillator();
+  }
+
+  async event void CC2420Power.startOscillatorDone() 
+  {
+    // default configuration (addresses, etc) has been written
+    call CC2420Power.rfOff();
+    call CC2420Tx.unlockChipSpi();
+    post startDoneTask();
+  }
+
+  task void startDoneTask() 
+  {
+    call CC2420Config.setChannel(IEEE154_DEFAULT_CURRENTCHANNEL);
+    call CC2420Config.setShortAddr(IEEE154_DEFAULT_SHORTADDRESS);
+    call CC2420Config.setPanAddr(IEEE154_DEFAULT_PANID);
+    call CC2420Config.setPanCoordinator(FALSE);  
+    call CC2420Config.setPromiscuousMode(FALSE);
+    call CC2420Config.setCCAMode(IEEE154_DEFAULT_CCAMODE);
+    call CC2420Config.setTxPower(dBmToPA_LEVEL(IEEE154_DEFAULT_TRANSMITPOWER_dBm));
+    call CC2420Config.sync();
+    call SpiResource.release();
+    m_stop = FALSE;
+    m_state = S_RADIO_OFF;
+    signal SplitControl.startDone(SUCCESS);
+  }
+
+  command error_t SplitControl.stop() 
+  {
+    atomic {
+      if (m_state == S_STOPPED)
+        return EALREADY;
+    }
+    post stopTask();
+    return SUCCESS;
+  }
+
+  task void stopTask()
+  {
+    atomic {
+      if (m_state == S_RADIO_OFF)
+        m_state = S_STOPPING;
+    }
+    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();
+  }
+
+  void stopContinue()
+  {
+    call SpiResource.request();
+  }
+
+  void stopReserved()
+  {
+    // we own the SPI bus
+    atomic {
+      call CC2420Power.rfOff();
+      call CC2420Tx.unlockChipSpi();
+      call TxControl.stop();
+      call CC2420Power.stopOscillator(); 
+      call CC2420Power.stopVReg();
+      call SpiResource.release();
+      m_state  = S_STOPPED;
+      signal SplitControl.stopDone(SUCCESS);
+    }
+  }
+
+  /*********************************/
+  /*  PIB Updates                  */
+  /*********************************/
+  
+  // input: power in dBm, output: PA_LEVEL parameter for cc2420 TXCTRL register
+  uint8_t dBmToPA_LEVEL(int dBm)
+  {
+    uint8_t result;
+    // the cc2420 has 8 discrete (documented) values - we take the closest
+    if (dBm >= 0)
+      result = 31;
+    else if (dBm > -2)
+      result = 27;
+    else if (dBm > -4)
+      result = 23;
+    else if (dBm > -6)
+      result = 19;
+    else if (dBm > -9)
+      result = 15;
+    else if (dBm > -13)
+      result = 11;
+    else if (dBm > -20)
+      result = 7;
+    else
+      result = 3;
+    return result;
+  }
+
+  event void PIBUpdate.notify[uint8_t PIBAttribute](const void* PIBAttributeValue)
+  {
+    uint8_t txpower;
+    switch (PIBAttribute)
+    {
+      case IEEE154_macShortAddress:
+        call CC2420Config.setShortAddr(*((ieee154_macShortAddress_t*) PIBAttributeValue));
+        break;
+      case IEEE154_macPANId:
+        call CC2420Config.setPanAddr(*((ieee154_macPANId_t*) PIBAttributeValue));
+        break;
+      case IEEE154_phyCurrentChannel:
+        call CC2420Config.setChannel(*((ieee154_phyCurrentChannel_t*) PIBAttributeValue));
+        break;
+      case IEEE154_macPanCoordinator:
+        call CC2420Config.setPanCoordinator(*((ieee154_macPanCoordinator_t*) PIBAttributeValue));
+        break;
+      case IEEE154_phyTransmitPower:
+        // lower 6 bits are twos-complement in dBm (range -32..+31 dBm)
+        txpower = (*((ieee154_phyTransmitPower_t*) PIBAttributeValue)) & 0x3F;
+        if (txpower & 0x20)
+          txpower |= 0xC0; // make it negative, to be interpreted as int8_t
+        call CC2420Config.setTxPower(dBmToPA_LEVEL((int8_t) txpower));
+        break;
+      case IEEE154_phyCCAMode:
+        call CC2420Config.setCCAMode(*((ieee154_phyCCAMode_t*) PIBAttributeValue));
+        break;
+    }
+  }
+
+  command void RadioPromiscuousMode.set( bool val )
+  {
+    call CC2420Config.setPromiscuousMode(val);
+  }
+
+  /*********************************/
+  /* Energy Detection              */
+  /*********************************/
+
+  command error_t EnergyDetection.start(uint32_t duration)
+  {
+    error_t status = FAIL;
+    atomic {
+      if (m_state == S_RADIO_OFF){
+        m_state = S_ED;
+        m_edDuration = duration;
+        status = SUCCESS;
+      }
+    }
+    if (status == SUCCESS)
+      call SpiResource.request(); // we will not give up the SPI until we're done
+    return status;
+  }
+
+  void edReserved()
+  {
+    int8_t value, maxEnergy = -128;
+    uint32_t start = call LocalTime.get();
+    call CC2420Config.sync(); // put PIB changes into operation (if any)
+    call CC2420Power.rxOn();
+    // 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)
+        continue;
+      if (value > maxEnergy)
+        maxEnergy = value;
+    }
+    // P = RSSI_VAL + RSSI_OFFSET [dBm] 
+    // RSSI_OFFSET is approximately -45.
+    if (maxEnergy > -128)
+      maxEnergy -= 45; 
+    call CC2420Power.rfOff();
+    m_state = S_RADIO_OFF;
+    call SpiResource.release();
+    signal EnergyDetection.done(SUCCESS, maxEnergy);
+  }
+
+  /****************************************/
+  /*     Transceiver Off                  */
+  /****************************************/
+
+  async command error_t RadioOff.off()
+  {
+    atomic {
+      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;
+    }
+    call SpiResource.release(); // may fail
+    if (call RxControl.stop() == EALREADY) // will trigger offStopRxDone()
+      offStopRxDone();
+    return SUCCESS;
+  }
+  
+  void offStopRxDone()
+  {
+    if (call SpiResource.immediateRequest() == SUCCESS)
+      offSpiReserved();
+    else
+      call SpiResource.request();  // will trigger offSpiReserved()
+  }
+
+  void offSpiReserved()
+  {
+    call TxControl.stop();
+    call CC2420Power.rfOff();
+    call CC2420Config.sync(); // put any PIB updates into operation
+    call CC2420Tx.unlockChipSpi();
+    call SpiResource.release();
+    m_state = S_RADIO_OFF;
+    signal RadioOff.offDone();
+  }
+
+  async command bool RadioOff.isOff()
+  {
+    return m_state == S_RADIO_OFF;
+  }
+
+  /****************************************/
+  /*     Receive Operations               */
+  /****************************************/
+
+  async command error_t RadioRx.prepare()
+  {
+    atomic {
+      if (call RadioRx.isPrepared())
+        return EALREADY;
+      else if (m_state != S_RADIO_OFF)
+        return FAIL;
+      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
+  }
+
+  async command bool RadioRx.isPrepared()
+  { 
+    return m_state == S_RX_PREPARED;
+  }
+
+  async command error_t RadioRx.receive(ieee154_reftime_t *t0, uint32_t dt)
+  {
+    atomic {
+      if (m_state != S_RX_PREPARED){
+        call Leds.led0On();
+        return FAIL;
+      }
+      if (t0 != NULL && dt)
+        call ReliableWait.waitRx(t0, dt);
+      else
+        signal ReliableWait.waitRxDone();
+    }
+    return SUCCESS;
+  }
+
+  async event void ReliableWait.waitRxDone()
+  {
+    atomic {
+      if (call CC2420Power.rxOn() != SUCCESS)
+        call Leds.led0On();
+      m_state = S_RECEIVING;
+    }
+    call CC2420Tx.lockChipSpi();
+    call SpiResource.release();    
+  }
+
+  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;
+  }
+
+  async command bool RadioRx.isReceiving()
+  { 
+    return m_state == S_RECEIVING;
+  }
+
+  /******************************/
+  /*     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()
+  }
+
+  void txSpiReserved()
+  {
+    call CC2420Config.sync();
+    call TxControl.start();
+    if (call CC2420Tx.loadTXFIFO(m_txdata) != SUCCESS)
+      call Leds.led0On();
+  }
+
+  async event void CC2420Tx.loadTXFIFODone(ieee154_txframe_t *data, error_t error)
+  {
+    if (m_state != S_LOAD_TXFIFO || error != SUCCESS)
+      call Leds.led0On();
+    m_state = S_TX_LOADED;
+    signal RadioTx.loadDone();  // we keep owning the SPI
+  }
+
+  async command ieee154_txframe_t* RadioTx.getLoadedFrame()
+  {
+    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();
+  }
+
+  async command void Timestamp.modifyMACPayload(uint8_t token, uint8_t offset, uint8_t* buf, uint8_t len )
+  {
+    if (m_state == S_TX_ACTIVE)
+      call CC2420Tx.modify(offset+1+token, buf, len);
+  }
+
+  async event void CC2420Tx.sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime, 
+      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();
+  }
+
+  void txDoneRxControlStopped()
+  {
+    // get SPI to switch radio off
+    if (call SpiResource.isOwner() || call SpiResource.immediateRequest() == SUCCESS) 
+      txDoneSpiReserved();
+    else
+      call SpiResource.request(); // will trigger txDoneSpiReserved()
+  }
+
+  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)
+  {
+    post rxControlStopDoneTask();
+  }
+
+  task void rxControlStopDoneTask()
+  {
+    if (m_stop && m_state != S_STOPPING)
+      return;
+    switch (m_state)
+    {
+      case S_OFF_PENDING: offStopRxDone(); break;
+      case S_RX_PREPARED: rxStartRxDone(); break;
+      case S_TX_ACTIVE: txDoneRxControlStopped(); break;
+      case S_STOPPING: stopContinue(); break;            
+      default: // huh ?
+           call Leds.led0On(); break;
+    }
+  }
+
+  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() 
+  {
+    switch (m_state)
+    {
+      case S_STARTING: startReserved(); break;
+      case S_ED: edReserved(); break;
+      case S_RESERVE_RX_SPI: rxSpiReserved(); break;
+      case S_LOAD_TXFIFO: txSpiReserved(); break;
+      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 ?
+           call Leds.led0On(); break;
+    }
+  }
+
+
+  default event void SplitControl.startDone(error_t error){}
+  default event void SplitControl.stopDone(error_t error){}
+  default async event void Timestamp.transmissionStarted(uint8_t frameType, uint8_t msduHandle, uint8_t *msdu, uint8_t token){}
+  default async event void Timestamp.transmittedSFD(uint32_t time, uint8_t frameType, uint8_t msduHandle, uint8_t *msdu, uint8_t token){}
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420TransmitP.nc b/tos/chips/cc2420_tkn154/CC2420TransmitP.nc
new file mode 100644 (file)
index 0000000..b839a99
--- /dev/null
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author David Moss
+ * @author Jung Il Choi Initial SACK implementation
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+#include "crc.h"
+#include "message.h"
+
+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 CC2420Packet;
+  uses interface CC2420PacketBody;
+  uses interface GpioCapture as CaptureSFD;
+  uses interface GeneralIO as CCA;
+  uses interface GeneralIO as CSN;
+  uses interface GeneralIO as SFD;
+
+/*  uses interface Resource as SpiResource;*/
+  uses interface ChipSpiResource;
+  uses interface CC2420Fifo as TXFIFO;
+  uses interface CC2420Ram as TXFIFO_RAM;
+  uses interface CC2420Register as TXCTRL;
+  uses interface CC2420Strobe as SNOP;
+  uses interface CC2420Strobe as STXON;
+  uses interface CC2420Strobe as STXONCCA;
+  uses interface CC2420Strobe as SFLUSHTX;
+  uses interface CC2420Strobe as SRXON;
+  uses interface CC2420Strobe as SRFOFF;
+  uses interface CC2420Strobe as SFLUSHRX;
+  uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
+  uses interface CC2420Register as MDMCTRL1;
+  uses interface CaptureTime;
+  uses interface ReferenceTime;
+
+  uses interface CC2420Receive;
+  uses interface Leds;
+}
+
+implementation {
+
+  typedef enum {
+    S_STOPPED,
+    S_STARTED,
+    S_LOAD,
+    S_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;
+  
+  cc2420_transmit_state_t m_state = S_STOPPED;
+  
+  bool m_receiving = FALSE;
+  
+  uint16_t m_prev_time;
+  
+  /** Byte reception/transmission indicator */
+  bool sfdHigh;
+  
+  /** Let the CC2420 driver keep a lock on the SPI while waiting for an ack */
+  norace bool abortSpiRelease;
+  
+  /** 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;
+  
+
+  /***************** 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() {
+    call CCA.makeInput();
+    call CSN.makeOutput();
+    call SFD.makeInput();
+    return SUCCESS;
+  }
+
+  /***************** AsyncStdControl Commands ****************/
+  async command error_t AsyncStdControl.start() {
+    atomic {
+      if (m_state == S_STARTED)
+        return EALREADY;
+      call CaptureSFD.captureRisingEdge();
+      m_state = S_STARTED;
+      m_receiving = FALSE;
+    }
+    return SUCCESS;
+  }
+
+  async command error_t AsyncStdControl.stop() {
+    atomic {
+      m_state = S_STOPPED;
+      call BackoffAlarm.stop();
+      call CaptureSFD.disable();
+/*      call SpiResource.release();  // REMOVE*/
+      call CSN.set();
+    }
+    return SUCCESS;
+  }
+
+
+  /**************** 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) {*/
+/*  }*/
+  
+  
+  
+  /**
+   * The CaptureSFD event is actually an interrupt from the capture pin
+   * which is connected to timing circuitry and timer modules.  This
+   * type of interrupt allows us to see what time (being some relative value)
+   * the event occurred, and lets us accurately timestamp our packets.  This
+   * allows higher levels in our system to synchronize with other nodes.
+   *
+   * Because the SFD events can occur so quickly, and the interrupts go
+   * in both directions, we set up the interrupt but check the SFD pin to
+   * determine if that interrupt condition has already been met - meaning,
+   * we should fall through and continue executing code where that interrupt
+   * would have picked up and executed had our microcontroller been fast enough.
+   */
+  async event void CaptureSFD.captured( uint16_t time ) {
+    // "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();
+        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;
+        }
+        /** Fall Through because the next interrupt was already received */
+        
+      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 ) ) {
+          m_state = S_ACK_WAIT;
+          call BackoffAlarm.start( 200 ); // we need to have *completely* received the ACK
+        } else {
+          signalDone(FALSE, SUCCESS);
+        }
+        
+        if ( !call SFD.get() ) {
+          break;
+        }
+        /** Fall Through because the next interrupt was already received */
+        
+      default:
+        if ( !m_receiving ) {
+          sfdHigh = TRUE;
+          call CaptureSFD.captureFallingEdge();
+/*          signal TimeStamp.receivedSFD( time );*/
+          call CaptureTime.convert(time, &m_timestamp, -8);
+          call CC2420Receive.sfd( &m_timestamp );
+          m_receiving = TRUE;
+          m_prev_time = time;
+          if ( call SFD.get() ) {
+            // wait for the next interrupt before moving on
+            return;
+          }
+        }
+        
+        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
+          call CC2420Receive.sfd_dropped();
+        }
+        break;
+      
+      }
+    }
+  }
+
+  /***************** ChipSpiResource Events ****************/
+  async event void ChipSpiResource.releasing() {
+    if(abortSpiRelease) {
+      call ChipSpiResource.abortRelease();
+    }
+  }
+  
+  
+  /***************** CC2420Receive Events ****************/
+  /**
+   * If the packet we just received was an ack that we were expecting,
+   * our send is complete.
+   */
+  async event void CC2420Receive.receive(  uint8_t type, message_t *ackFrame ){
+/*  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);
+        }
+      }
+    }
+  }
+
+  /***************** 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 ) {*/
+/*  }*/
+
+}
+
diff --git a/tos/chips/cc2420_tkn154/CC2420Tx.nc b/tos/chips/cc2420_tkn154/CC2420Tx.nc
new file mode 100644 (file)
index 0000000..53e1fc9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2008, Technische Universitaet Berlin
+ * 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 Technische Universitaet Berlin 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 COPYRIGHT
+ * OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+#include "TKN154_MAC.h"
+#include "TKN154_PHY.h"
+interface CC2420Tx {
+
+  async command error_t loadTXFIFO(ieee154_txframe_t *data);
+  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);
+
+  async command bool cca();
+  async command void lockChipSpi();
+  async command void unlockChipSpi();  
+
+  async event void transmissionStarted ( ieee154_txframe_t *data );
+  async event void transmittedSFD ( uint32_t time, ieee154_txframe_t *data );
+
+  /**
+   * Modify the contents of a packet. This command can only be used
+   * when an SFD capture event for the sending packet is signalled.
+   *
+   * @param offset in the message to start modifying.
+   * @param buf to data to write
+   * @param len of bytes to write
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */  
+  async command error_t modify( uint8_t offset, uint8_t* buf, uint8_t len );
+
+}
+
diff --git a/tos/chips/cc2420_tkn154/CaptureTime.nc b/tos/chips/cc2420_tkn154/CaptureTime.nc
new file mode 100644 (file)
index 0000000..45e7300
--- /dev/null
@@ -0,0 +1,43 @@
+/* 
+ * Copyright (c) 2008, Technische Universitaet Berlin 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
+ * Technische Universitaet Berlin 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 COPYRIGHT OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+interface CaptureTime
+{
+  /**
+   * Convert a capture time (+ symbol offset) to local time.
+   *
+   * @param   time  capture time
+   * @param   localTime capture time converted to local time + offset symbols
+   * @param   offset time in symbols (16 us) to add to capture time
+   */
+  async command void convert(uint16_t time, ieee154_reftime_t *localTime, int16_t offset);
+}
diff --git a/tos/chips/cc2420_tkn154/ReferenceTime.nc b/tos/chips/cc2420_tkn154/ReferenceTime.nc
new file mode 100644 (file)
index 0000000..e91e0e6
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+ * Copyright (c) 2008, Technische Universitaet Berlin 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
+ * Technische Universitaet Berlin 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 COPYRIGHT OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+interface ReferenceTime
+{
+  /** 
+   * Gets current reference time plus dt symbols.
+   */
+  async command void getNow(ieee154_reftime_t* reftime, uint16_t dt);
+
+  /** 
+   * Converts reference time to local time.
+   */
+  async command uint32_t toLocalTime(ieee154_reftime_t* refTime);
+}
diff --git a/tos/chips/cc2420_tkn154/ReliableWait.nc b/tos/chips/cc2420_tkn154/ReliableWait.nc
new file mode 100644 (file)
index 0000000..02140b1
--- /dev/null
@@ -0,0 +1,49 @@
+/* 
+ * Copyright (c) 2008, Technische Universitaet Berlin 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
+ * Technische Universitaet Berlin 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 COPYRIGHT OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+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();
+}
diff --git a/tos/chips/cc2420_tkn154/TKN154_PHY.h b/tos/chips/cc2420_tkn154/TKN154_PHY.h
new file mode 100644 (file)
index 0000000..12b69f0
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008, Technische Universitaet Berlin
+ * 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 Technische Universitaet Berlin 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 COPYRIGHT 
+ * OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+// PHY constants for the CC2420
+#ifndef __TKN154_PHY_H
+#define __TKN154_PHY_H
+
+#include "TKN154_MAC.h"
+
+enum {
+
+  IEEE154_SUPPORTED_CHANNELS  = 0x07FFF800,
+  IEEE154_SYMBOLS_PER_OCTET   = 2,
+  IEEE154_TXPOWER_TOLERANCE   = 0x80,
+  IEEE154_SHR_DURATION        = (5 * IEEE154_SYMBOLS_PER_OCTET),
+  IEEE154_MAX_FRAME_DURATION  = (IEEE154_SHR_DURATION + ((IEEE154_aMaxPHYPacketSize + 1) * IEEE154_SYMBOLS_PER_OCTET)),
+  IEEE154_PREAMBLE_LENGTH     = (4*IEEE154_SYMBOLS_PER_OCTET),
+  IEEE154_SYNC_SYMBOL_OFFSET  = (1 * IEEE154_SYMBOLS_PER_OCTET),
+  IEEE154_MIN_LIFS_PERIOD     = 40,
+  IEEE154_MIN_SIFS_PERIOD     = 12,
+  IEEE154_ACK_WAIT_DURATION   = (20 + 12 + IEEE154_SHR_DURATION + 6 * IEEE154_SYMBOLS_PER_OCTET),
+  // TODO: check BATT_LIFE_EXT
+  IEEE154_BATT_LIFE_EXT_PERIODS      = 1,
+  IEEE154_BATT_LIFE_EXT_PERIOD_TERM3 = 1,
+  IEEE154_TIMESTAMP_SUPPORTED        = TRUE,
+
+};
+
+#include "Timer62500hz.h"
+#define TSymbolIEEE802154 T62500hz
+
+#endif
+
diff --git a/tos/chips/cc2420_tkn154/Timestamp.nc b/tos/chips/cc2420_tkn154/Timestamp.nc
new file mode 100644 (file)
index 0000000..0f04163
--- /dev/null
@@ -0,0 +1,82 @@
+/* 
+ * Copyright (c) 2008, Technische Universitaet Berlin 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
+ * Technische Universitaet Berlin 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 COPYRIGHT OWNER OR 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$ $Date$ 
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+#include "IEEE802154.h"
+interface Timestamp
+{
+  /**
+   * The transmission of a packet has started (the PHY preamble is being 
+   * transmitted).
+   * Within the event handler the <code>modifyPayload()<\code> command can 
+   * be called to modify the contents of the frame's payload.
+   *
+   * @param frameType     the type of frame (BEACON=0, DATA=1, ACK=2, COMMAND=3)
+   * @param msduHandle    for DATA frames the handle associated with the MSDU,
+   *                      otherwise undefined
+   * @param payload       the MAC payload (e.g. in a DATA frame this is the msdu,
+   *                      in a BEACON frame this is the first byte of the SFSpec)
+   * @param token         a token to be used as parameter for the
+   *                      <code>modifyPayload()<\code> command
+   */
+  async event void transmissionStarted(uint8_t frameType, uint8_t msduHandle, uint8_t *payload, uint8_t token);
+
+  /**
+   * The Start-of-Frame Delimiter of an outgoing frame has been transmitted.
+   * Within the event handler the <code>modifyPayload()<\code> command may
+   * be called to modify the contents of the frame's payload.
+   *
+   * @param time          the time when the SFD was transmitted, expressed
+   *                      in 15.4 symbols as determined by a call to a T62500hz
+   *                      Alarm/Timer.getNow()
+   * @param frameType     the type of frame (BEACON=0, DATA=1, ACK=2, COMMAND=3)
+   * @param msduHandle    for DATA frames the handle associated with the MSDU,
+   *                      otherwise undefined
+   * @param payload       the MAC payload (e.g. in a DATA frame this is the msdu,
+   *                      in a BEACON frame this is the first byte of the SFSpec)
+   * @param token         a token to be used as parameter for the
+   *                      <code>modifyPayload()<\code> command
+   */
+  async event void transmittedSFD(uint32_t time, uint8_t frameType, uint8_t msduHandle, uint8_t *payload, uint8_t token);
+
+  /**
+   * Modify (overwrite) the contents of the MAC payload. This command must 
+   * only be called in the context of a <code>transmittedSFD()<\code> event and it
+   * should return fast. Note: the smaller offset is the faster 
+   * <code>transmittedSFD()<\code> must be finished (offset of zero might not work).
+   *
+   * @param token   the token signalled by <code>transmittedSFD()<\code>
+   * @param offset  the offset in the frame's payload to start modifying; 
+   *                an offset of zero means the first byte of the MAC payload field
+   * @param buf     data to write
+   * @param len     number of bytes to write
+   */
+  async command void modifyMACPayload(uint8_t token, uint8_t offset, uint8_t* buf, uint8_t len);
+}