]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
New CC2420 architecture in place for 2.0.2 release. See the README.txt file for...
authorrincon <rincon>
Wed, 4 Jul 2007 00:37:14 +0000 (00:37 +0000)
committerrincon <rincon>
Wed, 4 Jul 2007 00:37:14 +0000 (00:37 +0000)
53 files changed:
tos/chips/cc2420/CC2420.h [new file with mode: 0644]
tos/chips/cc2420/CC2420ActiveMessageC.nc [new file with mode: 0644]
tos/chips/cc2420/CC2420ActiveMessageP.nc [new file with mode: 0644]
tos/chips/cc2420/IEEE802154.h [new file with mode: 0644]
tos/chips/cc2420/README.txt [new file with mode: 0644]
tos/chips/cc2420/alarm/AlarmMultiplexC.nc [new file with mode: 0644]
tos/chips/cc2420/control/CC2420ControlC.nc [new file with mode: 0644]
tos/chips/cc2420/control/CC2420ControlP.nc [new file with mode: 0644]
tos/chips/cc2420/csma/CC2420CsmaC.nc [new file with mode: 0644]
tos/chips/cc2420/csma/CC2420CsmaP.nc [new file with mode: 0644]
tos/chips/cc2420/htmlreport_3-July-2007_05-05-PM.tar.gz [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Config.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Fifo.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Packet.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420PacketBody.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Power.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Ram.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Receive.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Register.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Strobe.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/CC2420Transmit.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/ChipSpiResource.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/PowerCycle.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/RadioBackoff.nc [new file with mode: 0644]
tos/chips/cc2420/interfaces/ReceiveIndicator.nc [new file with mode: 0644]
tos/chips/cc2420/link/PacketLinkC.nc [new file with mode: 0644]
tos/chips/cc2420/link/PacketLinkDummyC.nc [new file with mode: 0644]
tos/chips/cc2420/link/PacketLinkDummyP.nc [new file with mode: 0644]
tos/chips/cc2420/link/PacketLinkP.nc [new file with mode: 0644]
tos/chips/cc2420/link/readme.txt [new file with mode: 0644]
tos/chips/cc2420/lowpan/CC2420TinyosNetworkC.nc [new file with mode: 0644]
tos/chips/cc2420/lowpan/CC2420TinyosNetworkP.nc [new file with mode: 0644]
tos/chips/cc2420/lowpan/readme.txt [new file with mode: 0644]
tos/chips/cc2420/lpl/DefaultLpl.h [new file with mode: 0644]
tos/chips/cc2420/lpl/DefaultLplC.nc [new file with mode: 0644]
tos/chips/cc2420/lpl/DefaultLplP.nc [new file with mode: 0644]
tos/chips/cc2420/lpl/DummyLplC.nc [new file with mode: 0644]
tos/chips/cc2420/lpl/DummyLplP.nc [new file with mode: 0644]
tos/chips/cc2420/lpl/PowerCycleC.nc [new file with mode: 0644]
tos/chips/cc2420/lpl/PowerCycleP.nc [new file with mode: 0644]
tos/chips/cc2420/lpl/readme.txt [new file with mode: 0644]
tos/chips/cc2420/packet/CC2420PacketC.nc [new file with mode: 0644]
tos/chips/cc2420/receive/CC2420ReceiveC.nc [new file with mode: 0644]
tos/chips/cc2420/receive/CC2420ReceiveP.nc [new file with mode: 0644]
tos/chips/cc2420/spi/CC2420SpiC.nc [new file with mode: 0644]
tos/chips/cc2420/spi/CC2420SpiP.nc [new file with mode: 0644]
tos/chips/cc2420/spi/CC2420SpiWireC.nc [new file with mode: 0644]
tos/chips/cc2420/transmit/CC2420TransmitC.nc [new file with mode: 0644]
tos/chips/cc2420/transmit/CC2420TransmitP.nc [new file with mode: 0644]
tos/chips/cc2420/unique/UniqueReceiveC.nc [new file with mode: 0644]
tos/chips/cc2420/unique/UniqueReceiveP.nc [new file with mode: 0644]
tos/chips/cc2420/unique/UniqueSendC.nc [new file with mode: 0644]
tos/chips/cc2420/unique/UniqueSendP.nc [new file with mode: 0644]

diff --git a/tos/chips/cc2420/CC2420.h b/tos/chips/cc2420/CC2420.h
new file mode 100644 (file)
index 0000000..46afe34
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * 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
+ * @version $Revision$ $Date$
+ */
+
+#ifndef __CC2420_H__
+#define __CC2420_H__
+
+typedef uint8_t cc2420_status_t;
+
+/**
+ * CC2420 header.  An I-frame (interoperability frame) header has an 
+ * extra network byte specified by 6LowPAN
+ */
+typedef nx_struct cc2420_header_t {
+  nxle_uint8_t length;
+  nxle_uint16_t fcf;
+  nxle_uint8_t dsn;
+  nxle_uint16_t destpan;
+  nxle_uint16_t dest;
+  nxle_uint16_t src;
+  
+  /** I-Frame 6LowPAN interoperability byte */
+#ifdef CC2420_IFRAME_TYPE
+  nxle_uint8_t network;
+#endif
+
+  nxle_uint8_t type;
+} cc2420_header_t;
+  
+/**
+ * CC2420 Packet Footer
+ */
+typedef nx_struct cc2420_footer_t {
+} cc2420_footer_t;
+
+/**
+ * CC2420 Packet metadata. Contains extra information about the message
+ * that will not be transmitted
+ */
+typedef nx_struct cc2420_metadata_t {
+  nx_uint8_t tx_power;
+  nx_uint8_t rssi;
+  nx_uint8_t lqi;
+  nx_bool crc;
+  nx_bool ack;
+  nx_uint16_t time;
+  nx_uint16_t rxInterval;
+
+  /** Packet Link Metadata */
+#ifdef PACKET_LINK
+  nx_uint16_t maxRetries;
+  nx_uint16_t retryDelay;
+#endif
+
+} cc2420_metadata_t;
+
+
+typedef nx_struct cc2420_packet_t {
+  cc2420_header_t packet;
+  nx_uint8_t data[];
+} cc2420_packet_t;
+
+
+#ifndef TOSH_DATA_LENGTH
+#define TOSH_DATA_LENGTH 28
+#endif
+
+#ifndef CC2420_DEF_CHANNEL
+#define CC2420_DEF_CHANNEL 26
+#endif
+
+#ifndef CC2420_DEF_RFPOWER
+#define CC2420_DEF_RFPOWER 31
+#endif
+
+/**
+ * Ideally, your receive history size should be equal to the number of
+ * RF neighbors your node will have
+ */
+#ifndef RECEIVE_HISTORY_SIZE
+#define RECEIVE_HISTORY_SIZE 4
+#endif
+
+/** 
+ * The 6LowPAN ID has yet to be defined for a TinyOS network.
+ */
+#ifndef TINYOS_6LOWPAN_NETWORK_ID
+#define TINYOS_6LOWPAN_NETWORK_ID 0x0
+#endif
+
+
+enum {
+  // size of the header not including the length byte
+  MAC_HEADER_SIZE = sizeof( cc2420_header_t ) - 1,
+  // size of the footer (FCS field)
+  MAC_FOOTER_SIZE = sizeof( uint16_t ),
+  // MDU
+  MAC_PACKET_SIZE = MAC_HEADER_SIZE + TOSH_DATA_LENGTH + MAC_FOOTER_SIZE,
+};
+
+enum cc2420_enums {
+  CC2420_TIME_ACK_TURNAROUND = 7, // jiffies
+  CC2420_TIME_VREN = 20,          // jiffies
+  CC2420_TIME_SYMBOL = 2,         // 2 symbols / jiffy
+  CC2420_BACKOFF_PERIOD = ( 20 / CC2420_TIME_SYMBOL ), // symbols
+  CC2420_MIN_BACKOFF = ( 20 / CC2420_TIME_SYMBOL ),  // platform specific?
+  CC2420_ACK_WAIT_DELAY = 256,    // jiffies
+};
+
+enum cc2420_status_enums {
+  CC2420_STATUS_RSSI_VALID = 1 << 1,
+  CC2420_STATUS_LOCK = 1 << 2,
+  CC2420_STATUS_TX_ACTIVE = 1 << 3,
+  CC2420_STATUS_ENC_BUSY = 1 << 4,
+  CC2420_STATUS_TX_UNDERFLOW = 1 << 5,
+  CC2420_STATUS_XOSC16M_STABLE = 1 << 6,
+};
+
+enum cc2420_config_reg_enums {
+  CC2420_SNOP = 0x00,
+  CC2420_SXOSCON = 0x01,
+  CC2420_STXCAL = 0x02,
+  CC2420_SRXON = 0x03,
+  CC2420_STXON = 0x04,
+  CC2420_STXONCCA = 0x05,
+  CC2420_SRFOFF = 0x06,
+  CC2420_SXOSCOFF = 0x07,
+  CC2420_SFLUSHRX = 0x08,
+  CC2420_SFLUSHTX = 0x09,
+  CC2420_SACK = 0x0a,
+  CC2420_SACKPEND = 0x0b,
+  CC2420_SRXDEC = 0x0c,
+  CC2420_STXENC = 0x0d,
+  CC2420_SAES = 0x0e,
+  CC2420_MAIN = 0x10,
+  CC2420_MDMCTRL0 = 0x11,
+  CC2420_MDMCTRL1 = 0x12,
+  CC2420_RSSI = 0x13,
+  CC2420_SYNCWORD = 0x14,
+  CC2420_TXCTRL = 0x15,
+  CC2420_RXCTRL0 = 0x16,
+  CC2420_RXCTRL1 = 0x17,
+  CC2420_FSCTRL = 0x18,
+  CC2420_SECCTRL0 = 0x19,
+  CC2420_SECCTRL1 = 0x1a,
+  CC2420_BATTMON = 0x1b,
+  CC2420_IOCFG0 = 0x1c,
+  CC2420_IOCFG1 = 0x1d,
+  CC2420_MANFIDL = 0x1e,
+  CC2420_MANFIDH = 0x1f,
+  CC2420_FSMTC = 0x20,
+  CC2420_MANAND = 0x21,
+  CC2420_MANOR = 0x22,
+  CC2420_AGCCTRL = 0x23,
+  CC2420_AGCTST0 = 0x24,
+  CC2420_AGCTST1 = 0x25,
+  CC2420_AGCTST2 = 0x26,
+  CC2420_FSTST0 = 0x27,
+  CC2420_FSTST1 = 0x28,
+  CC2420_FSTST2 = 0x29,
+  CC2420_FSTST3 = 0x2a,
+  CC2420_RXBPFTST = 0x2b,
+  CC2420_FMSTATE = 0x2c,
+  CC2420_ADCTST = 0x2d,
+  CC2420_DACTST = 0x2e,
+  CC2420_TOPTST = 0x2f,
+  CC2420_TXFIFO = 0x3e,
+  CC2420_RXFIFO = 0x3f,
+};
+
+enum cc2420_ram_addr_enums {
+  CC2420_RAM_TXFIFO = 0x000,
+  CC2420_RAM_RXFIFO = 0x080,
+  CC2420_RAM_KEY0 = 0x100,
+  CC2420_RAM_RXNONCE = 0x110,
+  CC2420_RAM_SABUF = 0x120,
+  CC2420_RAM_KEY1 = 0x130,
+  CC2420_RAM_TXNONCE = 0x140,
+  CC2420_RAM_CBCSTATE = 0x150,
+  CC2420_RAM_IEEEADR = 0x160,
+  CC2420_RAM_PANID = 0x168,
+  CC2420_RAM_SHORTADR = 0x16a,
+};
+
+enum cc2420_nonce_enums {
+  CC2420_NONCE_BLOCK_COUNTER = 0,
+  CC2420_NONCE_KEY_SEQ_COUNTER = 2,
+  CC2420_NONCE_FRAME_COUNTER = 3,
+  CC2420_NONCE_SOURCE_ADDRESS = 7,
+  CC2420_NONCE_FLAGS = 15,
+};
+
+enum cc2420_main_enums {
+  CC2420_MAIN_RESETn = 15,
+  CC2420_MAIN_ENC_RESETn = 14,
+  CC2420_MAIN_DEMOD_RESETn = 13,
+  CC2420_MAIN_MOD_RESETn = 12,
+  CC2420_MAIN_FS_RESETn = 11,
+  CC2420_MAIN_XOSC16M_BYPASS = 0,
+};
+
+enum cc2420_mdmctrl0_enums {
+  CC2420_MDMCTRL0_RESERVED_FRAME_MODE = 13,
+  CC2420_MDMCTRL0_PAN_COORDINATOR = 12,
+  CC2420_MDMCTRL0_ADR_DECODE = 11,
+  CC2420_MDMCTRL0_CCA_HYST = 8,
+  CC2420_MDMCTRL0_CCA_MOD = 6,
+  CC2420_MDMCTRL0_AUTOCRC = 5,
+  CC2420_MDMCTRL0_AUTOACK = 4,
+  CC2420_MDMCTRL0_PREAMBLE_LENGTH = 0,
+};
+
+enum cc2420_mdmctrl1_enums {
+  CC2420_MDMCTRL1_CORR_THR = 6,
+  CC2420_MDMCTRL1_DEMOD_AVG_MODE = 5,
+  CC2420_MDMCTRL1_MODULATION_MODE = 4,
+  CC2420_MDMCTRL1_TX_MODE = 2,
+  CC2420_MDMCTRL1_RX_MODE = 0,
+};
+
+enum cc2420_rssi_enums {
+  CC2420_RSSI_CCA_THR = 8,
+  CC2420_RSSI_RSSI_VAL = 0,
+};
+
+enum cc2420_syncword_enums {
+  CC2420_SYNCWORD_SYNCWORD = 0,
+};
+
+enum cc2420_txctrl_enums {
+  CC2420_TXCTRL_TXMIXBUF_CUR = 14,
+  CC2420_TXCTRL_TX_TURNAROUND = 13,
+  CC2420_TXCTRL_TXMIX_CAP_ARRAY = 11,
+  CC2420_TXCTRL_TXMIX_CURRENT = 9,
+  CC2420_TXCTRL_PA_CURRENT = 6,
+  CC2420_TXCTRL_RESERVED = 5,
+  CC2420_TXCTRL_PA_LEVEL = 0,
+};
+
+enum cc2420_rxctrl0_enums {
+  CC2420_RXCTRL0_RXMIXBUF_CUR = 12,
+  CC2420_RXCTRL0_HIGH_LNA_GAIN = 10,
+  CC2420_RXCTRL0_MED_LNA_GAIN = 8,
+  CC2420_RXCTRL0_LOW_LNA_GAIN = 6,
+  CC2420_RXCTRL0_HIGH_LNA_CURRENT = 4,
+  CC2420_RXCTRL0_MED_LNA_CURRENT = 2,
+  CC2420_RXCTRL0_LOW_LNA_CURRENT = 0,
+};
+
+enum cc2420_rxctrl1_enums {
+  CC2420_RXCTRL1_RXBPF_LOCUR = 13,
+  CC2420_RXCTRL1_RXBPF_MIDCUR = 12,
+  CC2420_RXCTRL1_LOW_LOWGAIN = 11,
+  CC2420_RXCTRL1_MED_LOWGAIN = 10,
+  CC2420_RXCTRL1_HIGH_HGM = 9,
+  CC2420_RXCTRL1_MED_HGM = 8,
+  CC2420_RXCTRL1_LNA_CAP_ARRAY = 6,
+  CC2420_RXCTRL1_RXMIX_TAIL = 4,
+  CC2420_RXCTRL1_RXMIX_VCM = 2,
+  CC2420_RXCTRL1_RXMIX_CURRENT = 0,
+};
+
+enum cc2420_rsctrl_enums {
+  CC2420_FSCTRL_LOCK_THR = 14,
+  CC2420_FSCTRL_CAL_DONE = 13,
+  CC2420_FSCTRL_CAL_RUNNING = 12,
+  CC2420_FSCTRL_LOCK_LENGTH = 11,
+  CC2420_FSCTRL_LOCK_STATUS = 10,
+  CC2420_FSCTRL_FREQ = 0,
+};
+
+enum cc2420_secctrl0_enums {
+  CC2420_SECCTRL0_RXFIFO_PROTECTION = 9,
+  CC2420_SECCTRL0_SEC_CBC_HEAD = 8,
+  CC2420_SECCTRL0_SEC_SAKEYSEL = 7,
+  CC2420_SECCTRL0_SEC_TXKEYSEL = 6,
+  CC2420_SECCTRL0_SEC_RXKEYSEL = 5,
+  CC2420_SECCTRL0_SEC_M = 2,
+  CC2420_SECCTRL0_SEC_MODE = 0,
+};
+
+enum cc2420_secctrl1_enums {
+  CC2420_SECCTRL1_SEC_TXL = 8,
+  CC2420_SECCTRL1_SEC_RXL = 0,
+};
+
+enum cc2420_battmon_enums {
+  CC2420_BATTMON_BATT_OK = 6,
+  CC2420_BATTMON_BATTMON_EN = 5,
+  CC2420_BATTMON_BATTMON_VOLTAGE = 0,
+};
+
+enum cc2420_iocfg0_enums {
+  CC2420_IOCFG0_BCN_ACCEPT = 11,
+  CC2420_IOCFG0_FIFO_POLARITY = 10,
+  CC2420_IOCFG0_FIFOP_POLARITY = 9,
+  CC2420_IOCFG0_SFD_POLARITY = 8,
+  CC2420_IOCFG0_CCA_POLARITY = 7,
+  CC2420_IOCFG0_FIFOP_THR = 0,
+};
+
+enum cc2420_iocfg1_enums {
+  CC2420_IOCFG1_HSSD_SRC = 10,
+  CC2420_IOCFG1_SFDMUX = 5,
+  CC2420_IOCFG1_CCAMUX = 0,
+};
+
+enum cc2420_manfidl_enums {
+  CC2420_MANFIDL_PARTNUM = 12,
+  CC2420_MANFIDL_MANFID = 0,
+};
+
+enum cc2420_manfidh_enums {
+  CC2420_MANFIDH_VERSION = 12,
+  CC2420_MANFIDH_PARTNUM = 0,
+};
+
+enum cc2420_fsmtc_enums {
+  CC2420_FSMTC_TC_RXCHAIN2RX = 13,
+  CC2420_FSMTC_TC_SWITCH2TX = 10,
+  CC2420_FSMTC_TC_PAON2TX = 6,
+  CC2420_FSMTC_TC_TXEND2SWITCH = 3,
+  CC2420_FSMTC_TC_TXEND2PAOFF = 0,
+};
+
+enum cc2420_sfdmux_enums {
+  CC2420_SFDMUX_SFD = 0,
+  CC2420_SFDMUX_XOSC16M_STABLE = 24,
+};
+
+#endif
diff --git a/tos/chips/cc2420/CC2420ActiveMessageC.nc b/tos/chips/cc2420/CC2420ActiveMessageC.nc
new file mode 100644 (file)
index 0000000..84a6728
--- /dev/null
@@ -0,0 +1,113 @@
+/*                                                                     tab:4
+ * "Copyright (c) 2005 Stanford University. 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 STANFORD UNIVERSITY 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 STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * STANFORD UNIVERSITY 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 STANFORD UNIVERSITY
+ * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS."
+ */
+
+/**
+ * The Active Message layer for the CC2420 radio. This configuration
+ * just layers the AM dispatch (CC2420ActiveMessageM) on top of the
+ * underlying CC2420 radio packet (CC2420CsmaCsmaCC), which is
+ * inherently an AM packet (acknowledgements based on AM destination
+ * addr and group). Note that snooping may not work, due to CC2420
+ * early packet rejection if acknowledgements are enabled.
+ *
+ * @author Philip Levis
+ * @author David Moss
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+#include "AM.h"
+
+configuration CC2420ActiveMessageC {
+  provides {
+    interface SplitControl;
+    interface AMSend[am_id_t id];
+    interface Receive[am_id_t id];
+    interface Receive as Snoop[am_id_t id];
+    interface AMPacket;
+    interface Packet;
+    interface CC2420Packet;
+    interface PacketAcknowledgements;
+    interface RadioBackoff[am_id_t amId];
+    interface LowPowerListening;
+    interface PacketLink;
+  }
+}
+implementation {
+
+  components CC2420ActiveMessageP as AM;
+  components CC2420CsmaC as CsmaC;
+  components ActiveMessageAddressC;
+  components UniqueSendC;
+  components UniqueReceiveC;
+  components CC2420TinyosNetworkC;
+  components CC2420PacketC;
+  components CC2420ControlC;
+  
+#if defined(LOW_POWER_LISTENING) || defined(ACK_LOW_POWER_LISTENING)
+  components DefaultLplC as LplC;
+#else
+  components DummyLplC as LplC;
+#endif
+
+#if defined(PACKET_LINK)
+  components PacketLinkC as LinkC;
+#else
+  components PacketLinkDummyC as LinkC;
+#endif
+
+  
+  RadioBackoff = CsmaC;
+  Packet = AM;
+  AMSend = AM;
+  Receive = AM.Receive;
+  Snoop = AM.Snoop;
+  AMPacket = AM;
+  PacketLink = LinkC;
+  LowPowerListening = LplC;
+  CC2420Packet = CC2420PacketC;
+  PacketAcknowledgements = CC2420PacketC;
+  
+  
+  // SplitControl Layers
+  SplitControl = LplC;
+  LplC.SubControl -> CsmaC;
+  
+  // Send Layers
+  AM.SubSend -> UniqueSendC;
+  UniqueSendC.SubSend -> LinkC;
+  LinkC.SubSend -> LplC.Send;
+  LplC.SubSend -> CC2420TinyosNetworkC.Send;
+  CC2420TinyosNetworkC.SubSend -> CsmaC;
+  
+  // Receive Layers
+  AM.SubReceive -> LplC;
+  LplC.SubReceive -> UniqueReceiveC.Receive;
+  UniqueReceiveC.SubReceive -> CC2420TinyosNetworkC.Receive;
+  CC2420TinyosNetworkC.SubReceive -> CsmaC;
+
+  AM.ActiveMessageAddress -> ActiveMessageAddressC;
+  AM.CC2420Packet -> CC2420PacketC;
+  AM.CC2420PacketBody -> CC2420PacketC;
+  AM.CC2420Config -> CC2420ControlC;
+  
+}
diff --git a/tos/chips/cc2420/CC2420ActiveMessageP.nc b/tos/chips/cc2420/CC2420ActiveMessageP.nc
new file mode 100644 (file)
index 0000000..0f93440
--- /dev/null
@@ -0,0 +1,218 @@
+/*                                                                     tab:4
+ * "Copyright (c) 2005 Stanford University. 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 STANFORD UNIVERSITY 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 STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * STANFORD UNIVERSITY 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 STANFORD UNIVERSITY
+ * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS."
+ */
+
+
+/**
+ * Active message implementation on top of the CC2420 radio. This
+ * implementation uses the 16-bit addressing mode of 802.15.4: the
+ * only additional byte it adds is the AM id byte, as the first byte
+ * of the data payload.
+ *
+ * @author Philip Levis
+ * @version $Revision$ $Date$
+ */
+#include "CC2420.h"
+
+module CC2420ActiveMessageP {
+  provides {
+    interface AMSend[am_id_t id];
+    interface Receive[am_id_t id];
+    interface Receive as Snoop[am_id_t id];
+    interface AMPacket;
+    interface Packet;
+  }
+  uses {
+    interface Send as SubSend;
+    interface Receive as SubReceive;
+    interface CC2420Packet;
+    interface CC2420PacketBody;
+    interface CC2420Config;
+    interface ActiveMessageAddress;
+  }
+}
+implementation {
+
+  enum {
+    CC2420_SIZE = MAC_HEADER_SIZE + MAC_FOOTER_SIZE,
+  };
+  
+  /***************** AMSend Commands ****************/
+  command error_t AMSend.send[am_id_t id](am_addr_t addr,
+                                         message_t* msg,
+                                         uint8_t len) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader( msg );
+    header->type = id;
+    header->dest = addr;
+    header->destpan = call CC2420Config.getPanAddr();
+    
+    return call SubSend.send( msg, len + CC2420_SIZE );
+  }
+
+  command error_t AMSend.cancel[am_id_t id](message_t* msg) {
+    return call SubSend.cancel(msg);
+  }
+
+  command uint8_t AMSend.maxPayloadLength[am_id_t id]() {
+    return call Packet.maxPayloadLength();
+  }
+
+  command void* AMSend.getPayload[am_id_t id](message_t* m) {
+    return call Packet.getPayload(m, NULL);
+  }
+
+  /***************** Receive Commands ****************/
+  command void* Receive.getPayload[am_id_t id](message_t* m, uint8_t* len) {
+    return call Packet.getPayload(m, len);
+  }
+
+  command uint8_t Receive.payloadLength[am_id_t id](message_t* m) {
+    return call Packet.payloadLength(m);
+  }
+  
+  /***************** Snoop Commands ****************/
+  command void* Snoop.getPayload[am_id_t id](message_t* m, uint8_t* len) {
+    return call Packet.getPayload(m, len);
+  }
+
+  command uint8_t Snoop.payloadLength[am_id_t id](message_t* m) {
+    return call Packet.payloadLength(m);
+  }
+
+  /***************** AMPacket Commands ****************/
+  command am_addr_t AMPacket.address() {
+    return call ActiveMessageAddress.amAddress();
+  }
+  command am_addr_t AMPacket.destination(message_t* amsg) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader(amsg);
+    return header->dest;
+  }
+  command am_addr_t AMPacket.source(message_t* amsg) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader(amsg);
+    return header->src;
+  }
+
+  command void AMPacket.setDestination(message_t* amsg, am_addr_t addr) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader(amsg);
+    header->dest = addr;
+  }
+
+  command void AMPacket.setSource(message_t* amsg, am_addr_t addr) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader(amsg);
+    header->src = addr;
+  }
+
+  command bool AMPacket.isForMe(message_t* amsg) {
+    return (call AMPacket.destination(amsg) == call AMPacket.address() ||
+           call AMPacket.destination(amsg) == AM_BROADCAST_ADDR);
+  }
+
+  command am_id_t AMPacket.type(message_t* amsg) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader(amsg);
+    return header->type;
+  }
+
+  command void AMPacket.setType(message_t* amsg, am_id_t type) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader(amsg);
+    header->type = type;
+  }
+  
+  command am_group_t AMPacket.group(message_t* amsg) {
+    return (call CC2420PacketBody.getHeader(amsg))->destpan;
+  }
+
+  command void AMPacket.setGroup(message_t* amsg, am_group_t grp) {
+    // Overridden intentionally when we send()
+    (call CC2420PacketBody.getHeader(amsg))->destpan = grp;
+  }
+
+  command am_group_t AMPacket.localGroup() {
+    return call CC2420Config.getPanAddr();
+  }
+  
+
+  /***************** Packet Commands ****************/
+  command void Packet.clear(message_t* msg) {
+  }
+  
+  command uint8_t Packet.payloadLength(message_t* msg) {
+    return (call CC2420PacketBody.getHeader(msg))->length - CC2420_SIZE;
+  }
+  
+  command void Packet.setPayloadLength(message_t* msg, uint8_t len) {
+    (call CC2420PacketBody.getHeader(msg))->length  = len + CC2420_SIZE;
+  }
+  
+  command uint8_t Packet.maxPayloadLength() {
+    return TOSH_DATA_LENGTH;
+  }
+  
+  command void* Packet.getPayload(message_t* msg, uint8_t* len) {
+    if (len != NULL) {
+      *len = call Packet.payloadLength(msg);
+    }
+    return msg->data;
+  }
+
+  
+  /***************** SubSend Events ****************/
+  event void SubSend.sendDone(message_t* msg, error_t result) {
+    signal AMSend.sendDone[call AMPacket.type(msg)](msg, result);
+  }
+
+  
+  /***************** SubReceive Events ****************/
+  event message_t* SubReceive.receive(message_t* msg, void* payload, uint8_t len) {
+    if (call AMPacket.isForMe(msg)) {
+      return signal Receive.receive[call AMPacket.type(msg)](msg, payload, len - CC2420_SIZE);
+    }
+    else {
+      return signal Snoop.receive[call AMPacket.type(msg)](msg, payload, len - CC2420_SIZE);
+    }
+  }
+  
+
+  /***************** ActiveMessageAddress Events ****************/
+  async event void ActiveMessageAddress.changed() {
+  }
+  
+  /***************** CC2420Config Events ****************/
+  event void CC2420Config.syncDone( error_t error ) {
+  }
+  
+  /***************** Defaults ****************/
+  default event message_t* Receive.receive[am_id_t id](message_t* msg, void* payload, uint8_t len) {
+    return msg;
+  }
+  
+  default event message_t* Snoop.receive[am_id_t id](message_t* msg, void* payload, uint8_t len) {
+    return msg;
+  }
+
+  default event void AMSend.sendDone[uint8_t id](message_t* msg, error_t err) {
+    return;
+  }
+
+}
diff --git a/tos/chips/cc2420/IEEE802154.h b/tos/chips/cc2420/IEEE802154.h
new file mode 100644 (file)
index 0000000..6329034
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#ifndef __IEEE802154_H__
+#define __IEEE802154_H__
+
+enum ieee154_fcf_enums {
+  IEEE154_FCF_FRAME_TYPE = 0,
+  IEEE154_FCF_SECURITY_ENABLED = 3,
+  IEEE154_FCF_FRAME_PENDING = 4,
+  IEEE154_FCF_ACK_REQ = 5,
+  IEEE154_FCF_INTRAPAN = 6,
+  IEEE154_FCF_DEST_ADDR_MODE = 10,
+  IEEE154_FCF_SRC_ADDR_MODE = 14,
+};
+
+enum ieee154_fcf_type_enums {
+  IEEE154_TYPE_BEACON = 0,
+  IEEE154_TYPE_DATA = 1,
+  IEEE154_TYPE_ACK = 2,
+  IEEE154_TYPE_MAC_CMD = 3,
+};
+
+enum iee154_fcf_addr_mode_enums {
+  IEEE154_ADDR_NONE = 0,
+  IEEE154_ADDR_SHORT = 2,
+  IEEE154_ADDR_EXT = 3,
+};
+
+#endif
diff --git a/tos/chips/cc2420/README.txt b/tos/chips/cc2420/README.txt
new file mode 100644 (file)
index 0000000..33d184b
--- /dev/null
@@ -0,0 +1,102 @@
+
+============================================================
+CC2420 2.0.2 Release Notes 7/2/07
+
+Updates (Moss)
+__________________________________________
+* New chip SPI bus arbitration working with Receive and Transmit.
+
+* Applied TUnit automated unit testing to CC2420 development
+  > Caught lots of bugs, especially through regression testing
+  > Source code in tinyos-2.x-contribs/tunit/
+
+* Applied TEP115 behavior to CC2420 SplitControl in Csma and Lpl
+
+* Updated ActiveMessageAddressC to provide the ActiveMessageAddress interface
+  > Updated CC2420ConfigP to handle ActiveMessageAddress.addressChanged() and
+    sync automatically upon address change events.
+
+* Updated CC2420Config interface to enable/disable sw/hw acknowledgements
+
+* Updated CC2420ConfigP to share register editing through single functions
+
+* Acknowledge after packet length and FCF check out valid.  
+  > The destination address is confirmed in hardware, so we don't need 
+    to download the entire header before acking.
+
+* Moved the getHeader() and getMetadata() commands to an internal interface
+  called CC2420PacketBody, provided by CC2420PacketC
+
+* Separated core functionality into different sub-packages/directories
+  > Updated micaz, telosb, intelmote2 .platform files
+  > Logically organizes code
+
+* Updated some LPL architecture
+  > Removed continuous modulation because it didn't work 100% and I don't have 
+    time to make it work.  
+  > Decreased backoffs and decreased on-time for detects, saving energy.
+
+* Updated to the new AMPacket interface; made the radio set the outbound
+  packet's destpan after send().
+
+
+Known issues
+__________________________________________
+
+
+
+
+============================================================
+CC2420 Release Notes 4/11/07
+
+This CC2420 stack contains two low power listening strategies,
+a packet retransmission layer, unique send and receive layers,
+ability to specify backoff and use of clear channel assessments
+on outbound messages, direct RSSI readings, ability to change 
+channels on the fly, an experimental 6LowPAN layer (not
+implemented by default), general bug fixes, and more.
+
+
+Known Issues
+__________________________________________
+ > LPL Lockups when the node is also accessing the USART.
+   This is a SPI bus issue, where shutting off the SPI
+   bus in the middle of an operation may cause the node
+   to hang.  Look to future versions on CVS for the fix.
+
+ > NoAck LPL doesn't ack at the end properly, and also isn't
+   finished being implemented. The CRC of the packet needs to 
+   manually be loaded into TXFIFO before continuous modulation.
+
+ > LPL stack is optimized for reliability at this point, since
+   SFD sampling is not implemented in this version. 
+
+Low Power Listening Schemes and Preprocessor Variables
+__________________________________________
+There are two low power listening schemes.  
+The default is called "AckLpl", because it inserts acknowledgement gaps andshort backoffs during the packet retransmission process. 
+This allows the transmitter to stop transmitting early, but increases the 
+power consumption per receive check.  This is better for slow receive
+check, high transmission rate networks.
+
+The second is called "NoAckLpl", because it does not insert acknowledgement
+gaps or backoffs in the retransmission process, so the receive checks are 
+shorter but the transmissions are longer.  This is more experimental than
+the Ack LPL version.  The radio continuously modulates the channel when
+delivering its packetized preamble.  This is better for fast receive check,
+low transmission rate networks.
+
+To compile in the default Ack LPL version, #define the preprocessor variable:
+  LOW_POWER_LISTENING
+  
+To compile in the PacketLink (auto-retransmission) layer, #define:
+  PACKET_LINK
+  
+To remove all acknowledgements, #define (or use CC2420Config in 2.0.2)
+  CC2420_NO_ACKNOWLEDGEMENTS
+  
+To use hardware auto-acks instead of software acks, #define:
+  CC2420_HW_ACKNOWLEDGEMENTS
+
+
diff --git a/tos/chips/cc2420/alarm/AlarmMultiplexC.nc b/tos/chips/cc2420/alarm/AlarmMultiplexC.nc
new file mode 100644 (file)
index 0000000..a63a925
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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
+ */
+
+/**
+ * A component that multiplexes the use of an alarm. The assumption is
+ * that its use is mutually exclusive and users check whether the
+ * events are for them.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#include <Timer.h>
+
+configuration AlarmMultiplexC {
+
+  provides interface Init;
+  provides interface Alarm<T32khz,uint32_t> as Alarm32khz32;
+
+}
+
+implementation {
+
+  components new HplCC2420AlarmC() as Alarm;
+
+  Init = Alarm;
+  Alarm32khz32 = Alarm;
+
+}
diff --git a/tos/chips/cc2420/control/CC2420ControlC.nc b/tos/chips/cc2420/control/CC2420ControlC.nc
new file mode 100644 (file)
index 0000000..8eaf9ca
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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 for configuring a ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+#include "IEEE802154.h"
+
+configuration CC2420ControlC {
+
+  provides interface Resource;
+  provides interface CC2420Config;
+  provides interface CC2420Power;
+  provides interface Read<uint16_t> as ReadRssi;
+  
+}
+
+implementation {
+  
+  components CC2420ControlP;
+  Resource = CC2420ControlP;
+  CC2420Config = CC2420ControlP;
+  CC2420Power = CC2420ControlP;
+  ReadRssi = CC2420ControlP;
+
+  components MainC;
+  MainC.SoftwareInit -> CC2420ControlP;
+  
+  components CC2420ActiveMessageC;
+  CC2420ControlP.AMPacket -> CC2420ActiveMessageC;
+  
+  components AlarmMultiplexC as Alarm;
+  CC2420ControlP.StartupTimer -> Alarm;
+
+  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.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.RXCTRL1 -> Spi.RXCTRL1;
+  CC2420ControlP.RSSI  -> Spi.RSSI;
+
+  components new CC2420SpiC() as SyncSpiC;
+  CC2420ControlP.SyncResource -> SyncSpiC;
+
+  components new CC2420SpiC() as RssiResource;
+  CC2420ControlP.RssiResource -> RssiResource;
+  
+  components ActiveMessageAddressC;
+  CC2420ControlP.ActiveMessageAddress -> ActiveMessageAddressC;
+
+}
+
diff --git a/tos/chips/cc2420/control/CC2420ControlP.nc b/tos/chips/cc2420/control/CC2420ControlP.nc
new file mode 100644 (file)
index 0000000..582d8b0
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * 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)
+ * @version $Revision$ $Date$
+ */
+
+#include "Timer.h"
+
+module CC2420ControlP {
+
+  provides interface Init;
+  provides interface Resource;
+  provides interface CC2420Config;
+  provides interface CC2420Power;
+  provides interface Read<uint16_t> as ReadRssi;
+
+  uses interface Alarm<T32khz,uint32_t> as StartupTimer;
+  uses interface GeneralIO as CSN;
+  uses interface GeneralIO as RSTN;
+  uses interface GeneralIO as VREN;
+  uses interface GpioInterrupt as InterruptCCA;
+  uses interface ActiveMessageAddress;
+
+  uses interface CC2420Ram as PANID;
+  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 AMPacket;
+  
+  uses interface Resource as SpiResource;
+  uses interface Resource as RssiResource;
+  uses interface Resource as SyncResource;
+
+  uses interface Leds;
+
+}
+
+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;
+  
+  uint8_t m_tx_power;
+  
+  uint16_t m_pan;
+  
+  uint16_t m_short_addr;
+  
+  bool m_sync_busy;
+  
+  bool autoAckEnabled;
+  
+  bool hwAutoAckDefault;
+  
+  norace cc2420_control_state_t m_state = S_VREG_STOPPED;
+  
+  /***************** Prototypes ****************/
+
+  void writeFsctrl();
+  void writeMdmctrl0();
+  void writeId();
+
+  task void sync();
+  task void syncDone();
+    
+  /***************** Init Commands ****************/
+  command error_t Init.init() {
+    call CSN.makeOutput();
+    call RSTN.makeOutput();
+    call VREN.makeOutput();
+    
+    m_short_addr = call ActiveMessageAddress.amAddress();
+    m_pan = call ActiveMessageAddress.amGroup();
+    m_tx_power = CC2420_DEF_RFPOWER;
+    m_channel = CC2420_DEF_CHANNEL;
+    
+#if defined(CC2420_NO_ACKNOWLEDGEMENTS)
+    autoAckEnabled = FALSE;
+#else
+    autoAckEnabled = TRUE;
+#endif
+
+#if defined(CC2420_HW_ACKNOWLEDGEMENTS)
+    hwAutoAckDefault = TRUE;
+#else
+    hwAutoAckDefault = FALSE;
+#endif
+
+    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();
+    }
+  }
+
+  /***************** 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 StartupTimer.start( CC2420_TIME_VREN );
+    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 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 ) );
+    }
+    return SUCCESS;
+  }
+
+
+  async command error_t CC2420Power.stopOscillator() {
+    atomic {
+      if ( m_state != S_XOSC_STARTED ) {
+        return FAIL;
+      }
+      m_state = S_VREG_STARTED;
+      call SXOSCOFF.strobe();
+    }
+    return SUCCESS;
+  }
+
+  async command error_t CC2420Power.rxOn() {
+    atomic {
+      if ( m_state != S_XOSC_STARTED ) {
+        return FAIL;
+      }
+      call SRXON.strobe();
+    }
+    return SUCCESS;
+  }
+
+  async command error_t CC2420Power.rfOff() {
+    atomic {  
+      if ( m_state != S_XOSC_STARTED ) {
+        return FAIL;
+      }
+      call SRFOFF.strobe();
+    }
+    return SUCCESS;
+  }
+
+  
+  /***************** CC2420Config Commands ****************/
+  command uint8_t CC2420Config.getChannel() {
+    atomic return m_channel;
+  }
+
+  command void CC2420Config.setChannel( uint8_t channel ) {
+    atomic m_channel = channel;
+  }
+
+  command uint16_t CC2420Config.getShortAddr() {
+    atomic return m_short_addr;
+  }
+
+  command void CC2420Config.setShortAddr( uint16_t addr ) {
+    atomic m_short_addr = addr;
+  }
+
+  command uint16_t CC2420Config.getPanAddr() {
+    return m_pan;
+  }
+
+  command void CC2420Config.setPanAddr( uint16_t pan ) {
+    atomic m_pan = pan;
+  }
+
+  /**
+   * Sync must be called to commit software parameters configured on
+   * the microcontroller (through the CC2420Config interface) to the
+   * CC2420 radio chip.
+   */
+  command error_t CC2420Config.sync() {
+    atomic {
+      if ( m_sync_busy ) {
+        return FAIL;
+      }
+      
+      m_sync_busy = TRUE;
+      if ( m_state == S_XOSC_STARTED ) {
+        call SyncResource.request();
+      } else {
+        post syncDone();
+      }
+    }
+    return SUCCESS;
+  }
+
+  /**
+   * Sync must be called for acknowledgement changes to take effect
+   * @param enableAutoAck TRUE to enable auto acknowledgements
+   * @param hwAutoAck TRUE to default to hardware auto acks, FALSE to
+   *     default to software auto acknowledgements
+   */
+  command void CC2420Config.setAutoAck(bool enableAutoAck, bool hwAutoAck) {
+    autoAckEnabled = enableAutoAck;
+    hwAutoAckDefault = hwAutoAck;
+  }
+  
+  /**
+   * @return TRUE if hardware auto acks are the default, FALSE if software
+   *     acks are the default
+   */
+  async command bool CC2420Config.isHwAutoAckDefault() {
+    bool isHwAck;
+    atomic {
+      isHwAck = hwAutoAckDefault;
+    }
+    return isHwAck;    
+  }
+  
+  /**
+   * @return TRUE if auto acks are enabled
+   */
+  async command bool CC2420Config.isAutoAckEnabled() {
+    bool isAckEnabled;
+    atomic {
+      isAckEnabled = autoAckEnabled;
+    }
+    return isAckEnabled;
+  }
+  
+  /***************** ReadRssi Commands ****************/
+  command error_t ReadRssi.read() { 
+    return call RssiResource.request();
+  }
+  
+  /***************** Spi Resources Events ****************/
+  event void SyncResource.granted() {
+    call CSN.clr();
+    call SRFOFF.strobe();
+    writeFsctrl();
+    writeMdmctrl0();
+    writeId();
+    call CSN.set();
+    call CSN.clr();
+    call SRXON.strobe();
+    call CSN.set();
+    call SyncResource.release();
+    post syncDone();
+  }
+
+  event void SpiResource.granted() {
+    call CSN.clr();
+    signal Resource.granted();
+  }
+
+  event void RssiResource.granted() { 
+    uint16_t data;
+    call CSN.clr();
+    call RSSI.read(&data);
+    call CSN.set();
+    
+    call RssiResource.release();
+    data += 0x7f;
+    data &= 0x00ff;
+    signal ReadRssi.readDone(SUCCESS, data); 
+  }
+  
+  /***************** StartupTimer Events ****************/
+  async event void StartupTimer.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 IOCFG1.write( 0 );
+    writeId();
+    call CSN.set();
+    call CSN.clr();
+    signal CC2420Power.startOscillatorDone();
+  }
+  /***************** ActiveMessageAddress Events ****************/
+  async event void ActiveMessageAddress.changed() {
+    atomic {
+      m_short_addr = call ActiveMessageAddress.amAddress();
+      m_pan = call ActiveMessageAddress.amGroup();
+    }
+    
+    post sync();
+  }
+  
+  /***************** Tasks ****************/
+  /**
+   * Attempt to synchronize our current settings with the CC2420
+   */
+  task void sync() {
+    call CC2420Config.sync();
+  }
+  
+  task void syncDone() {
+    atomic m_sync_busy = FALSE;
+    signal CC2420Config.syncDone( SUCCESS );
+  }
+  
+  
+  /***************** 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 {
+      call MDMCTRL0.write( ( 1 << CC2420_MDMCTRL0_RESERVED_FRAME_MODE ) |
+          ( 1 << CC2420_MDMCTRL0_ADR_DECODE ) |
+          ( 2 << CC2420_MDMCTRL0_CCA_HYST ) |
+          ( 3 << CC2420_MDMCTRL0_CCA_MOD ) |
+          ( 1 << CC2420_MDMCTRL0_AUTOCRC ) |
+          ( (autoAckEnabled && hwAutoAckDefault) << CC2420_MDMCTRL0_AUTOACK ) |
+          ( 0 << 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 PANID register
+   */
+  void writeId() {
+    nxle_uint16_t id[ 2 ];
+
+    atomic {
+      id[ 0 ] = m_pan;
+      id[ 1 ] = m_short_addr;
+    }
+    
+    call PANID.write(0, (uint8_t*)&id, sizeof(id));
+  }
+
+
+  
+  /***************** Defaults ****************/
+  default event void CC2420Config.syncDone( error_t error ) {
+  }
+
+  default event void ReadRssi.readDone(error_t error, uint16_t data) {
+  }
+  
+}
diff --git a/tos/chips/cc2420/csma/CC2420CsmaC.nc b/tos/chips/cc2420/csma/CC2420CsmaC.nc
new file mode 100644 (file)
index 0000000..7e8dd51
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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
+ */
+
+/**
+ * Basic implementation of a CSMA MAC for the ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+#include "IEEE802154.h"
+
+configuration CC2420CsmaC {
+
+  provides interface SplitControl;
+  provides interface Send;
+  provides interface Receive;
+  provides interface RadioBackoff[am_id_t amId];
+
+}
+
+implementation {
+
+  components CC2420CsmaP as CsmaP;
+  RadioBackoff = CsmaP;
+  SplitControl = CsmaP;
+  Send = CsmaP;
+  
+  components CC2420ActiveMessageC;
+  CsmaP.AMPacket -> CC2420ActiveMessageC;
+  
+  components CC2420ControlC;
+  CsmaP.Resource -> CC2420ControlC;
+  CsmaP.CC2420Power -> CC2420ControlC;
+
+  components CC2420TransmitC;
+  CsmaP.SubControl -> CC2420TransmitC;
+  CsmaP.CC2420Transmit -> CC2420TransmitC;
+  CsmaP.SubBackoff -> CC2420TransmitC;
+
+  components CC2420ReceiveC;
+  Receive = CC2420ReceiveC;
+  CsmaP.SubControl -> CC2420ReceiveC;
+
+  components CC2420PacketC;
+  CsmaP.CC2420Packet -> CC2420PacketC;
+  CsmaP.CC2420PacketBody -> CC2420PacketC;
+  
+  components RandomC;
+  CsmaP.Random -> RandomC;
+
+  components new StateC();
+  CsmaP.SplitControlState -> StateC;
+  
+  components LedsC as Leds;
+  CsmaP.Leds -> Leds;
+  
+}
diff --git a/tos/chips/cc2420/csma/CC2420CsmaP.nc b/tos/chips/cc2420/csma/CC2420CsmaP.nc
new file mode 100644 (file)
index 0000000..fe49782
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+module CC2420CsmaP {
+
+  provides interface SplitControl;
+  provides interface Send;
+  provides interface RadioBackoff[am_id_t amId];
+
+  uses interface Resource;
+  uses interface CC2420Power;
+  uses interface StdControl as SubControl;
+  uses interface CC2420Transmit;
+  uses interface RadioBackoff as SubBackoff;
+  uses interface Random;
+  uses interface AMPacket;
+  uses interface Leds;
+  uses interface CC2420Packet;
+  uses interface CC2420PacketBody;
+  uses interface State as SplitControlState;
+
+}
+
+implementation {
+
+  enum {
+    S_STOPPED,
+    S_STARTING,
+    S_STARTED,
+    S_STOPPING,
+    S_TRANSMITTING,
+  };
+
+  message_t* m_msg;
+  
+  error_t sendErr = SUCCESS;
+  
+  /** TRUE if we are to use CCA when sending the current packet */
+  norace bool ccaOn;
+  
+  /****************** Prototypes ****************/
+  task void startDone_task();
+  task void startDone_task();
+  task void stopDone_task();
+  task void sendDone_task();
+  
+  void shutdown();
+
+  /***************** SplitControl Commands ****************/
+  command error_t SplitControl.start() {
+    if(call SplitControlState.requestState(S_STARTING) == SUCCESS) {
+      call CC2420Power.startVReg();
+      return SUCCESS;
+    
+    } else if(call SplitControlState.isState(S_STARTED)) {
+      return EALREADY;
+      
+    } else if(call SplitControlState.isState(S_STARTING)) {
+      return SUCCESS;
+    }
+    
+    return EBUSY;
+  }
+
+  command error_t SplitControl.stop() {
+    if (call SplitControlState.isState(S_STARTED)) {
+      call SplitControlState.forceState(S_STOPPING);
+      shutdown();
+      return SUCCESS;
+      
+    } else if(call SplitControlState.isState(S_STOPPED)) {
+      return EALREADY;
+    
+    } else if(call SplitControlState.isState(S_TRANSMITTING)) {
+      call SplitControlState.forceState(S_STOPPING);
+      // At sendDone, the radio will shut down
+      return SUCCESS;
+    
+    } else if(call SplitControlState.isState(S_STOPPING)) {
+      return SUCCESS;
+    }
+    
+    return EBUSY;
+  }
+
+  /***************** Send Commands ****************/
+  command error_t Send.cancel( message_t* p_msg ) {
+    return call CC2420Transmit.cancel();
+  }
+
+  command error_t Send.send( message_t* p_msg, uint8_t len ) {
+    
+    cc2420_header_t* header = call CC2420PacketBody.getHeader( p_msg );
+    cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( p_msg );
+
+    atomic {
+      if (!call SplitControlState.isState(S_STARTED)) {
+        return FAIL;
+      }
+      
+      call SplitControlState.forceState(S_TRANSMITTING);
+      m_msg = p_msg;
+    }
+
+    header->length = len;
+    header->fcf &= 1 << IEEE154_FCF_ACK_REQ;
+    header->fcf |= ( ( IEEE154_TYPE_DATA << IEEE154_FCF_FRAME_TYPE ) |
+                    ( 1 << IEEE154_FCF_INTRAPAN ) |
+                    ( IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE ) |
+                    ( IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE ) );
+    header->src = call AMPacket.address();
+    metadata->ack = FALSE;
+    metadata->rssi = 0;
+    metadata->lqi = 0;
+    metadata->time = 0;
+    
+    ccaOn = TRUE;
+    signal RadioBackoff.requestCca[((cc2420_header_t*)(m_msg->data - 
+        sizeof(cc2420_header_t)))->type](m_msg);
+    call CC2420Transmit.send( m_msg, ccaOn );
+    return SUCCESS;
+
+  }
+
+  command void* Send.getPayload(message_t* m) {
+    return m->data;
+  }
+
+  command uint8_t Send.maxPayloadLength() {
+    return TOSH_DATA_LENGTH;
+  }
+
+  /**************** RadioBackoff Commands ****************/
+  /**
+   * Must be called within a requestInitialBackoff event
+   * @param backoffTime the amount of time in some unspecified units to backoff
+   */
+  async command void RadioBackoff.setInitialBackoff[am_id_t amId](uint16_t backoffTime) {
+    call SubBackoff.setInitialBackoff(backoffTime);
+  }
+  
+  /**
+   * Must be called within a requestCongestionBackoff event
+   * @param backoffTime the amount of time in some unspecified units to backoff
+   */
+  async command void RadioBackoff.setCongestionBackoff[am_id_t amId](uint16_t backoffTime) {
+    call SubBackoff.setCongestionBackoff(backoffTime);
+  }
+      
+  /**
+   * Enable CCA for the outbound packet.  Must be called within a requestCca
+   * event
+   * @param ccaOn TRUE to enable CCA, which is the default.
+   */
+  async command void RadioBackoff.setCca[am_id_t amId](bool useCca) {
+    ccaOn = useCca;
+  }
+  
+
+  /**************** Events ****************/
+  async event void CC2420Transmit.sendDone( message_t* p_msg, error_t err ) {
+    atomic sendErr = err;
+    post sendDone_task();
+  }
+
+  async event void CC2420Power.startVRegDone() {
+    call Resource.request();
+  }
+  
+  event void Resource.granted() {
+    call CC2420Power.startOscillator();
+  }
+
+  async event void CC2420Power.startOscillatorDone() {
+    post startDone_task();
+  }
+  
+  /***************** SubBackoff Events ****************/
+  async event void SubBackoff.requestInitialBackoff(message_t *msg) {
+    call SubBackoff.setInitialBackoff ( call Random.rand16() 
+        % (0x1F * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF);
+        
+    signal RadioBackoff.requestInitialBackoff[((cc2420_header_t*)(msg->data - 
+        sizeof(cc2420_header_t)))->type](msg);
+  }
+
+  async event void SubBackoff.requestCongestionBackoff(message_t *msg) {
+    call SubBackoff.setCongestionBackoff( call Random.rand16() 
+        % (0x7 * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF);
+
+    signal RadioBackoff.requestCongestionBackoff[((cc2420_header_t*)(msg->data - 
+        sizeof(cc2420_header_t)))->type](msg);
+  }
+  
+  async event void SubBackoff.requestCca(message_t *msg) {
+    // Lower layers than this do not configure the CCA settings
+  }
+  
+  
+  /***************** Tasks ****************/
+  task void sendDone_task() {
+    error_t packetErr;
+    atomic packetErr = sendErr;
+    if(call SplitControlState.isState(S_STOPPING)) {
+      shutdown();
+      
+    } else {
+      call SplitControlState.forceState(S_STARTED);
+    }
+    
+    signal Send.sendDone( m_msg, packetErr );
+  }
+
+  task void startDone_task() {
+    call SubControl.start();
+    call CC2420Power.rxOn();
+    call Resource.release();
+    call SplitControlState.forceState(S_STARTED);
+    signal SplitControl.startDone( SUCCESS );
+  }
+  
+  task void stopDone_task() {
+    call SplitControlState.forceState(S_STOPPED);
+    signal SplitControl.stopDone( SUCCESS );
+  }
+  
+  
+  /***************** Functions ****************/
+  /**
+   * Shut down all sub-components and turn off the radio
+   */
+  void shutdown() {
+    call SubControl.stop();
+    call CC2420Power.stopVReg();
+    post stopDone_task();
+  }
+
+  /***************** Defaults ***************/
+  default event void SplitControl.startDone(error_t error) {
+  }
+  
+  default event void SplitControl.stopDone(error_t error) {
+  }
+  
+  
+  default async event void RadioBackoff.requestInitialBackoff[am_id_t amId](
+      message_t *msg) {
+  }
+
+  default async event void RadioBackoff.requestCongestionBackoff[am_id_t amId](
+      message_t *msg) {
+  }
+  
+  default async event void RadioBackoff.requestCca[am_id_t amId](
+      message_t *msg) {
+  }
+}
+
diff --git a/tos/chips/cc2420/htmlreport_3-July-2007_05-05-PM.tar.gz b/tos/chips/cc2420/htmlreport_3-July-2007_05-05-PM.tar.gz
new file mode 100644 (file)
index 0000000..70a7aa0
Binary files /dev/null and b/tos/chips/cc2420/htmlreport_3-July-2007_05-05-PM.tar.gz differ
diff --git a/tos/chips/cc2420/interfaces/CC2420Config.nc b/tos/chips/cc2420/interfaces/CC2420Config.nc
new file mode 100644 (file)
index 0000000..8e11a09
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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>
+ * @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.
+   */
+  command error_t sync();
+  event void syncDone( error_t error );
+
+  /**
+   * 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.
+   */
+  command uint16_t getShortAddr();
+  command void setShortAddr( uint16_t address );
+
+  /**
+   * Change the PAN address of the radio.
+   */
+  command uint16_t getPanAddr();
+  command void setPanAddr( uint16_t address );
+
+  
+  /**
+   * Sync must be called for acknowledgement changes to take effect
+   * @param enableAutoAck TRUE to enable auto acknowledgements
+   * @param hwAutoAck TRUE to default to hardware auto acks, FALSE to
+   *     default to software auto acknowledgements
+   */
+  command void setAutoAck(bool enableAutoAck, bool hwAutoAck);
+  
+  /**
+   * @return TRUE if hardware auto acks are the default, FALSE if software
+   *     acks are the default
+   */
+  async command bool isHwAutoAckDefault();
+  
+  /**
+   * @return TRUE if auto acks are enabled
+   */
+  async command bool isAutoAckEnabled();
+  
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420Fifo.nc b/tos/chips/cc2420/interfaces/CC2420Fifo.nc
new file mode 100644 (file)
index 0000000..115a0d3
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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
+ */
+
+/**
+ * HAL abstraction for accessing the FIFO registers of a ChipCon
+ * CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+interface CC2420Fifo {
+
+  /**
+   * Start reading from the FIFO. The <code>readDone</code> event will
+   * be signalled upon completion.
+   *
+   * @param data a pointer to the receive buffer.
+   * @param length number of bytes to read.
+   * @return status byte returned when sending the last address byte
+   * of the SPI transaction.
+   */
+  async command cc2420_status_t beginRead( uint8_t* data, uint8_t length );
+
+  /**
+   * Continue reading from the FIFO without having to send the address
+   * byte again. The <code>readDone</code> event will be signalled
+   * upon completion.
+   *
+   * @param data a pointer to the receive buffer.
+   * @param length number of bytes to read.
+   * @return SUCCESS always.
+   */
+  async command error_t continueRead( uint8_t* data, uint8_t length );
+
+  /**
+   * Signals the completion of a read operation.
+   *
+   * @param data a pointer to the receive buffer.
+   * @param length number of bytes read.
+   * @param error notification of how the operation went
+   */
+  async event void readDone( uint8_t* data, uint8_t length, error_t error );
+
+  /**
+   * Start writing the FIFO. The <code>writeDone</code> event will be
+   * signalled upon completion.
+   *
+   * @param data a pointer to the send buffer.
+   * @param length number of bytes to write.
+   * @return status byte returned when sending the last address byte
+   * of the SPI transaction.
+   */
+  async command cc2420_status_t write( uint8_t* data, uint8_t length );
+
+  /**
+   * Signals the completion of a write operation.
+   *
+   * @param data a pointer to the send buffer.
+   * @param length number of bytes written.
+   * @param error notification of how the operation went
+   */
+  async event void writeDone( uint8_t* data, uint8_t length, error_t error );
+
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420Packet.nc b/tos/chips/cc2420/interfaces/CC2420Packet.nc
new file mode 100644 (file)
index 0000000..b18df71
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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 Chad Metcalf
+ */
+
+#include "message.h"
+
+interface CC2420Packet {
+  
+  /**
+   * Get transmission power setting for current packet.
+   *
+   * @param the message
+   */
+  async command uint8_t getPower( message_t* p_msg );
+
+  /**
+   * Set transmission power for a given packet. Valid ranges are
+   * between 0 and 31.
+   *
+   * @param p_msg the message.
+   * @param power transmission power.
+   */
+  async command void setPower( message_t* p_msg, uint8_t power );
+  
+  /**
+   * Get rssi value for a given packet. For received packets, it is
+   * the received signal strength when receiving that packet. For sent
+   * packets, it is the received signal strength of the ack if an ack
+   * was received.
+   */
+  async command int8_t getRssi( message_t* p_msg );
+
+  /**
+   * Get lqi value for a given packet. For received packets, it is the
+   * link quality indicator value when receiving that packet. For sent
+   * packets, it is the link quality indicator value of the ack if an
+   * ack was received.
+   */
+  async command uint8_t getLqi( message_t* p_msg );
+  
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420PacketBody.nc b/tos/chips/cc2420/interfaces/CC2420PacketBody.nc
new file mode 100644 (file)
index 0000000..c61cd4a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+
+/**
+ * Internal interface for the CC2420 to get portions of a packet.
+ * @author David Moss
+ */
+interface CC2420PacketBody {
+
+  /**
+   * @return pointer to the cc2420_header_t of the given message
+   */
+  async command cc2420_header_t *getHeader(message_t *msg);
+  
+  /**
+   * @return pointer to the cc2420_metadata_t of the given message
+   */
+  async command cc2420_metadata_t *getMetadata(message_t *msg);
+  
+}
+
diff --git a/tos/chips/cc2420/interfaces/CC2420Power.nc b/tos/chips/cc2420/interfaces/CC2420Power.nc
new file mode 100644 (file)
index 0000000..74012e5
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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>
+ * @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();
+
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420Ram.nc b/tos/chips/cc2420/interfaces/CC2420Ram.nc
new file mode 100644 (file)
index 0000000..a41712d
--- /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
+ */
+
+/**
+ * HAL abstraction for accessing theRAM of a ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+
+interface CC2420Ram {
+
+  /**
+   * Read data from a RAM. This operation is sychronous.
+   *
+   * @param offset within the field.
+   * @param data a pointer to the receive buffer.
+   * @param length number of bytes to read.
+   * @return status byte returned when sending the last byte
+   * of the SPI transaction.
+   */
+  async command cc2420_status_t read( uint8_t offset, uint8_t* data, uint8_t length );
+
+  /**
+   * Write data to RAM. This operation is sychronous.
+   *
+   * @param offset within the field.
+   * @param data a pointer to the send buffer.
+   * @param length number of bytes to write.
+   * @return status byte returned when sending the last address byte
+   * of the SPI transaction.
+   */
+  async command cc2420_status_t write( uint8_t offset, uint8_t* data, uint8_t length );
+
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420Receive.nc b/tos/chips/cc2420/interfaces/CC2420Receive.nc
new file mode 100644 (file)
index 0000000..70230b0
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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>
+ * @version $Revision$ $Date$
+ */
+
+interface CC2420Receive {
+
+  /**
+   * Notification that an SFD capture has occured.
+   *
+   * @param time at which the capture happened.
+   */
+  async command void sfd( uint16_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/interfaces/CC2420Register.nc b/tos/chips/cc2420/interfaces/CC2420Register.nc
new file mode 100644 (file)
index 0000000..a5cc3c6
--- /dev/null
@@ -0,0 +1,57 @@
+/*                                                                     tab:4
+ * "Copyright (c) 2005 Stanford University. 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 STANFORD UNIVERSITY 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 STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * STANFORD UNIVERSITY 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 STANFORD UNIVERSITY
+ * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+
+/**
+ * Interface representing one of the Read/Write registers on the
+ * CC2420 radio. The return values (when appropriate) refer to the
+ * status byte returned on the CC2420 SO pin. A full list of RW
+ * registers can be found on page 61 of the CC2420 datasheet (rev
+ * 1.2). Page 25 of the same document describes the protocol for
+ * interacting with these registers over the CC2420 SPI bus.
+ *
+ * @author Philip Levis
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+
+interface CC2420Register {
+
+  /**
+   * Read a 16-bit data word from the register.
+   *
+   * @param data pointer to place the register value.
+   * @return status byte from the read.
+   */
+  async command cc2420_status_t read(uint16_t* data);
+
+  /**
+   * Write a 16-bit data word to the register.
+   * 
+   * @param data value to write to register.
+   * @return status byte from the write.
+   */
+  async command cc2420_status_t write(uint16_t data);
+
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420Strobe.nc b/tos/chips/cc2420/interfaces/CC2420Strobe.nc
new file mode 100644 (file)
index 0000000..0e2a666
--- /dev/null
@@ -0,0 +1,47 @@
+/*                                                                     tab:4
+ * "Copyright (c) 2005 Stanford University. 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 STANFORD UNIVERSITY 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 STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * STANFORD UNIVERSITY 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 STANFORD UNIVERSITY
+ * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+
+/**
+ * Interface representing one of the CC2420 command strobe registers.
+ * Writing to one of these registers enacts a command on the CC2420,
+ * such as power-up, transmission, or clear a FIFO.
+ *
+ * @author Philip Levis
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+
+interface CC2420Strobe {
+
+  /**
+   * Send a command strobe to the register. The return value is the
+   * CC2420 status register. Table 5 on page 27 of the CC2420
+   * datasheet (v1.2) describes the contents of this register.
+   * 
+   * @return Status byte from the CC2420.
+   */
+  async command cc2420_status_t strobe();
+
+}
diff --git a/tos/chips/cc2420/interfaces/CC2420Transmit.nc b/tos/chips/cc2420/interfaces/CC2420Transmit.nc
new file mode 100644 (file)
index 0000000..0052a6b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 for the transmit path implementaiton of the
+ * ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#include "message.h"
+
+interface CC2420Transmit {
+
+  /**
+   * Send a message
+   *
+   * @param p_msg message to send.
+   * @param useCca TRUE if this Tx should use clear channel assessments
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */
+  async command error_t send( message_t* p_msg, bool useCca );
+
+  /**
+   * Send the previous message again
+   * @param useCca TRUE if this re-Tx should use clear channel assessments
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */
+  async command error_t resend(bool useCca);
+
+  /**
+   * Cancel sending of the message.
+   *
+   * @return SUCCESS if the request was accepted, FAIL otherwise.
+   */
+  async command error_t cancel();
+
+  /**
+   * Signal that a message has been sent
+   *
+   * @param p_msg message to send.
+   * @param error notifaction of how the operation went.
+   */
+  async event void sendDone( message_t* p_msg, error_t error );
+
+  /**
+   * 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/interfaces/ChipSpiResource.nc b/tos/chips/cc2420/interfaces/ChipSpiResource.nc
new file mode 100644 (file)
index 0000000..385a002
--- /dev/null
@@ -0,0 +1,41 @@
+
+/**
+ * Interface for the SPI resource for an entire chip.  The chip accesses
+ * the platform SPI resource one time, but can have multiple clients 
+ * using the SPI bus on top.  When all of the clients are released, the
+ * chip will normally try to release itself from the platforms SPI bus.
+ * In some cases, this isn't desirable - so even though upper components
+ * aren't actively using the SPI bus, they can tell the chip to hold onto
+ * it so they can have immediate access when they need. 
+ *
+ * Any component that aborts a release MUST attempt the release at a later
+ * time if they don't acquire and release the SPI bus naturally after the
+ * abort.
+ * 
+ * @author David Moss
+ */
+interface ChipSpiResource {
+  
+  /**
+   * The SPI bus is about to be automatically released.  Modules that aren't
+   * using the SPI bus but still want the SPI bus to stick around must call
+   * abortRelease() within the event.
+   */
+  async event void releasing();
+
+  
+  /**
+   * Abort the release of the SPI bus.  This must be called only with the
+   * releasing() event
+   */
+  async command void abortRelease();
+  
+  /**
+   * Release the SPI bus if there are no objections
+   * @return SUCCESS if the SPI bus is released from the chip.
+   *      FAIL if the SPI bus is already in use.
+   *      EBUSY if some component aborted the release.
+   */
+  async command error_t attemptRelease();
+  
+}
diff --git a/tos/chips/cc2420/interfaces/PowerCycle.nc b/tos/chips/cc2420/interfaces/PowerCycle.nc
new file mode 100644 (file)
index 0000000..aef2dab
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Manage the CC2420's duty cycle and power management
+ * @author David Moss
+ */
+interface PowerCycle {
+  
+  /**
+   * Set the sleep interval, in binary milliseconds
+   * @param sleepIntervalMs the sleep interval in [ms]
+   */
+  command void setSleepInterval(uint16_t sleepIntervalMs);
+  
+  /**
+   * @return the sleep interval in [ms]
+   */
+  command uint16_t getSleepInterval();
+  
+  /**
+   * @deprecated Should be removed in the future when the PowerCycle
+   *     component does packet-level detects and is in full control of radio
+   *     power.
+   */
+  event void detected();
+  
+}
+
diff --git a/tos/chips/cc2420/interfaces/RadioBackoff.nc b/tos/chips/cc2420/interfaces/RadioBackoff.nc
new file mode 100644 (file)
index 0000000..26071b9
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Interface to request and specify backoff periods for messages
+ * 
+ * We use a call back method for setting the backoff as opposed to 
+ * events that return backoff values.  
+ * 
+ * This is because of fan-out issues with multiple components wanting to
+ * affect backoffs for whatever they're interested in:
+ * If you signal out an *event* to request an initial backoff and
+ * several components happen to be listening, then those components
+ * would be required to return a backoff value.  We don't want that
+ * behavior.
+ * With this strategy, components can listen for the requests and then
+ * decide if they want to affect the behavior.  If the component wants to
+ * affect the behavior, it calls back using the setXYZBackoff(..) command.
+ * If several components call back, then the last component to get its 
+ * word in has the final say. 
+ *
+ * @author David Moss
+ */
+interface RadioBackoff {
+
+  /**
+   * Must be called within a requestInitialBackoff event
+   * @param backoffTime the amount of time in some unspecified units to backoff
+   */
+  async command void setInitialBackoff(uint16_t backoffTime);
+  
+  /**
+   * Must be called within a requestCongestionBackoff event
+   * @param backoffTime the amount of time in some unspecified units to backoff
+   */
+  async command void setCongestionBackoff(uint16_t backoffTime);
+  
+  /**
+   * Enable CCA for the outbound packet.  Must be called within a requestCca
+   * event
+   * @param ccaOn TRUE to enable CCA, which is the default.
+   */
+  async command void setCca(bool ccaOn);
+
+
+  /**  
+   * Request for input on the initial backoff
+   * Reply using setInitialBackoff(..)
+   * @param msg pointer to the message being sent
+   */
+  async event void requestInitialBackoff(message_t *msg);
+  
+  /**
+   * Request for input on the congestion backoff
+   * Reply using setCongestionBackoff(..)
+   * @param msg pointer to the message being sent
+   */
+  async event void requestCongestionBackoff(message_t *msg);
+  
+  /**
+   * Request for input on whether or not to use CCA on the outbound packet.
+   * Replies should come in the form of setCca(..)
+   * @param msg pointer to the message being sent
+   */
+  async event void requestCca(message_t *msg);
+}
+
diff --git a/tos/chips/cc2420/interfaces/ReceiveIndicator.nc b/tos/chips/cc2420/interfaces/ReceiveIndicator.nc
new file mode 100644 (file)
index 0000000..db2807f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Interface to obtain energy, byte, and packet receive check readings
+ * @author David Moss
+ */
+interface ReceiveIndicator {
+  
+  /**
+   * @return TRUE if the indicator is showing we are actively receiving at this
+   * level
+   */
+  command bool isReceiving();
+  
+}
+
diff --git a/tos/chips/cc2420/link/PacketLinkC.nc b/tos/chips/cc2420/link/PacketLinkC.nc
new file mode 100644 (file)
index 0000000..9e2c273
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+
+/**
+ * Reliable Packet Link Functionality
+ * @author David Moss
+ * @author Jon Wyant
+ */
+
+#warning "*** USING PACKET LINK LAYER"
+
+configuration PacketLinkC {
+  provides {
+    interface Send;
+    interface PacketLink;
+  }
+  
+  uses {
+    interface Send as SubSend;
+  }
+}
+
+implementation {
+
+  components PacketLinkP,
+      ActiveMessageC,
+      CC2420PacketC,
+      RandomC,
+      new StateC() as SendStateC,
+      new TimerMilliC() as DelayTimerC;
+  
+  PacketLink = PacketLinkP;
+  Send = PacketLinkP.Send;
+  SubSend = PacketLinkP.SubSend;
+  
+  PacketLinkP.SendState -> SendStateC;
+  PacketLinkP.DelayTimer -> DelayTimerC;
+  PacketLinkP.PacketAcknowledgements -> ActiveMessageC;
+  PacketLinkP.AMPacket -> ActiveMessageC;
+  PacketLinkP.CC2420PacketBody -> CC2420PacketC;
+
+}
diff --git a/tos/chips/cc2420/link/PacketLinkDummyC.nc b/tos/chips/cc2420/link/PacketLinkDummyC.nc
new file mode 100644 (file)
index 0000000..2ea159c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+
+/**
+ * Dummy configuration for PacketLink Layer
+ * @author David Moss
+ * @author Jon Wyant
+ */
+configuration PacketLinkDummyC {
+  provides {
+    interface Send;
+    interface PacketLink;
+  }
+  
+  uses {
+    interface Send as SubSend;
+  }
+}
+
+implementation {
+  components PacketLinkDummyP,
+      ActiveMessageC;
+  
+  PacketLink = PacketLinkDummyP;
+  Send = SubSend;
+  
+  PacketLinkDummyP.PacketAcknowledgements -> ActiveMessageC;
+  
+}
+
diff --git a/tos/chips/cc2420/link/PacketLinkDummyP.nc b/tos/chips/cc2420/link/PacketLinkDummyP.nc
new file mode 100644 (file)
index 0000000..1688da6
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+
+/**
+ * Dummy module for Packet Link layer
+ * @author David Moss
+ * @author Jon Wyant
+ */
+
+module PacketLinkDummyP {
+  provides {
+    interface PacketLink;
+  }
+  
+  uses {
+    interface PacketAcknowledgements;
+  }
+}
+
+implementation {
+  
+  /***************** PacketLink Commands ***************/
+  /**
+   * Set the maximum number of times attempt message delivery
+   * Default is 0
+   * @param msg
+   * @param maxRetries the maximum number of attempts to deliver
+   *     the message
+   */
+  command void PacketLink.setRetries(message_t *msg, uint16_t maxRetries) {
+  }
+
+  /**
+   * Set a delay between each retry attempt
+   * @param msg
+   * @param retryDelay the delay betweeen retry attempts, in milliseconds
+   */
+  command void PacketLink.setRetryDelay(message_t *msg, uint16_t retryDelay) {
+  }
+
+  /** 
+   * @return the maximum number of retry attempts for this message
+   */
+  command uint16_t PacketLink.getRetries(message_t *msg) {
+    return 0;
+  }
+
+  /**
+   * @return the delay between retry attempts in ms for this message
+   */
+  command uint16_t PacketLink.getRetryDelay(message_t *msg) {
+    return 0;
+  }
+
+  /**
+   * @return TRUE if the message was delivered.
+   *     This should always be TRUE if the message was sent to the
+   *     AM_BROADCAST_ADDR
+   */
+  command bool PacketLink.wasDelivered(message_t *msg) {
+    return call PacketAcknowledgements.wasAcked(msg);
+  }
+}
+
diff --git a/tos/chips/cc2420/link/PacketLinkP.nc b/tos/chips/cc2420/link/PacketLinkP.nc
new file mode 100644 (file)
index 0000000..a54645f
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+
+/**
+ * Reliable Packet Link Functionality
+ * @author David Moss
+ * @author Jon Wyant
+ */
+#include "CC2420.h"
+
+module PacketLinkP {
+  provides {
+    interface Send;
+    interface PacketLink;
+  }
+  
+  uses {
+    interface Send as SubSend;
+    interface State as SendState;
+    interface PacketAcknowledgements;
+    interface Timer<TMilli> as DelayTimer;
+    interface AMPacket;
+    interface CC2420PacketBody;
+  }
+}
+
+implementation {
+  
+  /** The message currently being sent */
+  message_t *currentSendMsg;
+  
+  /** Length of the current send message */
+  uint8_t currentSendLen;
+  
+  /** The length of the current send message */
+  uint16_t totalRetries;
+  
+  
+  /**
+   * Send States
+   */
+  enum {
+    S_IDLE,
+    S_SENDING,
+  };
+  
+  
+  /***************** Prototypes ***************/
+  task void send();
+  void signalDone(error_t error);
+    
+  /***************** PacketLink Commands ***************/
+  /**
+   * Set the maximum number of times attempt message delivery
+   * Default is 0
+   * @param msg
+   * @param maxRetries the maximum number of attempts to deliver
+   *     the message
+   */
+  command void PacketLink.setRetries(message_t *msg, uint16_t maxRetries) {
+    (call CC2420PacketBody.getMetadata(msg))->maxRetries = maxRetries;
+  }
+
+  /**
+   * Set a delay between each retry attempt
+   * @param msg
+   * @param retryDelay the delay betweeen retry attempts, in milliseconds
+   */
+  command void PacketLink.setRetryDelay(message_t *msg, uint16_t retryDelay) {
+    (call CC2420PacketBody.getMetadata(msg))->retryDelay = retryDelay;
+  }
+
+  /** 
+   * @return the maximum number of retry attempts for this message
+   */
+  command uint16_t PacketLink.getRetries(message_t *msg) {
+    return (call CC2420PacketBody.getMetadata(msg))->maxRetries;
+  }
+
+  /**
+   * @return the delay between retry attempts in ms for this message
+   */
+  command uint16_t PacketLink.getRetryDelay(message_t *msg) {
+    return (call CC2420PacketBody.getMetadata(msg))->retryDelay;
+  }
+
+  /**
+   * @return TRUE if the message was delivered.
+   */
+  command bool PacketLink.wasDelivered(message_t *msg) {
+    return call PacketAcknowledgements.wasAcked(msg);
+  }
+  
+  /***************** Send Commands ***************/
+  /**
+   * Each call to this send command gives the message a single
+   * DSN that does not change for every copy of the message
+   * sent out.  For messages that are not acknowledged, such as
+   * a broadcast address message, the receiving end does not
+   * signal receive() more than once for that message.
+   */
+  command error_t Send.send(message_t *msg, uint8_t len) {
+    error_t error;
+    if(call SendState.requestState(S_SENDING) == SUCCESS) {
+    
+      currentSendMsg = msg;
+      currentSendLen = len;
+      totalRetries = 0;
+
+      if(call PacketLink.getRetries(msg) > 0) {
+        call PacketAcknowledgements.requestAck(msg);
+      }
+     
+      if((error = call SubSend.send(msg, len)) != SUCCESS) {
+        call SendState.toIdle();
+      }
+      
+      return error;
+    }
+    return EBUSY;
+  }
+
+  command error_t Send.cancel(message_t *msg) {
+    if(currentSendMsg == msg) {
+      call SendState.toIdle();
+      return call SubSend.cancel(msg);
+    }
+    
+    return FAIL;
+  }
+  
+  
+  command uint8_t Send.maxPayloadLength() {
+    return call SubSend.maxPayloadLength();
+  }
+
+  command void *Send.getPayload(message_t* msg) {
+    return call SubSend.getPayload(msg);
+  }
+  
+  
+  /***************** SubSend Events ***************/
+  event void SubSend.sendDone(message_t* msg, error_t error) {
+    if(call SendState.getState() == S_SENDING) {
+      totalRetries++;
+      if(call PacketAcknowledgements.wasAcked(msg)) {
+        signalDone(SUCCESS);
+        return;
+        
+      } else if(totalRetries < call PacketLink.getRetries(currentSendMsg)) {
+        
+        if(call PacketLink.getRetryDelay(currentSendMsg) > 0) {
+          // Resend after some delay
+          call DelayTimer.startOneShot(call PacketLink.getRetryDelay(currentSendMsg));
+          
+        } else {
+          // Resend immediately
+          post send();
+        }
+        
+        return;
+      }
+    }
+    
+    signalDone(error);
+  }
+  
+  
+  /***************** Timer Events ****************/  
+  /**
+   * When this timer is running, that means we're sending repeating messages
+   * to a node that is receive check duty cycling.
+   */
+  event void DelayTimer.fired() {
+    if(call SendState.getState() == S_SENDING) {
+      post send();
+    }
+  }
+  
+  /***************** Tasks ***************/
+  task void send() {
+    if(call PacketLink.getRetries(currentSendMsg) > 0) {
+      call PacketAcknowledgements.requestAck(currentSendMsg);
+    }
+    
+    if(call SubSend.send(currentSendMsg, currentSendLen) != SUCCESS) {
+      post send();
+    }
+  }
+  
+  /***************** Functions ***************/  
+  void signalDone(error_t error) {
+    call DelayTimer.stop();
+    call SendState.toIdle();
+    signal Send.sendDone(currentSendMsg, error);
+  }
+}
+
diff --git a/tos/chips/cc2420/link/readme.txt b/tos/chips/cc2420/link/readme.txt
new file mode 100644 (file)
index 0000000..6793e1d
--- /dev/null
@@ -0,0 +1,6 @@
+PacketLink is used for link-layer retransmissions guided by your own
+application requirements.  It will fail if it receives false-acknowledgements,
+which is completely possible in 802.15.4.
+
+See TEP 127 for more details.
+
diff --git a/tos/chips/cc2420/lowpan/CC2420TinyosNetworkC.nc b/tos/chips/cc2420/lowpan/CC2420TinyosNetworkC.nc
new file mode 100644 (file)
index 0000000..3581b12
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Original TinyOS T-Frames use a packet header that is not compatible with
+ * other 6LowPAN networks.  They do not include the network byte 
+ * responsible for identifying the packing as being sourced from a TinyOS
+ * network.
+ *
+ * TinyOS I-Frames are interoperability packets that do include a network
+ * byte as defined by 6LowPAN specifications.  The I-Frame header type is
+ * the default packet header used in TinyOS networks.
+ *
+ * Since either packet header is acceptable, this layer must do some 
+ * preprocessing (sorry) to figure out whether or not it needs to include 
+ * the functionality to process I-frames.  If I-Frames are used, then
+ * the network byte is added on the way out and checked on the way in.
+ * If the packet came from a network different from a TinyOS network, the
+ * user may access it through the DispatchP's NonTinyosReceive[] Receive 
+ * interface and process it in a different radio stack.
+ *
+ * If T-Frames are used instead, this layer is simply pass-through wiring to the
+ * layer beneath.  
+ *
+ * Define "CC2420_IFRAME_TYPE" to use the interoperability frame and 
+ * this layer
+ * 
+ * @author David Moss
+ */
+#include "CC2420.h"
+
+configuration CC2420TinyosNetworkC {
+  provides {
+    interface Send;
+    interface Receive;
+  }
+  
+  uses {
+    interface Receive as SubReceive;
+    interface Send as SubSend;
+  }
+}
+
+implementation {
+
+#ifdef CC2420_IFRAME_TYPE
+  components CC2420TinyosNetworkP;
+  components CC2420PacketC;
+  
+  CC2420TinyosNetworkP.Send = Send;
+  CC2420TinyosNetworkP.Receive = Receive;
+  CC2420TinyosNetworkP.SubSend = SubSend;
+  CC2420TinyosNetworkP.SubReceive = SubReceive;
+  
+  CC2420TinyosNetworkP.CC2420PacketBody -> CC2420PacketC;
+
+#else
+  Send = SubSend;
+  Receive = SubReceive;
+#endif
+
+}
+
diff --git a/tos/chips/cc2420/lowpan/CC2420TinyosNetworkP.nc b/tos/chips/cc2420/lowpan/CC2420TinyosNetworkP.nc
new file mode 100644 (file)
index 0000000..0bd6dc5
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+
+/**
+ * Fills in the network ID byte for outgoing packets for compatibility with
+ * other 6LowPAN networks.  Filters incoming packets that are not
+ * TinyOS network compatible.  Provides the 6LowpanSnoop interface to
+ * sniff for packets that were not originated from TinyOS.
+ *
+ * @author David Moss
+ */
+#include "CC2420.h"
+
+module CC2420TinyosNetworkP {
+  provides {
+    interface Send;
+    interface Receive;
+    
+    interface Receive as NonTinyosReceive[uint8_t networkId];
+  }
+  
+  uses {
+    interface Send as SubSend;
+    interface Receive as SubReceive;
+    interface CC2420PacketBody;
+  }
+}
+
+implementation {
+
+  /***************** Send Commands ****************/
+  command error_t Send.send(message_t* msg, uint8_t len) {
+    (call CC2420PacketBody.getHeader(msg))->network = TINYOS_6LOWPAN_NETWORK_ID;
+    return call SubSend.send(msg, len);
+  }
+
+  command error_t Send.cancel(message_t* msg) {
+    return call SubSend.cancel(msg);
+  }
+
+  command uint8_t Send.maxPayloadLength() {
+    return call SubSend.maxPayloadLength();
+  }
+
+  command void* Send.getPayload(message_t* msg) {
+    return call SubSend.getPayload(msg);
+  }
+  
+  /***************** Receive Commands ****************/
+  command void* Receive.getPayload(message_t* msg, uint8_t* len) {
+    return call SubReceive.getPayload(msg, len);
+  }
+
+  command uint8_t Receive.payloadLength(message_t* msg) {
+    return call SubReceive.payloadLength(msg);
+  }
+  
+  /***************** NonTinyosReceive Commands ****************/
+  command void* NonTinyosReceive.getPayload[uint8_t networkId](message_t* msg, uint8_t* len) {
+    return call SubReceive.getPayload(msg, len);
+  }
+
+  command uint8_t NonTinyosReceive.payloadLength[uint8_t networkId](message_t* msg) {
+    return call SubReceive.payloadLength(msg);
+  }
+  
+  /***************** SubSend Events *****************/
+  event void SubSend.sendDone(message_t* msg, error_t error) {
+    signal Send.sendDone(msg, error);
+  }
+  
+  /***************** SubReceive Events ***************/
+  event message_t *SubReceive.receive(message_t *msg, void *payload, uint8_t len) {
+    if((call CC2420PacketBody.getHeader(msg))->network == TINYOS_6LOWPAN_NETWORK_ID) {
+      return signal Receive.receive(msg, payload, len);
+      
+    } else {
+      return signal NonTinyosReceive.receive[(call CC2420PacketBody.getHeader(msg))->network](msg, payload, len);
+    }
+  }
+  
+  /***************** Defaults ****************/
+  default event message_t *NonTinyosReceive.receive[uint8_t networkId](message_t *msg, void *payload, uint8_t len) {
+    return msg;
+  }
+  
+}
diff --git a/tos/chips/cc2420/lowpan/readme.txt b/tos/chips/cc2420/lowpan/readme.txt
new file mode 100644 (file)
index 0000000..7081277
--- /dev/null
@@ -0,0 +1 @@
+See TEP 125 for more information.
diff --git a/tos/chips/cc2420/lpl/DefaultLpl.h b/tos/chips/cc2420/lpl/DefaultLpl.h
new file mode 100644 (file)
index 0000000..2c74351
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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 David Moss
+  */
+#ifndef DEFAULTLPL_H
+#define DEFAULTLPL_H
+
+/**
+ * Low Power Listening Send States
+ */
+typedef enum {
+  S_LPL_NOT_SENDING,    // DEFAULT
+  S_LPL_FIRST_MESSAGE,  // 1. Sending the first message
+  S_LPL_SENDING,        // 2. Sending all other messages
+  S_LPL_CLEAN_UP,       // 3. Clean up the transmission
+} lpl_sendstate_t;
+
+
+/**
+ * Amount of time, in milliseconds, to keep the radio on after
+ * a successful receive addressed to this node
+ */
+#ifndef DELAY_AFTER_RECEIVE
+#define DELAY_AFTER_RECEIVE 100
+#endif
+
+/**
+ * This is a measured value of the time in ms the radio is actually on
+ * We round this up to err on the side of better performance ratios
+ */
+#ifndef DUTY_ON_TIME
+#define DUTY_ON_TIME 5 
+#endif
+
+/**
+ * The maximum number of CCA checks performed on each wakeup.
+ * If there are too few, the receiver may wake up between messages
+ * and not detect the transmitter.
+ *
+ * The on-time had to increase from the original version to allow multiple
+ * transmitters to co-exist.  This is due to using ack's, which then requires us
+ * to extend the backoff period.  In networks that transmit frequently, possibly
+ * with multiple transmitters, this power scheme makes sense.  
+ *
+ * In networks that transmit very infrequently or without multiple transmitters,
+ * it makes more sense to go with no acks and no backoffs and make the
+ * receive check as short as possible.
+ */
+#ifndef MAX_LPL_CCA_CHECKS
+
+#if defined(PLATFORM_TELOSB) || defined(PLATFORM_TMOTE)
+#define MAX_LPL_CCA_CHECKS 400
+#else
+#define MAX_LPL_CCA_CHECKS 400
+#endif
+
+#endif
+
+/**
+ * The minimum number of samples that must be taken in CC2420DutyCycleP
+ * that show the channel is not clear before a detection event is issued
+ */
+#ifndef MIN_SAMPLES_BEFORE_DETECT
+#define MIN_SAMPLES_BEFORE_DETECT 3
+#endif
+
+#endif
+
diff --git a/tos/chips/cc2420/lpl/DefaultLplC.nc b/tos/chips/cc2420/lpl/DefaultLplC.nc
new file mode 100644 (file)
index 0000000..e750ae7
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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 Power Listening for the CC2420
+ * @author David Moss
+ */
+
+
+#include "DefaultLpl.h"
+#warning "*** USING DEFAULT POWER LISTENING LAYER"
+
+configuration DefaultLplC {
+  provides {
+    interface LowPowerListening;
+    interface Send;
+    interface Receive;
+    interface SplitControl;
+    interface State as SendState;
+  }
+  
+  uses { 
+    interface Send as SubSend;
+    interface Receive as SubReceive;
+    interface SplitControl as SubControl;
+  }
+}
+
+implementation {
+  components MainC,
+      DefaultLplP,
+      PowerCycleC,
+      CC2420ActiveMessageC,
+      CC2420CsmaC,
+      CC2420TransmitC,
+      CC2420PacketC,
+      RandomC,
+      new StateC() as SendStateC,
+      new TimerMilliC() as OffTimerC,
+      new TimerMilliC() as SendDoneTimerC,
+      LedsC;
+  
+  LowPowerListening = DefaultLplP;
+  Send = DefaultLplP;
+  Receive = DefaultLplP;
+  SplitControl = PowerCycleC;
+  SendState = SendStateC;
+  
+  SubControl = DefaultLplP.SubControl;
+  SubReceive = DefaultLplP.SubReceive;
+  SubSend = DefaultLplP.SubSend;
+  
+  
+  MainC.SoftwareInit -> DefaultLplP;
+  
+  
+  DefaultLplP.SplitControlState -> PowerCycleC.SplitControlState;
+  DefaultLplP.RadioPowerState -> PowerCycleC.RadioPowerState;
+  DefaultLplP.SendState -> SendStateC;
+  DefaultLplP.OffTimer -> OffTimerC;
+  DefaultLplP.SendDoneTimer -> SendDoneTimerC;
+  DefaultLplP.PowerCycle -> PowerCycleC;
+  DefaultLplP.Resend -> CC2420TransmitC;
+  DefaultLplP.PacketAcknowledgements -> CC2420ActiveMessageC;
+  DefaultLplP.AMPacket -> CC2420ActiveMessageC;
+  DefaultLplP.CC2420PacketBody -> CC2420PacketC;
+  DefaultLplP.RadioBackoff -> CC2420CsmaC;
+  DefaultLplP.Random -> RandomC;
+  DefaultLplP.Leds -> LedsC;
+  
+}
diff --git a/tos/chips/cc2420/lpl/DefaultLplP.nc b/tos/chips/cc2420/lpl/DefaultLplP.nc
new file mode 100644 (file)
index 0000000..6891995
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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 Power Listening for the CC2420.  This component is responsible for
+ * delivery of an LPL packet, and for turning off the radio when the radio
+ * has run out of tasks.
+ *
+ * The PowerCycle component is responsible for duty cycling the radio
+ * and performing receive detections.
+ *
+ * @author David Moss
+ */
+
+#include "DefaultLpl.h"
+#include "AM.h"
+
+module DefaultLplP {
+  provides {
+    interface Init;
+    interface LowPowerListening;
+    interface Send;
+    interface Receive;
+  }
+  
+  uses {
+    interface Send as SubSend;
+    interface CC2420Transmit as Resend;
+    interface RadioBackoff[am_id_t amId];
+    interface Receive as SubReceive;
+    interface AMPacket;
+    interface SplitControl as SubControl;
+    interface PowerCycle;
+    interface CC2420PacketBody;
+    interface PacketAcknowledgements;
+    interface State as SendState;
+    interface State as RadioPowerState;
+    interface State as SplitControlState;
+    interface Timer<TMilli> as OffTimer;
+    interface Timer<TMilli> as SendDoneTimer;
+    interface Random;
+    interface Leds;
+  }
+}
+
+implementation {
+  
+  /** The message currently being sent */
+  norace message_t *currentSendMsg;
+  
+  /** The length of the current send message */
+  uint8_t currentSendLen;
+  
+  /** TRUE if the radio is duty cycling and not always on */
+  bool dutyCycling;
+
+  /**
+   * Radio State
+   */
+  enum {
+    S_OFF,
+    S_ON,
+  };
+  
+  /**
+   * Send States
+   */
+  enum {
+    S_IDLE,
+    S_SENDING,
+  };
+  
+  enum {
+    ONE_MESSAGE = 0,
+  };
+  
+  /***************** Prototypes ***************/
+  task void send();
+  task void resend();
+  task void startRadio();
+  task void stopRadio();
+  
+  void initializeSend();
+  void startOffTimer();
+  uint16_t getActualDutyCycle(uint16_t dutyCycle);
+  
+  /***************** Init Commands ***************/
+  command error_t Init.init() {
+    dutyCycling = FALSE;
+    return SUCCESS;
+  }
+  
+  /***************** LowPowerListening Commands ***************/
+  /**
+   * Set this this node's radio sleep interval, in milliseconds.
+   * Once every interval, the node will sleep and perform an Rx check 
+   * on the radio.  Setting the sleep interval to 0 will keep the radio
+   * always on.
+   *
+   * This is the equivalent of setting the local duty cycle rate.
+   *
+   * @param sleepIntervalMs the length of this node's Rx check interval, in [ms]
+   */
+  command void LowPowerListening.setLocalSleepInterval(
+      uint16_t sleepIntervalMs) {
+    call PowerCycle.setSleepInterval(sleepIntervalMs);
+  }
+  
+  /**
+   * @return the local node's sleep interval, in [ms]
+   */
+  command uint16_t LowPowerListening.getLocalSleepInterval() {
+    return call PowerCycle.getSleepInterval();
+  }
+  
+  /**
+   * Set this node's radio duty cycle rate, in units of [percentage*100].
+   * For example, to get a 0.05% duty cycle,
+   * <code>
+   *   call LowPowerListening.setDutyCycle(5);
+   * </code>
+   *
+   * For a 100% duty cycle (always on),
+   * <code>
+   *   call LowPowerListening.setDutyCycle(10000);
+   * </code>
+   *
+   * This is the equivalent of setting the local sleep interval explicitly.
+   * 
+   * @param dutyCycle The duty cycle percentage, in units of [percentage*100]
+   */
+  command void LowPowerListening.setLocalDutyCycle(uint16_t dutyCycle) {
+    call PowerCycle.setSleepInterval(
+        call LowPowerListening.dutyCycleToSleepInterval(dutyCycle));
+  }
+  
+  /**
+   * @return this node's radio duty cycle rate, in units of [percentage*100]
+   */
+  command uint16_t LowPowerListening.getLocalDutyCycle() {
+    return call LowPowerListening.sleepIntervalToDutyCycle(
+        call PowerCycle.getSleepInterval());
+  }
+  
+  
+  /**
+   * Configure this outgoing message so it can be transmitted to a neighbor mote
+   * with the specified Rx sleep interval.
+   * @param msg Pointer to the message that will be sent
+   * @param sleepInterval The receiving node's sleep interval, in [ms]
+   */
+  command void LowPowerListening.setRxSleepInterval(message_t *msg, 
+      uint16_t sleepIntervalMs) {
+    (call CC2420PacketBody.getMetadata(msg))->rxInterval = sleepIntervalMs;
+  }
+  
+  /**
+   * @return the destination node's sleep interval configured in this message
+   */
+  command uint16_t LowPowerListening.getRxSleepInterval(message_t *msg) {
+    return (call CC2420PacketBody.getMetadata(msg))->rxInterval;
+  }
+  
+  /**
+   * Configure this outgoing message so it can be transmitted to a neighbor mote
+   * with the specified Rx duty cycle rate.
+   * Duty cycle is in units of [percentage*100], i.e. 0.25% duty cycle = 25.
+   * 
+   * @param msg Pointer to the message that will be sent
+   * @param dutyCycle The duty cycle of the receiving mote, in units of 
+   *     [percentage*100]
+   */
+  command void LowPowerListening.setRxDutyCycle(message_t *msg, 
+      uint16_t dutyCycle) {
+    (call CC2420PacketBody.getMetadata(msg))->rxInterval =
+        call LowPowerListening.dutyCycleToSleepInterval(dutyCycle);
+  }
+  
+    
+  /**
+   * @return the destination node's duty cycle configured in this message
+   *     in units of [percentage*100]
+   */
+  command uint16_t LowPowerListening.getRxDutyCycle(message_t *msg) {
+    return call LowPowerListening.sleepIntervalToDutyCycle(
+        (call CC2420PacketBody.getMetadata(msg))->rxInterval);
+  }
+  
+  /**
+   * Convert a duty cycle, in units of [percentage*100], to
+   * the sleep interval of the mote in milliseconds
+   * @param dutyCycle The duty cycle in units of [percentage*100]
+   * @return The equivalent sleep interval, in units of [ms]
+   */
+  command uint16_t LowPowerListening.dutyCycleToSleepInterval(
+      uint16_t dutyCycle) {
+    dutyCycle = getActualDutyCycle(dutyCycle);
+    
+    if(dutyCycle == 10000) {
+      return 0;
+    }
+    
+    return (DUTY_ON_TIME * (10000 - dutyCycle)) / dutyCycle;
+  }
+  
+  /**
+   * Convert a sleep interval, in units of [ms], to a duty cycle
+   * in units of [percentage*100]
+   * @param sleepInterval The sleep interval in units of [ms]
+   * @return The duty cycle in units of [percentage*100]
+   */
+  command uint16_t LowPowerListening.sleepIntervalToDutyCycle(
+      uint16_t sleepInterval) {
+    if(sleepInterval == 0) {
+      return 10000;
+    }
+    
+    return getActualDutyCycle((DUTY_ON_TIME * 10000) 
+        / (sleepInterval + DUTY_ON_TIME));
+  }
+
+  
+  /***************** Send Commands ***************/
+  /**
+   * Each call to this send command gives the message a single
+   * DSN that does not change for every copy of the message
+   * sent out.  For messages that are not acknowledged, such as
+   * a broadcast address message, the receiving end does not
+   * signal receive() more than once for that message.
+   */
+  command error_t Send.send(message_t *msg, uint8_t len) {
+    if(call SplitControlState.getState() == S_OFF) {
+      // Everything is off right now, start SplitControl and try again
+      return EOFF;
+    }
+    
+    if(call SendState.requestState(S_LPL_SENDING) == SUCCESS) {
+      currentSendMsg = msg;
+      currentSendLen = len;
+      
+      // In case our off timer is running...
+      call OffTimer.stop();
+      call SendDoneTimer.stop();
+      
+      if(call RadioPowerState.getState() == S_ON) {
+        initializeSend();
+        return SUCCESS;
+        
+      } else {
+        post startRadio();
+      }
+      
+      return SUCCESS;
+    }
+    
+    return FAIL;
+  }
+
+  command error_t Send.cancel(message_t *msg) {
+    if(currentSendMsg == msg) {
+      call SendState.toIdle();
+      call SendDoneTimer.stop();
+      startOffTimer();
+      return call SubSend.cancel(msg);
+    }
+    
+    return FAIL;
+  }
+  
+  
+  command uint8_t Send.maxPayloadLength() {
+    return call SubSend.maxPayloadLength();
+  }
+
+  command void *Send.getPayload(message_t* msg) {
+    return call SubSend.getPayload(msg);
+  }
+  
+  
+  /***************** RadioBackoff Events ****************/
+  async event void RadioBackoff.requestInitialBackoff[am_id_t amId](message_t *msg) {
+    if((call CC2420PacketBody.getMetadata(msg))->rxInterval 
+        > ONE_MESSAGE) {
+      call RadioBackoff.setInitialBackoff[amId]( call Random.rand16() 
+          % (0x4 * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF);
+    }
+  }
+  
+  async event void RadioBackoff.requestCongestionBackoff[am_id_t amId](message_t *msg) {
+    if((call CC2420PacketBody.getMetadata(msg))->rxInterval 
+        > ONE_MESSAGE) {
+      call RadioBackoff.setCongestionBackoff[amId]( call Random.rand16() 
+          % (0x3 * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF);
+    }
+  }
+  
+  async event void RadioBackoff.requestCca[am_id_t amId](message_t *msg) {
+  }
+  
+  /***************** Receive Commands ***************/
+  command void *Receive.getPayload(message_t* msg, uint8_t* len) {
+    return call SubReceive.getPayload(msg, len);
+  }
+
+  command uint8_t Receive.payloadLength(message_t* msg) {
+    return call SubReceive.payloadLength(msg);
+  }
+
+
+  /***************** DutyCycle Events ***************/
+  /**
+   * A transmitter was detected.  You must now take action to
+   * turn the radio off when the transaction is complete.
+   */
+  event void PowerCycle.detected() {
+    // At this point, the duty cycling has been disabled temporary
+    // and it will be this component's job to turn the radio back off
+    // Wait long enough to see if we actually receive a packet, which is
+    // just a little longer in case there is more than one lpl transmitter on
+    // the channel.
+    
+    if(call SendState.isIdle()) {
+      startOffTimer();
+    }
+  }
+  
+  
+  /***************** SubControl Events ***************/
+  event void SubControl.startDone(error_t error) {
+    if(!error) {
+      call RadioPowerState.forceState(S_ON);
+      
+      if(call SendState.getState() == S_LPL_FIRST_MESSAGE
+          || call SendState.getState() == S_LPL_SENDING) {
+        initializeSend();
+      }
+    }
+  }
+    
+  event void SubControl.stopDone(error_t error) {
+    if(!error) {
+
+      if(call SendState.getState() == S_LPL_FIRST_MESSAGE
+          || call SendState.getState() == S_LPL_SENDING) {
+        // We're in the middle of sending a message; start the radio back up
+        post startRadio();
+        
+      } else {        
+        call OffTimer.stop();
+        call SendDoneTimer.stop();
+      }
+    }
+  }
+  
+  /***************** SubSend Events ***************/
+  event void SubSend.sendDone(message_t* msg, error_t error) {
+   
+    switch(call SendState.getState()) {
+    case S_LPL_SENDING:
+      if(call SendDoneTimer.isRunning()) {
+        if(!call PacketAcknowledgements.wasAcked(msg)) {
+          post resend();
+          return;
+        }
+      }
+      break;
+      
+    case S_LPL_CLEAN_UP:
+      /**
+       * We include this state so upper layers can't send a different message
+       * before the last message gets done sending
+       */
+      break;
+      
+    default:
+      break;
+    }  
+    
+    call SendState.toIdle();
+    call SendDoneTimer.stop();
+    startOffTimer();
+    signal Send.sendDone(msg, error);
+  }
+  
+  /***************** SubReceive Events ***************/
+  /**
+   * If the received message is new, we signal the receive event and
+   * start the off timer.  If the last message we received had the same
+   * DSN as this message, then the chances are pretty good
+   * that this message should be ignored, especially if the destination address
+   * as the broadcast address
+   */
+  event message_t *SubReceive.receive(message_t* msg, void* payload, 
+      uint8_t len) {
+    startOffTimer();
+    return signal Receive.receive(msg, payload, len);
+  }
+  
+  /***************** Timer Events ****************/
+  event void OffTimer.fired() {
+    /*
+     * Only stop the radio if the radio is supposed to be off permanently
+     * or if the duty cycle is on and our sleep interval is not 0
+     */
+    if(call SplitControlState.getState() == S_OFF
+        || (call PowerCycle.getSleepInterval() > 0
+            && call SplitControlState.getState() == S_ON
+                && call SendState.getState() == S_LPL_NOT_SENDING)) { 
+      post stopRadio();
+    }
+  }
+  
+  /**
+   * When this timer is running, that means we're sending repeating messages
+   * to a node that is receive check duty cycling.
+   */
+  event void SendDoneTimer.fired() {
+    if(call SendState.getState() == S_LPL_SENDING) {
+      // The next time SubSend.sendDone is signaled, send is complete.
+      call SendState.forceState(S_LPL_CLEAN_UP);
+    }
+  }
+  
+  /***************** Resend Events ****************/
+  /**
+   * Signal that a message has been sent
+   *
+   * @param p_msg message to send.
+   * @param error notifaction of how the operation went.
+   */
+  async event void Resend.sendDone( message_t* p_msg, error_t error ) {
+    // This is actually caught by SubSend.sendDone
+  }
+  
+  
+  /***************** Tasks ***************/
+  task void send() {
+    if(call SubSend.send(currentSendMsg, currentSendLen) != SUCCESS) {
+      post send();
+    }
+  }
+  
+  task void resend() {
+    if(call Resend.resend(TRUE) != SUCCESS) {
+      post resend();
+    }
+  }
+  
+  task void startRadio() {
+    if(call SubControl.start() != SUCCESS) {
+      post startRadio();
+    }
+  }
+  
+  task void stopRadio() {
+    if(call SendState.getState() == S_LPL_NOT_SENDING) {
+      if(call SubControl.stop() != SUCCESS) {
+        post stopRadio();
+      }
+    }
+  }
+  
+  /***************** Functions ***************/
+  void initializeSend() {
+    if(call LowPowerListening.getRxSleepInterval(currentSendMsg) 
+      > ONE_MESSAGE) {
+    
+      if(call AMPacket.destination(currentSendMsg) == AM_BROADCAST_ADDR) {
+        call PacketAcknowledgements.noAck(currentSendMsg);
+      } else {
+        // Send it repetitively within our transmit window
+        call PacketAcknowledgements.requestAck(currentSendMsg);
+      }
+
+      call SendDoneTimer.startOneShot(
+          call LowPowerListening.getRxSleepInterval(currentSendMsg) + 20);
+    }
+        
+    post send();
+  }
+  
+  
+  void startOffTimer() {
+    call OffTimer.startOneShot(DELAY_AFTER_RECEIVE);
+  }
+  
+  /**
+   * Check the bounds on a given duty cycle
+   * We're never over 100%, and we're never at 0%
+   */
+  uint16_t getActualDutyCycle(uint16_t dutyCycle) {
+    if(dutyCycle > 10000) {
+      return 10000;
+    } else if(dutyCycle == 0) {
+      return 1;
+    }
+    
+    return dutyCycle;
+  }  
+}
+
diff --git a/tos/chips/cc2420/lpl/DummyLplC.nc b/tos/chips/cc2420/lpl/DummyLplC.nc
new file mode 100644 (file)
index 0000000..4d0c5d8
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Dummy low power listening interface used when LowPowerListening is not
+ * compiled in with the application.
+ * Sleep interval is always 0, and duty cycle is always 100%
+ * @author David Moss
+ */
+configuration DummyLplC {
+  provides {
+    interface Send;
+    interface Receive;
+    interface LowPowerListening;
+    interface SplitControl;
+    interface State as SendState;
+  }
+  
+  uses {
+    interface Send as SubSend;
+    interface Receive as SubReceive;
+    interface SplitControl as SubControl;
+  }
+}
+
+implementation {
+  components DummyLplP;
+  components new StateC();
+  
+  Send = SubSend;
+  Receive = SubReceive;
+  SplitControl = SubControl;
+  LowPowerListening = DummyLplP;
+  SendState = StateC;
+  
+}
+
diff --git a/tos/chips/cc2420/lpl/DummyLplP.nc b/tos/chips/cc2420/lpl/DummyLplP.nc
new file mode 100644 (file)
index 0000000..dbc6bb5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Dummy low power listening interface used when LowPowerListening is not
+ * compiled in with the application.
+ * Sleep interval is always 0, and duty cycle is always 100%
+ * @author David Moss
+ */
+module DummyLplP {
+  provides {
+    interface LowPowerListening;
+  }
+}
+
+implementation {
+
+  command void LowPowerListening.setLocalSleepInterval(uint16_t sleepIntervalMs) {
+  }
+  
+  command uint16_t LowPowerListening.getLocalSleepInterval() {
+    return 0;
+  }
+  
+  command void LowPowerListening.setLocalDutyCycle(uint16_t dutyCycle) {
+  }
+  
+  command uint16_t LowPowerListening.getLocalDutyCycle() {
+    return 10000;
+  }
+  
+  command void LowPowerListening.setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs) {
+  }
+  
+  command uint16_t LowPowerListening.getRxSleepInterval(message_t *msg) {
+    return 0;
+  }
+  
+  command void LowPowerListening.setRxDutyCycle(message_t *msg, uint16_t dutyCycle) {
+  }
+  
+  command uint16_t LowPowerListening.getRxDutyCycle(message_t *msg) {
+    return 10000;
+  }
+  
+  command uint16_t LowPowerListening.dutyCycleToSleepInterval(uint16_t dutyCycle) {
+    return 0;
+  }
+  
+  command uint16_t LowPowerListening.sleepIntervalToDutyCycle(uint16_t sleepInterval) {
+    return 10000;
+  }
+  
+}
+
diff --git a/tos/chips/cc2420/lpl/PowerCycleC.nc b/tos/chips/cc2420/lpl/PowerCycleC.nc
new file mode 100644 (file)
index 0000000..41dca27
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Use this component to duty cycle the radio. When a message is heard, 
+ * disable DutyCycling.
+ *
+ * @author David Moss dmm@rincon.com
+ */
+
+configuration PowerCycleC {
+  provides {
+    interface PowerCycle;
+    interface SplitControl;
+    interface State as SplitControlState;
+    interface State as RadioPowerState;
+  }
+}
+
+implementation {
+  components PowerCycleP,
+      CC2420TransmitC,
+      CC2420ReceiveC,
+      CC2420CsmaC,
+      LedsC,
+      new StateC() as RadioPowerStateC,
+      new StateC() as SplitControlStateC,
+      new TimerMilliC() as OnTimerC,
+      new TimerMilliC() as CheckTimerC;
+
+#if defined(LOW_POWER_LISTENING) || defined(ACK_LOW_POWER_LISTENING)
+  components DefaultLplC as LplC;
+#else
+  components DummyLplC as LplC;
+#endif
+
+  PowerCycle = PowerCycleP;
+  SplitControl = PowerCycleP;
+  SplitControlState = SplitControlStateC;
+  RadioPowerState = RadioPowerStateC;
+  
+  PowerCycleP.EnergyIndicator -> CC2420TransmitC.EnergyIndicator;
+  PowerCycleP.ByteIndicator -> CC2420TransmitC.ByteIndicator;
+  PowerCycleP.PacketIndicator -> CC2420ReceiveC.PacketIndicator;
+  PowerCycleP.SubControl -> CC2420CsmaC;
+  PowerCycleP.SendState -> LplC;
+  PowerCycleP.RadioPowerState -> RadioPowerStateC;
+  PowerCycleP.SplitControlState -> SplitControlStateC;
+  PowerCycleP.OnTimer -> OnTimerC;
+  PowerCycleP.Leds -> LedsC;
+    
+}
+
+
diff --git a/tos/chips/cc2420/lpl/PowerCycleP.nc b/tos/chips/cc2420/lpl/PowerCycleP.nc
new file mode 100644 (file)
index 0000000..862315c
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/** 
+ * Module to duty cycle the radio on and off, performing CCA receive checks.
+ * When a carrier is sensed, this will leave the radio on. It is then up
+ * to higher layers to turn the radio off again.  Once the radio is turned
+ * off, this module will automatically continue duty cycling and looking for
+ * a modulated signal.
+ *
+ * Suggested TODO's:
+ *  > TransmitC and ReceiveC provide Energy, Byte, and Packet indicators.
+ *    Tap into those to add more detection levels and granularity. Only let
+ *    the radio turn off when we're not actively receiving bytes.  Right now
+ *    the packet indicator is a little backwards.
+ *  > Let one component be in charge of maintaining State information about
+ *    the power of the radio, probably lower in the stack.
+ *  > Wire SplitControl, Send, and Receive through this component.  Make it
+ *    responsible for packet-level detections and being completely responsible
+ *    for controlling the power of the radio without the use of upper layers
+ *  > Remove unnecessary State components and Timers.
+ *
+ * @author David Moss
+ */
+module PowerCycleP {
+  provides {
+    interface PowerCycle;
+    interface SplitControl;
+  }
+
+  uses {
+    interface Timer<TMilli> as OnTimer;
+    interface SplitControl as SubControl;
+    interface State as RadioPowerState;
+    interface State as SplitControlState;
+    interface State as SendState;
+    interface Leds;
+    interface ReceiveIndicator as EnergyIndicator;
+    interface ReceiveIndicator as ByteIndicator;
+    interface ReceiveIndicator as PacketIndicator;
+  }
+}
+
+implementation {
+  
+  /** The current period of the duty cycle, equivalent of wakeup interval */
+  uint16_t sleepInterval = 0;
+  
+  /** The number of times the CCA has been sampled in this wakeup period */
+  uint16_t ccaChecks;
+  
+  /**
+   * Radio Power, Check State, and Duty Cycling State
+   */
+  enum {
+    S_OFF, // off by default
+    S_TURNING_ON,
+    S_ON,
+    S_TURNING_OFF,
+  };
+  
+  
+  /***************** Prototypes ****************/
+  task void stopRadio();
+  task void startRadio();
+  task void getCca();
+  
+  bool finishSplitControlRequests();
+  bool isDutyCycling();
+  
+  
+  /***************** PowerCycle Commands ****************/
+  /**
+   * Set the sleep interval, in binary milliseconds
+   * @param sleepIntervalMs the sleep interval in [ms]
+   */
+  command void PowerCycle.setSleepInterval(uint16_t sleepIntervalMs) {
+    if (!sleepInterval && sleepIntervalMs) {
+      // We were always on, now lets duty cycle
+      post stopRadio();  // Might want to delay turning off the radio
+    }
+    
+    sleepInterval = sleepIntervalMs;
+    
+    if(sleepInterval == 0 && call SplitControlState.isState(S_ON)) {
+      /*
+       * Leave the radio on permanently if sleepInterval == 0 and the radio is 
+       * supposed to be enabled
+       */
+      if(call RadioPowerState.getState() == S_OFF) {
+        call SubControl.start();
+      }
+    }
+  }
+  
+  /**
+   * @return the sleep interval in [ms]
+   */
+  command uint16_t PowerCycle.getSleepInterval() {
+    return sleepInterval;
+  }
+  
+  
+  /***************** SplitControl Commands ****************/
+  command error_t SplitControl.start() {
+    if(call SplitControlState.isState(S_ON)) {
+      return EALREADY;
+      
+    } else if(call SplitControlState.isState(S_TURNING_ON)) {
+      return SUCCESS;
+    
+    } else if(!call SplitControlState.isState(S_OFF)) {
+      return EBUSY;
+    }
+    
+    // Radio was off, now has been told to turn on or duty cycle.
+    call SplitControlState.forceState(S_TURNING_ON);
+    
+    if(sleepInterval > 0) {
+      // Begin duty cycling
+      post stopRadio();
+      return SUCCESS;
+      
+    } else {
+      post startRadio();
+      return SUCCESS;
+    }
+  }
+  
+  command error_t SplitControl.stop() {
+    if(call SplitControlState.isState(S_OFF)) {
+      return EALREADY;
+      
+    } else if(call SplitControlState.isState(S_TURNING_OFF)) {
+      return SUCCESS;
+    
+    } else if(!call SplitControlState.isState(S_ON)) {
+      return EBUSY;
+    }
+    
+    call SplitControlState.forceState(S_TURNING_OFF);
+    post stopRadio();
+    return SUCCESS;
+  }
+  
+  /***************** Timer Events ****************/
+  event void OnTimer.fired() {
+    if(isDutyCycling()) {
+      if(call RadioPowerState.getState() == S_OFF) {
+        ccaChecks = 0;
+        
+         /*
+          * Turn on the radio only after the uC is fully awake.  ATmega128's 
+          * have this issue when running on an external crystal.
+          */
+         post getCca();
+        
+      } else {
+        // Someone else turned on the radio, try again in awhile
+        call OnTimer.startOneShot(sleepInterval);
+      }
+    }
+  }
+  
+  /***************** SubControl Events ****************/
+  event void SubControl.startDone(error_t error) {
+    call RadioPowerState.forceState(S_ON);
+    //call Leds.led2On();
+    
+    if(finishSplitControlRequests()) {
+      return;
+      
+    } else if(isDutyCycling()) {
+      post getCca();
+    }
+  }
+  
+  event void SubControl.stopDone(error_t error) {
+    call RadioPowerState.forceState(S_OFF);
+    //call Leds.led2Off();
+    
+    if(finishSplitControlRequests()) {
+      return;
+      
+    } else if(isDutyCycling()) {
+      call OnTimer.startOneShot(sleepInterval);
+    }
+    
+  }
+  
+  
+  /***************** Tasks ****************/
+  task void stopRadio() {
+    error_t error = call SubControl.stop();
+    if(error != SUCCESS) {
+      // Already stopped?
+      finishSplitControlRequests();
+      call OnTimer.startOneShot(sleepInterval);
+    }
+  }
+  
+  task void startRadio() {
+    if(call SubControl.start() != SUCCESS) {
+      post startRadio();
+    }
+  }
+  
+  task void getCca() {
+    uint8_t detects = 0;
+    if(isDutyCycling()) {
+      
+      ccaChecks++;
+      if(ccaChecks == 1) {
+        // Microcontroller is ready, turn on the radio and sample a few times
+        post startRadio();
+        return;
+      }
+
+      atomic {
+        for( ; ccaChecks < MAX_LPL_CCA_CHECKS && call SendState.isIdle(); ccaChecks++) {
+          if(call PacketIndicator.isReceiving()) {
+            signal PowerCycle.detected();
+            return;
+          }
+          
+          if(call EnergyIndicator.isReceiving()) {
+            detects++;
+            if(detects > MIN_SAMPLES_BEFORE_DETECT) {
+              signal PowerCycle.detected(); 
+              return;
+            }
+            // Leave the radio on for upper layers to perform some transaction
+          }
+        }
+      }
+      
+      if(call SendState.isIdle()) {
+        post stopRadio();
+      }
+    }  
+  }
+  
+  /**
+   * @return TRUE if the radio should be actively duty cycling
+   */
+  bool isDutyCycling() {
+    return sleepInterval > 0 && call SplitControlState.isState(S_ON);
+  }
+  
+  
+  /**
+   * @return TRUE if we successfully handled a SplitControl request
+   */
+  bool finishSplitControlRequests() {
+    if(call SplitControlState.isState(S_TURNING_OFF)) {
+      call SplitControlState.forceState(S_OFF);
+      signal SplitControl.stopDone(SUCCESS);
+      return TRUE;
+      
+    } else if(call SplitControlState.isState(S_TURNING_ON)) {
+      // Starting while we're duty cycling first turns off the radio
+      call SplitControlState.forceState(S_ON);
+      signal SplitControl.startDone(SUCCESS);
+      return TRUE;
+    }
+    
+    return FALSE;
+  }
+  
+  /**************** Defaults ****************/
+  default event void PowerCycle.detected() {
+  }
+
+
+  default event void SplitControl.startDone(error_t error) {
+  }
+  
+  default event void SplitControl.stopDone(error_t error) {
+  }
+}
+
+
diff --git a/tos/chips/cc2420/lpl/readme.txt b/tos/chips/cc2420/lpl/readme.txt
new file mode 100644 (file)
index 0000000..4fe5dc6
--- /dev/null
@@ -0,0 +1,98 @@
+
+ARCHITECTURE
+=======================================================
+The default LPL implementation uses a packet train with acknowledgements
+enabled, shortened backoffs, and a spinning energy checking loop.
+
+The default strategy can be improved by implementing a different architecture.
+Right now the architecture looks like this:
+
+
+  +----------------------------------+
+  |           DefaultLplP            | -> To lower level Send
+  | Responsible for retransmissions  | -> To lower level SplitControl
+  | and turning the radio off when   | <- From lower level Receive
+  | done, or on when starting to     |
+  | transmit                         |
+  +----------------------------------+
+  |           PowerCycleP            |
+  | Responsible for performing       | -> To lower level SplitControl
+  | receive checks and leaving the   |
+  | radio on                         |
+  +----------------------------------+
+  
+I think the architecture should be changed.  If you're interested in doing work 
+in this area, there's lots of development and research to be done.
+
+First, take a look at tinyos-2.x-contrib/wustl/upma.  The architecture of the
+CC2420 stack there is implemented to define a low-level abstraction layer
+which separates radio-specific functionality from radio-independent
+functionality.  This is nice.  By providing certain interfaces from the 
+radio-dependant functionality, it makes it easier to maintain MAC layer 
+stuff independent of the radio.  And that includes LPL.
+
+One of the things that radio stack uses is an Alarm instead of a spinning
+task/while loop.  Whereas the implementation here uses a static number of 
+loops to detect if energy is on the channel, we would be better able
+to achieve the smallest radio asynchronous receive check on-time by using an 
+alarm.  After all, the radio only has to be on to span the quiet gaps in a 
+transmitter's transmission, and we know approximately the duration of those
+quiet gaps based on the backoff period, which the stack defines.
+
+I recommend we redo some of the LPL architecture to look more like this:
+
+  +----------------------------------+
+  |          DefaultLplP             |
+  | Responsible for retransmissions  |
+  +----------------------------------+
+           |   |   |       (Send, Receive, SplitControl goes through PowerCycle)
+  +----------------------------------+
+  |          PowerCycleP             |
+  | Responsible for managing radio   | -> To lower level Send
+  | on/off power, and telling        | -> To lower level SplitControl
+  | PacketDetectP when to start/stop | <- From lower level Receive
+  | its job                          |
+  +----------------------------------+
+  |         PacketDetectP            |
+  | Responsible for detecting        | <- EnergyIndicator
+  | energy, bytes, and/or packets.   | <- ByteIndicator
+  | Notify PowerCycle when packets   | <- PacketIndicator
+  | are detected                     |
+  +----------------------------------+
+  
+This is pretty radio independent.
+
+OTHER LOW POWER LISTENING STRATEGIES
+=============================================================
+Other low power listening layers can be implemented as well:
+  * Continuous modulation / No Acknowledgements:
+     > Allows the receiver to achieve the lowest possible receive check
+       on time.  It's shown to be several times more efficient on the receive 
+       check than the default.  This is a radio-dependent LPL strategy
+       and the CC2420 can acheive it by putting some transmit register into
+       test mode where it continually retransmits the contents of the TXFIFO.
+       The CRC of the packet must be uploaded into the TXFIFO because it won't
+       be calculated by the CC2420.  Not sure if the preamble and sync bytes
+       need to be uploaded as well.  The transmitter takes a hit because it
+       cannot receive acks in the middle of its packet train.   But since
+       the receiver's energy consumption is so low, it's possible to increase
+       the number of receive checks in order to lower the duration of the 
+       transmission.
+     > This strategy would be a good match for networks that must get data
+       through quickly when there is data, but doesn't see too many
+       transmissions in any given geographical area of the network.  Also
+       a good strategy where your transmitters have more power.
+       
+  * 802.15.4/ZigBee End Node:
+     > Queue up packets to Send to a particular destination until that node 
+       checks in at some random time.  Use fields in the ack frame to let the 
+       node know that packets are available.  Good match for networks where one 
+       node has access to line power and other nodes are on batteries.
+       
+   * Low throughput acknowledgement LPL:
+     > Just like the default, only it uses the ByteIndicator to turn off
+       the radio as soon as it stops receiving bytes and no packet was
+       received.  Able to get a much shorter receive check at the expense
+       of decreased probability that you'll receive messages in a congested
+       network.
+       
diff --git a/tos/chips/cc2420/packet/CC2420PacketC.nc b/tos/chips/cc2420/packet/CC2420PacketC.nc
new file mode 100644 (file)
index 0000000..00ad73b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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 Chad Metcalf
+ */
+
+#include "IEEE802154.h"
+#include "message.h"
+
+module CC2420PacketC {
+
+  provides {
+    interface CC2420Packet;
+    interface PacketAcknowledgements as Acks;
+    interface CC2420PacketBody;
+  }
+
+}
+
+implementation {
+
+
+  /***************** PacketAcknowledgement Commands ****************/
+  async command error_t Acks.requestAck( message_t* p_msg ) {
+    (call CC2420PacketBody.getHeader( p_msg ))->fcf |= 1 << IEEE154_FCF_ACK_REQ;
+    return SUCCESS;
+  }
+
+  async command error_t Acks.noAck( message_t* p_msg ) {
+    (call CC2420PacketBody.getHeader( p_msg ))->fcf &= ~(1 << IEEE154_FCF_ACK_REQ);
+    return SUCCESS;
+  }
+
+  async command bool Acks.wasAcked( message_t* p_msg ) {
+    return (call CC2420PacketBody.getMetadata( p_msg ))->ack;
+  }
+
+  /***************** CC2420Packet Commands ****************/
+  async command void CC2420Packet.setPower( message_t* p_msg, uint8_t power ) {
+    if ( power > 31 )
+      power = 31;
+    (call CC2420PacketBody.getMetadata( p_msg ))->tx_power = power;
+  }
+
+  async command uint8_t CC2420Packet.getPower( message_t* p_msg ) {
+    return (call CC2420PacketBody.getMetadata( p_msg ))->tx_power;
+  }
+   
+  async command int8_t CC2420Packet.getRssi( message_t* p_msg ) {
+    return (call CC2420PacketBody.getMetadata( p_msg ))->rssi;
+  }
+
+  async command error_t CC2420Packet.getLqi( message_t* p_msg ) {
+    return (call CC2420PacketBody.getMetadata( p_msg ))->lqi;
+  }
+
+  /***************** CC2420PacketBody Commands ****************/
+  async command cc2420_header_t *CC2420PacketBody.getHeader( message_t* msg ) {
+    return (cc2420_header_t*)( msg->data - sizeof( cc2420_header_t ) );
+  }
+
+  async command cc2420_metadata_t *CC2420PacketBody.getMetadata( message_t* msg ) {
+    return (cc2420_metadata_t*)msg->metadata;
+  }
+
+}
diff --git a/tos/chips/cc2420/receive/CC2420ReceiveC.nc b/tos/chips/cc2420/receive/CC2420ReceiveC.nc
new file mode 100644 (file)
index 0000000..1492f58
--- /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>
+ * @version $Revision$ $Date$
+ */
+
+configuration CC2420ReceiveC {
+
+  provides interface StdControl;
+  provides interface CC2420Receive;
+  provides interface Receive;
+  provides interface ReceiveIndicator as PacketIndicator;
+
+}
+
+implementation {
+  components MainC;
+  components CC2420ReceiveP;
+  components CC2420PacketC;
+  components ActiveMessageAddressC;
+  components new CC2420SpiC() as Spi;
+  components CC2420ControlC;
+  
+  components HplCC2420PinsC as Pins;
+  components HplCC2420InterruptsC as InterruptsC;
+
+  components LedsC as Leds;
+  CC2420ReceiveP.Leds -> Leds;
+
+  StdControl = CC2420ReceiveP;
+  CC2420Receive = CC2420ReceiveP;
+  Receive = CC2420ReceiveP;
+  PacketIndicator = CC2420ReceiveP.PacketIndicator;
+
+  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.CC2420Packet -> CC2420PacketC;
+  CC2420ReceiveP.CC2420PacketBody -> CC2420PacketC;
+  CC2420ReceiveP.CC2420Config -> CC2420ControlC;
+
+}
diff --git a/tos/chips/cc2420/receive/CC2420ReceiveP.nc b/tos/chips/cc2420/receive/CC2420ReceiveP.nc
new file mode 100644 (file)
index 0000000..b1dfb86
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * 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
+ * @version $Revision$ $Date$
+ */
+
+module CC2420ReceiveP {
+
+  provides interface Init;
+  provides interface StdControl;
+  provides interface CC2420Receive;
+  provides interface Receive;
+  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 CC2420Packet;
+  uses interface CC2420PacketBody;
+  uses interface CC2420Config;
+  
+  uses interface Leds;
+}
+
+implementation {
+
+  typedef enum {
+    S_STOPPED,
+    S_STARTED,
+    S_RX_LENGTH,
+    S_RX_FCF,
+    S_RX_PAYLOAD,
+  } cc2420_receive_state_t;
+
+  enum {
+    RXFIFO_SIZE = 128,
+    TIMESTAMP_QUEUE_SIZE = 8,
+    FCF_LENGTH = 2,
+  };
+
+  uint16_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];
+  
+  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 */
+  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;
+  
+  /***************** Prototypes ****************/
+  void reset_state();
+  void beginReceive();
+  void receive();
+  void waitForNextPacket();
+  void flush();
+  
+  task void receiveDone_task();
+  
+  /***************** Init Commands ****************/
+  command error_t Init.init() {
+    m_p_rx_buf = &m_rx_buf;
+    return SUCCESS;
+  }
+
+  /***************** StdControl ****************/
+  command error_t StdControl.start() {
+    atomic {
+      reset_state();
+      m_state = S_STARTED;
+      atomic receivingPacket = FALSE;
+      call InterruptFIFOP.enableFallingEdge();
+    }
+    return SUCCESS;
+  }
+
+
+  
+  command error_t StdControl.stop() {
+    atomic {
+      m_state = S_STOPPED;
+      reset_state();
+      call CSN.set();
+      call InterruptFIFOP.disable();
+    }
+    return SUCCESS;
+  }
+
+  /***************** Receive Commands ****************/
+  command void* Receive.getPayload(message_t* m, uint8_t* len) {
+    if (len != NULL) {
+      *len = ((uint8_t*) (call CC2420PacketBody.getHeader( m_p_rx_buf )))[0];
+    }
+    return m->data;
+  }
+
+  command uint8_t Receive.payloadLength(message_t* m) {
+    uint8_t* buf = (uint8_t*)(call CC2420PacketBody.getHeader( m_p_rx_buf ));
+    return buf[0];
+  }
+  
+  
+  /***************** CC2420Receive Commands ****************/
+  /**
+   * Start frame delimiter signifies the beginning/end of a packet
+   * See the CC2420 datasheet for details.
+   */
+  async command void CC2420Receive.sfd( uint16_t time ) {
+    if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) {
+      uint8_t tail =  ( ( m_timestamp_head + m_timestamp_size ) % 
+                        TIMESTAMP_QUEUE_SIZE );
+      m_timestamp_queue[ tail ] = time;
+      m_timestamp_size++;
+    }
+  }
+
+  async command void CC2420Receive.sfd_dropped() {
+    if ( m_timestamp_size ) {
+      m_timestamp_size--;
+    }
+  }
+
+  /***************** PacketIndicator Commands ****************/
+  command bool PacketIndicator.isReceiving() {
+    bool receiving;
+    atomic {
+      receiving = receivingPacket;
+    }
+    return receiving;
+  }
+  
+  
+  /***************** InterruptFIFOP Events ****************/
+  async event void InterruptFIFOP.fired() {
+    if ( m_state == S_STARTED ) {
+      beginReceive();
+      
+    } else {
+      m_missed_packets++;
+    }
+  }
+  
+  
+  /***************** SpiResource Events ****************/
+  event void SpiResource.granted() {
+    receive();
+  }
+  
+  /***************** 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 ) {
+    cc2420_header_t* header = call CC2420PacketBody.getHeader( m_p_rx_buf );
+    cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf );
+    uint8_t* buf = (uint8_t*) header;
+    rxFrameLength = buf[ 0 ];
+
+    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;
+        }
+        
+        if(rxFrameLength <= MAC_PACKET_SIZE) {
+          if(rxFrameLength > 0) {
+            if(rxFrameLength > FCF_LENGTH) {
+              // This packet has an FCF byte plus at least one more byte to read
+              call RXFIFO.continueRead(buf + 1, FCF_LENGTH);
+              
+            } else {
+              // This is really a bad packet, skip FCF and get it out of here.
+              m_state = S_RX_PAYLOAD;
+              call RXFIFO.continueRead(buf + 1, rxFrameLength);
+            }
+                            
+          } else {
+            // Length == 0; start reading the next packet
+            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:
+      m_state = S_RX_PAYLOAD;
+      if(call CC2420Config.isAutoAckEnabled() && !call CC2420Config.isHwAutoAckDefault()) {
+        if (((( header->fcf >> IEEE154_FCF_ACK_REQ ) & 0x01) == 1)
+            && ((( header->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7) == IEEE154_TYPE_DATA)) {
+          // CSn flippage cuts off our FIFO; SACK and begin reading again
+          call CSN.set();
+          call CSN.clr();
+          call SACK.strobe();
+          call CSN.set();
+          call CSN.clr();
+          call RXFIFO.beginRead(buf + 1 + FCF_LENGTH, 
+              rxFrameLength - FCF_LENGTH);
+          return;
+        }
+      }
+      
+      // Didn't flip CSn, we're ok to continue reading.
+      call RXFIFO.continueRead(buf + 1 + FCF_LENGTH, 
+          rxFrameLength - FCF_LENGTH);
+      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 ) {
+          metadata->time = m_timestamp_queue[ m_timestamp_head ];
+          m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;
+          m_timestamp_size--;
+        }
+      } else {
+        metadata->time = 0xffff;
+      }
+      
+      // We may have received an ack that should be processed by Transmit
+      // buf[rxFrameLength] >> 7 checks the CRC
+      if ( ( buf[ rxFrameLength ] >> 7 ) && rx_buf ) {
+        uint8_t type = ( header->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7;
+        signal CC2420Receive.receive( type, m_p_rx_buf );
+        if ( type == IEEE154_TYPE_DATA ) {
+          post receiveDone_task();
+          return;
+        }
+      }
+      
+      waitForNextPacket();
+      break;
+
+    default:
+      atomic receivingPacket = FALSE;
+      call CSN.set();
+      call SpiResource.release();
+      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() {
+    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;
+    m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data, 
+                                         rxFrameLength );
+
+    atomic receivingPacket = FALSE;
+    waitForNextPacket();
+  }
+
+  /****************** CC2420Config Events ****************/
+  event void CC2420Config.syncDone( error_t error ) {
+  }
+  
+  /****************** Functions ****************/
+  /**
+   * Attempt to acquire the SPI bus to receive a packet.
+   */
+  void beginReceive() { 
+    m_state = S_RX_LENGTH;
+    
+    atomic 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.clr();
+    call RXFIFO.beginRead( (uint8_t*)(call CC2420PacketBody.getHeader( m_p_rx_buf )), 1 );
+  }
+
+
+  /**
+   * Determine if there's a packet ready to go, or if we should do nothing
+   * until the next packet arrives
+   */
+  void waitForNextPacket() {
+    atomic {
+      if ( m_state == S_STOPPED ) {
+        call SpiResource.release();
+        return;
+      }
+      
+      atomic receivingPacket = FALSE;
+      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/spi/CC2420SpiC.nc b/tos/chips/cc2420/spi/CC2420SpiC.nc
new file mode 100644 (file)
index 0000000..e925e9a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * Implementation of basic SPI primitives for the ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+generic configuration CC2420SpiC() {
+
+  provides interface Resource;
+  provides interface ChipSpiResource;
+
+  // commands
+  provides interface CC2420Strobe as SFLUSHRX;
+  provides interface CC2420Strobe as SFLUSHTX;
+  provides interface CC2420Strobe as SNOP;
+  provides interface CC2420Strobe as SRXON;
+  provides interface CC2420Strobe as SRFOFF;
+  provides interface CC2420Strobe as STXON;
+  provides interface CC2420Strobe as STXONCCA;
+  provides interface CC2420Strobe as SXOSCON;
+  provides interface CC2420Strobe as SXOSCOFF;
+  
+  provides interface CC2420Strobe as SACK;
+
+  // registers
+  provides interface CC2420Register as FSCTRL;
+  provides interface CC2420Register as IOCFG0;
+  provides interface CC2420Register as IOCFG1;
+  provides interface CC2420Register as MDMCTRL0;
+  provides interface CC2420Register as MDMCTRL1;
+  provides interface CC2420Register as TXCTRL;
+  provides interface CC2420Register as RXCTRL1;
+  provides interface CC2420Register as RSSI;
+
+  // ram
+  provides interface CC2420Ram as IEEEADR;
+  provides interface CC2420Ram as PANID;
+  provides interface CC2420Ram as SHORTADR;
+  provides interface CC2420Ram as TXFIFO_RAM;
+
+  // fifos
+  provides interface CC2420Fifo as RXFIFO;
+  provides interface CC2420Fifo as TXFIFO;
+
+}
+
+implementation {
+
+  enum {
+    CLIENT_ID = unique( "CC2420Spi.Resource" ),
+  };
+
+  components HplCC2420PinsC as Pins;
+  components CC2420SpiWireC as Spi;
+  
+  ChipSpiResource = Spi.ChipSpiResource;
+  Resource = Spi.Resource[ CLIENT_ID ];
+  
+  // commands
+  SFLUSHRX = Spi.Strobe[ CC2420_SFLUSHRX ];
+  SFLUSHTX = Spi.Strobe[ CC2420_SFLUSHTX ];
+  SNOP = Spi.Strobe[ CC2420_SNOP ];
+  SRXON = Spi.Strobe[ CC2420_SRXON ];
+  SRFOFF = Spi.Strobe[ CC2420_SRFOFF ];
+  STXON = Spi.Strobe[ CC2420_STXON ];
+  STXONCCA = Spi.Strobe[ CC2420_STXONCCA ];
+  SXOSCON = Spi.Strobe[ CC2420_SXOSCON ];
+  SXOSCOFF = Spi.Strobe[ CC2420_SXOSCOFF ];
+  SACK = Spi.Strobe[ CC2420_SACK ];
+
+  // registers
+  FSCTRL = Spi.Reg[ CC2420_FSCTRL ];
+  IOCFG0 = Spi.Reg[ CC2420_IOCFG0 ];
+  IOCFG1 = Spi.Reg[ CC2420_IOCFG1 ];
+  MDMCTRL0 = Spi.Reg[ CC2420_MDMCTRL0 ];
+  MDMCTRL1 = Spi.Reg[ CC2420_MDMCTRL1 ];
+  TXCTRL = Spi.Reg[ CC2420_TXCTRL ];
+  RXCTRL1 = Spi.Reg[ CC2420_RXCTRL1 ];
+  RSSI = Spi.Reg[ CC2420_RSSI ];
+
+  // ram
+  IEEEADR = Spi.Ram[ CC2420_RAM_IEEEADR ];
+  PANID = Spi.Ram[ CC2420_RAM_PANID ];
+  SHORTADR = Spi.Ram[ CC2420_RAM_SHORTADR ];
+  TXFIFO_RAM = Spi.Ram[ CC2420_RAM_TXFIFO ];
+
+  // fifos
+  RXFIFO = Spi.Fifo[ CC2420_RXFIFO ];
+  TXFIFO = Spi.Fifo[ CC2420_TXFIFO ];
+
+}
+
diff --git a/tos/chips/cc2420/spi/CC2420SpiP.nc b/tos/chips/cc2420/spi/CC2420SpiP.nc
new file mode 100644 (file)
index 0000000..cdc2df9
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * 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 Roman Lim
+ * @version $Revision$ $Date$
+ */
+
+module CC2420SpiP {
+
+  provides {
+    interface ChipSpiResource;
+    interface Resource[ uint8_t id ];
+    interface CC2420Fifo as Fifo[ uint8_t id ];
+    interface CC2420Ram as Ram[ uint16_t id ];
+    interface CC2420Register as Reg[ uint8_t id ];
+    interface CC2420Strobe as Strobe[ uint8_t id ];
+  }
+  
+  uses {
+    interface Resource as SpiResource;
+    interface SpiByte;
+    interface SpiPacket;
+    interface State as WorkingState;
+    interface Leds;
+  }
+}
+
+implementation {
+
+  enum {
+    RESOURCE_COUNT = uniqueCount( "CC2420Spi.Resource" ),
+    NO_HOLDER = 0xFF,
+  };
+
+  /** WorkingStates */
+  enum {
+    S_IDLE,
+    S_BUSY,
+  };
+
+  /** Address to read/write on the CC2420, also maintains caller's client id */
+  norace uint16_t m_addr;
+  
+  /** Each bit represents a client ID that is requesting SPI bus access */
+  uint8_t m_requests = 0;
+  
+  /** The current client that owns the SPI bus */
+  uint8_t m_holder = NO_HOLDER;
+  
+  /** TRUE if it is safe to release the SPI bus after all users say ok */
+  bool release;
+  
+  /***************** Prototypes ****************/
+  error_t attemptRelease();
+  task void grant();
+  
+  /***************** ChipSpiResource Commands ****************/
+  /**
+   * Abort the release of the SPI bus.  This must be called only with the
+   * releasing() event
+   */
+  async command void ChipSpiResource.abortRelease() {
+    atomic release = FALSE;
+  }
+  
+  /**
+   * Release the SPI bus if there are no objections
+   */
+  async command error_t ChipSpiResource.attemptRelease() {
+    return attemptRelease();
+  }
+  
+  /***************** Resource Commands *****************/
+  async command error_t Resource.request[ uint8_t id ]() {
+        
+    atomic {
+      if ( call WorkingState.requestState(S_BUSY) == SUCCESS ) {
+        m_holder = id;
+        if(call SpiResource.isOwner()) {
+          post grant();
+          
+        } else {
+          call SpiResource.request();
+        }
+        
+      } else {
+        m_requests |= 1 << id;
+      }
+    }
+    return SUCCESS;
+  }
+  
+  async command error_t Resource.immediateRequest[ uint8_t id ]() {
+    error_t error;
+        
+    atomic {
+      if ( call WorkingState.requestState(S_BUSY) != SUCCESS ) {
+        return EBUSY;
+      }
+      
+      
+      if(call SpiResource.isOwner()) {
+        m_holder = id;
+        error = SUCCESS;
+      
+      } else if ((error = call SpiResource.immediateRequest()) == SUCCESS ) {
+        m_holder = id;
+        
+      } else {
+        call WorkingState.toIdle();
+      }
+    }
+    return error;
+  }
+
+  async command error_t Resource.release[ uint8_t id ]() {
+    uint8_t i;
+    atomic {
+      if ( m_holder != id ) {
+        return FAIL;
+      }
+
+      m_holder = NO_HOLDER;
+      if ( !m_requests ) {
+        call WorkingState.toIdle();
+        attemptRelease();
+        
+      } else {
+        for ( i = m_holder + 1; ; i++ ) {
+          i %= RESOURCE_COUNT;
+          
+          if ( m_requests & ( 1 << i ) ) {
+            m_holder = i;
+            m_requests &= ~( 1 << i );
+            post grant();
+            return SUCCESS;
+          }
+        }
+      }
+    }
+    
+    return SUCCESS;
+  }
+  
+  async command uint8_t Resource.isOwner[ uint8_t id ]() {
+    atomic return (m_holder == id);
+  }
+
+
+  /***************** SpiResource Events ****************/
+  event void SpiResource.granted() {
+    post grant();
+  }
+  
+  /***************** Fifo Commands ****************/
+  async command cc2420_status_t Fifo.beginRead[ uint8_t addr ]( uint8_t* data, 
+                                                                uint8_t len ) {
+    
+    cc2420_status_t status = 0;
+
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return status;
+      }
+    }
+    
+    m_addr = addr | 0x40;
+        
+    status = call SpiByte.write( m_addr );
+    call Fifo.continueRead[ addr ]( data, len );
+    
+    return status;
+    
+  }
+
+  async command error_t Fifo.continueRead[ uint8_t addr ]( uint8_t* data,
+                                                           uint8_t len ) {
+    return call SpiPacket.send( NULL, data, len );
+  }
+
+  async command cc2420_status_t Fifo.write[ uint8_t addr ]( uint8_t* data, 
+                                                            uint8_t len ) {
+
+    uint8_t status = 0;
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return status;
+      }
+    }
+    
+    m_addr = addr;
+
+    status = call SpiByte.write( m_addr );
+    call SpiPacket.send( data, NULL, len );
+
+    return status;
+
+  }
+
+  /***************** RAM Commands ****************/
+  async command cc2420_status_t Ram.read[ uint16_t addr ]( uint8_t offset,
+                                                           uint8_t* data, 
+                                                           uint8_t len ) {
+
+    cc2420_status_t status = 0;
+
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return status;
+      }
+    }
+    
+    addr += offset;
+
+    call SpiByte.write( addr | 0x80 );
+    status = call SpiByte.write( ( ( addr >> 1 ) & 0xc0 ) | 0x20 );
+    for ( ; len; len-- ) {
+      *data++ = call SpiByte.write( 0 );
+    }
+
+    return status;
+
+  }
+
+
+  async command cc2420_status_t Ram.write[ uint16_t addr ]( uint8_t offset,
+                                                            uint8_t* data, 
+                                                            uint8_t len ) {
+
+    cc2420_status_t status = 0;
+
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return status;
+      }
+    }
+    
+    addr += offset;
+
+    call SpiByte.write( addr | 0x80 );
+    call SpiByte.write( ( addr >> 1 ) & 0xc0 );
+    for ( ; len; len-- ) {
+      status = call SpiByte.write( *data++ );
+    }
+
+    return status;
+
+  }
+
+  /***************** Register Commands ****************/
+  async command cc2420_status_t Reg.read[ uint8_t addr ]( uint16_t* data ) {
+
+    cc2420_status_t status = 0;
+    
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return status;
+      }
+    }
+    
+    status = call SpiByte.write( addr | 0x40 );
+    *data = (uint16_t)call SpiByte.write( 0 ) << 8;
+    *data |= call SpiByte.write( 0 );
+    
+    return status;
+
+  }
+
+  async command cc2420_status_t Reg.write[ uint8_t addr ]( uint16_t data ) {
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return 0;
+      }
+    }
+    call SpiByte.write( addr );
+    call SpiByte.write( data >> 8 );
+    return call SpiByte.write( data & 0xff );
+  }
+
+  
+  /***************** Strobe Commands ****************/
+  async command cc2420_status_t Strobe.strobe[ uint8_t addr ]() {
+    atomic {
+      if(call WorkingState.isIdle()) {
+        return 0;
+      }
+    }
+    
+    return call SpiByte.write( addr );
+  }
+
+  /***************** SpiPacket Events ****************/
+  async event void SpiPacket.sendDone( uint8_t* tx_buf, uint8_t* rx_buf, 
+                                       uint16_t len, error_t error ) {
+    if ( m_addr & 0x40 ) {
+      signal Fifo.readDone[ m_addr & ~0x40 ]( rx_buf, len, error );
+    } else {
+      signal Fifo.writeDone[ m_addr ]( tx_buf, len, error );
+    }
+  }
+  
+  /***************** Functions ****************/
+  error_t attemptRelease() {
+    if(m_requests > 0 
+        || m_holder != NO_HOLDER 
+        || !call WorkingState.isIdle()) {
+      return FAIL;
+    }
+    
+    atomic release = TRUE;
+    signal ChipSpiResource.releasing();
+    atomic {
+      if(release) {
+        call SpiResource.release();
+        return SUCCESS;
+      }
+    }
+    
+    return EBUSY;
+  }
+  
+  task void grant() {
+    uint8_t holder;
+    atomic { 
+      holder = m_holder;
+    }
+    signal Resource.granted[ holder ]();
+  }
+
+  /***************** Defaults ****************/
+  default event void Resource.granted[ uint8_t id ]() {
+  }
+
+  default async event void Fifo.readDone[ uint8_t addr ]( uint8_t* rx_buf, uint8_t rx_len, error_t error ) {
+  }
+  
+  default async event void Fifo.writeDone[ uint8_t addr ]( uint8_t* tx_buf, uint8_t tx_len, error_t error ) {
+  }
+
+  default async event void ChipSpiResource.releasing() {
+  }
+  
+}
diff --git a/tos/chips/cc2420/spi/CC2420SpiWireC.nc b/tos/chips/cc2420/spi/CC2420SpiWireC.nc
new file mode 100644 (file)
index 0000000..c4a3a98
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+configuration CC2420SpiWireC {
+  
+  provides interface Resource[ uint8_t id ];
+  provides interface ChipSpiResource;
+  provides interface CC2420Fifo as Fifo[ uint8_t id ];
+  provides interface CC2420Ram as Ram[ uint16_t id ];
+  provides interface CC2420Register as Reg[ uint8_t id ];
+  provides interface CC2420Strobe as Strobe[ uint8_t id ];
+
+}
+
+implementation {
+
+  components CC2420SpiP as SpiP;
+  Resource = SpiP;
+  Fifo = SpiP;
+  Ram = SpiP;
+  Reg = SpiP;
+  Strobe = SpiP;
+  ChipSpiResource = SpiP;
+
+  components new StateC() as WorkingStateC;
+  SpiP.WorkingState -> WorkingStateC;
+  
+  components new HplCC2420SpiC();
+  SpiP.SpiResource -> HplCC2420SpiC;
+  SpiP.SpiByte -> HplCC2420SpiC;
+  SpiP.SpiPacket -> HplCC2420SpiC;
+
+  components LedsC;
+  SpiP.Leds -> LedsC;
+
+}
diff --git a/tos/chips/cc2420/transmit/CC2420TransmitC.nc b/tos/chips/cc2420/transmit/CC2420TransmitC.nc
new file mode 100644 (file)
index 0000000..fb7bcc3
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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 transmit path for the ChipCon CC2420 radio.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+#include "IEEE802154.h"
+
+configuration CC2420TransmitC {
+
+  provides {
+    interface StdControl;
+    interface CC2420Transmit;
+    interface RadioBackoff;
+    interface RadioTimeStamping;
+    interface ReceiveIndicator as EnergyIndicator;
+    interface ReceiveIndicator as ByteIndicator;
+  }
+}
+
+implementation {
+
+  components CC2420TransmitP;
+  StdControl = CC2420TransmitP;
+  CC2420Transmit = CC2420TransmitP;
+  RadioBackoff = CC2420TransmitP;
+  RadioTimeStamping = CC2420TransmitP;
+  EnergyIndicator = CC2420TransmitP.EnergyIndicator;
+  ByteIndicator = CC2420TransmitP.ByteIndicator;
+
+  components MainC;
+  MainC.SoftwareInit -> CC2420TransmitP;
+  MainC.SoftwareInit -> Alarm;
+  
+  components AlarmMultiplexC as Alarm;
+  CC2420TransmitP.BackoffTimer -> Alarm;
+
+  components HplCC2420PinsC as Pins;
+  CC2420TransmitP.CCA -> Pins.CCA;
+  CC2420TransmitP.CSN -> Pins.CSN;
+  CC2420TransmitP.SFD -> Pins.SFD;
+
+  components HplCC2420InterruptsC as Interrupts;
+  CC2420TransmitP.CaptureSFD -> Interrupts.CaptureSFD;
+
+  components new CC2420SpiC() as Spi;
+  CC2420TransmitP.SpiResource -> Spi;
+  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;
+  
+  components CC2420ReceiveC;
+  CC2420TransmitP.CC2420Receive -> CC2420ReceiveC;
+  
+  components CC2420PacketC;
+  CC2420TransmitP.CC2420Packet -> CC2420PacketC;
+  CC2420TransmitP.CC2420PacketBody -> CC2420PacketC;
+  
+  components LedsC;
+  CC2420TransmitP.Leds -> LedsC;
+}
diff --git a/tos/chips/cc2420/transmit/CC2420TransmitP.nc b/tos/chips/cc2420/transmit/CC2420TransmitP.nc
new file mode 100644 (file)
index 0000000..4fe02eb
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ * 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
+ * @version $Revision$ $Date$
+ */
+
+#include "CC2420.h"
+#include "crc.h"
+#include "message.h"
+
+module CC2420TransmitP {
+
+  provides interface Init;
+  provides interface StdControl;
+  provides interface CC2420Transmit as Send;
+  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 BackoffTimer;
+  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 CC2420Register as MDMCTRL1;
+
+  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_LOAD_CANCEL,
+    S_TX_CANCEL,
+    S_CCA_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 bool m_cca;
+  
+  norace uint8_t m_tx_power;
+  
+  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 */
+  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 send( message_t *p_msg, bool cca );
+  error_t resend( bool cca );
+  void loadTXFIFO();
+  void attemptSend();
+  void congestionBackoff();
+  error_t acquireSpiResource();
+  error_t releaseSpiResource();
+  void signalDone( error_t err );
+  
+  
+  /***************** Init Commands *****************/
+  command error_t Init.init() {
+    call CCA.makeInput();
+    call CSN.makeOutput();
+    call SFD.makeInput();
+    return SUCCESS;
+  }
+
+  /***************** StdControl Commands ****************/
+  command error_t StdControl.start() {
+    atomic {
+      call CaptureSFD.captureRisingEdge();
+      m_state = S_STARTED;
+      m_receiving = FALSE;
+      abortSpiRelease = FALSE;
+      m_tx_power = 0;
+    }
+    return SUCCESS;
+  }
+
+  command error_t StdControl.stop() {
+    atomic {
+      m_state = S_STOPPED;
+      call BackoffTimer.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 ) {
+    return send( p_msg, useCca );
+  }
+
+  async command error_t Send.resend(bool useCca) {
+    return resend( useCca );
+  }
+
+  async command error_t Send.cancel() {
+    atomic {
+      switch( m_state ) {
+      case S_LOAD:
+        m_state = S_LOAD_CANCEL;
+        break;
+        
+      case S_SAMPLE_CCA:
+        m_state = S_CCA_CANCEL;
+        break;
+        
+      case S_BEGIN_TRANSMIT:
+        m_state = S_TX_CANCEL;
+        break;
+        
+      default:
+        // cancel not allowed while radio is busy transmitting
+        return FAIL;
+      }
+    }
+
+    return SUCCESS;
+  }
+
+  async command error_t Send.modify( uint8_t offset, uint8_t* buf, 
+                                     uint8_t len ) {
+    call CSN.clr();
+    call TXFIFO_RAM.write( offset, buf, len );
+    call CSN.set();
+    return SUCCESS;
+  }
+  
+  /***************** 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 ) {
+    atomic {
+      switch( m_state ) {
+        
+      case S_SFD:
+        m_state = S_EFD;
+        sfdHigh = TRUE;
+        call CaptureSFD.captureFallingEdge();
+        signal TimeStamp.transmittedSFD( time, m_msg );
+        if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
+          // This is an ack packet, don't release the chip's SPI bus lock.
+          abortSpiRelease = TRUE;
+        }
+        releaseSpiResource();
+        call BackoffTimer.stop();
+
+        
+        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 ) ) {
+          m_state = S_ACK_WAIT;
+          call BackoffTimer.start( CC2420_ACK_WAIT_DELAY );
+        } else {
+          signalDone(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 CC2420Receive.sfd( time );
+          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 ) {
+          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* ack_msg ) {
+    cc2420_header_t* ack_header;
+    cc2420_header_t* msg_header;
+    cc2420_metadata_t* msg_metadata;
+    uint8_t* ack_buf;
+    uint8_t length;
+
+    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 ) {
+        call BackoffTimer.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(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_LOAD_CANCEL:
+    case S_CCA_CANCEL:
+    case S_TX_CANCEL:
+      call CSN.clr();
+      call SFLUSHTX.strobe();
+      call CSN.set();
+      releaseSpiResource();
+      atomic {
+        m_state = S_STARTED;
+      }
+      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 ( m_state == S_LOAD_CANCEL ) {
+      atomic {
+        call CSN.clr();
+        call SFLUSHTX.strobe();
+        call CSN.set();
+      }
+      releaseSpiResource();
+      m_state = S_STARTED;
+            
+    } else if ( !m_cca ) {
+      atomic {
+        if (m_state == S_LOAD_CANCEL) {
+          m_state = S_TX_CANCEL;
+        } else {
+          m_state = S_BEGIN_TRANSMIT;
+        }
+      }
+      attemptSend();
+      
+    } else {
+      releaseSpiResource();
+      atomic {
+        if (m_state == S_LOAD_CANCEL) {
+          m_state = S_CCA_CANCEL;
+        } else {
+          m_state = S_SAMPLE_CCA;
+        }
+      }
+      
+      signal RadioBackoff.requestInitialBackoff(m_msg);
+      call BackoffTimer.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 BackoffTimer.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 BackoffTimer.start( CC2420_TIME_ACK_TURNAROUND );
+          
+        } else {
+          congestionBackoff();
+        }
+        break;
+        
+      case S_CCA_CANCEL:
+        m_state = S_TX_CANCEL;
+        /** Fall Through */
+        
+      case S_BEGIN_TRANSMIT:
+      case S_TX_CANCEL:
+        if ( acquireSpiResource() == SUCCESS ) {
+          attemptSend();
+        }
+        break;
+        
+      case S_ACK_WAIT:
+        signalDone( SUCCESS );
+        break;
+
+      case S_SFD:
+        // We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD
+        // jiffies. Assume something is wrong.
+        call SFLUSHTX.strobe();
+        call CaptureSFD.captureRisingEdge();
+        releaseSpiResource();
+        signalDone( ERETRY );
+        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 send( message_t* p_msg, 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_state = S_LOAD;
+      m_cca = cca;
+      m_msg = p_msg;
+      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 BackoffTimer.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() {
+    uint8_t status;
+    bool congestion = TRUE;
+
+    atomic {
+      if (m_state == S_TX_CANCEL) {
+        call SFLUSHTX.strobe();
+        releaseSpiResource();
+        call CSN.set();
+        m_state = S_STARTED;
+        return;
+      }
+      
+      
+      call CSN.clr();
+
+      status = m_cca ? call STXONCCA.strobe() : call STXON.strobe();
+      if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) {
+        status = call SNOP.strobe();
+        if ( status & CC2420_STATUS_TX_ACTIVE ) {
+          congestion = FALSE;
+        }
+      }
+      
+      m_state = congestion ? S_SAMPLE_CCA : S_SFD;
+      call CSN.set();
+    }
+    
+    if ( congestion ) {
+      totalCcaChecks = 0;
+      releaseSpiResource();
+      congestionBackoff();
+    } else {
+      call BackoffTimer.start(CC2420_ABORT_PERIOD);
+    }
+  }
+  
+  
+  /**  
+   * Congestion Backoff
+   */
+  void congestionBackoff() {
+    atomic {
+      signal RadioBackoff.requestCongestionBackoff(m_msg);
+      call BackoffTimer.start(myCongestionBackoff);
+    }
+  }
+  
+  error_t acquireSpiResource() {
+    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;
+
+    if ( !tx_power ) {
+      tx_power = CC2420_DEF_RFPOWER;
+    }
+    
+    call CSN.clr();
+    
+    if ( m_tx_power != tx_power ) {
+      call TXCTRL.write( ( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) |
+                         ( 3 << CC2420_TXCTRL_PA_CURRENT ) |
+                         ( 1 << CC2420_TXCTRL_RESERVED ) |
+                         ( (tx_power & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) );
+    }
+    
+    m_tx_power = tx_power;
+    
+    call TXFIFO.write( (uint8_t*)header, header->length - 1);
+  }
+  
+  void signalDone( error_t err ) {
+    atomic m_state = S_STARTED;
+    abortSpiRelease = FALSE;
+    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/unique/UniqueReceiveC.nc b/tos/chips/cc2420/unique/UniqueReceiveC.nc
new file mode 100644 (file)
index 0000000..303ef54
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * This layer keeps a history of the past RECEIVE_HISTORY_SIZE received messages
+ * If the source address and dsn number of a newly received message matches
+ * our recent history, we drop the message because we've already seen it.
+ * This should sit at the bottom of the stack
+ * @author David Moss
+ */
+configuration UniqueReceiveC {
+  provides {
+    interface Receive;
+    interface Receive as DuplicateReceive;
+  }
+  
+  uses {
+    interface Receive as SubReceive;
+  }
+}
+
+implementation {
+  components UniqueReceiveP,
+      CC2420PacketC,
+      MainC;
+  
+  Receive = UniqueReceiveP.Receive;
+  DuplicateReceive = UniqueReceiveP.DuplicateReceive;
+  SubReceive = UniqueReceiveP.SubReceive;
+      
+  MainC.SoftwareInit -> UniqueReceiveP;
+  
+  UniqueReceiveP.CC2420PacketBody -> CC2420PacketC;
+  
+}
+
diff --git a/tos/chips/cc2420/unique/UniqueReceiveP.nc b/tos/chips/cc2420/unique/UniqueReceiveP.nc
new file mode 100644 (file)
index 0000000..bc3faf0
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/** 
+ * This layer keeps a history of the past RECEIVE_HISTORY_SIZE received messages
+ * If the source address and dsn number of a newly received message matches
+ * our recent history, we drop the message because we've already seen it.
+ * @author David Moss
+ */
+#include "CC2420.h"
+
+module UniqueReceiveP {
+  provides {
+    interface Receive;
+    interface Receive as DuplicateReceive;
+    interface Init;
+  }
+  
+  uses {
+    interface Receive as SubReceive;
+    interface CC2420PacketBody;
+  }
+}
+
+implementation {
+  
+  struct {
+    am_addr_t source;
+    uint8_t dsn;
+  } receivedMessages[RECEIVE_HISTORY_SIZE];
+  
+  uint8_t writeIndex = 0;
+  
+  /** History element containing info on a source previously received from */
+  uint8_t recycleSourceElement;
+  
+  enum {
+    INVALID_ELEMENT = 0xFF,
+  };
+  
+  /***************** Init Commands *****************/
+  command error_t Init.init() {
+    int i;
+    for(i = 0; i < RECEIVE_HISTORY_SIZE; i++) {
+      receivedMessages[i].source = (am_addr_t) 0xFFFF;
+      receivedMessages[i].dsn = 0;
+    }
+    return SUCCESS;
+  }
+  
+  /***************** Prototypes Commands ***************/
+  bool hasSeen(uint16_t msgSource, uint8_t msgDsn);
+  void insert(uint16_t msgSource, uint8_t msgDsn);
+  
+  /***************** Receive Commands ***************/
+  command void *Receive.getPayload(message_t* msg, uint8_t* len) {
+    return call SubReceive.getPayload(msg, len);
+  }
+
+  command uint8_t Receive.payloadLength(message_t* msg) {
+    return call SubReceive.payloadLength(msg);
+  }
+  
+  
+  /***************** DuplicateReceive Commands ****************/
+  command void *DuplicateReceive.getPayload(message_t* msg, uint8_t* len) {
+    return call SubReceive.getPayload(msg, len);
+  }
+
+  command uint8_t DuplicateReceive.payloadLength(message_t* msg) {
+    return call SubReceive.payloadLength(msg);
+  }
+  
+  /***************** SubReceive Events *****************/
+  event message_t *SubReceive.receive(message_t* msg, void* payload, 
+      uint8_t len) {
+    uint16_t msgSource = (call CC2420PacketBody.getHeader(msg))->src;
+    uint8_t msgDsn = (call CC2420PacketBody.getHeader(msg))->dsn;
+    
+    if(hasSeen(msgSource, msgDsn)) {
+      return signal DuplicateReceive.receive(msg, payload, len);
+      
+    } else {
+      insert(msgSource, msgDsn);
+      return signal Receive.receive(msg, payload, len);
+    }
+  }
+  
+  /****************** Functions ****************/  
+  /**
+   * This function does two things:
+   *  1. It loops through our entire receive history and detects if we've 
+   *     seen this DSN before from the given source (duplicate packet)
+   *  2. It detects if we've seen messages from this source before, so we know
+   *     where to update our history if it turns out this is a new message.
+   *
+   * The global recycleSourceElement variable stores the location of the next insert
+   * if we've received a packet from that source before.  Otherwise, it's up 
+   * to the insert() function to decide who to kick out of our history.
+   */
+  bool hasSeen(uint16_t msgSource, uint8_t msgDsn) {
+    int i;
+    recycleSourceElement = INVALID_ELEMENT;
+    
+    atomic {
+      for(i = 0; i < RECEIVE_HISTORY_SIZE; i++) {
+        if(receivedMessages[i].source == msgSource) {
+          if(receivedMessages[i].dsn == msgDsn) {
+            // Only exit this loop if we found a duplicate packet
+            return TRUE;
+          }
+          
+          recycleSourceElement = i;
+        }
+      }
+    }
+      
+    return FALSE;
+  }
+  
+  /**
+   * Insert the message into the history.  If we received a message from this
+   * source before, insert it into the same location as last time and verify
+   * that the "writeIndex" is not pointing to that location. Otherwise,
+   * insert it into the "writeIndex" location.
+   */
+  void insert(uint16_t msgSource, uint8_t msgDsn) {
+    uint8_t element = recycleSourceElement;
+    bool increment = FALSE;
+   
+    atomic {
+      if(element == INVALID_ELEMENT || writeIndex == element) {
+        // Use the writeIndex element to insert this new message into
+        element = writeIndex;
+        increment = TRUE;
+      }
+
+      receivedMessages[element].source = msgSource;
+      receivedMessages[element].dsn = msgDsn;
+      if(increment) {
+        writeIndex++;
+        writeIndex %= RECEIVE_HISTORY_SIZE;
+      }
+    }
+  }
+  
+  /***************** Defaults ****************/
+  default event message_t *DuplicateReceive.receive(message_t *msg, void *payload, uint8_t len) {
+    return msg;
+  }
+}
+
diff --git a/tos/chips/cc2420/unique/UniqueSendC.nc b/tos/chips/cc2420/unique/UniqueSendC.nc
new file mode 100644 (file)
index 0000000..615a459
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * Generate a unique dsn byte for this outgoing packet
+ * This should sit at the top of the stack
+ * @author David Moss
+ */
+configuration UniqueSendC {
+  provides {
+    interface Send;
+  }
+  
+  uses {
+    interface Send as SubSend;
+  }
+}
+
+implementation {
+  components UniqueSendP,
+      new StateC(),
+      RandomC,
+      CC2420PacketC,
+      MainC;
+      
+  Send = UniqueSendP.Send;
+  SubSend = UniqueSendP.SubSend;
+  
+  MainC.SoftwareInit -> UniqueSendP;
+  
+  UniqueSendP.State -> StateC;
+  UniqueSendP.Random -> RandomC;
+  UniqueSendP.CC2420PacketBody -> CC2420PacketC;
+  
+}
+
diff --git a/tos/chips/cc2420/unique/UniqueSendP.nc b/tos/chips/cc2420/unique/UniqueSendP.nc
new file mode 100644 (file)
index 0000000..1611c45
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2005-2006 Rincon Research 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 Rincon Research 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
+ * RINCON RESEARCH 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
+ */
+/**
+ * This layer is responsible for supplying a unique data sequence number (dsn)
+ * to each outgoing message.
+ * @author David Moss
+ */
+module UniqueSendP {
+  provides {
+    interface Send;
+    interface Init;
+  }
+  
+  uses {
+    interface Send as SubSend;
+    interface State;
+    interface Random;
+    interface CC2420PacketBody;
+  }
+}
+
+implementation {
+
+  uint8_t localSendId;
+  
+  enum {
+    S_IDLE,
+    S_SENDING,
+  };
+  
+  /***************** Init Commands ****************/
+  command error_t Init.init() {
+    localSendId = call Random.rand16();
+    return SUCCESS;
+  }
+
+  /***************** Send Commands ****************/
+  /**
+   * Each call to this send command gives the message a single
+   * DSN that does not change for every copy of the message
+   * sent out.  For messages that are not acknowledged, such as
+   * a broadcast address message, the receiving end does not
+   * signal receive() more than once for that message.
+   */
+  command error_t Send.send(message_t *msg, uint8_t len) {
+    error_t error;
+    if(call State.requestState(S_SENDING) == SUCCESS) {
+      (call CC2420PacketBody.getHeader(msg))->dsn = localSendId++;
+      
+      if((error = call SubSend.send(msg, len)) != SUCCESS) {
+        call State.toIdle();
+      }
+      
+      return error;
+    }
+    
+    return EBUSY;
+  }
+
+  command error_t Send.cancel(message_t *msg) {
+    return call SubSend.cancel(msg);
+  }
+  
+  
+  command uint8_t Send.maxPayloadLength() {
+    return call SubSend.maxPayloadLength();
+  }
+
+  command void *Send.getPayload(message_t* msg) {
+    return call SubSend.getPayload(msg);
+  }
+  
+  /***************** SubSend Events ****************/
+  event void SubSend.sendDone(message_t *msg, error_t error) {
+    call State.toIdle();
+    signal Send.sendDone(msg, error);
+  }
+  
+}
+