diff --git a/apps/PppRouter/Makefile b/apps/PppRouter/Makefile index d20dc8f2d4..557b9a8d7e 100644 --- a/apps/PppRouter/Makefile +++ b/apps/PppRouter/Makefile @@ -79,7 +79,7 @@ PFLAGS += -DPPP_HDLC_TX_FRAME_LIMIT=8 ### Configure printf() output ################################################################################ -PFLAGS += -DNEW_PRINTF_SEMANTICS -DPRINTFUART_ENABLED +#PFLAGS += -DNEW_PRINTF_SEMANTICS -DPRINTFUART_ENABLED ################################################################################ ### Configure this application diff --git a/apps/PppRouter/PppRouterC.nc b/apps/PppRouter/PppRouterC.nc index bdf27b8e3e..9741e9be25 100644 --- a/apps/PppRouter/PppRouterC.nc +++ b/apps/PppRouter/PppRouterC.nc @@ -34,6 +34,10 @@ configuration PppRouterC { PppDaemonC.HdlcUart -> HdlcUartC; PppDaemonC.UartControl -> HdlcUartC; +#if defined(PRINTFUART_ENABLED) + components PrintfC,SerialStartC; +#endif + // SDH : don't bother including the PppPrintfC by default // components PppPrintfC, PppC;; // PppPrintfC.Ppp -> PppDaemonC; diff --git a/apps/RadioCountToLeds1/Makefile b/apps/RadioCountToLeds1/Makefile new file mode 100644 index 0000000000..37f0e6e996 --- /dev/null +++ b/apps/RadioCountToLeds1/Makefile @@ -0,0 +1,13 @@ +COMPONENT=RadioCountToLedsAppC +CFLAGS+=-DCC2520_HW_ACKNOWLEDGEMENTS +CFLAGS+=-DCC2520_HW_SECURITY +CFLAGS+=-DPRINTF_BUFFER_SIZE=500 +CFLAGS+=-DCC2520_DEF_CHANNEL=22 +CFLAGS+=-DTFRAMES_ENABLED +CFLAGS+=-DPACKET_LINK +CFLAGS+=-DTOSH_DATA_LENGTH=50 +#CFLAGS+=-I%T/lib/printf +CFLAGS+=-I$(TOSDIR)/lib/printf +CFLAGS+=-DPRINTFUART_ENABLED +CFLAGS+=-I./ +include $(MAKERULES) diff --git a/apps/RadioCountToLeds1/RadioCountToLeds.h b/apps/RadioCountToLeds1/RadioCountToLeds.h new file mode 100644 index 0000000000..3dcc45ad12 --- /dev/null +++ b/apps/RadioCountToLeds1/RadioCountToLeds.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2005 The Regents of the University of California. + * 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 copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2002-2003 Intel Corporation + * All rights reserved. + * + * This file is distributed under the terms in the attached INTEL-LICENSE + * file. If you do not find these files, copies can be found by writing to + * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, + * 94704. Attention: Intel License Inquiry. + */ + +#ifndef RADIO_COUNT_TO_LEDS_H +#define RADIO_COUNT_TO_LEDS_H + +typedef nx_struct radio_count_msg { + nx_uint16_t counter; +} radio_count_msg_t; + +enum { + AM_RADIO_COUNT_MSG = 6, +}; + +#endif diff --git a/apps/RadioCountToLeds1/RadioCountToLedsAppC.nc b/apps/RadioCountToLeds1/RadioCountToLedsAppC.nc new file mode 100644 index 0000000000..215626e41b --- /dev/null +++ b/apps/RadioCountToLeds1/RadioCountToLedsAppC.nc @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000-2005 The Regents of the University of California. + * 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 copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2002-2003 Intel Corporation + * All rights reserved. + * + * This file is distributed under the terms in the attached INTEL-LICENSE + * file. If you do not find these files, copies can be found by writing to + * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, + * 94704. Attention: Intel License Inquiry. + */ + +#include "RadioCountToLeds.h" + +/** + * Configuration for the RadioCountToLeds application. RadioCountToLeds + * maintains a 4Hz counter, broadcasting its value in an AM packet + * every time it gets updated. A RadioCountToLeds node that hears a counter + * displays the bottom three bits on its LEDs. This application is a useful + * test to show that basic AM communication and timers work. + * + * @author Philip Levis + * @date June 6 2005 + */ + +configuration RadioCountToLedsAppC {} +implementation { + components MainC, RadioCountToLedsC as App, LedsC, NoLedsC; + //components new SecAMSenderC(AM_RADIO_COUNT_MSG) as AMSenderC; + components new AMSenderC(AM_RADIO_COUNT_MSG); + components new AMReceiverC(AM_RADIO_COUNT_MSG); + components new TimerMilliC(); + components CC2520KeyC; + components ActiveMessageC; + + App.Boot -> MainC.Boot; + App.Receive -> AMReceiverC; + App.AMSend -> AMSenderC; + App.AMControl -> ActiveMessageC; + App.Leds -> LedsC; + App.MilliTimer -> TimerMilliC; + App.Packet -> AMSenderC; + App.CC2520Key -> CC2520KeyC; + + components new TimerMilliC() as SendTimer; + App.SendTimer -> SendTimer; + + components CC2520ActiveMessageC as Radio; + App.PacketLink -> Radio; + + components CC2520PacketC; + App.CC2520PacketBody -> CC2520PacketC; + + components PrintfC,SerialStartC; +} diff --git a/apps/RadioCountToLeds1/RadioCountToLedsC.nc b/apps/RadioCountToLeds1/RadioCountToLedsC.nc new file mode 100644 index 0000000000..d37e2b5102 --- /dev/null +++ b/apps/RadioCountToLeds1/RadioCountToLedsC.nc @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2000-2005 The Regents of the University of California. + * 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 copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2002-2003 Intel Corporation + * All rights reserved. + * + * This file is distributed under the terms in the attached INTEL-LICENSE + * file. If you do not find these files, copies can be found by writing to + * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, + * 94704. Attention: Intel License Inquiry. + */ + +#include "Timer.h" +#include "RadioCountToLeds.h" +#include "printf.h" +/** + * Implementation of the RadioCountToLeds application. RadioCountToLeds + * maintains a 4Hz counter, broadcasting its value in an AM packet + * every time it gets updated. A RadioCountToLeds node that hears a counter + * displays the bottom three bits on its LEDs. This application is a useful + * test to show that basic AM communication and timers work. + * + * @author Philip Levis + * @date June 6 2005 + */ + +module RadioCountToLedsC { + uses { + interface Leds; + interface Boot; + interface Receive; + interface AMSend; + interface Timer as MilliTimer; + interface Timer as SendTimer; + interface SplitControl as AMControl; + interface Packet; + interface CC2520Key; + interface CC2520PacketBody; + + interface PacketLink; + } +} +implementation { + + message_t packet; + uint8_t key[16] = {0x98,0x67,0x7F,0xAF,0xD6,0xAD,0xB7,0x0C,0x59,0xE8,0xD9,0x47,0xC9,0x71,0x15,0x0F}; + uint8_t keyReady = 0; // should be set to 1 when key setting is done + + bool locked; + uint16_t counter = 0; + + event void Boot.booted() + { + call AMControl.start(); + } + + event void AMControl.startDone(error_t err) + { + if (err == SUCCESS) { + call CC2520Key.setKey(key); + // if(TOS_NODE_ID == 1) + //call MilliTimer.startPeriodic(4096); + } else { + call AMControl.start(); + } + } + + event void AMControl.stopDone(error_t err) + { + } + event void CC2520Key.setKeyDone(uint8_t status) + { + keyReady = 1; + } + + event void CC2520Key.getKeyDone(uint8_t status, uint8_t *ptr) + { + } + + event void SendTimer.fired() + { + if (call AMSend.send(AM_BROADCAST_ADDR, &packet, + sizeof(radio_count_msg_t)) == SUCCESS) { + locked = TRUE; + //printf("SendTimer fired\n"); + //printfflush(); + } + + + } + + uint8_t getMICLength(uint8_t securityLevel) { + if(securityLevel == SEC_MIC_32 || securityLevel == SEC_ENC_MIC_32) + return 4; + else if(securityLevel == SEC_MIC_64 || securityLevel == SEC_ENC_MIC_64) + return 8; + else if(securityLevel == SEC_ENC_MIC_128 || securityLevel == SEC_ENC_MIC_128) + return 16; + return 0; + } + + void readBefore() + { + uint8_t i; + cc2520_header_t* header = call CC2520PacketBody.getHeader( &packet ); + uint8_t *ptr = (uint8_t *)header; + uint8_t micLength = getMICLength(header->secHdr.secLevel); + uint8_t encryptLength = header->length - CC2520_SIZE - micLength; + printf("Packet Before Encryption\n"); + printf("header Length:%x\n", header->length); + printf("MIC Length:%x\t%x\n",micLength,encryptLength); + for(i=0;ilength - micLength -1;i++) { + printf("%x\t",ptr[i]); + } + printfflush(); + } + + event void MilliTimer.fired() + { + int ret; + counter++; + //printf("MilliTimer fired\n"); + //printfflush(); + dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter); + if (locked) { + return; + } + else if(keyReady == 1) { + + radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t)); + + if (rcm == NULL) { + return; + } + + rcm->counter = counter; + //call CC2420Security.setCtr(&packet, 0, 0); + //call CC2420Security.setCbcMac(&packet, 0, 0, 16); + //call CC2420Security.setCcm(&packet, 1, 0, 16); + call PacketLink.setRetries(&packet, 1); + //call SendTimer.startOneShot(5000); + //readBefore(); + ret= call AMSend.send(AM_BROADCAST_ADDR, &packet, + sizeof(radio_count_msg_t)); + printf("return:%x\n",ret); + printfflush(); + } + } + + event message_t* Receive.receive(message_t* bufPtr, + void* payload, uint8_t len) + { + dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len); + if (len != sizeof(radio_count_msg_t)) {return bufPtr;} + else { + radio_count_msg_t* rcm = (radio_count_msg_t*)payload; + printf("counter:%x\n",rcm->counter); + printfflush(); + if (rcm->counter & 0x1) { + call Leds.led0On(); + } + else { + call Leds.led0Off(); + } + if (rcm->counter & 0x2) { + call Leds.led1On(); + } + else { + call Leds.led1Off(); + } + if (rcm->counter & 0x4) { + call Leds.led2On(); + } + else { + call Leds.led2Off(); + } + return bufPtr; + } + } + + event void AMSend.sendDone(message_t* msg, error_t error) + { + printf("AMSend sendDone:%x\n",error); + printfflush(); + if (&packet == msg) { + locked = FALSE; + } + } + +} diff --git a/apps/tests/TestPrintf/Makefile b/apps/tests/TestPrintf/Makefile index 0be6b263bb..871e52ea75 100644 --- a/apps/tests/TestPrintf/Makefile +++ b/apps/tests/TestPrintf/Makefile @@ -1,5 +1,4 @@ COMPONENT=TestPrintfAppC -CFLAGS += -I$(TINYOS_OS_DIR)/lib/printf - -TINYOS_ROOT_DIR?=../../.. -include $(TINYOS_ROOT_DIR)/Makefile.include +CFLAGS += -I$(TOSDIR)/lib/printf +CFLAGS += -DDEFAULT_LOG_LEVEL=3 +include $(MAKERULES) diff --git a/apps/tests/TestPrintf/TestPrintfC.nc b/apps/tests/TestPrintf/TestPrintfC.nc index 676e0d7d27..5f9e42de10 100644 --- a/apps/tests/TestPrintf/TestPrintfC.nc +++ b/apps/tests/TestPrintf/TestPrintfC.nc @@ -60,11 +60,16 @@ implementation { } event void Timer.fired() { - printf("Hi I am writing to you from my TinyOS application!!\n"); - printf("Here is a uint8: %u\n", dummyVar1); - printf("Here is a uint16: %u\n", dummyVar2); - printf("Here is a uint32: %lu\n", dummyVar3); - printfflush(); + int i=32; + + pr_emergency("Emergency value:%d\n",i); + pr_alert("Alert value:%d\n",i); + pr_critical("Critical value:%d\n",i); + pr_error("Error value:%d\n",i); + pr_warning("Warning value:%d\n",i); + pr_info("Info value:%d\n",i); + pr_debug("Debug value:%d\n",i); + printfflush(); } } diff --git a/apps/tests/TestRPL/udp/Makefile b/apps/tests/TestRPL/udp/Makefile index a9c2dba7a1..ca7d1388a5 100644 --- a/apps/tests/TestRPL/udp/Makefile +++ b/apps/tests/TestRPL/udp/Makefile @@ -80,14 +80,14 @@ CFLAGS+=-DPACKET_INTERVAL=5120UL CFLAGS+=-DRPL_ROOT_ADDR=11 -<<<<<<< HEAD -# enable printf -CFLAGS += -DNEW_PRINTF_SEMANTICS -DPRINTFUART_ENABLED -DPRINTF_BUFFER_SIZE=1024 -======= + + + + GOALS += blip rpl ->>>>>>> BLIP+RPL: updating /apps + TINYOS_ROOT_DIR?=../../../.. include $(TINYOS_ROOT_DIR)/Makefile.include diff --git a/apps/tests/blip/TestLinkLocal/Makefile b/apps/tests/blip/TestLinkLocal/Makefile index 9d8daec918..4cd7bcfb0b 100644 --- a/apps/tests/blip/TestLinkLocal/Makefile +++ b/apps/tests/blip/TestLinkLocal/Makefile @@ -1,5 +1,7 @@ COMPONENT=TestLinkLocalAppC +GOALS += blip TINYOS_ROOT_DIR?=../../../.. include $(TINYOS_ROOT_DIR)/Makefile.include CFLAGS += -DIN6_NO_GLOBAL -DLIB6LOWPAN_HC_VERSION=-1 CFLAGS += -DPRINTFUART_ENABLED +PFLAGS += -DIN6_PREFIX=\"fec0::\" diff --git a/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc b/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc index 1690b2c06c..9727ec3d77 100644 --- a/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc +++ b/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc @@ -15,6 +15,7 @@ configuration TestLinkLocalAppC { TestLinkLocalC.Timer -> TimerMilliC; TestLinkLocalC.Leds -> LedsC; + components PrintfC,SerialStartC; components StaticIPAddressTosIdC; // Use TOS_NODE_ID in address //components StaticIPAddressC; // Use LocalIeee154 in address } diff --git a/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc b/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc index 29c484d45e..0dcdf41438 100644 --- a/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc +++ b/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc @@ -1,5 +1,5 @@ -#include +#include "blip_printf.h" #include module TestLinkLocalC { @@ -23,7 +23,6 @@ module TestLinkLocalC { }; event void Boot.booted() { - printfUART_init(); call SplitControl.start(); m_data.seqno = 0; } @@ -51,16 +50,16 @@ module TestLinkLocalC { event void Sock.recvfrom(struct sockaddr_in6 *src, void *payload, uint16_t len, struct ip6_metadata *meta) { nx_struct echo_state *cmd = payload; - printfUART("TestLinkLocalC: recv from: "); - printfUART_in6addr(&src->sin6_addr); - printfUART("\n"); + printf("TestLinkLocalC: recv from: "); + printf_in6addr(&src->sin6_addr); + printf("\n"); if (cmd->cmd == CMD_ECHO) { cmd->cmd = CMD_REPLY; call Sock.sendto(src, payload, len); call Leds.led1Toggle(); } else { - printfUART("TestLinkLocalC: reply seqno: %li\n", cmd->seqno); + printf("TestLinkLocalC: reply seqno: %li\n", cmd->seqno); call Leds.led2Toggle(); } } diff --git a/cc2520/CC2520.h b/cc2520/CC2520.h new file mode 100644 index 0000000000..47047ed7e4 --- /dev/null +++ b/cc2520/CC2520.h @@ -0,0 +1,870 @@ +/* + * 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 + * @author David Moss + * @version $Revision: 1.12 $ $Date: 2008/06/23 23:40:21 $ + */ + +#ifndef __CC2520_H__ +#define __CC2520_H__ + + + + +typedef uint8_t cc2520_status_t; + +#ifndef TFRAMES_ENABLED +#define CC2520_IFRAME_TYPE +#endif + +#ifndef PRINTF_ENABLED +#define PRINTF_ENABLED 0 +#endif + + +/* + *Security Header: + * --------------------------------------------------------- + * |Bytes:1 | 4 | 0/1/5/9 | + * |-------------------------------------------------------| + * |Security Control | Frame Counter | Key Identifier | + * -------------------------------------------------------- + * Security Control : Specifies the Security Level(bit 0-2) and key identifier mode(bit 3-4) + * Frame Counter : It is used to ensure the freshness(uniqueness) of each frame.Used + * to provide protection from Replay Attack + * + */ + +/* + *Security Levels + *---------------------------------------------------------------------- + *|Security Level | Security Suite Name | Description | + *---------------------------------------------------------------------- + *|0 | None | No security | + *---------------------------------------------------------------------- + *|1 | MIC-32 | 32 Bit Authentication | + *---------------------------------------------------------------------- + *|2 | MIC-64 | 64 Bit Authentication | + *---------------------------------------------------------------------- + *|3 | MIC-128 | 128 Bit Authentication| + *---------------------------------------------------------------------- + *|4 | ENC | Encryption | + *---------------------------------------------------------------------- + *|5 | ENC-MIC-32 | Encryption and 32bit | + *| | | Authentication | + *---------------------------------------------------------------------- + *|6 | ENC-MIC-64 | Encryption and 64bit | + *| | | Authentication | + *---------------------------------------------------------------------- + *|7 | ENC-MIC-128 | Encryption and 128bit | + *| | | Authentication | + *---------------------------------------------------------------------- + */ + +/*Key Identifier Modes + * --------------------------------------------------------------------- + *|Key Identifer Mode| Description | + *---------------------------------------------------------------------- + *|00 | Key is determined implicitly from the originator | + *| | and recipient(s) of the frame,as indicated in the| + *| | frame header | + *---------------------------------------------------------------------- + *|01 | Key is determined from the 1-octet key Index | + *| | subfield of the keyidentifier field of the | + *| | auxiliary security header in conjunction with | + *| | macDefaultKeySource | + *---------------------------------------------------------------------- + *|10 | Key is determined from the 4-octet key source | + *| | subfield and the 1-octet key index subfield of | + *| | of the keyidentifier field | + *---------------------------------------------------------------------- + *|11 | Key is determined from the 8-octet key source | + *| | subfield and the 1-octet key index subfield of | + *| | of the keyidentifier field | + *---------------------------------------------------------------------- + */ + +/* + *Key Identifier Field: + * The key Identifier field has a variable length and identifies the key that is used + * for cryptographic protection of outgoing frames,either explicitly or in conjunction + * with implicitly defined side information.The key identifier field shall be present + * only if the key identifier mode subfield of the security control field of the + * auxiliary security header is set to a value different than 0x00. + * ------------------------- + * |Octets:0/4/8|1 | + * ------------------------- + * |Key Source |Key Index | + * ------------------------- + * + * Key Source : Indicates the originator of a group key + * Key Index : Allows unique identification of different keys with the same + * originator. + * + */ + + +typedef nx_struct security_header_t { + nx_uint8_t secLevel:3; + nx_uint8_t keyMode:2; //This will fix it to 0x00 + nx_uint8_t reserved:3; + nx_uint32_t frameCounter; +} security_header_t; + + +/** + * CC2520 header. An I-frame (interoperability frame) header has an + * extra network byte specified by 6LowPAN + */ +typedef nx_struct cc2520_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; + /** CC2420 802.15.4 header ends here */ +#ifdef CC2520_HW_SECURITY + security_header_t secHdr; +#endif + /** I-Frame 6LowPAN interoperability byte */ +#ifdef CC2520_IFRAME_TYPE + nxle_uint8_t network; +#endif + nxle_uint8_t type; + +} cc2520_header_t; + +/** + * CC2420 Packet Footer + */ +typedef nx_struct cc2520_footer_t { +} cc2520_footer_t; + +/** + * CC2520 Packet metadata. Contains extra information about the message + * that will not be transmitted. + * + * Note that the first two bytes automatically take in the values of the + * FCS when the payload is full. Do not modify the first two bytes of metadata. + */ +typedef nx_struct cc2520_metadata_t { + nx_uint8_t rssi; + nx_uint8_t lqi; + nx_uint8_t tx_power; + nx_bool crc; + nx_bool ack; + nx_bool timesync; + nx_uint32_t timestamp; + nx_uint16_t rxInterval; + + /** Packet Link Metadata */ +//#ifdef PACKET_LINK + nx_uint16_t maxRetries; + nx_uint16_t retryDelay; +//#endif + +} cc2520_metadata_t; + + +typedef nx_struct cc2520_packet_t { + cc2520_header_t packet; + nx_uint8_t data[]; +} cc2520_packet_t; + + +#ifndef TOSH_DATA_LENGTH +#define TOSH_DATA_LENGTH 28//28 +#endif + +#ifndef CC2520_DEF_CHANNEL +#define CC2520_DEF_CHANNEL 26 +#endif + +#ifndef CC2520_DEF_RFPOWER +#define CC2520_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 NALP ID for a TinyOS network is 63 (TEP 125). + */ +#ifndef TINYOS_6LOWPAN_NETWORK_ID +#define TINYOS_6LOWPAN_NETWORK_ID 0x3f +#endif + + +enum { + // size of the header not including the length byte + MAC_HEADER_SIZE = sizeof( cc2520_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, + + CC2520_SIZE = MAC_HEADER_SIZE + MAC_FOOTER_SIZE, +}; + +enum cc2520_enums { + CC2520_TIME_ACK_TURNAROUND = 7, // jiffies + CC2520_TIME_VREN = 200, // jiffies CC2520_VREG_MAX_STARTUP_TIME -- lijo + CC2520_TIME_SYMBOL = 16,//2, // 2 symbols / jiffy + CC2520_BACKOFF_PERIOD = ( 20 / CC2520_TIME_SYMBOL ), // symbols + CC2520_MIN_BACKOFF = ( 20 / CC2520_TIME_SYMBOL ), // platform specific? + CC2520_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,*/ + + // modified by lijo on 03/12/2009 + + CC2520_STATUS_RX_ACTIVE = 1 << 0, + CC2520_STATUS_TX_ACTIVE = 1 << 1, + CC2520_STATUS_DPUL_ACTIVE = 1 << 2, + CC2520_STATUS_DPUH_ACTIVE = 1 << 3, + CC2520_STATUS_EXCEP_CHANNEL_B = 1 << 4, + CC2520_STATUS_EXCEP_CHANNEL_A = 1 << 5, + CC2520_STATUS_RSSI_VALID = 1 << 6, + CC2520_STATUS_XOSC16M_STABLE = 1 << 7, +}; + +/* +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 cc2520_config_reg_enums { + + // FREG Registers + + CC2520_FRMFILT0 = 0x00, + CC2520_FRMFILT1 = 0x01, + CC2520_SRCMATCH = 0x02, + CC2520_SRCSHORTEN0 = 0x04, + CC2520_SRCSHORTEN1 = 0x05, + CC2520_SRCSHORTEN2 = 0x06, + CC2520_SRCEXTEN0 = 0x08, + CC2520_SRCEXTEN1 = 0x09, + CC2520_SRCEXTEN2 = 0x0A, + CC2520_FRMCTRL0 = 0x0C, + CC2520_FRMCTRL1 = 0x0D, + CC2520_RXENABLE0 = 0x0E, + CC2520_RXENABLE1 = 0x0F, + CC2520_EXCFLAG0 = 0x10, + CC2520_EXCFLAG1 = 0x11, + CC2520_EXCFLAG2 = 0x12, + CC2520_EXCMASKA0 = 0x14, + CC2520_EXCMASKA1 = 0x15, + CC2520_EXCMASKA2 = 0x16, + CC2520_EXCMASKB0 = 0x18, + CC2520_EXCMASKB1 = 0x19, + CC2520_EXCMASKB2 = 0x1A, + CC2520_EXCBINDX0 = 0x1C, + CC2520_EXCBINDX1 = 0x1D, + CC2520_EXCBINDY0 = 0x1E, + CC2520_EXCBINDY1 = 0x1F, + CC2520_GPIOCTRL0 = 0x20, + CC2520_GPIOCTRL1 = 0x21, + CC2520_GPIOCTRL2 = 0x22, + CC2520_GPIOCTRL3 = 0x23, + CC2520_GPIOCTRL4 = 0x24, + CC2520_GPIOCTRL5 = 0x25, + CC2520_GPIOPOLARITY = 0x26, + CC2520_GPIOCTRL = 0x28, + CC2520_DPUCON = 0x2A, + CC2520_DPUSTAT = 0x2C, + CC2520_FREQCTRL = 0x2E, + CC2520_FREQTUNE = 0x2F, + CC2520_TXPOWER = 0x30, + CC2520_TXCTRL = 0x31, + CC2520_FSMSTAT0 = 0x32, + CC2520_FSMSTAT1 = 0x33, + CC2520_FIFOPCTRL = 0x34, + CC2520_FSMCTRL = 0x35, + CC2520_CCACTRL0 = 0x36, + CC2520_CCACTRL1 = 0x37, + CC2520_RSSI = 0x38, + CC2520_RSSISTAT = 0x39, + CC2520_RXFIRST = 0x3C, + CC2520_RXFIFOCNT = 0x3E, + CC2520_TXFIFOCNT = 0x3F, + + // SREG registers + CC2520_CHIPID = 0x40, + CC2520_VERSION = 0x42, + CC2520_EXTCLOCK = 0x44, + CC2520_MDMCTRL0 = 0x46, + CC2520_MDMCTRL1 = 0x47, + CC2520_FREQEST = 0x48, + CC2520_RXCTRL = 0x4A, + CC2520_FSCTRL = 0x4C, + CC2520_FSCAL0 = 0x4E, + CC2520_FSCAL1 = 0x4F, + CC2520_FSCAL2 = 0x50, + CC2520_FSCAL3 = 0x51, + CC2520_AGCCTRL0 = 0x52, + CC2520_AGCCTRL1 = 0x53, + CC2520_AGCCTRL2 = 0x54, + CC2520_AGCCTRL3 = 0x55, + CC2520_ADCTEST0 = 0x56, + CC2520_ADCTEST1 = 0x57, + CC2520_ADCTEST2 = 0x58, + CC2520_MDMTEST0 = 0x5A, + CC2520_MDMTEST1 = 0x5B, + CC2520_DACTEST0 = 0x5C, + CC2520_DACTEST1 = 0x5D, + CC2520_ATEST = 0x5E, + CC2520_DACTEST2 = 0x5F, + CC2520_PTEST0 = 0x60, + CC2520_PTEST1 = 0x61, + CC2520_RESERVED = 0x62, + CC2520_DPUBIST = 0x7A, + CC2520_ACTBIST = 0x7C, + CC2520_RAMBIST = 0x7E, + +}; + +enum cc2520_spi_command_enums +{ + CC2520_CMD_SNOP = 0x00, // + CC2520_CMD_IBUFLD = 0x02, // + CC2520_CMD_SIBUFEX = 0x03, // + CC2520_CMD_SSAMPLECCA = 0x04, // + CC2520_CMD_SRES = 0x0f, // + CC2520_CMD_MEMORY_MASK = 0x0f, // + CC2520_CMD_MEMORY_READ = 0x10, // MEMRD + CC2520_CMD_MEMORY_WRITE = 0x20, // MEMWR + CC2520_CMD_RXBUF = 0x30, // + CC2520_CMD_RXBUFCP = 0x38, // + CC2520_CMD_RXBUFMOV = 0x32, // + CC2520_CMD_TXBUF = 0x3A, // + CC2520_CMD_TXBUFCP = 0x3E, // + CC2520_CMD_RANDOM = 0x3C, // + CC2520_CMD_SXOSCON = 0x40, // + CC2520_CMD_STXCAL = 0x41, // + CC2520_CMD_SRXON = 0x42, // + CC2520_CMD_STXON = 0x43, // + CC2520_CMD_STXONCCA = 0x44, // + CC2520_CMD_SRFOFF = 0x45, // + CC2520_CMD_SXOSCOFF = 0x46, // + CC2520_CMD_SFLUSHRX = 0x47, // + CC2520_CMD_SFLUSHTX = 0x48, // + CC2520_CMD_SACK = 0x49, // + CC2520_CMD_SACKPEND = 0x4A, // + CC2520_CMD_SNACK = 0x4B, // + CC2520_CMD_SRXMASKBITSET = 0x4C, // + CC2520_CMD_SRXMASKBITCLR = 0x4D, // + CC2520_CMD_RXMASKAND = 0x4E, // + CC2520_CMD_RXMASKOR = 0x4F, // + CC2520_CMD_MEMCP = 0x50, // + CC2520_CMD_MEMCPR = 0x52, // + CC2520_CMD_MEMXCP = 0x54, // + CC2520_CMD_MEMXWR = 0x56, // + CC2520_CMD_BCLR = 0x58, // + CC2520_CMD_BSET = 0x59, // + CC2520_CMD_CTR_UCTR = 0x60, // + CC2520_CMD_CBCMAC = 0x64, // + CC2520_CMD_UCBCMAC = 0x66, // + CC2520_CMD_CCM = 0x68, // + CC2520_CMD_UCCM = 0x6A, // + CC2520_CMD_ECB = 0x70, // + CC2520_CMD_ECBO = 0x72, // + CC2520_CMD_ECBX = 0x74, // + CC2520_CMD_INC = 0x78, // + CC2520_CMD_ABORT = 0x7F, // + CC2520_CMD_REGISTER_READ = 0x80, // + CC2520_CMD_REGISTER_WRITE = 0xC0, // +}; + +enum cc2520_security_enums{ + CC2520_NO_SEC = 0, + CC2520_CBC_MAC = 1, + CC2520_CTR = 2, + CC2520_CCM = 3, + NO_SEC = 0, + CBC_MAC_4 = 1, + CBC_MAC_8 = 2, + CBC_MAC_16 = 3, + CTR = 4, + CCM_4 = 5, + CCM_8 = 6, + CCM_16 = 7 +}; + + +//Different Security Levels + +enum security_levels { + SEC_NONE = 0x00, + SEC_MIC_32 = 0x01, + SEC_MIC_64 = 0x02, + SEC_MIC_128 = 0x03, + SEC_ENC = 0x04, + SEC_ENC_MIC_32 = 0x05, + SEC_ENC_MIC_64 = 0x06, + SEC_ENC_MIC_128 = 0x07, +}; + +//Different Flags +enum initialization_flags{ + FLAG_NONE = 0x00, + FLAG_MIC_32 = 0x09, + FLAG_MIC_64 = 0x19, + FLAG_MIC_128 = 0x39, + FLAG_ENC = 0x01, + FLAG_ENC_MIC_32 = 0x09, + FLAG_ENC_MIC_64 = 0x19, + FLAG_ENC_MIC_128 = 0x39, +}; + +/* +enum cc2520_exception_enums { + + CC2520_EXC_RF_IDLE = 0x00, + CC2520_EXC_TX_FRM_DONE = 0x01, + CC2520_EXC_TX_ACK_DONE = 0x02, + CC2520_EXC_TX_UNDERFLOW = 0x03, + CC2520_EXC_TX_OVERFLOW = 0x04, + CC2520_EXC_RX_UNDERFLOW = 0x05, + CC2520_EXC_RX_OVERFLOW = 0x06, + CC2520_EXC_RXENABLE_ZERO = 0x07, + CC2520_EXC_RX_FRM_DONE = 0x08, + CC2520_EXC_RX_FRM_ACCEPTED = 0x09, + CC2520_EXC_SRC_MATCH_DONE = 0x0A, + CC2520_EXC_SRC_MATCH_FOUND = 0x0B, + CC2520_EXC_FIFOP = 0x0C, + CC2520_EXC_SFD = 0x0D, + CC2520_EXC_DPU_DONE_L = 0x0E, + CC2520_EXC_DPU_DONE_H = 0x0F, + CC2520_EXC_MEMADDR_ERROR = 0x10, + CC2520_EXC_USAGE_ERROR = 0x11, + CC2520_EXC_OPERAND_ERROR = 0x12, + CC2520_EXC_SPI_ERROR = 0x13, + CC2520_EXC_RF_NO_LOCK = 0x14, + CC2520_EXC_RX_FRM_ABORTED = 0x15, + CC2520_EXC_RXBUFMOV_TIMEOUT = 0x16, +};*/ + +enum cc2520_exception_enums { + + CC2520_EXC_RF_IDLE = 0x01, + CC2520_EXC_TX_FRM_DONE = 0x02, + CC2520_EXC_TX_ACK_DONE = 0x03, + CC2520_EXC_TX_UNDERFLOW = 0x04, + CC2520_EXC_TX_OVERFLOW = 0x05, + CC2520_EXC_RX_UNDERFLOW = 0x06, + CC2520_EXC_RX_OVERFLOW = 0x07, + CC2520_EXC_RXENABLE_ZERO = 0x08, + CC2520_EXC_RX_FRM_DONE = 0x09, + CC2520_EXC_RX_FRM_ACCEPTED = 0x0A, + CC2520_EXC_SRC_MATCH_DONE = 0x0B, + CC2520_EXC_SRC_MATCH_FOUND = 0x0C, + CC2520_EXC_FIFOP = 0x0D, + CC2520_EXC_SFD = 0x0E, + CC2520_EXC_DPU_DONE_L = 0x0F, + CC2520_EXC_DPU_DONE_H = 0x10, + CC2520_EXC_MEMADDR_ERROR = 0x11, + CC2520_EXC_USAGE_ERROR = 0x12, + CC2520_EXC_OPERAND_ERROR = 0x13, + CC2520_EXC_SPI_ERROR = 0x14, + CC2520_EXC_RF_NO_LOCK = 0x15, + CC2520_EXC_RX_FRM_ABORTED = 0x16, + CC2520_EXC_RXBUFMOV_TIMEOUT = 0x17, +}; + +enum cc2520_GPIO_output_enums { + + CC2520_GPIO_EXC_CH_A = 0x21, + CC2520_GPIO_EXC_CH_B = 0x22, + CC2520_GPIO_EXC_CH_INVA = 0x23, + CC2520_GPIO_EXC_CH_INVB = 0x24, + CC2520_GPIO_EXC_CH_RX = 0x25, + C2520_GPIO_EXC_CH_ERR = 0x26, + CC2520_GPIO_FIFO = 0x27, + CC2520_GPIO_FIFOP = 0x28, + CC2520_GPIO_CCA = 0x29, + CC2520_GPIO_SFD = 0x2A, + CC2520_GPIO_RSSI_VALID = 0x2C, + CC2520_GPIO_SAMPLED_CCA = 0x2D, + CC2520_GPIO_SNIFFER_CLK = 0x31, + CC2520_GPIO_SNIFFER_DATA = 0x32, + CC2520_GPIO_RX_ACTIVE = 0x43, + CC2520_GPIO_TX_ACTIVE = 0x44, + CC2520_GPIO_LOW = 0x7E, + CC2520_GPIO_HIGH = 0x7F, +}; + +enum cc2520_reg_access_enums { + CC2520_FREG_MASK = 0x3F, // highest address in FREG + CC2520_SREG_MASK = 0x7F, // highest address in SREG + //CC2520_CMD_REGISTER_WRITE = 0xC0, +}; +/* + 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 cc2520_ram_addr_enums { + + CC2520_RAM_TXFIFO = 0x100, + CC2520_RAM_RXFIFO = 0x180, + CC2520_RAM_TXFRAME = 0x200, //Allocate 127 Bytes MTU to a Frame + CC2520_RAM_RXFRAME = 0x280, + CC2520_RAM_KEY0 = 0x300, + CC2520_RAM_TXNONCE = 0x310, + CC2520_RAM_RXNONCE = 0x320, + CC2520_RAM_SABUF = 0x220, + CC2520_RAM_CBCSTATE = 0x360, + + + + CC2520_RAM_PANID = 0x3F2, + CC2520_RAM_SHORTADR = 0x3F4, + CC2520_RAM_IEEEADR = 0x3EA, +}; + +enum cc2520_nonce_enums { + CC2520_NONCE_BLOCK_COUNTER = 0, + CC2520_NONCE_KEY_SEQ_COUNTER = 2, + CC2520_NONCE_FRAME_COUNTER = 3, + CC2520_NONCE_SOURCE_ADDRESS = 7, + CC2520_NONCE_FLAGS = 15, +}; + + + +enum cc2520_mdmctrl0_enums { + + CC2520_MDMCTRL0_DEM_NUM_ZEROS = 6, + CC2520_MDMCTRL0_DEMOD_AVG_MODE = 5, + CC2520_MDMCTRL0_PREAMBLE_LENGTH = 1, + CC2520_MDMCTRL0_TX_FILTER = 0, +}; + +enum cc2520_mdmctrl1_enums { + + CC2520_MDMCTRL1_RESERVED = 6, + CC2520_MDMCTRL1_CORR_THR_SFD = 5, + CC2520_MDMCTRL1_CORR_THR = 0, +}; + + +enum cc2520_frmctrl0_enums { + + CC2520_FMCTRL0_APPEND_DATA_MODE = 7, + CC2520_FMCTRL0_AUTOCRC = 6, + CC2520_FMCTRL0_AUTOACK = 5, + CC2520_FMCTRL0_ENERGY_SCAN = 4, + CC2520_FMCTRL0_RX_MODE = 2, + CC2520_FMCTRL0_TX_MODE = 0, + + +}; + +enum cc2520_freqctrl_enums { + + CC2520_FREQCTRL_RESERVED = 7, + CC2520_FREQCTRL_FREQ = 0, +}; + +enum cc2520_txpower_enums { + CC2520_TXPOWER_PA_POWER = 0, +}; + +enum cc2520_frmfilt0_enums { + + CC2520_FRMFILT0_RESERVED = 7, + CC2520_FRMFILT0_FCF_RESERVED_MASK = 4, + CC2520_FRMFILT0_MAX_FRAME_VERSION = 2, + CC2520_FRMFILT0_PAN_COORDINATOR = 1, + CC2520_FRMFILT0_FRAME_FILTER_EN = 0, + +}; + +enum cc2520_frmfilt1_enums { + + CC2520_FRMFILT1_ACCEPT_FT_4TO7 = 7, + CC2520_FRMFILT1_ACCEPT_FT_3_MAC_CMD = 6, + CC2520_FRMFILT1_ACCEPT_FT_2_ACK = 5, + CC2520_FRMFILT1_ACCEPT_FT_1_DATA = 4, + CC2520_FRMFILT1_ACCEPT_FT_0_BEACON = 3, + C2520_FRMFILT1_MODIFY_FT_FILTER = 1, + C2520_FRMFILT1_RESERVED = 0, +}; + +enum cc2520_srcmatch_enums { + CC2520_SRCMATCH_RESERVED = 3, + CC2520_SRCMATCH_PEND_DATAREQ_ONLY = 2, + CC2520_SRCMATCH_AUTOPEND = 1, + CC2520_SRCMATCH_ENABLE = 0, +}; + +enum cc2520_fifopctrl_enums { + + CC2520_FIFOPCTRL_RESERVED = 7, + CC2520_FIFOPCTRL_FIFOP_THR = 0, +}; + + +enum cc2520_ccactrl0_enums { + + CC2520_CCACTRL0_CCA_THR = 0, +}; + +typedef union cc2520_rxctrl { + uint8_t value; +} cc2520_rxctrl_t; +static cc2520_rxctrl_t cc2520_rxctrl_default = {.value = 0x32}; + +enum +{ + CC2520_INVALID_TIMESTAMP = 0x80000000L, +}; + + +/* +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, +}; + +enum +{ + CC2420_INVALID_TIMESTAMP = 0x80000000L, +}; +*/ +#endif diff --git a/cc2520/CC2520ActiveMessageC _unedit.nc b/cc2520/CC2520ActiveMessageC _unedit.nc new file mode 100644 index 0000000000..f82b4ea4c1 --- /dev/null +++ b/cc2520/CC2520ActiveMessageC _unedit.nc @@ -0,0 +1,118 @@ +/* + * "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 CC2520 radio. This configuration + * just layers the AM dispatch (CC2520ActiveMessageM) on top of the + * underlying CC2520 radio packet (CC2520CsmaCsmaCC), which is + * inherently an AM packet (acknowledgements based on AM destination + * addr and group). Note that snooping may not work, due to CC2520 + * early packet rejection if acknowledgements are enabled. + * + * @author Philip Levis + * @author David Moss + * @version $Revision: 1.12 $ $Date: 2008/06/11 00:46:23 $ + */ + +#include "CC2520.h" +#include "AM.h" + +configuration CC2520ActiveMessageC { + 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 CC2520Packet; + interface PacketAcknowledgements; + interface LinkPacketMetadata; + interface RadioBackoff[am_id_t amId]; + interface LowPowerListening; + interface PacketLink; + interface SendNotifier[am_id_t amId]; + } +} +implementation { + + components CC2520ActiveMessageP as AM; + components CC2520CsmaC as CsmaC; + components ActiveMessageAddressC; + components UniqueSendC; + components UniqueReceiveC; + components CC2520TinyosNetworkC; + components CC2520PacketC; + components CC2520ControlC; + +#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 = AM; + Packet = AM; + AMSend = AM; + SendNotifier = AM; + Receive = AM.Receive; + Snoop = AM.Snoop; + AMPacket = AM; + PacketLink = LinkC; + LowPowerListening = LplC; + CC2520Packet = CC2520PacketC; + PacketAcknowledgements = CC2520PacketC; + LinkPacketMetadata = CC2520PacketC; + + // SplitControl Layers + SplitControl = LplC; + LplC.SubControl -> CsmaC; + + // Send Layers + AM.SubSend -> UniqueSendC; + UniqueSendC.SubSend -> LinkC; + LinkC.SubSend -> LplC.Send; + LplC.SubSend -> CC2520TinyosNetworkC.Send; + CC2520TinyosNetworkC.SubSend -> CsmaC; + + // Receive Layers + AM.SubReceive -> LplC; + LplC.SubReceive -> UniqueReceiveC.Receive; + UniqueReceiveC.SubReceive -> CC2520TinyosNetworkC.Receive; + CC2520TinyosNetworkC.SubReceive -> CsmaC; + + AM.ActiveMessageAddress -> ActiveMessageAddressC; + AM.CC2520Packet -> CC2520PacketC; + AM.CC2520PacketBody -> CC2520PacketC; + AM.CC2520Config -> CC2520ControlC; + + AM.SubBackoff -> CsmaC; + +} diff --git a/cc2520/CC2520ActiveMessageC.nc b/cc2520/CC2520ActiveMessageC.nc new file mode 100644 index 0000000000..8b828c8037 --- /dev/null +++ b/cc2520/CC2520ActiveMessageC.nc @@ -0,0 +1,99 @@ +/* + * "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 CC2520 radio. This configuration + * just layers the AM dispatch (CC2520ActiveMessageM) on top of the + * underlying CC2520 radio packet (CC2520CsmaCsmaCC), which is + * inherently an AM packet (acknowledgements based on AM destination + * addr and group). Note that snooping may not work, due to CC2520 + * early packet rejection if acknowledgements are enabled. + * + * @author Philip Levis + * @author David Moss + * @version $Revision: 1.12 $ $Date: 2008/06/11 00:46:23 $ + */ + +#include "CC2520.h" +#include "AM.h" + +configuration CC2520ActiveMessageC { + 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 CC2520Packet; + interface PacketAcknowledgements; + interface LinkPacketMetadata; + interface RadioBackoff[am_id_t amId]; + interface LowPowerListening; + interface PacketLink; + interface SendNotifier[am_id_t amId]; + } +} +implementation { + + + enum { + CC2520_AM_SEND_ID = unique(RADIO_SEND_RESOURCE), + }; + + components CC2520RadioC as Radio; + components CC2520ActiveMessageP as AM; + components ActiveMessageAddressC; + components CC2520CsmaC as CsmaC; + components CC2520ControlC; + components CC2520PacketC; + + SplitControl = Radio; + RadioBackoff = AM; + Packet = AM; + AMSend = AM; + SendNotifier = AM; + Receive = AM.Receive; + Snoop = AM.Snoop; + AMPacket = AM; + PacketLink = Radio; + LowPowerListening = Radio; + CC2520Packet = Radio; + PacketAcknowledgements = Radio; + LinkPacketMetadata = Radio; + + // Radio resource for the AM layer + AM.SubSend -> Radio.ActiveSend; + AM.SubReceive -> Radio.ActiveReceive; + + AM.ActiveMessageAddress -> ActiveMessageAddressC; + AM.CC2520Packet -> CC2520PacketC; + AM.CC2520PacketBody -> CC2520PacketC; + AM.CC2520Config -> CC2520ControlC; + + AM.SubBackoff -> CsmaC; + + + + +} diff --git a/cc2520/CC2520ActiveMessageP.nc b/cc2520/CC2520ActiveMessageP.nc new file mode 100644 index 0000000000..ad1ae1eb02 --- /dev/null +++ b/cc2520/CC2520ActiveMessageP.nc @@ -0,0 +1,291 @@ +/* + * "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 CC2520 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: 1.18 $ $Date: 2008/06/24 05:32:31 $ + */ + +#include "CC2520.h" + +module CC2520ActiveMessageP @safe() { + 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; + interface SendNotifier[am_id_t id]; + interface RadioBackoff[am_id_t id]; + } + + uses { + interface Send as SubSend; + interface Receive as SubReceive; + interface CC2520Packet; + interface CC2520PacketBody; + interface CC2520Config; + interface ActiveMessageAddress; + interface RadioBackoff as SubBackoff; + } +} +implementation { + + + uint32_t frameCounter = 0; + uint8_t micLength = 0; + /***************** AMSend Commands ****************/ + command error_t AMSend.send[am_id_t id](am_addr_t addr, + message_t* msg, + uint8_t len) { + cc2520_header_t* header = call CC2520PacketBody.getHeader( msg ); + #ifdef CC2520_HW_SECURITY + security_header_t* secHdr = (security_header_t*)&header->secHdr; + #endif + header->type = id; + header->dest = addr; + header->destpan = call CC2520Config.getPanAddr(); + header->src = call AMPacket.address(); + header->fcf |= ( 1 << IEEE154_FCF_INTRAPAN ) | + ( IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE ) | + ( IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE ) ; + header->length = len + CC2520_SIZE; + #ifdef CC2520_HW_SECURITY + /*Filling the security control byte*/ + secHdr->secLevel = SEC_ENC; + secHdr->keyMode = 0; //We will remove the key identifier field for now + secHdr->reserved = 0; + /*Filling the frame counter field*/ + secHdr->frameCounter = frameCounter; + /*Enabling the security bit in FCF*/ + header->fcf |= 1 << IEEE154_FCF_SECURITY_ENABLED; + frameCounter++; + micLength = 0; + + if(secHdr->secLevel == SEC_MIC_32 || secHdr->secLevel == SEC_ENC_MIC_32){ + micLength = 4; + }else if(secHdr->secLevel == SEC_MIC_64 || secHdr->secLevel == SEC_ENC_MIC_64){ + micLength = 8; + }else if(secHdr->secLevel == SEC_ENC_MIC_128 || secHdr->secLevel == SEC_ENC_MIC_128){ + micLength = 16; + } + len += micLength; + #endif + signal SendNotifier.aboutToSend[id](addr, msg); + return call SubSend.send( msg, len ); + } + + 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, uint8_t len) { + return call Packet.getPayload(m, len); + } + + /***************** AMPacket Commands ****************/ + command am_addr_t AMPacket.address() { + return call ActiveMessageAddress.amAddress(); + } + + command am_addr_t AMPacket.destination(message_t* amsg) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + return header->dest; + } + + command am_addr_t AMPacket.source(message_t* amsg) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + return header->src; + } + + command void AMPacket.setDestination(message_t* amsg, am_addr_t addr) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + header->dest = addr; + } + + command void AMPacket.setSource(message_t* amsg, am_addr_t addr) { + cc2520_header_t* header = call CC2520PacketBody.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) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + return header->type; + } + + command void AMPacket.setType(message_t* amsg, am_id_t type) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + header->type = type; + } + + command am_group_t AMPacket.group(message_t* amsg) { + return (call CC2520PacketBody.getHeader(amsg))->destpan; + } + + command void AMPacket.setGroup(message_t* amsg, am_group_t grp) { + // Overridden intentionally when we send() + (call CC2520PacketBody.getHeader(amsg))->destpan = grp; + } + + command am_group_t AMPacket.localGroup() { + return call CC2520Config.getPanAddr(); + } + + + /***************** Packet Commands ****************/ + command void Packet.clear(message_t* msg) { + memset(call CC2520PacketBody.getHeader(msg), 0x0, sizeof(cc2520_header_t)); + memset(call CC2520PacketBody.getMetadata(msg), 0x0, sizeof(cc2520_metadata_t)); + } + + command uint8_t Packet.payloadLength(message_t* msg) { + return (call CC2520PacketBody.getHeader(msg))->length - CC2520_SIZE; + } + + command void Packet.setPayloadLength(message_t* msg, uint8_t len) { + (call CC2520PacketBody.getHeader(msg))->length = len + CC2520_SIZE; + } + + command uint8_t Packet.maxPayloadLength() { + return TOSH_DATA_LENGTH; + } + + command void* Packet.getPayload(message_t* msg, uint8_t len) { + return call SubSend.getPayload(msg, len); + } + + + /***************** 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 CC2520PacketBody.getMetadata(msg))->crc) { + return msg; + } + + if (call AMPacket.isForMe(msg)) { + return signal Receive.receive[call AMPacket.type(msg)](msg, payload, len); + } + else { + return signal Snoop.receive[call AMPacket.type(msg)](msg, payload, len); + } + } + + + /***************** ActiveMessageAddress Events ****************/ + async event void ActiveMessageAddress.changed() { + } + + /***************** CC2520Config Events ****************/ + event void CC2520Config.syncDone( error_t error ) { + } + + + /***************** RadioBackoff ***********************/ + + async event void SubBackoff.requestInitialBackoff(message_t *msg) { + signal RadioBackoff.requestInitialBackoff[(TCAST(cc2520_header_t* ONE, + (uint8_t*)msg + offsetof(message_t, data) - sizeof(cc2520_header_t)))->type](msg); + } + + async event void SubBackoff.requestCongestionBackoff(message_t *msg) { + signal RadioBackoff.requestCongestionBackoff[(TCAST(cc2520_header_t* ONE, + (uint8_t*)msg + offsetof(message_t, data) - sizeof(cc2520_header_t)))->type](msg); + } + async event void SubBackoff.requestCca(message_t *msg) { + // Lower layers than this do not configure the CCA settings + signal RadioBackoff.requestCca[(TCAST(cc2520_header_t* ONE, + (uint8_t*)msg + offsetof(message_t, data) - sizeof(cc2520_header_t)))->type](msg); + } + + 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) { + call SubBackoff.setCca(useCca); + } + + + + /***************** 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) { + } + + default event void SendNotifier.aboutToSend[am_id_t amId](am_addr_t addr, message_t *msg) { + } + default async event void RadioBackoff.requestInitialBackoff[am_id_t id]( + message_t *msg) { + } + + default async event void RadioBackoff.requestCongestionBackoff[am_id_t id]( + message_t *msg) { + } + + default async event void RadioBackoff.requestCca[am_id_t id]( + message_t *msg) { + } + +} diff --git a/cc2520/CC2520ActiveMessageP_unedit.nc b/cc2520/CC2520ActiveMessageP_unedit.nc new file mode 100644 index 0000000000..bde24d2c03 --- /dev/null +++ b/cc2520/CC2520ActiveMessageP_unedit.nc @@ -0,0 +1,261 @@ +/* + * "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 CC2520 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: 1.18 $ $Date: 2008/06/24 05:32:31 $ + */ + +#include "CC2520.h" + +module CC2520ActiveMessageP @safe() { + 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; + interface SendNotifier[am_id_t id]; + interface RadioBackoff[am_id_t id]; + } + + uses { + interface Send as SubSend; + interface Receive as SubReceive; + interface CC2520Packet; + interface CC2520PacketBody; + interface CC2520Config; + interface ActiveMessageAddress; + interface RadioBackoff as SubBackoff; + } +} +implementation { + + /***************** AMSend Commands ****************/ + command error_t AMSend.send[am_id_t id](am_addr_t addr, + message_t* msg, + uint8_t len) { + cc2520_header_t* header = call CC2520PacketBody.getHeader( msg ); + header->type = id; + header->dest = addr; + header->destpan = call CC2520Config.getPanAddr(); + header->src = call AMPacket.address(); + signal SendNotifier.aboutToSend[id](addr, msg); + + return call SubSend.send( msg, len ); + } + + 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, uint8_t len) { + return call Packet.getPayload(m, len); + } + + /***************** AMPacket Commands ****************/ + command am_addr_t AMPacket.address() { + return call ActiveMessageAddress.amAddress(); + } + + command am_addr_t AMPacket.destination(message_t* amsg) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + return header->dest; + } + + command am_addr_t AMPacket.source(message_t* amsg) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + return header->src; + } + + command void AMPacket.setDestination(message_t* amsg, am_addr_t addr) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + header->dest = addr; + } + + command void AMPacket.setSource(message_t* amsg, am_addr_t addr) { + cc2520_header_t* header = call CC2520PacketBody.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) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + return header->type; + } + + command void AMPacket.setType(message_t* amsg, am_id_t type) { + cc2520_header_t* header = call CC2520PacketBody.getHeader(amsg); + header->type = type; + } + + command am_group_t AMPacket.group(message_t* amsg) { + return (call CC2520PacketBody.getHeader(amsg))->destpan; + } + + command void AMPacket.setGroup(message_t* amsg, am_group_t grp) { + // Overridden intentionally when we send() + (call CC2520PacketBody.getHeader(amsg))->destpan = grp; + } + + command am_group_t AMPacket.localGroup() { + return call CC2520Config.getPanAddr(); + } + + + /***************** Packet Commands ****************/ + command void Packet.clear(message_t* msg) { + memset(call CC2520PacketBody.getHeader(msg), 0x0, sizeof(cc2520_header_t)); + memset(call CC2520PacketBody.getMetadata(msg), 0x0, sizeof(cc2520_metadata_t)); + } + + command uint8_t Packet.payloadLength(message_t* msg) { + return (call CC2520PacketBody.getHeader(msg))->length - CC2520_SIZE; + } + + command void Packet.setPayloadLength(message_t* msg, uint8_t len) { + (call CC2520PacketBody.getHeader(msg))->length = len + CC2520_SIZE; + } + + command uint8_t Packet.maxPayloadLength() { + return TOSH_DATA_LENGTH; + } + + command void* Packet.getPayload(message_t* msg, uint8_t len) { + return call SubSend.getPayload(msg, len); + } + + + /***************** 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 CC2520PacketBody.getMetadata(msg))->crc) { + return msg; + } + + if (call AMPacket.isForMe(msg)) { + return signal Receive.receive[call AMPacket.type(msg)](msg, payload, len); + } + else { + return signal Snoop.receive[call AMPacket.type(msg)](msg, payload, len); + } + } + + + /***************** ActiveMessageAddress Events ****************/ + async event void ActiveMessageAddress.changed() { + } + + /***************** CC2520Config Events ****************/ + event void CC2520Config.syncDone( error_t error ) { + } + + + /***************** RadioBackoff ***********************/ + + async event void SubBackoff.requestInitialBackoff(message_t *msg) { + signal RadioBackoff.requestInitialBackoff[(TCAST(cc2520_header_t* ONE, + (uint8_t*)msg + offsetof(message_t, data) - sizeof(cc2520_header_t)))->type](msg); + } + + async event void SubBackoff.requestCongestionBackoff(message_t *msg) { + signal RadioBackoff.requestCongestionBackoff[(TCAST(cc2520_header_t* ONE, + (uint8_t*)msg + offsetof(message_t, data) - sizeof(cc2520_header_t)))->type](msg); + } + async event void SubBackoff.requestCca(message_t *msg) { + // Lower layers than this do not configure the CCA settings + signal RadioBackoff.requestCca[(TCAST(cc2520_header_t* ONE, + (uint8_t*)msg + offsetof(message_t, data) - sizeof(cc2520_header_t)))->type](msg); + } + + 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) { + call SubBackoff.setCca(useCca); + } + + + + /***************** 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) { + } + + default event void SendNotifier.aboutToSend[am_id_t amId](am_addr_t addr, message_t *msg) { + } + default async event void RadioBackoff.requestInitialBackoff[am_id_t id]( + message_t *msg) { + } + + default async event void RadioBackoff.requestCongestionBackoff[am_id_t id]( + message_t *msg) { + } + + default async event void RadioBackoff.requestCca[am_id_t id]( + message_t *msg) { + } + +} diff --git a/cc2520/CC2520RadioC.nc b/cc2520/CC2520RadioC.nc new file mode 100644 index 0000000000..cc65040994 --- /dev/null +++ b/cc2520/CC2520RadioC.nc @@ -0,0 +1,79 @@ +#include "CC2520.h" + +configuration CC2520RadioC +{ + + provides { + interface SplitControl; + interface Resource[uint8_t clientId]; + + interface Send as BareSend; + interface Receive as BareReceive; + interface Packet as BarePacket; + + interface Send as ActiveSend; + interface Receive as ActiveReceive; + + interface CC2520Packet; + interface PacketAcknowledgements; + interface LinkPacketMetadata; + interface LowPowerListening; + interface PacketLink; + } + +} + + +implementation +{ + + components CC2520CsmaC as CsmaC; + components UniqueSendC; + components UniqueReceiveC; + components CC2520TinyosNetworkC; + components CC2520PacketC; + components CC2520ControlC; + +#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 + //splitcontrol layers + SplitControl=LplC; + LplC.SubControl -> CsmaC; + + + + PacketLink = LinkC; + LowPowerListening = LplC; + CC2520Packet = CC2520PacketC; + PacketAcknowledgements = CC2520PacketC; + LinkPacketMetadata = CC2520PacketC; + + + Resource = CC2520TinyosNetworkC; + BarePacket = CC2520TinyosNetworkC.BarePacket; + BareSend = CC2520TinyosNetworkC.Send; + BareReceive = CC2520TinyosNetworkC.Receive; + + ActiveSend = CC2520TinyosNetworkC.ActiveSend; + ActiveReceive = CC2520TinyosNetworkC.ActiveReceive; + + // Send Layers + CC2520TinyosNetworkC.SubSend -> UniqueSendC; + UniqueSendC.SubSend -> LinkC; + LinkC.SubSend -> LplC.Send; + LplC.SubSend -> CsmaC; + + // Receive Layers + CC2520TinyosNetworkC.SubReceive -> LplC; + LplC.SubReceive -> UniqueReceiveC.Receive; + UniqueReceiveC.SubReceive -> CsmaC; +} diff --git a/cc2520/CC2520TimeSyncMessage.h b/cc2520/CC2520TimeSyncMessage.h new file mode 100644 index 0000000000..a744fd385b --- /dev/null +++ b/cc2520/CC2520TimeSyncMessage.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2007, Vanderbilt 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 THE VANDERBILT 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 THE VANDERBILT + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE VANDERBILT 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 THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Author: Miklos Maroti + */ + +#ifndef __TIMESYNCMESSAGE_H__ +#define __TIMESYNCMESSAGE_H__ + +// this value is sent in the air +typedef nx_uint32_t timesync_radio_t; + +#endif//__TIMESYNCMESSAGE_H__ diff --git a/cc2520/CC2520TimeSyncMessageC.nc b/cc2520/CC2520TimeSyncMessageC.nc new file mode 100644 index 0000000000..4ced284522 --- /dev/null +++ b/cc2520/CC2520TimeSyncMessageC.nc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2007, Vanderbilt 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 THE VANDERBILT 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 THE VANDERBILT + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE VANDERBILT 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 THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/** + * The Active Message layer for the CC2420 radio with timesync support. This + * configuration is just layer above CC2420ActiveMessageC that supports + * TimeSyncPacket and TimeSyncAMSend interfaces (TEP 133) + * + * @author: Miklos Maroti + * @author: Brano Kusy (CC2420 port) + */ + +#include +#include + +configuration CC2520TimeSyncMessageC +{ + provides + { + interface SplitControl; + interface Receive[am_id_t id]; + interface Receive as Snoop[am_id_t id]; + interface Packet; + interface AMPacket; + + interface TimeSyncAMSend as TimeSyncAMSend32khz[am_id_t id]; + interface TimeSyncPacket as TimeSyncPacket32khz; + + interface TimeSyncAMSend as TimeSyncAMSendMilli[am_id_t id]; + interface TimeSyncPacket as TimeSyncPacketMilli; + } +} + +implementation +{ + components CC2520TimeSyncMessageP, CC2520ActiveMessageC, CC2520PacketC, LedsC; + + TimeSyncAMSend32khz = CC2520TimeSyncMessageP; + TimeSyncPacket32khz = CC2520TimeSyncMessageP; + + TimeSyncAMSendMilli = CC2520TimeSyncMessageP; + TimeSyncPacketMilli = CC2520TimeSyncMessageP; + + Packet = CC2520TimeSyncMessageP; + CC2520TimeSyncMessageP.SubSend -> CC2520ActiveMessageC.AMSend; + CC2520TimeSyncMessageP.SubPacket -> CC2520ActiveMessageC.Packet; + + CC2520TimeSyncMessageP.PacketTimeStamp32khz -> CC2520PacketC; + CC2520TimeSyncMessageP.PacketTimeStampMilli -> CC2520PacketC; + CC2520TimeSyncMessageP.PacketTimeSyncOffset -> CC2520PacketC; + components Counter32khz32C, new CounterToLocalTimeC(T32khz) as LocalTime32khzC, LocalTimeMilliC; + LocalTime32khzC.Counter -> Counter32khz32C; + CC2520TimeSyncMessageP.LocalTime32khz -> LocalTime32khzC; + CC2520TimeSyncMessageP.LocalTimeMilli -> LocalTimeMilliC; + CC2520TimeSyncMessageP.Leds -> LedsC; + + SplitControl = CC2520ActiveMessageC; + Receive = CC2520ActiveMessageC.Receive; + Snoop = CC2520ActiveMessageC.Snoop; + AMPacket = CC2520ActiveMessageC; +} diff --git a/cc2520/CC2520TimeSyncMessageP.nc b/cc2520/CC2520TimeSyncMessageP.nc new file mode 100644 index 0000000000..c7e9549e4d --- /dev/null +++ b/cc2520/CC2520TimeSyncMessageP.nc @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2007, Vanderbilt 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 THE VANDERBILT 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 THE VANDERBILT + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE VANDERBILT 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 THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * @author: Miklos Maroti + * @author: Brano Kusy (CC2420 port) + */ +#include "CC2520TimeSyncMessage.h" + +module CC2520TimeSyncMessageP +{ + provides + { + interface TimeSyncAMSend as TimeSyncAMSend32khz[uint8_t id]; + interface TimeSyncAMSend as TimeSyncAMSendMilli[uint8_t id]; + interface Packet; + + interface TimeSyncPacket as TimeSyncPacket32khz; + interface TimeSyncPacket as TimeSyncPacketMilli; + } + + uses + { + interface AMSend as SubSend[uint8_t id]; + interface Packet as SubPacket; + + interface PacketTimeStamp as PacketTimeStamp32khz; + interface PacketTimeStamp as PacketTimeStampMilli; + interface PacketTimeSyncOffset; + + interface LocalTime as LocalTime32khz; + interface LocalTime as LocalTimeMilli; + interface Leds; + } +} + +implementation +{ + // TODO: change the Packet.payloadLength and Packet.maxPayloadLength commands to async + inline void* getFooter(message_t* msg) + { + // we use the payload length that we export (the smaller one) + return msg->data + call Packet.payloadLength(msg); + } + +/*----------------- Packet -----------------*/ + command void Packet.clear(message_t* msg) + { + call PacketTimeSyncOffset.cancel(msg); + call SubPacket.clear(msg); + } + + command void Packet.setPayloadLength(message_t* msg, uint8_t len) + { + call SubPacket.setPayloadLength(msg, len + sizeof(timesync_radio_t)); + } + + command uint8_t Packet.payloadLength(message_t* msg) + { + return call SubPacket.payloadLength(msg) - sizeof(timesync_radio_t); + } + + command uint8_t Packet.maxPayloadLength() + { + return call SubPacket.maxPayloadLength() - sizeof(timesync_radio_t); + } + + command void* Packet.getPayload(message_t* msg, uint8_t len) + { + return call SubPacket.getPayload(msg, len + sizeof(timesync_radio_t)); + } + +/*----------------- TimeSyncAMSend32khz -----------------*/ + command error_t TimeSyncAMSend32khz.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len, uint32_t event_time) + { + error_t err; + void * timesync = msg->data + len; + *(timesync_radio_t*)timesync = event_time; + + err = call SubSend.send[id](addr, msg, len + sizeof(timesync_radio_t)); + call PacketTimeSyncOffset.set(msg); + return err; + } + + command error_t TimeSyncAMSend32khz.cancel[am_id_t id](message_t* msg) + { + call PacketTimeSyncOffset.cancel(msg); + return call SubSend.cancel[id](msg); + } + + default event void TimeSyncAMSend32khz.sendDone[am_id_t id](message_t* msg, error_t error) {} + + command uint8_t TimeSyncAMSend32khz.maxPayloadLength[am_id_t id]() + { + return call SubSend.maxPayloadLength[id]() - sizeof(timesync_radio_t); + } + + command void* TimeSyncAMSend32khz.getPayload[am_id_t id](message_t* msg, uint8_t len) + { + return call SubSend.getPayload[id](msg, len + sizeof(timesync_radio_t)); + } + +/*----------------- TimeSyncAMSendMilli -----------------*/ + command error_t TimeSyncAMSendMilli.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len, uint32_t event_time) + { + // compute elapsed time in millisecond + event_time = ((event_time - call LocalTimeMilli.get()) << 5) + call LocalTime32khz.get(); + return call TimeSyncAMSend32khz.send[id](addr, msg, len, event_time); + } + + command error_t TimeSyncAMSendMilli.cancel[am_id_t id](message_t* msg) + { + return call TimeSyncAMSend32khz.cancel[id](msg); + } + + default event void TimeSyncAMSendMilli.sendDone[am_id_t id](message_t* msg, error_t error){} + + command uint8_t TimeSyncAMSendMilli.maxPayloadLength[am_id_t id]() + { + return call TimeSyncAMSend32khz.maxPayloadLength[id](); + } + + command void* TimeSyncAMSendMilli.getPayload[am_id_t id](message_t* msg, uint8_t len) + { + return call TimeSyncAMSend32khz.getPayload[id](msg, len); + } + +/*----------------- SubSend.sendDone -------------------*/ + event void SubSend.sendDone[am_id_t id](message_t* msg, error_t error) + { + signal TimeSyncAMSend32khz.sendDone[id](msg, error); + signal TimeSyncAMSendMilli.sendDone[id](msg, error); + } + +/*----------------- TimeSyncPacket32khz -----------------*/ + command bool TimeSyncPacket32khz.isValid(message_t* msg) + { + timesync_radio_t* timesync = getFooter(msg); + return call PacketTimeStamp32khz.isValid(msg) && *timesync != CC2520_INVALID_TIMESTAMP; + } + + command uint32_t TimeSyncPacket32khz.eventTime(message_t* msg) + { + timesync_radio_t* timesync = getFooter(msg); + + return (uint32_t)(*timesync) + call PacketTimeStamp32khz.timestamp(msg); + } + +/*----------------- TimeSyncPacketMilli -----------------*/ + command bool TimeSyncPacketMilli.isValid(message_t* msg) + { + timesync_radio_t* timesync = getFooter(msg); + return call PacketTimeStampMilli.isValid(msg) && *timesync != CC2520_INVALID_TIMESTAMP; + } + + command uint32_t TimeSyncPacketMilli.eventTime(message_t* msg) + { + timesync_radio_t* timesync = getFooter(msg); + return ((int32_t)(*timesync) >> 5) + call PacketTimeStampMilli.timestamp(msg); + } +} diff --git a/cc2520/IEEE802154.h b/cc2520/IEEE802154.h new file mode 100644 index 0000000000..824fe9d2b3 --- /dev/null +++ b/cc2520/IEEE802154.h @@ -0,0 +1,40 @@ +/* + * 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 + * @version $Revision: 1.7 $ $Date: 2007/07/04 00:37:14 $ + */ + +#ifndef __IEEE802154_H__ +#define __IEEE802154_H__ + +#include + +#endif diff --git a/cc2520/README.txt b/cc2520/README.txt new file mode 100644 index 0000000000..e9409be12f --- /dev/null +++ b/cc2520/README.txt @@ -0,0 +1,119 @@ + +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 + +To stop using address recognition on the radio hardware, #define: + CC2420_NO_ADDRESS_RECOGNITION + + + +============================================================ +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(). + + +7/5/07: +* Added two methods to enable/disable automatic address recognition: + - Preprocessor CC2420_NO_ADDRESS_RECOGNITION to disable address recognition at + compile time + - CC2420Config.setAddressRecognition(bool on) through CC2420ControlC + +* Allowed the CC2420ReceiveP to perform software address checks to support + the case where a base station type application must sniff packets from other + address, but also SACK packets destined for its address + +* Updated CC2420Config interface to provide an async getShortAddr() and getPanAddr() + + +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. + diff --git a/cc2520/alarm/AlarmMultiplexC.nc b/cc2520/alarm/AlarmMultiplexC.nc new file mode 100644 index 0000000000..7930abeb34 --- /dev/null +++ b/cc2520/alarm/AlarmMultiplexC.nc @@ -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 + * @version $Revision: 1.1 $ $Date: 2007/07/04 00:37:14 $ + */ + +#include + +configuration AlarmMultiplexC { + + provides interface Init; + provides interface Alarm as Alarm32khz32; + +} + +implementation { + + components new HplCC2520AlarmC() as Alarm; + + Init = Alarm; + Alarm32khz32 = Alarm; + +} diff --git a/cc2520/control/CC2520ControlC.nc b/cc2520/control/CC2520ControlC.nc new file mode 100644 index 0000000000..4baba7c8a7 --- /dev/null +++ b/cc2520/control/CC2520ControlC.nc @@ -0,0 +1,151 @@ +/* + * 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 + * @version $Revision: 1.3 $ $Date: 2008/05/14 21:33:07 $ + */ + +#include "CC2520.h" +#include "IEEE802154.h" + +configuration CC2520ControlC { + + provides interface Resource; + provides interface CC2520Config; + provides interface CC2520Power; + provides interface Read as ReadRssi; + +} + +implementation { + + components CC2520ControlP; + Resource = CC2520ControlP; + CC2520Config = CC2520ControlP; + CC2520Power = CC2520ControlP; + ReadRssi = CC2520ControlP; + + components MainC; + MainC.SoftwareInit -> CC2520ControlP; + + components AlarmMultiplexC as Alarm; + CC2520ControlP.StartupTimer -> Alarm; + + components HplCC2520PinsC as Pins; + CC2520ControlP.CSN -> Pins.CSN; + CC2520ControlP.RSTN -> Pins.RSTN; + CC2520ControlP.VREN -> Pins.VREN; + + components HplCC2520InterruptsC as Interrupts; + CC2520ControlP.InterruptCCA -> Interrupts.InterruptCCA; + + components new CC2520SpiC() as Spi; + CC2520ControlP.SpiResource -> Spi; + CC2520ControlP.SRXON -> Spi.SRXON; + CC2520ControlP.SRFOFF -> Spi.SRFOFF; + CC2520ControlP.SXOSCON -> Spi.SXOSCON; + CC2520ControlP.SXOSCOFF -> Spi.SXOSCOFF; + + CC2520ControlP.SNOP -> Spi.SNOP; + + CC2520ControlP.FSCTRL -> Spi.FSCTRL; + + + //CC2420ControlP.IOCFG0 -> Spi.IOCFG0; + //CC2420ControlP.IOCFG1 -> Spi.IOCFG1; + + // Newly Added on 15-11-10 Lijo ******************/ + + CC2520ControlP.TXPOWER -> Spi.TXPOWER; + //CC2520ControlP.TXCTRL -> Spi.TXCTRL; + + CC2520ControlP.FREQCTRL -> Spi.FREQCTRL; + + CC2520ControlP.CCACTRL0 -> Spi.CCACTRL0; + + CC2520ControlP.AGCCTRL1 -> Spi.AGCCTRL1; + + + CC2520ControlP.RXCTRL -> Spi.RXCTRL; + CC2520ControlP.FSCAL1 -> Spi.FSCAL1; + + + CC2520ControlP.ADCTEST0 -> Spi.ADCTEST0; + CC2520ControlP.ADCTEST1 -> Spi.ADCTEST1; + CC2520ControlP.ADCTEST2 -> Spi.ADCTEST2; + + CC2520ControlP.FRMCTRL0 -> Spi.FRMCTRL0; + CC2520ControlP.EXTCLOCK -> Spi.EXTCLOCK; + + CC2520ControlP.GPIOCTRL0 -> Spi.GPIOCTRL0; + CC2520ControlP.GPIOCTRL1 -> Spi.GPIOCTRL1; + CC2520ControlP.GPIOCTRL2 -> Spi.GPIOCTRL2; + CC2520ControlP.GPIOCTRL3 -> Spi.GPIOCTRL3; + CC2520ControlP.GPIOCTRL4 -> Spi.GPIOCTRL4; + CC2520ControlP.GPIOCTRL5 -> Spi.GPIOCTRL5; + + CC2520ControlP.GPIOPOLARITY -> Spi.GPIOPOLARITY; + + CC2520ControlP.FRMCTRL1 -> Spi.FRMCTRL1; + + CC2520ControlP.FRMFILT0 -> Spi.FRMFILT0; + CC2520ControlP.FRMFILT1 -> Spi.FRMFILT1; + CC2520ControlP.FIFOPCTRL -> Spi.FIFOPCTRL; + //*************************************************/ + + + + CC2520ControlP.MDMCTRL0 -> Spi.MDMCTRL0; + CC2520ControlP.MDMCTRL1 -> Spi.MDMCTRL1; + + CC2520ControlP.PANID -> Spi.PANID; + //CC2520ControlP.RXCTRL1 -> Spi.RXCTRL1; + CC2520ControlP.RSSI -> Spi.RSSI; + + components new CC2520SpiC() as SyncSpiC; + CC2520ControlP.SyncResource -> SyncSpiC; + + components new CC2520SpiC() as RssiResource; + CC2520ControlP.RssiResource -> RssiResource; + + components ActiveMessageAddressC; + CC2520ControlP.ActiveMessageAddress -> ActiveMessageAddressC; + + components LedsC as Leds; + CC2520ControlP.Leds -> Leds; + components LocalIeeeEui64C; + CC2520ControlP.LocalIeeeEui64 -> LocalIeeeEui64C; + +} + diff --git a/cc2520/control/CC2520ControlP.nc b/cc2520/control/CC2520ControlP.nc new file mode 100644 index 0000000000..e49a69e8e9 --- /dev/null +++ b/cc2520/control/CC2520ControlP.nc @@ -0,0 +1,832 @@ +/* + * 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 + * @author David Moss + * @author Urs Hunkeler (ReadRssi implementation) + * @version $Revision: 1.7 $ $Date: 2008/06/24 04:07:28 $ + */ + +#include "Timer.h" +#include "CC2520.h" + +// IEEE 802.15.4 defined constants (2.4 GHz logical channels) +#define MIN_CHANNEL 11 // 2405 MHz +#define MAX_CHANNEL 26 // 2480 MHz +#define CHANNEL_SPACING 5 // MHz + +module CC2520ControlP @safe() { + + provides interface Init; + provides interface Resource; + provides interface CC2520Config; + provides interface CC2520Power; + provides interface Read as ReadRssi; + + uses interface Alarm 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 CC2520Ram as PANID; + + uses interface CC2520Register as FSCTRL; + //uses interface CC2420Register as IOCFG0; + //uses interface CC2420Register as IOCFG1; + + uses interface CC2520Register as MDMCTRL0; + uses interface CC2520Register as MDMCTRL1; + uses interface CC2520Register as RXCTRL; + uses interface CC2520Register as RSSI; + + // Newly Added on 15-11-10 Lijo ******************/ + + uses interface CC2520Register as AGCCTRL1; + uses interface CC2520Register as TXPOWER; + uses interface CC2520Register as CCACTRL0; + uses interface CC2520Register as FSCAL1; + uses interface CC2520Register as FRMCTRL1; + + uses interface CC2520Register as FREQCTRL; + + uses interface CC2520Register as ADCTEST0; + uses interface CC2520Register as ADCTEST1; + uses interface CC2520Register as ADCTEST2; + + uses interface CC2520Register as FRMCTRL0; + uses interface CC2520Register as EXTCLOCK; + + uses interface CC2520Register as GPIOCTRL0; + uses interface CC2520Register as GPIOCTRL1; + uses interface CC2520Register as GPIOCTRL2; + uses interface CC2520Register as GPIOCTRL3; + uses interface CC2520Register as GPIOCTRL4; + uses interface CC2520Register as GPIOCTRL5; + uses interface CC2520Register as GPIOPOLARITY; + + uses interface CC2520Register as FRMFILT0; + uses interface CC2520Register as FRMFILT1; + uses interface CC2520Register as FIFOPCTRL; + + + //*************************************************/ + uses interface CC2520Strobe as SRXON; + uses interface CC2520Strobe as SRFOFF; + uses interface CC2520Strobe as SXOSCOFF; + uses interface CC2520Strobe as SXOSCON; + uses interface CC2520Strobe as SNOP; + + uses interface Resource as SpiResource; + uses interface Resource as RssiResource; + uses interface Resource as SyncResource; + + uses interface Leds; + uses interface LocalIeeeEui64; +} + +implementation { + + typedef enum { + S_VREG_STOPPED, + S_VREG_STARTING, + S_VREG_STARTED, + S_XOSC_STARTING, + S_XOSC_STARTED, + } cc2520_control_state_t; + + uint8_t m_channel; + + uint8_t m_tx_power; + + uint16_t m_pan; + + // temporary LIjo.. + uint16_t *data1; + + uint16_t m_short_addr; + + ieee_eui64_t m_ext_addr; + + bool m_sync_busy; + + /** TRUE if acknowledgments are enabled */ + bool autoAckEnabled; + + /** TRUE if acknowledgments are generated in hardware only */ + bool hwAutoAckDefault; + + /** TRUE if software or hardware address recognition is enabled */ + bool addressRecognition; + + /** TRUE if address recognition should also be performed in hardware */ + bool hwAddressRecognition; + + norace cc2520_control_state_t m_state = S_VREG_STOPPED; + + /***************** Prototypes ****************/ + + void writeFreqctrl(); + void Write_Default_Registers_Value(); + void writeId(); + + task void sync(); + task void syncDone(); + + /***************** Init Commands ****************/ + command error_t Init.init() { + int i, t; + call CSN.makeOutput(); + call RSTN.makeOutput(); + call VREN.makeOutput(); + + m_short_addr = call ActiveMessageAddress.amAddress(); + m_pan = call ActiveMessageAddress.amGroup(); + m_tx_power = CC2520_DEF_RFPOWER; + m_channel = CC2520_DEF_CHANNEL; + m_ext_addr = call LocalIeeeEui64.getId(); + for (i = 0; i < 4; i++) { + t = m_ext_addr.data[i]; + m_ext_addr.data[i] = m_ext_addr.data[7-i]; + m_ext_addr.data[7-i] = t; + } + + +#if defined(CC2520_NO_ADDRESS_RECOGNITION) + addressRecognition = FALSE; +#else + addressRecognition = TRUE; +#endif + +#if defined(CC2520_HW_ADDRESS_RECOGNITION) + hwAddressRecognition = TRUE; +#else + hwAddressRecognition = FALSE; +#endif + + +#if defined(CC2520_NO_ACKNOWLEDGEMENTS) + autoAckEnabled = FALSE; +#else + autoAckEnabled = TRUE; +#endif + +#if defined(CC2520_HW_ACKNOWLEDGEMENTS) + hwAutoAckDefault = TRUE; + hwAddressRecognition = 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 CC2520Power.startVReg() { + uint8_t i; + atomic { + if ( m_state != S_VREG_STOPPED ) { + return FAIL; + } + m_state = S_VREG_STARTING; + } + + /* + // CSN is active low + call CSN.set(); + + // start up voltage regulator + call VREN.clr(); + call VREN.set(); + // do a reset + call RSTN.clr(); + // hold line low for Tdres + call BusyWait.wait( 200 ); // typical .1ms VR startup time + + call RSTN.set(); + // wait another .2ms for xosc to stabilize + call BusyWait.wait( 200 ); + + + */ + // Newly Added on 15-11-10 Lijo ************************/ + + if(m_state == S_VREG_STARTING) + { + //printf("Vreg starting .."); + //printfflush(); + } + call RSTN.clr(); + call CSN.clr(); + call VREN.clr(); + for(i=0;i<0xFF;i++); + //call CSN.set(); + call VREN.set(); + + call RSTN.clr(); + + + //******************************************************** + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + call StartupTimer.start( CC2520_TIME_VREN ); + call RSTN.set(); + + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + call CSN.set(); + return SUCCESS; + } + + async command error_t CC2520Power.stopVReg() { + m_state = S_VREG_STOPPED; + + + call RSTN.clr(); + call VREN.clr(); + call RSTN.set(); + return SUCCESS; + } + + async command error_t CC2520Power.startOscillator() { + uint8_t i; + atomic { + if ( m_state != S_VREG_STARTED ) { + return FAIL; + } + + m_state = S_XOSC_STARTING; + + // printf("\n start the oscillator"); + // printfflush(); + + // Waiting for the Crystal Oscillator to Stabilize. + + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + + + + call InterruptCCA.enableRisingEdge(); + + call CSN.clr(); + call SXOSCON.strobe(); + call CSN.set(); + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + + + + Write_Default_Registers_Value(); + + writeFreqctrl(); + + + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + + call CSN.clr(); + call SRXON.strobe(); + call CSN.set(); + + + + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + + + } + + + return SUCCESS; + } + + + async command error_t CC2520Power.stopOscillator() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + m_state = S_VREG_STARTED; + call CSN.clr(); + call SXOSCOFF.strobe(); + call CSN.set(); + + } + return SUCCESS; + } + + async command error_t CC2520Power.rxOn() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + call CSN.clr(); + call SRXON.strobe(); + call CSN.set(); + + } + return SUCCESS; + } + + async command error_t CC2520Power.rfOff() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + call CSN.clr(); + call SRFOFF.strobe(); + call CSN.set(); + + } + return SUCCESS; + } + + + /***************** CC2420Config Commands ****************/ + command uint8_t CC2520Config.getChannel() { + atomic return m_channel; + } + + command void CC2520Config.setChannel( uint8_t channel ) { + + atomic m_channel = channel; + } + + async command uint16_t CC2520Config.getShortAddr() { + atomic return m_short_addr; + } + + command void CC2520Config.setShortAddr( uint16_t addr ) { + atomic m_short_addr = addr; + } + + command ieee_eui64_t CC2520Config.getExtAddr() { + return m_ext_addr; + } + + + async command uint16_t CC2520Config.getPanAddr() { + atomic return m_pan; + } + + command void CC2520Config.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 CC2520Config.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; + } + + /** + * @param enableAddressRecognition TRUE to turn address recognition on + * @param useHwAddressRecognition TRUE to perform address recognition first + * in hardware. This doesn't affect software address recognition. The + * driver must sync with the chip after changing this value. + */ + command void CC2520Config.setAddressRecognition(bool enableAddressRecognition, bool useHwAddressRecognition) { + atomic { + addressRecognition = enableAddressRecognition; + hwAddressRecognition = useHwAddressRecognition; + } + } + + /** + * @return TRUE if address recognition is enabled + */ + async command bool CC2520Config.isAddressRecognitionEnabled() { + atomic return addressRecognition; + } + + /** + * @return TRUE if address recognition is performed first in hardware. + */ + async command bool CC2520Config.isHwAddressRecognitionDefault() { + atomic return hwAddressRecognition; + } + + + /** + * 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 CC2520Config.setAutoAck(bool enableAutoAck, bool hwAutoAck) { + atomic autoAckEnabled = enableAutoAck; + atomic hwAutoAckDefault = hwAutoAck; + } + + /** + * @return TRUE if hardware auto acks are the default, FALSE if software + * acks are the default + */ + async command bool CC2520Config.isHwAutoAckDefault() { + atomic return hwAutoAckDefault; + } + + /** + * @return TRUE if auto acks are enabled + */ + async command bool CC2520Config.isAutoAckEnabled() { + atomic return autoAckEnabled; + } + + /***************** ReadRssi Commands ****************/ + command error_t ReadRssi.read() { + return call RssiResource.request(); + } + + /***************** Spi Resources Events ****************/ + event void SyncResource.granted() { + + call CSN.clr(); + call SRFOFF.strobe(); + call CSN.set(); + + + writeFreqctrl(); + Write_Default_Registers_Value(); + writeId(); + + 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 CC2520Power.startVRegDone(); + } + } + + /***************** InterruptCCA Events ****************/ + async event void InterruptCCA.fired() { + m_state = S_XOSC_STARTED; + call InterruptCCA.disable(); + + writeId(); + #ifdef PRINTF + printf("cca interrupt fired");printfflush(); + #endif + signal CC2520Power.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 CC2520Config.sync(); + } + + task void syncDone() { + atomic m_sync_busy = FALSE; + signal CC2520Config.syncDone( SUCCESS ); + } + + + /***************** Functions ****************/ + /** + * Write teh FSCTRL register + */ + void writeFreqctrl() { + uint8_t channel; + + atomic { + channel = m_channel; + } + + call CSN.set(); + call CSN.clr(); + call FREQCTRL.write(MIN_CHANNEL + ((channel - MIN_CHANNEL)*CHANNEL_SPACING)); + call CSN.set(); + } + + /** + * Write the Default_Register_Values register + * Disabling hardware address recognition improves acknowledgment success + * rate and low power communications reliability by causing the local node + * to do work while the real destination node of the packet is acknowledging. + */ +void Write_Default_Registers_Value() { + uint8_t ret_value; + uint16_t data; + call CSN.set(); + call CSN.clr(); + + switch ((CC2520_DEF_RFPOWER)) + { + case 0x1F : + call TXPOWER.write(0xF7); // 5dbm Powerlevel 31 + + break; + case 0x1B : + call TXPOWER.write(0xF2); // 3dbm Powerlevel 27 + break; + case 0x17 : + call TXPOWER.write(0xAB); // 2dbm Powerlevel 23 + + break; + case 0x13 : + call TXPOWER.write(0x13); // 1 dbm Powerlevel 19 + + break; + case 0x0F : + call TXPOWER.write(0x32); // 0 dbm Powerlevel 15 + + break; + case 0x0B : + call TXPOWER.write(0x81); // -2 dbm Powerlevel 11 + + break; + case 0x07 : + call TXPOWER.write(0x88); // -4 dbm Powerlevel 07 + + break; + case 0x03 : + call TXPOWER.write(0x2C); // -7 dbm Powerlevel 03 + + + break; + case 0x01 : + call TXPOWER.write(0x03); // -18 dbm Powerlevel 01 + + + break; + default : + call TXPOWER.write(0xF7); // Powerlevel default + + break; + + + } + + + call CSN.set(); + + + call CSN.clr(); + call TXPOWER.write(0xF7); + call CSN.set(); + + + call CSN.clr(); + call CCACTRL0.write(0x1A); // 0xF8 + call CSN.set(); + + call CSN.clr(); + call MDMCTRL0.write(0x85); + call CSN.set(); + + call CSN.clr(); + call MDMCTRL1.write(0x14); // 0x14 + call CSN.set(); + + call CSN.clr(); + call RXCTRL.write(0x3F); + call CSN.set(); + + call CSN.clr(); + call FSCTRL.write(0x5A); + call CSN.set(); + + + call CSN.clr(); + call FSCAL1.write(0x2B); // 0x03 + call CSN.set(); + + + call CSN.clr(); + call AGCCTRL1.write(0x11); + call CSN.set(); + + call CSN.clr(); + call ADCTEST0.write(0x10); + call CSN.set(); + + call CSN.clr(); + call ADCTEST1.write(0x0E); + call CSN.set(); + + call CSN.clr(); + call ADCTEST2.write(0x03); + call CSN.set(); + + call CSN.clr(); + call FRMCTRL0.write(0x40); // changed from 0x40 + call CSN.set(); + + call CSN.clr(); + call EXTCLOCK.write(0x00); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL1.write(CC2520_GPIO_FIFO); + call CSN.set(); + + + call CSN.clr(); + call GPIOCTRL4.write(CC2520_GPIO_FIFOP); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL2.write(CC2520_GPIO_CCA);// CC2520_GPIO_SAMPLED_CCA + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL0.write(CC2520_GPIO_SFD); + call CSN.set(); + + call CSN.clr(); + call GPIOPOLARITY.write(0x0F); + call CSN.set(); + + + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + call CSN.clr(); + call MDMCTRL1.read(data1); + call CSN.set(); + + call CSN.clr(); + call FRMFILT0.write(0xc0); // changed from 0xc0 + call CSN.set(); + + + call CSN.clr(); + call FRMCTRL1.write(0x03); // 0x48 0x60 + call CSN.set(); + + call CSN.clr(); + call FIFOPCTRL.write(0x7F); // 0x48 0x60 + call CSN.set(); + + call CSN.clr(); + ret_value =0x00; + ret_value = call SNOP.strobe(); + call CSN.set(); + + } + + + + + + + + + /** + * Write the PANID register + */ + void writeId() { + nxle_uint16_t id[ 2 ]; + + atomic { + id[ 0 ] = m_pan; + id[ 1 ] = m_short_addr; + } + call CSN.set(); + call CSN.clr(); + + call PANID.write(0, (uint8_t*)&id, sizeof(id)); + call CSN.set(); + } + + + + /***************** Defaults ****************/ + default event void CC2520Config.syncDone( error_t error ) { + } + + default event void ReadRssi.readDone(error_t error, uint16_t data) { + } + +} diff --git a/cc2520/control/CC2520ControlP_mam.nc b/cc2520/control/CC2520ControlP_mam.nc new file mode 100644 index 0000000000..e8e02c9645 --- /dev/null +++ b/cc2520/control/CC2520ControlP_mam.nc @@ -0,0 +1,860 @@ +/* + * 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 + * @author David Moss + * @author Urs Hunkeler (ReadRssi implementation) + * @version $Revision: 1.7 $ $Date: 2008/06/24 04:07:28 $ + */ + +#include "Timer.h" +#include "CC2520.h" + +// IEEE 802.15.4 defined constants (2.4 GHz logical channels) +#define MIN_CHANNEL 11 // 2405 MHz +#define MAX_CHANNEL 26 // 2480 MHz +#define CHANNEL_SPACING 5 // MHz + +module CC2520ControlP @safe() { + + provides interface Init; + provides interface Resource; + provides interface CC2520Config; + provides interface CC2520Power; + provides interface Read as ReadRssi; + + uses interface Alarm 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 CC2520Ram as PANID; + + uses interface CC2520Register as FSCTRL; + //uses interface CC2420Register as IOCFG0; + //uses interface CC2420Register as IOCFG1; + + uses interface CC2520Register as MDMCTRL0; + uses interface CC2520Register as MDMCTRL1; + uses interface CC2520Register as RXCTRL; + uses interface CC2520Register as RSSI; + + // Newly Added on 15-11-10 Lijo ******************/ + + uses interface CC2520Register as AGCCTRL1; + uses interface CC2520Register as TXPOWER; + uses interface CC2520Register as CCACTRL0; + uses interface CC2520Register as FSCAL1; + uses interface CC2520Register as FRMCTRL1; + + uses interface CC2520Register as FREQCTRL; + + uses interface CC2520Register as ADCTEST0; + uses interface CC2520Register as ADCTEST1; + uses interface CC2520Register as ADCTEST2; + + uses interface CC2520Register as FRMCTRL0; + uses interface CC2520Register as EXTCLOCK; + + uses interface CC2520Register as GPIOCTRL0; + uses interface CC2520Register as GPIOCTRL1; + uses interface CC2520Register as GPIOCTRL2; + uses interface CC2520Register as GPIOCTRL3; + uses interface CC2520Register as GPIOCTRL4; + uses interface CC2520Register as GPIOCTRL5; + uses interface CC2520Register as GPIOPOLARITY; + + uses interface CC2520Register as FRMFILT0; + uses interface CC2520Register as FRMFILT1; + uses interface CC2520Register as FIFOPCTRL; + + + //*************************************************/ + uses interface CC2520Strobe as SRXON; + uses interface CC2520Strobe as SRFOFF; + uses interface CC2520Strobe as SXOSCOFF; + uses interface CC2520Strobe as SXOSCON; + uses interface CC2520Strobe as SNOP; + + uses interface Resource as SpiResource; + uses interface Resource as RssiResource; + uses interface Resource as SyncResource; + + uses interface Leds; + uses interface LocalIeeeEui64; +} + +implementation { + + typedef enum { + S_VREG_STOPPED, + S_VREG_STARTING, + S_VREG_STARTED, + S_XOSC_STARTING, + S_XOSC_STARTED, + } cc2520_control_state_t; + + uint8_t m_channel; + + uint8_t m_tx_power; + + uint16_t m_pan; + + // temporary LIjo.. + uint16_t *data1; + + uint16_t m_short_addr; + + ieee_eui64_t m_ext_addr; + + bool m_sync_busy; + + /** TRUE if acknowledgments are enabled */ + bool autoAckEnabled; + + /** TRUE if acknowledgments are generated in hardware only */ + bool hwAutoAckDefault; + + /** TRUE if software or hardware address recognition is enabled */ + bool addressRecognition; + + /** TRUE if address recognition should also be performed in hardware */ + bool hwAddressRecognition; + + norace cc2520_control_state_t m_state = S_VREG_STOPPED; + + /***************** Prototypes ****************/ + + void writeFreqctrl(); + void Write_Default_Registers_Value(); + void writeId(); + + task void sync(); + task void syncDone(); + + /***************** Init Commands ****************/ + command error_t Init.init() { + int i, t; + call CSN.makeOutput(); + call RSTN.makeOutput(); + call VREN.makeOutput(); + + m_short_addr = call ActiveMessageAddress.amAddress(); + m_pan = call ActiveMessageAddress.amGroup(); + m_tx_power = CC2520_DEF_RFPOWER; + m_channel = CC2520_DEF_CHANNEL; + m_ext_addr = call LocalIeeeEui64.getId(); + for (i = 0; i < 4; i++) { + t = m_ext_addr.data[i]; + m_ext_addr.data[i] = m_ext_addr.data[7-i]; + m_ext_addr.data[7-i] = t; + } + + +#if defined(CC2520_NO_ADDRESS_RECOGNITION) + addressRecognition = FALSE; +#else + addressRecognition = TRUE; +#endif + +#if defined(CC2520_HW_ADDRESS_RECOGNITION) + hwAddressRecognition = TRUE; +#else + hwAddressRecognition = FALSE; +#endif + + +#if defined(CC2520_NO_ACKNOWLEDGEMENTS) + autoAckEnabled = FALSE; +#else + autoAckEnabled = TRUE; +#endif + +#if defined(CC2520_HW_ACKNOWLEDGEMENTS) + hwAutoAckDefault = TRUE; + hwAddressRecognition = 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 CC2520Power.startVReg() { + uint8_t i; + atomic { + if ( m_state != S_VREG_STOPPED ) { + return FAIL; + } + m_state = S_VREG_STARTING; + } + + /* + // CSN is active low + call CSN.set(); + + // start up voltage regulator + call VREN.clr(); + call VREN.set(); + // do a reset + call RSTN.clr(); + // hold line low for Tdres + call BusyWait.wait( 200 ); // typical .1ms VR startup time + + call RSTN.set(); + // wait another .2ms for xosc to stabilize + call BusyWait.wait( 200 ); + + + */ + // Newly Added on 15-11-10 Lijo ************************/ + + if(m_state == S_VREG_STARTING) + { + //printf("Vreg starting .."); + //printfflush(); + } + call RSTN.clr(); + call CSN.clr(); + call VREN.clr(); + for(i=0;i<0xFF;i++); + //call CSN.set(); + call VREN.set(); + + call RSTN.clr(); + + + //******************************************************** + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + call StartupTimer.start( CC2520_TIME_VREN ); + call RSTN.set(); + + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + call CSN.set(); + return SUCCESS; + } + + async command error_t CC2520Power.stopVReg() { + m_state = S_VREG_STOPPED; + + + call RSTN.clr(); + call VREN.clr(); + call RSTN.set(); + return SUCCESS; + } + + async command error_t CC2520Power.startOscillator() { + uint8_t i; + atomic { + if ( m_state != S_VREG_STARTED ) { + return FAIL; + } + + m_state = S_XOSC_STARTING; + + + + + // Waiting for the Crystal Oscillator to Stabilize. + + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + + + + call InterruptCCA.enableRisingEdge(); + + call CSN.clr(); + call SXOSCON.strobe(); + call CSN.set(); + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + + + + Write_Default_Registers_Value(); + + writeFreqctrl(); + + + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + + call CSN.clr(); + call SRXON.strobe(); + call CSN.set(); + + + + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + + + } + + + return SUCCESS; + } + + + async command error_t CC2520Power.stopOscillator() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + m_state = S_VREG_STARTED; + call CSN.clr(); + call SXOSCOFF.strobe(); + call CSN.set(); + + } + return SUCCESS; + } + + async command error_t CC2520Power.rxOn() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + call CSN.clr(); + call SRXON.strobe(); + call CSN.set(); + + } + return SUCCESS; + } + + async command error_t CC2520Power.rfOff() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + call CSN.clr(); + call SRFOFF.strobe(); + call CSN.set(); + + } + return SUCCESS; + } + + + /***************** CC2420Config Commands ****************/ + command uint8_t CC2520Config.getChannel() { + atomic return m_channel; + } + + command void CC2520Config.setChannel( uint8_t channel ) { + + atomic m_channel = channel; + } + + async command uint16_t CC2520Config.getShortAddr() { + atomic return m_short_addr; + } + + command void CC2520Config.setShortAddr( uint16_t addr ) { + atomic m_short_addr = addr; + } + + command ieee_eui64_t CC2520Config.getExtAddr() { + return m_ext_addr; + } + + + async command uint16_t CC2520Config.getPanAddr() { + atomic return m_pan; + } + + command void CC2520Config.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 CC2520Config.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; + } + + /** + * @param enableAddressRecognition TRUE to turn address recognition on + * @param useHwAddressRecognition TRUE to perform address recognition first + * in hardware. This doesn't affect software address recognition. The + * driver must sync with the chip after changing this value. + */ + command void CC2520Config.setAddressRecognition(bool enableAddressRecognition, bool useHwAddressRecognition) { + atomic { + addressRecognition = enableAddressRecognition; + hwAddressRecognition = useHwAddressRecognition; + } + } + + /** + * @return TRUE if address recognition is enabled + */ + async command bool CC2520Config.isAddressRecognitionEnabled() { + atomic return addressRecognition; + } + + /** + * @return TRUE if address recognition is performed first in hardware. + */ + async command bool CC2520Config.isHwAddressRecognitionDefault() { + atomic return hwAddressRecognition; + } + + + /** + * 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 CC2520Config.setAutoAck(bool enableAutoAck, bool hwAutoAck) { + atomic autoAckEnabled = enableAutoAck; + atomic hwAutoAckDefault = hwAutoAck; + } + + /** + * @return TRUE if hardware auto acks are the default, FALSE if software + * acks are the default + */ + async command bool CC2520Config.isHwAutoAckDefault() { + atomic return hwAutoAckDefault; + } + + /** + * @return TRUE if auto acks are enabled + */ + async command bool CC2520Config.isAutoAckEnabled() { + atomic return autoAckEnabled; + } + + /***************** ReadRssi Commands ****************/ + command error_t ReadRssi.read() { + return call RssiResource.request(); + } + + /***************** Spi Resources Events ****************/ + event void SyncResource.granted() { + + call CSN.clr(); + call SRFOFF.strobe(); + call CSN.set(); + + + writeFreqctrl(); + Write_Default_Registers_Value(); + writeId(); + + 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 CC2520Power.startVRegDone(); + } + } + + /***************** InterruptCCA Events ****************/ + async event void InterruptCCA.fired() { + m_state = S_XOSC_STARTED; + call InterruptCCA.disable(); + + writeId(); + + signal CC2520Power.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 CC2520Config.sync(); + } + + task void syncDone() { + atomic m_sync_busy = FALSE; + signal CC2520Config.syncDone( SUCCESS ); + } + + + /***************** Functions ****************/ + /** + * Write teh FSCTRL register + */ + void writeFreqctrl() { + uint8_t channel; + + atomic { + channel = m_channel; + } + + call CSN.set(); + call CSN.clr(); + call FREQCTRL.write(MIN_CHANNEL + ((channel - MIN_CHANNEL)*CHANNEL_SPACING)); + call CSN.set(); + } + + /** + * Write the Default_Register_Values register + * Disabling hardware address recognition improves acknowledgment success + * rate and low power communications reliability by causing the local node + * to do work while the real destination node of the packet is acknowledging. + */ +void Write_Default_Registers_Value() { + uint8_t ret_value; + uint16_t data; + call CSN.set(); + call CSN.clr(); + + switch ((CC2520_DEF_RFPOWER)) + { + case 0x1F : + call TXPOWER.write(0xF7); // 5dbm Powerlevel 31 + + break; + case 0x1B : + call TXPOWER.write(0xF2); // 3dbm Powerlevel 27 + break; + case 0x17 : + call TXPOWER.write(0xAB); // 2dbm Powerlevel 23 + + break; + case 0x13 : + call TXPOWER.write(0x13); // 1 dbm Powerlevel 19 + + break; + case 0x0F : + call TXPOWER.write(0x32); // 0 dbm Powerlevel 15 + + break; + case 0x0B : + call TXPOWER.write(0x81); // -2 dbm Powerlevel 11 + + break; + case 0x07 : + call TXPOWER.write(0x88); // -4 dbm Powerlevel 07 + + break; + case 0x03 : + call TXPOWER.write(0x2C); // -7 dbm Powerlevel 03 + + + break; + case 0x01 : + call TXPOWER.write(0x03); // -18 dbm Powerlevel 01 + + + break; + default : + call TXPOWER.write(0xF7); // Powerlevel default + + break; + + + } + + + call CSN.set(); + + + call CSN.clr(); + call CCACTRL0.write(0x1A); // 0xF8 + call CSN.set(); + + call CSN.clr(); + call MDMCTRL0.write(0x85); + call CSN.set(); + + call CSN.clr(); + call MDMCTRL1.write(0x14); // 0x14 + call CSN.set(); + + call CSN.clr(); + call RXCTRL.write(0x3F); + call CSN.set(); + + call CSN.clr(); + call FSCTRL.write(0x5A); + call CSN.set(); + + + call CSN.clr(); + call FSCAL1.write(0x2B); // 0x03 + call CSN.set(); + + + call CSN.clr(); + call AGCCTRL1.write(0x11); + call CSN.set(); + + call CSN.clr(); + call ADCTEST0.write(0x10); + call CSN.set(); + + call CSN.clr(); + call ADCTEST1.write(0x0E); + call CSN.set(); + + call CSN.clr(); + call ADCTEST2.write(0x03); + call CSN.set(); + + call CSN.clr(); + call FRMCTRL0.write(0x40); // 0x48 0x60 + call CSN.set(); + + call CSN.clr(); + call EXTCLOCK.write(0x00); + call CSN.set(); + + +/* Mam wrote this thing check what is there here*/ + call CSN.clr(); + //call GPIOCTRL0.write(CC2520_GPIO_FIFO); + call GPIOCTRL1.write(CC2520_GPIO_FIFO); + call CSN.set(); + + call CSN.clr(); + //call GPIOCTRL1.write(CC2520_GPIO_CCA);// CC2520_GPIO_SAMPLED_CCA + call GPIOCTRL3.write(CC2520_GPIO_CCA);// CC2520_GPIO_SAMPLED_CCA + call CSN.set(); + + call CSN.clr(); + //call GPIOCTRL2.write(CC2520_GPIO_RSSI_VALID); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL5.write(CC2520_GPIO_SFD); + //call GPIOCTRL4.write(CC2520_GPIO_SFD); + call CSN.set(); + + call CSN.clr(); + //call GPIOCTRL5.write(CC2520_GPIO_FIFOP); + call GPIOCTRL2.write(CC2520_GPIO_FIFOP); + call CSN.set(); + + +/* call CSN.clr(); + call GPIOCTRL0.write(CC2520_GPIO_FIFO); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL1.write(CC2520_GPIO_CCA);// CC2520_GPIO_SAMPLED_CCA + //call GPIOCTRL1.write(CC2520_GPIO_SAMPLED_CCA); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL2.write(CC2520_GPIO_RSSI_VALID); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL3.write(CC2520_GPIO_SFD); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL4.write(CC2520_EXC_TX_FRM_DONE); + call CSN.set(); + + call CSN.clr(); + call GPIOCTRL5.write(CC2520_GPIO_FIFOP); + call CSN.set(); + */ + + + call CSN.clr(); + call GPIOPOLARITY.write(0x0F); + call CSN.set(); + + call CSN.clr(); + call SNOP.strobe(); + call CSN.set(); + + call CSN.clr(); + call MDMCTRL1.read(data1); + call CSN.set(); + + call CSN.clr(); + call FRMFILT0.write(0xC0); // 0x48 0x60 + call CSN.set(); + + + call CSN.clr(); + call FRMCTRL1.write(0x03); // 0x48 0x60 + call CSN.set(); + + call CSN.clr(); + call FIFOPCTRL.write(0x7F); // 0x48 0x60 + call CSN.set(); + + call CSN.clr(); + ret_value =0x00; + ret_value = call SNOP.strobe(); + call CSN.set(); + + } + + + + + + + + + /** + * Write the PANID register + */ + void writeId() { + nxle_uint16_t id[ 2 ]; + + atomic { + id[ 0 ] = m_pan; + id[ 1 ] = m_short_addr; + } + call CSN.set(); + call CSN.clr(); + + call PANID.write(0, (uint8_t*)&id, sizeof(id)); + call CSN.set(); + } + + + + /***************** Defaults ****************/ + default event void CC2520Config.syncDone( error_t error ) { + } + + default event void ReadRssi.readDone(error_t error, uint16_t data) { + } + +} diff --git a/cc2520/control/CC2520ControlP_orig.nc b/cc2520/control/CC2520ControlP_orig.nc new file mode 100644 index 0000000000..6bf39f42f2 --- /dev/null +++ b/cc2520/control/CC2520ControlP_orig.nc @@ -0,0 +1,693 @@ +/* + * 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 + * @author David Moss + * @author Urs Hunkeler (ReadRssi implementation) + * @version $Revision: 1.7 $ $Date: 2008/06/24 04:07:28 $ + */ + +#include "Timer.h" +#include "CC2520.h" +#include "printf.h" +// IEEE 802.15.4 defined constants (2.4 GHz logical channels) +#define MIN_CHANNEL 11 // 2405 MHz +#define MAX_CHANNEL 26 // 2480 MHz +#define CHANNEL_SPACING 5 // MHz + +module CC2520ControlP @safe() { + + provides interface Init; + provides interface Resource; + provides interface CC2520Config; + provides interface CC2520Power; + provides interface Read as ReadRssi; + + uses interface Alarm 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 CC2520Ram as PANID; + + uses interface CC2520Register as FSCTRL; + //uses interface CC2420Register as IOCFG0; + //uses interface CC2420Register as IOCFG1; + + uses interface CC2520Register as MDMCTRL0; + uses interface CC2520Register as MDMCTRL1; + uses interface CC2520Register as RXCTRL; + uses interface CC2520Register as RSSI; + + // Newly Added on 15-11-10 Lijo ******************/ + + uses interface CC2520Register as AGCCTRL1; + uses interface CC2520Register as TXPOWER; + uses interface CC2520Register as CCACTRL0; + uses interface CC2520Register as FSCAL1; + + uses interface CC2520Register as FREQCTRL; + + uses interface CC2520Register as ADCTEST0; + uses interface CC2520Register as ADCTEST1; + uses interface CC2520Register as ADCTEST2; + + uses interface CC2520Register as FRMCTRL0; + uses interface CC2520Register as EXTCLOCK; + + uses interface CC2520Register as GPIOCTRL0; + uses interface CC2520Register as GPIOCTRL1; + uses interface CC2520Register as GPIOCTRL2; + uses interface CC2520Register as GPIOCTRL3; + uses interface CC2520Register as GPIOCTRL4; + uses interface CC2520Register as GPIOCTRL5; + + + + + + //*************************************************/ + uses interface CC2520Strobe as SRXON; + uses interface CC2520Strobe as SRFOFF; + uses interface CC2520Strobe as SXOSCOFF; + uses interface CC2520Strobe as SXOSCON; + uses interface CC2520Strobe as SNOP; + + 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, + } cc2520_control_state_t; + + uint8_t m_channel; + + uint8_t m_tx_power; + + uint16_t m_pan; + + // temporary LIjo.. + uint16_t *data1; + + uint16_t m_short_addr; + + bool m_sync_busy; + + /** TRUE if acknowledgments are enabled */ + bool autoAckEnabled; + + /** TRUE if acknowledgments are generated in hardware only */ + bool hwAutoAckDefault; + + /** TRUE if software or hardware address recognition is enabled */ + bool addressRecognition; + + /** TRUE if address recognition should also be performed in hardware */ + bool hwAddressRecognition; + + norace cc2520_control_state_t m_state = S_VREG_STOPPED; + + /***************** Prototypes ****************/ + + void writeFreqctrl(); + void writeDefault_Register_Values(); + 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 = CC2520_DEF_RFPOWER; + m_channel = CC2520_DEF_CHANNEL; + + +#if defined(CC2520_NO_ADDRESS_RECOGNITION) + addressRecognition = FALSE; +#else + addressRecognition = TRUE; +#endif + +#if defined(CC2520_HW_ADDRESS_RECOGNITION) + hwAddressRecognition = TRUE; +#else + hwAddressRecognition = FALSE; +#endif + + +#if defined(CC2520_NO_ACKNOWLEDGEMENTS) + autoAckEnabled = FALSE; +#else + autoAckEnabled = TRUE; +#endif + +#if defined(CC2520_HW_ACKNOWLEDGEMENTS) + hwAutoAckDefault = TRUE; + hwAddressRecognition = 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 CC2520Power.startVReg() { + uint8_t i; + atomic { + if ( m_state != S_VREG_STOPPED ) { + return FAIL; + } + m_state = S_VREG_STARTING; + } + + /* + // CSN is active low + call CSN.set(); + + // start up voltage regulator + call VREN.clr(); + call VREN.set(); + // do a reset + call RSTN.clr(); + // hold line low for Tdres + call BusyWait.wait( 200 ); // typical .1ms VR startup time + + call RSTN.set(); + // wait another .2ms for xosc to stabilize + call BusyWait.wait( 200 ); + + + */ + // Newly Added on 15-11-10 Lijo ************************/ + + if(m_state == S_VREG_STARTING) + { + printf("Vreg starting .."); + //printfflush(); + } + call RSTN.clr(); + call CSN.clr(); + call VREN.clr(); + + call CSN.set(); + call VREN.set(); + + + call RSTN.clr(); + + for(i=0;i<0xFF;i++); + //******************************************************** + call StartupTimer.start( 1100 ); + call StartupTimer.start( CC2520_TIME_VREN ); + call RSTN.set(); + + call StartupTimer.start( 1100 ); + call CSN.set(); + + + for(i=0;i<0xFF;i++); + + for(i=0;i<0xFF;i++); + return SUCCESS; + } + + async command error_t CC2520Power.stopVReg() { + m_state = S_VREG_STOPPED; + call RSTN.clr(); + call VREN.clr(); + call RSTN.set(); + return SUCCESS; + } + + async command error_t CC2520Power.startOscillator() { + atomic { + if ( m_state != S_VREG_STARTED ) { + return FAIL; + } + + m_state = S_XOSC_STARTING; + + // Newly Added on 15-11-10 Lijo ************************/ + + + // Waiting for the Crystal Oscillator to Stabilize. + call StartupTimer.start( 1100 ); + + /*call IOCFG1.write( CC2420_SFDMUX_XOSC16M_STABLE << + CC2420_IOCFG1_CCAMUX );*/ + + call InterruptCCA.enableRisingEdge(); + + + printf("\nOSC_Status: %x\n", (call SXOSCON.strobe())); + printf("SNOP_Status: %x\n", (call SNOP.strobe())); + //printf("SRXON_Status: %x\n", (call SRXON.strobe())); + + /*call IOCFG0.write( ( 1 << CC2420_IOCFG0_FIFOP_POLARITY ) | + ( 127 << CC2420_IOCFG0_FIFOP_THR ) );*/ + + writeDefault_Register_Values(); + writeFreqctrl(); + } + + /* printf("SNOP_Status: %x\n", (call SNOP.strobe())); + printf("Register Reading .."); + printf("\n"); + call MDMCTRL0.read(data1); + printf("\n");*/ + + /*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 CC2520Power.stopOscillator() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + m_state = S_VREG_STARTED; + call SXOSCOFF.strobe(); + } + return SUCCESS; + } + + async command error_t CC2520Power.rxOn() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + + call SRXON.strobe(); + } + return SUCCESS; + } + + async command error_t CC2520Power.rfOff() { + atomic { + if ( m_state != S_XOSC_STARTED ) { + return FAIL; + } + call SRFOFF.strobe(); + } + return SUCCESS; + } + + + /***************** CC2420Config Commands ****************/ + command uint8_t CC2520Config.getChannel() { + atomic return m_channel; + } + + command void CC2520Config.setChannel( uint8_t channel ) { + + atomic m_channel = channel; + } + + async command uint16_t CC2520Config.getShortAddr() { + atomic return m_short_addr; + } + + command void CC2520Config.setShortAddr( uint16_t addr ) { + atomic m_short_addr = addr; + } + + async command uint16_t CC2520Config.getPanAddr() { + atomic return m_pan; + } + + command void CC2520Config.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 CC2520Config.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; + } + + /** + * @param enableAddressRecognition TRUE to turn address recognition on + * @param useHwAddressRecognition TRUE to perform address recognition first + * in hardware. This doesn't affect software address recognition. The + * driver must sync with the chip after changing this value. + */ + command void CC2520Config.setAddressRecognition(bool enableAddressRecognition, bool useHwAddressRecognition) { + atomic { + addressRecognition = enableAddressRecognition; + hwAddressRecognition = useHwAddressRecognition; + } + } + + /** + * @return TRUE if address recognition is enabled + */ + async command bool CC2520Config.isAddressRecognitionEnabled() { + atomic return addressRecognition; + } + + /** + * @return TRUE if address recognition is performed first in hardware. + */ + async command bool CC2520Config.isHwAddressRecognitionDefault() { + atomic return hwAddressRecognition; + } + + + /** + * 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 CC2520Config.setAutoAck(bool enableAutoAck, bool hwAutoAck) { + atomic autoAckEnabled = enableAutoAck; + atomic hwAutoAckDefault = hwAutoAck; + } + + /** + * @return TRUE if hardware auto acks are the default, FALSE if software + * acks are the default + */ + async command bool CC2520Config.isHwAutoAckDefault() { + atomic return hwAutoAckDefault; + } + + /** + * @return TRUE if auto acks are enabled + */ + async command bool CC2520Config.isAutoAckEnabled() { + atomic return autoAckEnabled; + } + + /***************** ReadRssi Commands ****************/ + command error_t ReadRssi.read() { + return call RssiResource.request(); + } + + /***************** Spi Resources Events ****************/ + event void SyncResource.granted() { + + call CSN.clr(); + call SRFOFF.strobe(); + writeFreqctrl(); + writeDefault_Register_Values(); + 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 CC2520Power.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 CC2520Power.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 CC2520Config.sync(); + } + + task void syncDone() { + atomic m_sync_busy = FALSE; + signal CC2520Config.syncDone( SUCCESS ); + } + + + /***************** Functions ****************/ + /** + * Write teh FSCTRL register + */ + void writeFreqctrl() { + uint8_t channel; + + atomic { + channel = m_channel; + } + + call FREQCTRL.write(MIN_CHANNEL + ((channel - MIN_CHANNEL)*CHANNEL_SPACING)); + } + + /** + * Write the Default_Register_Values register + * Disabling hardware address recognition improves acknowledgment success + * rate and low power communications reliability by causing the local node + * to do work while the real destination node of the packet is acknowledging. + */ + void writeDefault_Register_Values() { + { + uint8_t i; + + call CSN.clr(); + + //ret_value = call SRFOFF.strobe(); + //printf("SRFOFF_Status: %x\n", ret_value); + for(i=0;i<0xFF;i++); + + printf("CC2520 Status 1: %x \n", call SNOP.strobe()); + + call TXPOWER.write(0x32); + + for(i=0;i<0xFF;i++); + printf("CC2520 Status 2: %x \n", call SNOP.strobe()); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 3: %x \n", call SNOP.strobe()); + + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 4: %x \n", call SNOP.strobe()); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 5: %x \n", call SNOP.strobe()); + + call CSN.set(); + + /* + call CCACTRL0.write(0xF8); + call MDMCTRL0.write(0x85); + call MDMCTRL1.write(0x14); + call RXCTRL.write(0x3F); + call FSCTRL.write(0x5A); + call FSCAL1.write(0x03); + + call AGCCTRL1.write(0x11); + call ADCTEST0.write(0x10); + call ADCTEST1.write(0x0E); + call ADCTEST2.write(0x03); + + call FRMCTRL0.write(0x60); + call EXTCLOCK.write(0x00); + + call GPIOCTRL0.write(CC2520_GPIO_FIFO); + call GPIOCTRL1.write(CC2520_GPIO_CCA); + call GPIOCTRL2.write(CC2520_GPIO_RSSI_VALID); + call GPIOCTRL3.write(CC2520_GPIO_SFD); + call GPIOCTRL4.write(CC2520_EXC_TX_FRM_DONE); + call GPIOCTRL5.write(CC2520_GPIO_FIFOP); + + + + for(i=0;i<0xFF;i++); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 4: %x \n", call SNOP.strobe()); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 5: %x \n", call SNOP.strobe()); + call SNOP.strobe(); + call MDMCTRL0.read(data1); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 6: %x \n", call SNOP.strobe()); + for(i=0;i<0xFF;i++); + printf("CC2520 Status 7: %x \n", call SNOP.strobe()); */ + //call CSN.set(); + + + /* + call MDMCTRL0.write( ( 1 << CC2420_MDMCTRL0_RESERVED_FRAME_MODE ) | + ( (addressRecognition && hwAddressRecognition) << 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 CC2520Config.syncDone( error_t error ) { + } + + default event void ReadRssi.readDone(error_t error, uint16_t data) { + } + +} diff --git a/cc2520/csma/CC2520CsmaC.nc b/cc2520/csma/CC2520CsmaC.nc new file mode 100644 index 0000000000..0cee791407 --- /dev/null +++ b/cc2520/csma/CC2520CsmaC.nc @@ -0,0 +1,85 @@ +/* + * 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 + * @version $Revision: 1.2 $ $Date: 2008/05/14 21:33:07 $ + */ + +#include "CC2520.h" +#include "IEEE802154.h" + +configuration CC2520CsmaC { + + provides interface SplitControl; + provides interface Send; + provides interface Receive; + provides interface RadioBackoff; + +} + +implementation { + + components CC2520CsmaP as CsmaP; + RadioBackoff = CsmaP; + SplitControl = CsmaP; + Send = CsmaP; + + components CC2520ControlC; + CsmaP.Resource -> CC2520ControlC; + CsmaP.CC2520Power -> CC2520ControlC; + + components CC2520TransmitC; + CsmaP.SubControl -> CC2520TransmitC; + CsmaP.CC2520Transmit -> CC2520TransmitC; + CsmaP.SubBackoff -> CC2520TransmitC; + + components CC2520ReceiveC; + Receive = CC2520ReceiveC; + CC2520ReceiveC.Send -> CC2520TransmitC; + CsmaP.SubControl -> CC2520ReceiveC; + + components CC2520PacketC; + CsmaP.CC2520Packet -> CC2520PacketC; + CsmaP.CC2520PacketBody -> CC2520PacketC; + + components RandomC; + CsmaP.Random -> RandomC; + + components new StateC(); + CsmaP.SplitControlState -> StateC; + + components LedsC as Leds; + CsmaP.Leds -> Leds; + +} diff --git a/cc2520/csma/CC2520CsmaP.nc b/cc2520/csma/CC2520CsmaP.nc new file mode 100644 index 0000000000..fdaa442f7c --- /dev/null +++ b/cc2520/csma/CC2520CsmaP.nc @@ -0,0 +1,319 @@ +/* + * 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 + * @version $Revision: 1.7 $ $Date: 2008/06/24 04:07:28 $ + */ +#ifdef PRINTF +#include "printf.h" +#endif + +module CC2520CsmaP @safe() { + + provides interface SplitControl; + provides interface Send; + provides interface RadioBackoff; + + uses interface Resource; + uses interface CC2520Power; + uses interface StdControl as SubControl; + uses interface CC2520Transmit; + uses interface RadioBackoff as SubBackoff; + uses interface Random; + uses interface Leds; + uses interface CC2520Packet; + uses interface CC2520PacketBody; + uses interface State as SplitControlState; + +} + +implementation { + + enum { + S_STOPPED, + S_STARTING, + S_STARTED, + S_STOPPING, + S_TRANSMITTING, + }; + + message_t* ONE_NOK 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 CC2520Power.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 CC2520Transmit.cancel(); + } + + command error_t Send.send( message_t* p_msg, uint8_t len ) { + + cc2520_header_t* header = call CC2520PacketBody.getHeader( p_msg ); + cc2520_metadata_t* metadata = call CC2520PacketBody.getMetadata( p_msg ); + + atomic { + if (!call SplitControlState.isState(S_STARTED)) { + return FAIL; + } + + call SplitControlState.forceState(S_TRANSMITTING); + m_msg = p_msg; + } + + //header->length = len + CC2520_SIZE;//it is getting filled in cc2520ActiveMessage + header->fcf &= ((1 << IEEE154_FCF_ACK_REQ) | + (0x3 << IEEE154_FCF_SRC_ADDR_MODE) | + (0x3 << IEEE154_FCF_DEST_ADDR_MODE)); + + header->fcf |= ( ( IEEE154_TYPE_DATA << IEEE154_FCF_FRAME_TYPE ) | + ( 1 << IEEE154_FCF_INTRAPAN ) ); +/* + 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 ) );*/ + + metadata->ack = FALSE; + metadata->rssi = 0; + metadata->lqi = 0; + metadata->timesync = FALSE; + metadata->timestamp = CC2520_INVALID_TIMESTAMP; + + ccaOn = TRUE; + signal RadioBackoff.requestCca(m_msg); + call CC2520Transmit.send( m_msg, ccaOn ); + + + return SUCCESS; + + } + + command void* Send.getPayload(message_t* m, uint8_t len) { + if (len <= call Send.maxPayloadLength()) { + return (void* COUNT_NOK(len))m->data; + } + else { + return NULL; + } + } + + 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(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(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(bool useCca) { + ccaOn = useCca; + } + + + /**************** Events ****************/ + async event void CC2520Transmit.sendDone( message_t* p_msg, error_t err ) { + atomic sendErr = err; + post sendDone_task(); + } + + async event void CC2520Power.startVRegDone() { + #ifdef PRINTF + printf("\n resource request"); + printfflush(); + #endif + call Resource.request(); + } + + event void Resource.granted() { + uint8_t i; + + call CC2520Power.startOscillator(); + } + + async event void CC2520Power.startOscillatorDone() { + + post startDone_task(); + + } + + /***************** SubBackoff Events ****************/ + async event void SubBackoff.requestInitialBackoff(message_t *msg) { + call SubBackoff.setInitialBackoff ( call Random.rand16() + % (0x1F * CC2520_BACKOFF_PERIOD) + CC2520_MIN_BACKOFF); + + signal RadioBackoff.requestInitialBackoff(msg); + } + + async event void SubBackoff.requestCongestionBackoff(message_t *msg) { + call SubBackoff.setCongestionBackoff( call Random.rand16() + % (0x7 * CC2520_BACKOFF_PERIOD) + CC2520_MIN_BACKOFF); + + signal RadioBackoff.requestCongestionBackoff(msg); + } + + async event void SubBackoff.requestCca(message_t *msg) { + // Lower layers than this do not configure the CCA settings + signal RadioBackoff.requestCca(msg); + } + + + /***************** 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 CC2520Power.rxOn(); + //printf("\nstartdone task");printfflush(); + call Resource.release(); + call SplitControlState.forceState(S_STARTED); + signal SplitControl.startDone( SUCCESS ); + #ifdef PRINTF + printf("\n Csma-startDone.");printfflush(); + #endif + } + + 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 CC2520Power.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(message_t *msg) { + } + + default async event void RadioBackoff.requestCongestionBackoff(message_t *msg) { + } + + default async event void RadioBackoff.requestCca(message_t *msg) { + } + + +} + diff --git a/cc2520/htmlreport.tar.gz b/cc2520/htmlreport.tar.gz new file mode 100644 index 0000000000..19c8971c65 Binary files /dev/null and b/cc2520/htmlreport.tar.gz differ diff --git a/cc2520/interfaces/123.nc b/cc2520/interfaces/123.nc new file mode 100644 index 0000000000..f4e4399da2 --- /dev/null +++ b/cc2520/interfaces/123.nc @@ -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 + * @author David Moss + * @author Chad Metcalf + */ + +#include "message.h" + +interface CC2520Packet { + + /** + * 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/cc2520/interfaces/CC2520Config.nc b/cc2520/interfaces/CC2520Config.nc new file mode 100644 index 0000000000..70b0117a8c --- /dev/null +++ b/cc2520/interfaces/CC2520Config.nc @@ -0,0 +1,120 @@ +/* + * 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 + * @version $Revision: 1.3 $ $Date: 2008/06/16 15:33:32 $ + */ + +interface CC2520Config { + + /** + * 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 ); + + + + /** + * Get the long address of the radio: set in hardware + */ + command ieee_eui64_t getExtAddr(); + /** + * Change the short address of the radio. + */ + async command uint16_t getShortAddr(); + command void setShortAddr( uint16_t address ); + + /** + * Change the PAN address of the radio. + */ + async command uint16_t getPanAddr(); + command void setPanAddr( uint16_t address ); + + + /** + * @param enableAddressRecognition TRUE to turn address recognition on + * @param useHwAddressRecognition TRUE to perform address recognition first + * in hardware. This doesn't affect software address recognition. The + * driver must sync with the chip after changing this value. + */ + command void setAddressRecognition(bool enableAddressRecognition, bool useHwAddressRecognition); + + + /** + * @return TRUE if address recognition is enabled + */ + async command bool isAddressRecognitionEnabled(); + + /** + * @return TRUE if address recognition is performed first in hardware. + */ + async command bool isHwAddressRecognitionDefault(); + + /** + * 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/cc2520/interfaces/CC2520Fifo.nc b/cc2520/interfaces/CC2520Fifo.nc new file mode 100644 index 0000000000..11375f85d7 --- /dev/null +++ b/cc2520/interfaces/CC2520Fifo.nc @@ -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 + * @version $Revision: 1.2 $ $Date: 2008/06/03 04:43:03 $ + */ + +interface CC2520Fifo { + + /** + * Start reading from the FIFO. The readDone 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 cc2520_status_t beginRead( uint8_t* COUNT_NOK(length) data, uint8_t length ); + + /** + * Continue reading from the FIFO without having to send the address + * byte again. The readDone 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* COUNT_NOK(length) 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* COUNT_NOK(length) data, uint8_t length, error_t error ); + + /** + * Start writing the FIFO. The writeDone 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 cc2520_status_t write( uint8_t* COUNT_NOK(length) 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* COUNT_NOK(length) data, uint8_t length, error_t error ); + +} diff --git a/cc2520/interfaces/CC2520Key.nc b/cc2520/interfaces/CC2520Key.nc new file mode 100644 index 0000000000..a5f48541de --- /dev/null +++ b/cc2520/interfaces/CC2520Key.nc @@ -0,0 +1,24 @@ + + +interface CC2520Key +{ + + /*Note that for all the security instructions, the key and counter should * reside in RAM in reversed byte order compare to the data. This can be done + * by reversing the byte order of the key/counter before it is written to the + * RAM,or the MEMCPR instructions can be used to reverse the byte order of + * keys/counter that are already in the RAM + */ + + command error_t setKey(uint8_t *key); + event void setKeyDone(uint8_t status); + + command error_t getKey(uint8_t *key); + event void getKeyDone(uint8_t status, uint8_t *ptr); + + /* + * Returns the pointer to the nonce + */ + command uint8_t *getTXNonce(); + + +} diff --git a/cc2520/interfaces/CC2520Packet.nc b/cc2520/interfaces/CC2520Packet.nc new file mode 100644 index 0000000000..33eb981994 --- /dev/null +++ b/cc2520/interfaces/CC2520Packet.nc @@ -0,0 +1,78 @@ +/* + * 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 + * @author David Moss + * @author Chad Metcalf + */ + +#include "message.h" + +interface CC2520Packet { + + /** + * 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 ); + + async command uint8_t getNetwork( message_t* ONE p_msg ); + + async command void setNetwork( message_t* ONE p_msg, uint8_t networkId ); + +} diff --git a/cc2520/interfaces/CC2520PacketBody.nc b/cc2520/interfaces/CC2520PacketBody.nc new file mode 100644 index 0000000000..a6c8684522 --- /dev/null +++ b/cc2520/interfaces/CC2520PacketBody.nc @@ -0,0 +1,56 @@ +/* + * 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 CC2520PacketBody { + + /** + * @return pointer to the cc2420_header_t of the given message + */ + async command cc2520_header_t * ONE getHeader(message_t * ONE msg); + + /** + * @return pointer to the payload region of the message, after any headers + * works with extended addressing mode + */ + async command uint8_t * getPayload( message_t* msg); + + /** + * @return pointer to the cc2420_metadata_t of the given message + */ + async command cc2520_metadata_t * ONE getMetadata(message_t * ONE msg); + +} + diff --git a/cc2520/interfaces/CC2520Power.nc b/cc2520/interfaces/CC2520Power.nc new file mode 100644 index 0000000000..6febfbcbb7 --- /dev/null +++ b/cc2520/interfaces/CC2520Power.nc @@ -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 + * @version $Revision: 1.1 $ $Date: 2007/07/04 00:37:14 $ + */ + +interface CC2520Power { + + /** + * Start the voltage regulator on the CC2420. On SUCCESS, + * startVReg() 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, startOscillator + * 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/cc2520/interfaces/CC2520Ram.nc b/cc2520/interfaces/CC2520Ram.nc new file mode 100644 index 0000000000..2c5225dfc3 --- /dev/null +++ b/cc2520/interfaces/CC2520Ram.nc @@ -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 + * @version $Revision: 1.2 $ $Date: 2008/06/03 04:43:03 $ + */ + +#include "CC2520.h" + +interface CC2520Ram { + + /** + * 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 cc2520_status_t read( uint8_t offset, uint8_t* COUNT_NOK(length) 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 cc2520_status_t write( uint8_t offset, uint8_t* COUNT_NOK(length) data, uint8_t length ); + +} diff --git a/cc2520/interfaces/CC2520Receive.nc b/cc2520/interfaces/CC2520Receive.nc new file mode 100644 index 0000000000..9ce2ee06e6 --- /dev/null +++ b/cc2520/interfaces/CC2520Receive.nc @@ -0,0 +1,66 @@ +/* + * 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 + * @version $Revision: 1.4 $ $Date: 2008/06/17 07:28:24 $ + */ + +#include "message.h" + +interface CC2520Receive { + + /** + * Notification that an SFD capture has occured. + * + * @param time at which the capture happened. + */ + async command void sfd( uint32_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* ONE_NOK message ); + +} + diff --git a/cc2520/interfaces/CC2520Register.nc b/cc2520/interfaces/CC2520Register.nc new file mode 100644 index 0000000000..02ee2a8353 --- /dev/null +++ b/cc2520/interfaces/CC2520Register.nc @@ -0,0 +1,59 @@ +/* + * "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: 1.2 $ $Date: 2008/06/11 00:46:23 $ + */ + +#include "CC2520.h" + +interface CC2520Register { + + /** + * 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 cc2520_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 cc2520_status_t write(uint16_t data); + + + +} diff --git a/cc2520/interfaces/CC2520Strobe.nc b/cc2520/interfaces/CC2520Strobe.nc new file mode 100644 index 0000000000..dd9f678e04 --- /dev/null +++ b/cc2520/interfaces/CC2520Strobe.nc @@ -0,0 +1,47 @@ +/* + * "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: 1.2 $ $Date: 2008/06/11 00:46:23 $ + */ + +#include "CC2520.h" + +interface CC2520Strobe { + + /** + * 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 cc2520_status_t strobe(); + +} diff --git a/cc2520/interfaces/CC2520Transmit.nc b/cc2520/interfaces/CC2520Transmit.nc new file mode 100644 index 0000000000..1692b5b768 --- /dev/null +++ b/cc2520/interfaces/CC2520Transmit.nc @@ -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 + * @version $Revision: 1.2 $ $Date: 2008/06/03 04:43:03 $ + */ + +#include "message.h" + +interface CC2520Transmit { + + /** + * 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* ONE 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* ONE_NOK 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* COUNT_NOK(len) buf, uint8_t len ); + +} + diff --git a/cc2520/interfaces/ChipSpiResource.nc b/cc2520/interfaces/ChipSpiResource.nc new file mode 100644 index 0000000000..385a0024d9 --- /dev/null +++ b/cc2520/interfaces/ChipSpiResource.nc @@ -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/cc2520/interfaces/LowPowerListening.nc b/cc2520/interfaces/LowPowerListening.nc new file mode 100644 index 0000000000..c8649c85ed --- /dev/null +++ b/cc2520/interfaces/LowPowerListening.nc @@ -0,0 +1,129 @@ +/* + * 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 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 Power Listening interface + * + * @author David Moss + * @author Jonathan Hui + */ + +interface LowPowerListening { + + /** + * 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 setLocalSleepInterval(uint16_t sleepIntervalMs); + + /** + * @return the local node's sleep interval, in [ms] + */ + command uint16_t getLocalSleepInterval(); + + /** + * Set this node's radio duty cycle rate, in units of [percentage*100]. + * For example, to get a 0.05% duty cycle, + * + * call LowPowerListening.setDutyCycle(5); // or equivalently... + * call LowPowerListening.setDutyCycle(00005); // for better readability? + * + * + * For a 100% duty cycle (always on), + * + * call LowPowerListening.setDutyCycle(10000); + * + * + * This is the equivalent of setting the local sleep interval explicitly. + * + * @param dutyCycle The duty cycle percentage, in units of [percentage*100] + */ + command void setLocalDutyCycle(uint16_t dutyCycle); + + /** + * @return this node's radio duty cycle rate, in units of [percentage*100] + */ + command uint16_t getLocalDutyCycle(); + + + /** + * 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 setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs); + + /** + * @return the destination node's sleep interval configured in this message + */ + command uint16_t getRxSleepInterval(message_t *msg); + + /** + * 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 setRxDutyCycle(message_t *msg, uint16_t dutyCycle); + + /** + * @return the destination node's duty cycle configured in this message + * in units of [percentage*100] + */ + command uint16_t getRxDutyCycle(message_t *msg); + + /** + * 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 dutyCycleToSleepInterval(uint16_t 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 sleepIntervalToDutyCycle(uint16_t sleepInterval); + +} diff --git a/cc2520/interfaces/PacketTimeSyncOffset.nc b/cc2520/interfaces/PacketTimeSyncOffset.nc new file mode 100644 index 0000000000..d123cd87a6 --- /dev/null +++ b/cc2520/interfaces/PacketTimeSyncOffset.nc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2007, Vanderbilt 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 THE VANDERBILT 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 THE VANDERBILT + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE VANDERBILT 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 THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Author: Miklos Maroti, Brano Kusy + * + * Interface for one hop time synchronization. Allows to modify timesync + * messages in the MAC layer with elapsed time of an event (ETA timesync + * primitive). Interface also provides a command to determine offset within + * a CC2420 packet, where the timesync ETA value is stored. word 'timestamping' + * used in describing commands does not refer to metadata.timestamp value, + * rather it refers to the timesync ETA timestamp which is part of data + * payload and is transmitted over the air. + */ + +interface PacketTimeSyncOffset +{ + /** + * @param 'message_t *ONE msg' message to examine. + * + * Returns TRUE if the current message should be timestamped. + */ + async command bool isSet(message_t* msg); + + /** + * @param 'message_t *ONE msg' message to examine. + * + * Returns the offset of where the timesync timestamp is sotred in a + * CC2420 packet + */ + async command uint8_t get(message_t* msg); + + /** + * @param 'message_t *ONE msg' message to modify. + * + * Sets the current message to be timestamped in the MAC layer. + */ + async command void set(message_t* msg); + + /** + * @param 'message_t *ONE msg' message to modify. + * + * Cancels any pending requests to timestamp the message in MAC. + */ + async command void cancel(message_t* msg); +} diff --git a/cc2520/interfaces/PowerCycle.nc b/cc2520/interfaces/PowerCycle.nc new file mode 100644 index 0000000000..aef2dab8ec --- /dev/null +++ b/cc2520/interfaces/PowerCycle.nc @@ -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/cc2520/interfaces/RadioBackoff.nc b/cc2520/interfaces/RadioBackoff.nc new file mode 100644 index 0000000000..a9cb5ec867 --- /dev/null +++ b/cc2520/interfaces/RadioBackoff.nc @@ -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 * ONE 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 * ONE 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 * ONE msg); +} + diff --git a/cc2520/interfaces/ReceiveIndicator.nc b/cc2520/interfaces/ReceiveIndicator.nc new file mode 100644 index 0000000000..db2807fc3e --- /dev/null +++ b/cc2520/interfaces/ReceiveIndicator.nc @@ -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/cc2520/link/PacketLinkC.nc b/cc2520/link/PacketLinkC.nc new file mode 100644 index 0000000000..36431ebe58 --- /dev/null +++ b/cc2520/link/PacketLinkC.nc @@ -0,0 +1,68 @@ +/* + * 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, + CC2520PacketC, + 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 -> CC2520PacketC; + PacketLinkP.CC2520PacketBody -> CC2520PacketC; + +} diff --git a/cc2520/link/PacketLinkDummyC.nc b/cc2520/link/PacketLinkDummyC.nc new file mode 100644 index 0000000000..2ea159cef3 --- /dev/null +++ b/cc2520/link/PacketLinkDummyC.nc @@ -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/cc2520/link/PacketLinkDummyP.nc b/cc2520/link/PacketLinkDummyP.nc new file mode 100644 index 0000000000..1688da6707 --- /dev/null +++ b/cc2520/link/PacketLinkDummyP.nc @@ -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/cc2520/link/PacketLinkP.nc b/cc2520/link/PacketLinkP.nc new file mode 100644 index 0000000000..410bcf22e6 --- /dev/null +++ b/cc2520/link/PacketLinkP.nc @@ -0,0 +1,226 @@ +/* + * 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 "CC2520.h" + +module PacketLinkP { + provides { + interface Send; + interface PacketLink; + } + + uses { + interface Send as SubSend; + interface State as SendState; + interface PacketAcknowledgements; + interface Timer as DelayTimer; + interface CC2520PacketBody; + } +} + +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 CC2520PacketBody.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 CC2520PacketBody.getMetadata(msg))->retryDelay = retryDelay; + } + + /** + * @return the maximum number of retry attempts for this message + */ + command uint16_t PacketLink.getRetries(message_t *msg) { + return (call CC2520PacketBody.getMetadata(msg))->maxRetries; + } + + /** + * @return the delay between retry attempts in ms for this message + */ + command uint16_t PacketLink.getRetryDelay(message_t *msg) { + return (call CC2520PacketBody.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, uint8_t len) { + return call SubSend.getPayload(msg, len); + } + + + /***************** 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/cc2520/link/readme.txt b/cc2520/link/readme.txt new file mode 100644 index 0000000000..6793e1d100 --- /dev/null +++ b/cc2520/link/readme.txt @@ -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/cc2520/lowpan/CC2520TinyosNetworkC.nc b/cc2520/lowpan/CC2520TinyosNetworkC.nc new file mode 100644 index 0000000000..1621beeefa --- /dev/null +++ b/cc2520/lowpan/CC2520TinyosNetworkC.nc @@ -0,0 +1,102 @@ +/* + * 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 "CC2520.h" + +configuration CC2520TinyosNetworkC { + provides { + interface Send; + interface Resource[uint8_t clientId]; + interface Receive; + interface Packet as BarePacket; + interface Send as ActiveSend; + interface Receive as ActiveReceive; + } + + uses { + interface Receive as SubReceive; + interface Send as SubSend; + } +} + +implementation { + + + enum { + TINYOS_N_NETWORKS = uniqueCount(RADIO_SEND_RESOURCE), + }; + components MainC; + components CC2520TinyosNetworkP; + components CC2520PacketC; + components new FcfsResourceQueueC(TINYOS_N_NETWORKS); + CC2520TinyosNetworkP.BareSend = Send; + CC2520TinyosNetworkP.BareReceive = Receive; + CC2520TinyosNetworkP.SubSend = SubSend; + CC2520TinyosNetworkP.Resource = Resource; + CC2520TinyosNetworkP.SubReceive = SubReceive; + CC2520TinyosNetworkP.BarePacket=BarePacket; + CC2520TinyosNetworkP.ActiveSend = ActiveSend; + CC2520TinyosNetworkP.ActiveReceive = ActiveReceive; + + + CC2520TinyosNetworkP.CC2520Packet -> CC2520PacketC; + CC2520TinyosNetworkP.CC2520PacketBody -> CC2520PacketC; + CC2520TinyosNetworkP.Queue -> FcfsResourceQueueC; + MainC.SoftwareInit -> FcfsResourceQueueC; +} + diff --git a/cc2520/lowpan/CC2520TinyosNetworkP.nc b/cc2520/lowpan/CC2520TinyosNetworkP.nc new file mode 100644 index 0000000000..2d971677ab --- /dev/null +++ b/cc2520/lowpan/CC2520TinyosNetworkP.nc @@ -0,0 +1,259 @@ +/* + * 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 "CC2520.h" + +module CC2520TinyosNetworkP @safe() { + provides { + interface Send as BareSend; + interface Receive as BareReceive; + interface Packet as BarePacket; + interface Send as ActiveSend; + interface Receive as ActiveReceive; + interface Resource[uint8_t client]; + } + + uses { + interface Send as SubSend; + interface Receive as SubReceive; + interface CC2520Packet; + interface CC2520PacketBody; + interface ResourceQueue as Queue; + } +} + +implementation { + + enum { + CLIENT_AM, + CLIENT_BARE, + } m_busy_client; + + enum { + OWNER_NONE = 0xff, + TINYOS_N_NETWORKS = uniqueCount("RADIO_SEND_RESOURCE"), + } state; + + norace uint8_t resource_owner = OWNER_NONE, next_owner; + + command error_t ActiveSend.send(message_t* msg, uint8_t len) { + call CC2520Packet.setNetwork(msg, TINYOS_6LOWPAN_NETWORK_ID); + m_busy_client = CLIENT_AM; + return call SubSend.send(msg, len); + } + + command error_t ActiveSend.cancel(message_t* msg) { + return call SubSend.cancel(msg); + } + + command uint8_t ActiveSend.maxPayloadLength() { + return call SubSend.maxPayloadLength(); + } + + command void* ActiveSend.getPayload(message_t* msg, uint8_t len) { + if (len <= call ActiveSend.maxPayloadLength()) { + return msg->data; + } else { + return NULL; + } + } + + + /***************** Resource ****************/ + // SDH : 8-7-2009 : testing if there's more then one client allows + // the compiler to eliminate most of the logic when there's only one + // client. + task void grantTask() { + + + if (TINYOS_N_NETWORKS > 1) { + if (resource_owner == OWNER_NONE && !(call Queue.isEmpty())) { + resource_owner = call Queue.dequeue(); + + if (resource_owner != OWNER_NONE) { + signal Resource.granted[resource_owner](); + } + } + } else { + if (next_owner != resource_owner) { + resource_owner = next_owner; + signal Resource.granted[resource_owner](); + } + } + } + + async command error_t Resource.request[uint8_t id]() { + + post grantTask(); + + if (TINYOS_N_NETWORKS > 1) { + return call Queue.enqueue(id); + } else { + if (id == resource_owner) { + return EALREADY; + } else { + next_owner = id; + return SUCCESS; + } + } + } + + async command error_t Resource.immediateRequest[uint8_t id]() { + if (resource_owner == id) return EALREADY; + + if (TINYOS_N_NETWORKS > 1) { + if (resource_owner == OWNER_NONE && call Queue.isEmpty()) { + resource_owner = id; + return SUCCESS; + } + return FAIL; + } else { + resource_owner = id; + return SUCCESS; + } + } + async command error_t Resource.release[uint8_t id]() { + if (TINYOS_N_NETWORKS > 1) { + post grantTask(); + } + resource_owner = OWNER_NONE; + return SUCCESS; + } + async command bool Resource.isOwner[uint8_t id]() { + return (id == resource_owner); + } + + + /***************** BareSend Commands ****************/ + command error_t BareSend.send(message_t* msg, uint8_t len) { + call BarePacket.setPayloadLength(msg, len); + m_busy_client = CLIENT_BARE; + return call SubSend.send(msg, 0); + } + + command error_t BareSend.cancel(message_t* msg) { + return call SubSend.cancel(msg); + } + + command uint8_t BareSend.maxPayloadLength() { + return call SubSend.maxPayloadLength(); + } + + command void* BareSend.getPayload(message_t* msg, uint8_t len) { +#ifndef TFRAMES_ENABLED + cc2520_header_t *hdr = call CC2520PacketBody.getHeader(msg); + return hdr; +#else + // you really can't use BareSend with TFRAMES +#endif + } + + /***************** SubSend Events *****************/ + event void SubSend.sendDone(message_t* msg, error_t error) { + if (m_busy_client == CLIENT_AM) { + signal ActiveSend.sendDone(msg, error); + } else { + signal BareSend.sendDone(msg, error); + } + } + /***************** BarePacket Commands ****************/ + command void BarePacket.clear(message_t *msg) { + memset(msg, 0, sizeof(message_t)); + } + + command uint8_t BarePacket.payloadLength(message_t *msg) { + cc2520_header_t *hdr = call CC2520PacketBody.getHeader(msg); + return hdr->length + 1 - MAC_FOOTER_SIZE; + } + + command void BarePacket.setPayloadLength(message_t* msg, uint8_t len) { + cc2520_header_t *hdr = call CC2520PacketBody.getHeader(msg); + hdr->length = len - 1 + MAC_FOOTER_SIZE; + } + + command uint8_t BarePacket.maxPayloadLength() { + return TOSH_DATA_LENGTH + sizeof(cc2520_header_t); + } + + command void* BarePacket.getPayload(message_t* msg, uint8_t len) { + + } + /***************** SubReceive Events ***************/ + event message_t *SubReceive.receive(message_t *msg, void *payload, uint8_t len) { + + uint8_t network = call CC2520Packet.getNetwork(msg); + + if(!(call CC2520PacketBody.getMetadata(msg))->crc) { + return msg; + } +#ifndef TFRAMES_ENABLED + if (network == TINYOS_6LOWPAN_NETWORK_ID) { + return signal ActiveReceive.receive(msg, payload, len); + } else { + return signal BareReceive.receive(msg, + call BareSend.getPayload(msg, len), + len + sizeof(cc2520_header_t)); + } +#else + return signal ActiveReceive.receive(msg, payload, len); +#endif + + } + + + /***************** Defaults ****************/ + default event message_t *BareReceive.receive(message_t *msg, void *payload, uint8_t len) { + return msg; + } + default event void BareSend.sendDone(message_t *msg, error_t error) { + + } + default event message_t *ActiveReceive.receive(message_t *msg, void *payload, uint8_t len) { + return msg; + } + default event void ActiveSend.sendDone(message_t *msg, error_t error) { + + } + default event void Resource.granted[uint8_t client]() { + call Resource.release[client](); + } + + +} diff --git a/cc2520/lowpan/readme.txt b/cc2520/lowpan/readme.txt new file mode 100644 index 0000000000..708127785b --- /dev/null +++ b/cc2520/lowpan/readme.txt @@ -0,0 +1 @@ +See TEP 125 for more information. diff --git a/cc2520/lpl/DefaultLpl.h b/cc2520/lpl/DefaultLpl.h new file mode 100644 index 0000000000..f74db43b95 --- /dev/null +++ b/cc2520/lpl/DefaultLpl.h @@ -0,0 +1,103 @@ +/* + * 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 + * @author Tony O'Donovan + */ +#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 + * This includes the acknowledgement wait period and backoffs, + * which can typically be much longer than the transmission. + * + * Measured by Tony O'Donovan + */ +#ifndef DUTY_ON_TIME +#define DUTY_ON_TIME 11 +#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/cc2520/lpl/DefaultLplC.nc b/cc2520/lpl/DefaultLplC.nc new file mode 100644 index 0000000000..0d63516464 --- /dev/null +++ b/cc2520/lpl/DefaultLplC.nc @@ -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 LOW POWER COMMUNICATIONS ***" + +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, + CC2520ActiveMessageC, + CC2520CsmaC, + CC2520TransmitC, + CC2520PacketC, + 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 -> CC2520TransmitC; + DefaultLplP.PacketAcknowledgements -> CC2520ActiveMessageC; + DefaultLplP.AMPacket -> CC2520ActiveMessageC; + DefaultLplP.CC2520PacketBody -> CC2520PacketC; + DefaultLplP.RadioBackoff -> CC2520CsmaC; + DefaultLplP.Random -> RandomC; + DefaultLplP.Leds -> LedsC; + +} diff --git a/cc2520/lpl/DefaultLplP.nc b/cc2520/lpl/DefaultLplP.nc new file mode 100644 index 0000000000..857d728252 --- /dev/null +++ b/cc2520/lpl/DefaultLplP.nc @@ -0,0 +1,520 @@ +/* + * 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 CC2520Transmit as Resend; + interface RadioBackoff; + interface Receive as SubReceive; + interface AMPacket; + interface SplitControl as SubControl; + interface PowerCycle; + interface CC2520PacketBody; + interface PacketAcknowledgements; + interface State as SendState; + interface State as RadioPowerState; + interface State as SplitControlState; + interface Timer as OffTimer; + interface Timer 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 Power State + */ + enum { + S_OFF, // off by default + S_TURNING_ON, + S_ON, + S_TURNING_OFF, + }; + + /** + * 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, + * + * call LowPowerListening.setDutyCycle(5); + * + * + * For a 100% duty cycle (always on), + * + * call LowPowerListening.setDutyCycle(10000); + * + * + * 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 CC2520PacketBody.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 CC2520PacketBody.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 CC2520PacketBody.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 CC2520PacketBody.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 EBUSY; + } + + 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, uint8_t len) { + return call SubSend.getPayload(msg, len); + } + + + /***************** RadioBackoff Events ****************/ + async event void RadioBackoff.requestInitialBackoff(message_t *msg) { + if((call CC2520PacketBody.getMetadata(msg))->rxInterval + > ONE_MESSAGE) { + call RadioBackoff.setInitialBackoff( call Random.rand16() + % (0x4 * CC2520_BACKOFF_PERIOD) + CC2520_MIN_BACKOFF); + } + } + + async event void RadioBackoff.requestCongestionBackoff(message_t *msg) { + if((call CC2520PacketBody.getMetadata(msg))->rxInterval + > ONE_MESSAGE) { + call RadioBackoff.setCongestionBackoff( call Random.rand16() + % (0x3 * CC2520_BACKOFF_PERIOD) + CC2520_MIN_BACKOFF); + } + } + + async event void RadioBackoff.requestCca(message_t *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. + + 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_OFF + && 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/cc2520/lpl/DummyLplC.nc b/cc2520/lpl/DummyLplC.nc new file mode 100644 index 0000000000..3d9683bd14 --- /dev/null +++ b/cc2520/lpl/DummyLplC.nc @@ -0,0 +1,68 @@ +/* + * 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 + */ + +#warning "*** LOW POWER COMMUNICATIONS DISABLED ***" + +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/cc2520/lpl/DummyLplP.nc b/cc2520/lpl/DummyLplP.nc new file mode 100644 index 0000000000..dbc6bb5393 --- /dev/null +++ b/cc2520/lpl/DummyLplP.nc @@ -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/cc2520/lpl/PowerCycleC.nc b/cc2520/lpl/PowerCycleC.nc new file mode 100644 index 0000000000..6c87dfb3cc --- /dev/null +++ b/cc2520/lpl/PowerCycleC.nc @@ -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, + CC2520TransmitC, + CC2520ReceiveC, + CC2520CsmaC, + 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 -> CC2520TransmitC.EnergyIndicator; + PowerCycleP.ByteIndicator -> CC2520TransmitC.ByteIndicator; + PowerCycleP.PacketIndicator -> CC2520ReceiveC.PacketIndicator; + PowerCycleP.SubControl -> CC2520CsmaC; + PowerCycleP.SendState -> LplC; + PowerCycleP.RadioPowerState -> RadioPowerStateC; + PowerCycleP.SplitControlState -> SplitControlStateC; + PowerCycleP.OnTimer -> OnTimerC; + PowerCycleP.Leds -> LedsC; + +} + + diff --git a/cc2520/lpl/PowerCycleP.nc b/cc2520/lpl/PowerCycleP.nc new file mode 100644 index 0000000000..34099244f5 --- /dev/null +++ b/cc2520/lpl/PowerCycleP.nc @@ -0,0 +1,313 @@ +/* + * 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 + */ + +#include "DefaultLpl.h" + +module PowerCycleP { + provides { + interface PowerCycle; + interface SplitControl; + } + + uses { + interface Timer 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/cc2520/lpl/readme.txt b/cc2520/lpl/readme.txt new file mode 100644 index 0000000000..4fe5dc6567 --- /dev/null +++ b/cc2520/lpl/readme.txt @@ -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/cc2520/packet/CC2520PacketC.nc b/cc2520/packet/CC2520PacketC.nc new file mode 100644 index 0000000000..9ba0347dc7 --- /dev/null +++ b/cc2520/packet/CC2520PacketC.nc @@ -0,0 +1,72 @@ +/* + * 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 + * @author David Moss + * @author Chad Metcalf + */ + +configuration CC2520PacketC { + + provides { + interface CC2520Packet; + interface PacketAcknowledgements as Acks; + interface CC2520PacketBody; + interface LinkPacketMetadata; + + interface PacketTimeStamp as PacketTimeStamp32khz; + interface PacketTimeStamp as PacketTimeStampMilli; + interface PacketTimeSyncOffset; + } + +} + +implementation { + components CC2520PacketP; + CC2520Packet = CC2520PacketP; + Acks = CC2520PacketP; + CC2520PacketBody = CC2520PacketP; + LinkPacketMetadata = CC2520PacketP; + PacketTimeStamp32khz = CC2520PacketP; + PacketTimeStampMilli = CC2520PacketP; + PacketTimeSyncOffset = CC2520PacketP; + + + + components Counter32khz32C, new CounterToLocalTimeC(T32khz); + CounterToLocalTimeC.Counter -> Counter32khz32C; + CC2520PacketP.LocalTime32khz -> CounterToLocalTimeC; + + //DummyTimer is introduced to compile apps that use no timers + components HilTimerMilliC, new TimerMilliC() as DummyTimer; + CC2520PacketP.LocalTimeMilli -> HilTimerMilliC; +} diff --git a/cc2520/packet/CC2520PacketP.nc b/cc2520/packet/CC2520PacketP.nc new file mode 100644 index 0000000000..dc1a21a4ed --- /dev/null +++ b/cc2520/packet/CC2520PacketP.nc @@ -0,0 +1,254 @@ +/* + * 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 + * @author David Moss + * @author Chad Metcalf + */ + +#include "IEEE802154.h" +#include "message.h" +#include "CC2520.h" +#include "CC2520TimeSyncMessage.h" + +module CC2520PacketP @safe() { + + provides { + interface CC2520Packet; + interface PacketAcknowledgements as Acks; + interface CC2520PacketBody; + interface LinkPacketMetadata; + + interface PacketTimeStamp as PacketTimeStamp32khz; + interface PacketTimeStamp as PacketTimeStampMilli; + interface PacketTimeSyncOffset; + } + + uses interface LocalTime as LocalTime32khz; + uses interface LocalTime as LocalTimeMilli; +} + +implementation { + + + + + + /***************** PacketAcknowledgement Commands ****************/ + async command error_t Acks.requestAck( message_t* p_msg ) { + (call CC2520PacketBody.getHeader( p_msg ))->fcf |= 1 << IEEE154_FCF_ACK_REQ; + return SUCCESS; + } + + async command error_t Acks.noAck( message_t* p_msg ) { + (call CC2520PacketBody.getHeader( p_msg ))->fcf &= ~(1 << IEEE154_FCF_ACK_REQ); + return SUCCESS; + } + + async command bool Acks.wasAcked( message_t* p_msg ) { + return (call CC2520PacketBody.getMetadata( p_msg ))->ack; + } + + /***************** CC2420Packet Commands ****************/ + + int getAddressLength(int type) { + switch (type) { + case IEEE154_ADDR_SHORT: return 2; + case IEEE154_ADDR_EXT: return 8; + case IEEE154_ADDR_NONE: return 0; + default: return -100; + } + } + + uint8_t * ONE getNetwork(message_t * ONE msg) { + cc2520_header_t *hdr = (call CC2520PacketBody.getHeader( msg )); + int offset; + + offset = getAddressLength((hdr->fcf >> IEEE154_FCF_DEST_ADDR_MODE) & 0x3) + + getAddressLength((hdr->fcf >> IEEE154_FCF_SRC_ADDR_MODE) & 0x3) + + offsetof(cc2520_header_t, dest); + + return ((uint8_t *)hdr) + offset; + } + + async command void CC2520Packet.setPower( message_t* p_msg, uint8_t power ) { + if ( power > 31 ) + power = 31; + (call CC2520PacketBody.getMetadata( p_msg ))->tx_power = power; + } + + async command uint8_t CC2520Packet.getPower( message_t* p_msg ) { + return (call CC2520PacketBody.getMetadata( p_msg ))->tx_power; + } + + async command int8_t CC2520Packet.getRssi( message_t* p_msg ) { + return (call CC2520PacketBody.getMetadata( p_msg ))->rssi; + } + + async command uint8_t CC2520Packet.getLqi( message_t* p_msg ) { + return (call CC2520PacketBody.getMetadata( p_msg ))->lqi; + } + + async command uint8_t CC2520Packet.getNetwork( message_t* ONE p_msg ) { +#if defined(TFRAMES_ENABLED) + return TINYOS_6LOWPAN_NETWORK_ID; +#else + atomic + return *(getNetwork(p_msg)); +#endif + } + + async command void CC2520Packet.setNetwork( message_t* ONE p_msg , uint8_t networkId ) { +#if ! defined(TFRAMES_ENABLED) + atomic + *(getNetwork(p_msg)) = networkId; +#endif + } + + /***************** CC2420PacketBody Commands ****************/ + async command cc2520_header_t * ONE CC2520PacketBody.getHeader( message_t* ONE msg ) { + return TCAST(cc2520_header_t* ONE, (uint8_t *)msg + offsetof(message_t, data) - sizeof( cc2520_header_t )); + } + + async command uint8_t * CC2520PacketBody.getPayload( message_t* msg) { + cc2520_header_t *hdr = (call CC2520PacketBody.getHeader( msg )); + int offset; + + offset = getAddressLength((hdr->fcf >> IEEE154_FCF_DEST_ADDR_MODE) & 0x3) + + getAddressLength((hdr->fcf >> IEEE154_FCF_SRC_ADDR_MODE) & 0x3) + + offsetof(cc2520_header_t, dest); +#ifdef CC2520_HW_SECURITY + offset += 5; +#endif +#ifdef CC2520_IFRAME_TYPE + offset += 1; +#endif + return ((uint8_t *)hdr) + offset; + } + + + async command cc2520_metadata_t *CC2520PacketBody.getMetadata( message_t* msg ) { + + return (cc2520_metadata_t*)msg->metadata; + } + + async command bool LinkPacketMetadata.highChannelQuality(message_t* msg) { + return call CC2520Packet.getLqi(msg) > 105; + } + + /***************** PacketTimeStamp32khz Commands ****************/ + async command bool PacketTimeStamp32khz.isValid(message_t* msg) + { + + //call CC2520PacketBody.getMetadata( msg )->timestamp = 0; + return ((call CC2520PacketBody.getMetadata( msg ))->timestamp != CC2520_INVALID_TIMESTAMP); + } + + async command uint32_t PacketTimeStamp32khz.timestamp(message_t* msg) + { + + return (call CC2520PacketBody.getMetadata( msg ))->timestamp; + } + + async command void PacketTimeStamp32khz.clear(message_t* msg) + { + (call CC2520PacketBody.getMetadata( msg ))->timesync = FALSE; + (call CC2520PacketBody.getMetadata( msg ))->timestamp = CC2520_INVALID_TIMESTAMP; + + } + + async command void PacketTimeStamp32khz.set(message_t* msg, uint32_t value) + { + (call CC2520PacketBody.getMetadata( msg ))->timestamp = value; + + } + + /***************** PacketTimeStampMilli Commands ****************/ + // over the air value is always T32khz, which is used to capture SFD interrupt + // (Timer1 on micaZ, B1 on telos) + async command bool PacketTimeStampMilli.isValid(message_t* msg) + { + return call PacketTimeStamp32khz.isValid(msg); + } + + async command uint32_t PacketTimeStampMilli.timestamp(message_t* msg) + { + int32_t offset = call PacketTimeStamp32khz.timestamp(msg) - call LocalTime32khz.get(); + + return (offset >> 5) + call LocalTimeMilli.get(); + } + + async command void PacketTimeStampMilli.clear(message_t* msg) + { + call PacketTimeStamp32khz.clear(msg); + } + + async command void PacketTimeStampMilli.set(message_t* msg, uint32_t value) + { + int32_t offset = (value - call LocalTimeMilli.get()) << 5; + + + call PacketTimeStamp32khz.set(msg, offset + call LocalTime32khz.get()); + + } + /*----------------- PacketTimeSyncOffset -----------------*/ + async command bool PacketTimeSyncOffset.isSet(message_t* msg) + { + + return ((call CC2520PacketBody.getMetadata( msg ))->timesync); + } + + //returns offset of timestamp from the beginning of cc2420 header which is + // sizeof(cc2420_header_t)+datalen-sizeof(timesync_radio_t) + //uses packet length of the message which is + // MAC_HEADER_SIZE+MAC_FOOTER_SIZE+datalen + async command uint8_t PacketTimeSyncOffset.get(message_t* msg) + { + + return (call CC2520PacketBody.getHeader(msg))->length + + (sizeof(cc2520_header_t) - MAC_HEADER_SIZE) + - MAC_FOOTER_SIZE + - sizeof(timesync_radio_t); + } + + async command void PacketTimeSyncOffset.set(message_t* msg) + { + (call CC2520PacketBody.getMetadata( msg ))->timesync = TRUE; + + } + + async command void PacketTimeSyncOffset.cancel(message_t* msg) + { + (call CC2520PacketBody.getMetadata( msg ))->timesync = FALSE; + + } +} diff --git a/cc2520/receive/CC2520ReceiveC.nc b/cc2520/receive/CC2520ReceiveC.nc new file mode 100644 index 0000000000..46ab8b4717 --- /dev/null +++ b/cc2520/receive/CC2520ReceiveC.nc @@ -0,0 +1,96 @@ +/* + * 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 + * @version $Revision: 1.3 $ $Date: 2008/06/17 07:28:24 $ + */ + +configuration CC2520ReceiveC { + + provides interface StdControl; + provides interface CC2520Receive; + provides interface Receive; + provides interface ReceiveIndicator as PacketIndicator; + + uses interface CC2520Transmit as Send; +} + +implementation { + components MainC; + components CC2520ReceiveP; + components CC2520PacketC; + components new CC2520SpiC() as Spi; + components CC2520ControlC; + + components HplCC2520PinsC as Pins; + components HplCC2520InterruptsC as InterruptsC; + + components LedsC as Leds; + CC2520ReceiveP.Leds -> Leds; + + StdControl = CC2520ReceiveP; + CC2520Receive = CC2520ReceiveP; + Send = CC2520ReceiveP; + Receive = CC2520ReceiveP; + PacketIndicator = CC2520ReceiveP.PacketIndicator; + + MainC.SoftwareInit -> CC2520ReceiveP; + + CC2520ReceiveP.CSN -> Pins.CSN; + CC2520ReceiveP.FIFO -> Pins.FIFO; + CC2520ReceiveP.FIFOP -> Pins.FIFOP; + CC2520ReceiveP.InterruptFIFOP -> InterruptsC.InterruptFIFOP; + CC2520ReceiveP.SpiResource -> Spi; + CC2520ReceiveP.RXFIFO -> Spi.RXFIFO; + CC2520ReceiveP.SFLUSHRX -> Spi.SFLUSHRX; + CC2520ReceiveP.SACK -> Spi.SACK; + CC2520ReceiveP.SACKPEND -> Spi.SACKPEND; + CC2520ReceiveP.CC2520Packet -> CC2520PacketC; + CC2520ReceiveP.CC2520PacketBody -> CC2520PacketC; + CC2520ReceiveP.PacketTimeStamp -> CC2520PacketC; + CC2520ReceiveP.CC2520Config -> CC2520ControlC; + + #ifdef CC2520_HW_SECURITY + CC2520ReceiveP.RXFRAME -> Spi.RXFRAME; + CC2520ReceiveP.RXNonce -> Spi.RXNONCE; + CC2520ReceiveP.SNOP -> Spi.SNOP; + + components new HplCC2520SpiC(); + CC2520ReceiveP.SpiByte -> HplCC2520SpiC; + + components CC2520ActiveMessageC; + CC2520ReceiveP.AMPacket -> CC2520ActiveMessageC; + #endif + +} diff --git a/cc2520/receive/CC2520ReceiveP.nc b/cc2520/receive/CC2520ReceiveP.nc new file mode 100644 index 0000000000..2f9f824a1b --- /dev/null +++ b/cc2520/receive/CC2520ReceiveP.nc @@ -0,0 +1,655 @@ +/* + * 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 + * @author David Moss + * @author Jung Il Choi + * @version $Revision: 1.16 $ $Date: 2008/07/25 16:27:52 $ + */ + +#include "IEEE802154.h" +#include "message.h" +#include "AM.h" + +#ifndef FLAG_FIELD +#define FLAG_FIELD FLAG_ENC //M = 4 L = 2 +#endif + +#ifndef SECURITY_CONTROL +#define SECURITY_CONTROL SEC_ENC //MIC-64 +#endif + +module CC2520ReceiveP @safe() { + + provides interface Init; + provides interface StdControl; + provides interface CC2520Receive; + 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 CC2520Fifo as RXFIFO; + uses interface CC2520Strobe as SACK; + uses interface CC2520Strobe as SACKPEND; + uses interface CC2520Strobe as SFLUSHRX; + uses interface CC2520Transmit as Send; + uses interface CC2520Packet; + uses interface CC2520PacketBody; + uses interface CC2520Config; + uses interface PacketTimeStamp; + #ifdef CC2520_HW_SECURITY + uses interface CC2520Ram as RXFRAME; + uses interface CC2520Ram as RXNonce; + uses interface CC2520Strobe as SNOP; + uses interface SpiByte; + uses interface AMPacket; + #endif + + + uses interface Leds; +} + +implementation { + + typedef enum { + S_STOPPED, + S_STARTED, + S_RX_LENGTH, + S_RX_FCF, + S_RX_PAYLOAD, + } cc2520_receive_state_t; + + enum { + RXFIFO_SIZE = 128, + TIMESTAMP_QUEUE_SIZE = 8, + SACK_HEADER_LENGTH = 7, + //SACK_HEADER_LENGTH = 2, + }; + + uint32_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* ONE_NOK m_p_rx_buf; + + message_t m_rx_buf; + message_t ack_buf; + + #ifdef CC2520_HW_SECURITY + static uint8_t nonceRx[16]; + #endif + + cc2520_receive_state_t m_state; + + /***************** Prototypes ****************/ + void reset_state(); + void beginReceive(); + void receive(); + void waitForNextPacket(); + void flush(); + #ifdef CC2520_HW_SECURITY + error_t acquireSpiResource(void); + void decryptPacket(void); + uint8_t getMICLength(uint8_t securityLevel); + void initNonce(void); + #endif + bool passesAddressCheck(message_t * ONE msg); + + 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; + } + + /***************** CC2420Receive Commands ****************/ + /** + * Start frame delimiter signifies the beginning/end of a packet + * See the CC2420 datasheet for details. + */ + async command void CC2520Receive.sfd( uint32_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 CC2520Receive.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() { + //call Leds.led0On(); + if ( m_state == S_STARTED ) { + m_state = S_RX_LENGTH; + 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 ) { + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_p_rx_buf ); + uint8_t tmpLen __DEPUTY_UNUSED__ = sizeof(message_t) - (offsetof(message_t, data) - sizeof(cc2520_header_t)); + uint8_t* COUNT(tmpLen) buf = TCAST(uint8_t* COUNT(tmpLen), 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 > SACK_HEADER_LENGTH) { + // This packet has an FCF byte plus at least one more byte to read + call RXFIFO.continueRead(buf + 1, SACK_HEADER_LENGTH); + + } else { + // This is really a bad packet, skip FCF and get it out of here. + 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; + + /* + * The destination address check here is not completely optimized. If you + * are seeing issues with dropped acknowledgements, try removing + * the address check and decreasing SACK_HEADER_LENGTH to 2. + * The length byte and the FCF byte are the only two bytes required + * to know that the packet is valid and requested an ack. The destination + * address is useful when we want to sniff packets from other transmitters + * while acknowledging packets that were destined for our local address. + */ + if(call CC2520Config.isAutoAckEnabled() && !call CC2520Config.isHwAutoAckDefault()) { + if (((( header->fcf >> IEEE154_FCF_ACK_REQ ) & 0x01) == 1) + && ((header->dest == call CC2520Config.getShortAddr()) + || (header->dest == AM_BROADCAST_ADDR)) + && ((( 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 Leds.led1Toggle(); + call CSN.set(); + call CSN.clr(); + call RXFIFO.beginRead(buf + 1 + SACK_HEADER_LENGTH, + rxFrameLength - SACK_HEADER_LENGTH); +// call CSN.set(); +// call CSN.clr(); + return; + } + } + + // Didn't flip CSn, we're ok to continue reading. + call RXFIFO.continueRead(buf + 1 + SACK_HEADER_LENGTH, + rxFrameLength - SACK_HEADER_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(); + } + //new packet is buffered up, or we don't have timestamp in fifo, or ack + if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() + || !m_timestamp_size + || rxFrameLength <= 10) { + call PacketTimeStamp.clear(m_p_rx_buf); + } + else { + if (m_timestamp_size==1) + call PacketTimeStamp.set(m_p_rx_buf, m_timestamp_queue[ m_timestamp_head ]); + m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE; + m_timestamp_size--; + + if (m_timestamp_size>0) { + call PacketTimeStamp.clear(m_p_rx_buf); + m_timestamp_head = 0; + m_timestamp_size = 0; + } + } +/* + if ( m_timestamp_size ) { + if ( rxFrameLength > 10 ) { + call PacketTimeStamp.set(m_p_rx_buf, m_timestamp_queue[ m_timestamp_head ]); + m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE; + m_timestamp_size--; + } + } else { + call PacketTimeStamp.clear(m_p_rx_buf); + } +*/ + // 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; + // if ( type == IEEE154_TYPE_ACK ) + // call Leds.led0Toggle(); + + signal CC2520Receive.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() { + cc2520_metadata_t* metadata = call CC2520PacketBody.getMetadata( m_p_rx_buf ); + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_p_rx_buf); + uint8_t length = header->length; + uint8_t tmpLen __DEPUTY_UNUSED__ = sizeof(message_t) - (offsetof(message_t, data) - sizeof(cc2520_header_t)); + uint8_t* COUNT(tmpLen) buf = TCAST(uint8_t* COUNT(tmpLen), header); + metadata->crc = buf[ length ] >> 7; + metadata->lqi = buf[ length ] & 0x7f; + metadata->rssi = buf[ length - 1 ]; + + if (passesAddressCheck(m_p_rx_buf) && length >= CC2520_SIZE) { + if(((header->fcf >> IEEE154_FCF_ACK_REQ ) & 0x01) == 1) { + cc2520_header_t* ack_hdr = call CC2520PacketBody.getHeader(&ack_buf); + ack_hdr->length = 3 + CC2520_SIZE; + ack_hdr->fcf = (IEEE154_TYPE_ACK << IEEE154_FCF_FRAME_TYPE); + ack_hdr->dsn = header->dsn; + call Send.send(&ack_buf, 1); + } + #ifdef CC2520_HW_SECURITY + decryptPacket(); + #endif + m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data, + length - CC2520_SIZE); + } + + atomic receivingPacket = FALSE; + waitForNextPacket(); + + } + + /****************** CC2420Config Events ****************/ + event void CC2520Config.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 CSN.set(); +// call CSN.clr(); + 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 CC2520PacketBody.getHeader( m_p_rx_buf )), 1 ); + //call CSN.set(); + + } + + + /* + * Decrypt the received packet + */ + #ifdef CC2520_HW_SECURITY + + error_t acquireSpiResource() { + + error_t error = call SpiResource.immediateRequest(); + + if ( error != SUCCESS ) { + // printf("\nspi error:%d",error);printfflush(); + call SpiResource.request(); + } + return error; + } + + uint8_t getMICLength(uint8_t securityLevel) { + + if(securityLevel == SEC_MIC_32 || securityLevel == SEC_ENC_MIC_32) + return 4; + else if(securityLevel == SEC_MIC_64 || securityLevel == SEC_ENC_MIC_64) + return 8; + else if(securityLevel == SEC_ENC_MIC_128 || securityLevel == SEC_ENC_MIC_128) + return 16; + return 0; + } + + void reverseArray(uint8_t *ptr,uint8_t length) + { + uint8_t i,tmp; + for(i=0; i< length/2;i++) + { + tmp = ptr[i]; + ptr[i] = ptr[length -i]; + ptr[length-i] = tmp; + } + } + + + void initNonce(void) + { + uint8_t i; + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_p_rx_buf); + for(i=0;i> 8); + nonceRx[8] = (uint8_t)(call AMPacket.source( m_p_rx_buf) & 0xff); + nonceRx[13] = SECURITY_CONTROL; + nonceRx[15] = 0x01; + + reverseArray(nonceRx, 16); + call CSN.clr(); + call RXNonce.write(0, nonceRx, 16); + call CSN.set(); + } + + void decryptPacket(void) + { + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_p_rx_buf); + uint8_t *ptr = (uint8_t *)header; + uint8_t micLength = getMICLength(header->secHdr.secLevel); + uint8_t decryptLength = header->length - CC2520_SIZE - micLength; + uint8_t authLength = CC2520_SIZE - MAC_FOOTER_SIZE; + uint8_t length = header->length; + + acquireSpiResource(); + call CSN.clr(); + call RXFRAME.write(0, ptr,header->length); + call CSN.set(); + + + initNonce(); + + call CSN.clr(); + call SpiByte.write(CC2520_CMD_UCCM | HIGH_PRIORITY); + call SpiByte.write(CC2520_RAM_KEY0/16); + call SpiByte.write(decryptLength); + call SpiByte.write(CC2520_RAM_RXNONCE/16); + call SpiByte.write((HI_UINT16(CC2520_RAM_RXFRAME+1)<<4)|HI_UINT16(0)); + call SpiByte.write(LO_UINT16(CC2520_RAM_RXFRAME+1)); + call SpiByte.write(LO_UINT16(0)); //For Inline Security + call SpiByte.write(authLength); + call SpiByte.write(micLength); + call CSN.set(); + + call CSN.clr(); + while(call SNOP.strobe() & 0x08); + call CSN.set(); + + header->dsn = 0xff; + + call CSN.clr(); + call RXFRAME.read(0, ptr, length); + call CSN.set(); + + call SpiResource.release(); + + } + #endif + + + + /** + * 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; + + /* + * The FIFOP pin here is high when there are 0 bytes in the RX FIFO + * and goes low as soon as there are bytes in the RX FIFO. The pin + * is inverted from what the datasheet says, and its threshold is 127. + * Whenever the FIFOP line goes low, as you can see from the interrupt + * handler elsewhere in this module, it means we received a new packet. + * If the line stays low without generating an interrupt, that means + * there's still more data to be received. + */ + 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; + } + + /** + * @return TRUE if the given message passes address recognition + */ + bool passesAddressCheck(message_t *msg) { + cc2520_header_t *header = call CC2520PacketBody.getHeader( msg ); + int mode = (header->fcf >> IEEE154_FCF_DEST_ADDR_MODE) & 3; + ieee_eui64_t *ext_addr; + + if(!(call CC2520Config.isAddressRecognitionEnabled())) { + + return TRUE; + } + if (mode == IEEE154_ADDR_SHORT) { + return (header->dest == call CC2520Config.getShortAddr() + || header->dest == IEEE154_BROADCAST_ADDR); + } else if (mode == IEEE154_ADDR_EXT) { + + ieee_eui64_t local_addr = (call CC2520Config.getExtAddr()); + + ext_addr = TCAST(ieee_eui64_t* ONE, &header->dest); + // printf("\n link layer address:"); + // printf_buf(ext_addr,8); + return (memcmp(ext_addr->data, local_addr.data, IEEE_EUI64_LENGTH) == 0); + } else { + /* reject frames with either no address or invalid type */ + return FALSE; + } + } + + async event void Send.sendDone(message_t *p_msg, error_t error) { return; } + +} + diff --git a/cc2520/security/CC2520KeyC.nc b/cc2520/security/CC2520KeyC.nc new file mode 100644 index 0000000000..d5316b91ba --- /dev/null +++ b/cc2520/security/CC2520KeyC.nc @@ -0,0 +1,29 @@ + + +configuration CC2520KeyC +{ + provides interface CC2520Key; +} + +implementation +{ + components CC2520KeyP; + CC2520Key = CC2520KeyP; + + components new CC2520SpiC() as Spi; + CC2520KeyP.Key -> Spi.KEY; + CC2520KeyP.TXNonce -> Spi.TXNONCE; + CC2520KeyP.SpiResource -> Spi.Resource; + + components ActiveMessageAddressC; + CC2520KeyP.ActiveMessageAddress -> ActiveMessageAddressC; + + components MainC; + components AlarmMultiplexC as Alarm; + MainC.SoftwareInit -> CC2520KeyP; + MainC.SoftwareInit -> Alarm; + + components HplCC2520PinsC as Pins; + CC2520KeyP.CSN -> Pins.CSN; + +} diff --git a/cc2520/security/CC2520KeyP.nc b/cc2520/security/CC2520KeyP.nc new file mode 100644 index 0000000000..96a034e8e5 --- /dev/null +++ b/cc2520/security/CC2520KeyP.nc @@ -0,0 +1,175 @@ +#define NONCE_SIZE 16 + +#ifndef FLAG_FIELD +#define FLAG_FIELD FLAG_ENC //M = 4 L = 2 +#endif + +#ifndef SECURITY_CONTROL +#define SECURITY_CONTROL SEC_ENC //MIC-64 +#endif + +module CC2520KeyP +{ + provides interface CC2520Key; + provides interface Init; + uses{ + interface CC2520Ram as Key; + interface CC2520Ram as TXNonce; + interface GeneralIO as CSN; + interface Resource as SpiResource; + interface ActiveMessageAddress; + } +} + +implementation +{ + uint8_t *setKey = NULL; + uint8_t *getKey = NULL; + uint8_t operation; + enum flags{ + SETKEY=4, + GETKEY=5, + }; + static uint8_t nonceTx[NONCE_SIZE]; + static uint8_t nonceRx[NONCE_SIZE]; + /* + * The nonce must be correctly initialized before receive or transmit CTR or + * CCM operations are started.The format of the nonce is + *Initialization vector: + * Flags + Nonce + Sequence Counter + * --------------------------------------------------------------------- + *|Bytes:1|8 |4 |1 |2 | + *---------------------------------------------------------------------- + *|Flags | Source Address|Frame Counter|Security Level | Sequence Cnter| + *---------------------------------------------------------------------- + * + * Flags field + * + * ------------------------------------------------------ + * |Bits:7 |6 |5..3 |2..0 | + * ------------------------------------------------------ + * |Reserved |Adata | M' |L' | + * ------------------------------------------------------ + * + * Bit 7 is Reserved and should be set to 0. Adata indicates whether there is + * additional data or not + * + * M' is the length of the size of the authentication field. M' is encoded as + * (M-2)/2 and valid values are even numbers from 4 to 16. L' is size of the + * length field and is encoded as L-1. + * + * + */ + + command error_t Init.init() + { + uint8_t i; + // Initialise nonce bytes to 0 + for(i=0;i> 8); + nonceTx[8] = (uint8_t)(call ActiveMessageAddress.amAddress() & 0xff); + + // Set Security mode field of nonces (Byte 13) + nonceTx[13] = SECURITY_CONTROL; + nonceRx[13] = SECURITY_CONTROL; + + //Setting sequence counter to 1 + nonceTx[15] = 0x01; + nonceRx[15] = 0x01; + + //While transmitting just we have to copy the frameCounter into the nonce + return SUCCESS; + } + + task void resourceReq() + { + error_t error; + error = call SpiResource.immediateRequest(); + if(error != SUCCESS){ + post resourceReq(); + } + } + + void reverseArray(uint8_t *ptr,uint8_t length) + { + uint8_t i,tmp; + for(i=0; i< length/2;i++) + { + tmp = ptr[i]; + ptr[i] = ptr[length -i]; + ptr[length-i] = tmp; + } + } + + event void SpiResource.granted() + { + uint8_t ret; + if(operation == SETKEY) + { + reverseArray(setKey, 16); + reverseArray(nonceTx, 16); + reverseArray(nonceRx, 16); + + call CSN.clr(); + /*Load and reverse the key (or reverse in software before loading)*/ + ret = call Key.write(0, setKey, 16); + call CSN.set(); + + call CSN.clr(); + call TXNonce.write(0, nonceTx, 16); + call CSN.set(); + + + signal CC2520Key.setKeyDone(ret); + }else if(operation == GETKEY) + { + call CSN.clr(); + ret = call Key.read(0, getKey, 16); + call CSN.set(); + signal CC2520Key.getKeyDone(ret,getKey); + } + call SpiResource.release(); + } + + async event void ActiveMessageAddress.changed(){ + // TODO Auto-generated method stub + } + + + command uint8_t* CC2520Key.getTXNonce() + { + return nonceTx; + } + + command error_t CC2520Key.setKey(uint8_t *key) + { + setKey = key; + operation = SETKEY; + if(call SpiResource.request() != SUCCESS){ + post resourceReq(); + } + return SUCCESS; + } + + + command error_t CC2520Key.getKey(uint8_t *key) + { + getKey = key; + operation = GETKEY; + if(call SpiResource.request() != SUCCESS){ + post resourceReq(); + } + return SUCCESS; + } + + +} diff --git a/cc2520/spi/CC2520SpiC.nc b/cc2520/spi/CC2520SpiC.nc new file mode 100644 index 0000000000..4a37024667 --- /dev/null +++ b/cc2520/spi/CC2520SpiC.nc @@ -0,0 +1,247 @@ +/* + * 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 CC2520 radio. + * + * @author Jonathan Hui + * @version $Revision: 1.2 $ $Date: 2008/05/28 16:39:53 $ + */ + +generic configuration CC2520SpiC() { + + provides interface Resource; + provides interface ChipSpiResource; + + // commands + provides interface CC2520Strobe as SNOP; + provides interface CC2520Strobe as SXOSCON; + provides interface CC2520Strobe as STXCAL; + provides interface CC2520Strobe as SRXON; + provides interface CC2520Strobe as STXON; + provides interface CC2520Strobe as STXONCCA; + provides interface CC2520Strobe as SRFOFF; + provides interface CC2520Strobe as SXOSCOFF; + provides interface CC2520Strobe as SFLUSHRX; + provides interface CC2520Strobe as SFLUSHTX; + provides interface CC2520Strobe as SACK; + provides interface CC2520Strobe as SACKPEND; + //provides interface CC2520Strobe as SRXDEC; + //provides interface CC2520Strobe as STXENC; + //provides interface CC2520Strobe as SAES; + + // registers + //provides interface CC2520Register as MAIN; + provides interface CC2520Register as MDMCTRL0; + provides interface CC2520Register as MDMCTRL1; + provides interface CC2520Register as RSSI; + + //provides interface CC2520Register as TXCTRL; + provides interface CC2520Register as RXCTRL; + + provides interface CC2520Register as FSCTRL; + + provides interface CC2520Register as FRMCTRL1; + provides interface CC2520Register as RXENABLE1; + + + provides interface CC2520Register as CCACTRL0; + provides interface CC2520Register as AGCCTRL1; + provides interface CC2520Register as FSCAL1; + provides interface CC2520Register as TXPOWER; + provides interface CC2520Register as FREQCTRL; + provides interface CC2520Register as ADCTEST0; + provides interface CC2520Register as ADCTEST1; + provides interface CC2520Register as ADCTEST2; + + provides interface CC2520Register as FRMCTRL0; + provides interface CC2520Register as EXTCLOCK; + provides interface CC2520Register as GPIOCTRL0; + provides interface CC2520Register as GPIOCTRL1; + provides interface CC2520Register as GPIOCTRL2; + provides interface CC2520Register as GPIOCTRL3; + provides interface CC2520Register as GPIOCTRL4; + provides interface CC2520Register as GPIOCTRL5; + + provides interface CC2520Register as GPIOPOLARITY; + provides interface CC2520Register as EXCFLAG0; + provides interface CC2520Register as EXCFLAG1; + provides interface CC2520Register as EXCFLAG2; + provides interface CC2520Register as FSMSTAT1; + + provides interface CC2520Register as FRMFILT0; + provides interface CC2520Register as FRMFILT1; + provides interface CC2520Register as FIFOPCTRL; + + //provides interface CC2520Register as SYNCWORD; + //provides interface CC2520Register as RXCTRL1; + //provides interface CC2520Register as SECCTRL0; + //provides interface CC2520Register as SECCTRL1; + //provides interface CC2520Register as BATTMON; + //provides interface CC2520Register as IOCFG0; + //provides interface CC2520Register as IOCFG1; + // provides interface CC2520Register as MANFIDL; + //provides interface CC2520Register as MANFIDH; + //provides interface CC2520Register as FSMTC; + //provides interface CC2520Register as MANAND; + //provides interface CC2520Register as MANOR; + // provides interface CC2520Register as AGCCTRL; + + // ram + provides interface CC2520Ram as IEEEADR; + provides interface CC2520Ram as PANID; + provides interface CC2520Ram as SHORTADR; + provides interface CC2520Ram as TXFIFO_RAM; + + //Security in RAM +#ifdef CC2520_HW_SECURITY + provides interface CC2520Ram as KEY; + provides interface CC2520Ram as TXNONCE; + provides interface CC2520Ram as RXNONCE; + provides interface CC2520Ram as RXFRAME; + provides interface CC2520Ram as TXFRAME; +#endif + // fifos + provides interface CC2520Fifo as RXFIFO; + provides interface CC2520Fifo as TXFIFO; + +} + +implementation { + + enum { + CLIENT_ID = unique( "CC2520Spi.Resource" ), + }; + + components HplCC2520PinsC as Pins; + components CC2520SpiWireC as Spi; + + ChipSpiResource = Spi.ChipSpiResource; + Resource = Spi.Resource[ CLIENT_ID ]; + + // commands + SNOP = Spi.Strobe[ CC2520_CMD_SNOP ]; + SXOSCON = Spi.Strobe[ CC2520_CMD_SXOSCON ]; + STXCAL = Spi.Strobe[ CC2520_CMD_STXCAL ]; + SRXON = Spi.Strobe[ CC2520_CMD_SRXON ]; + STXON = Spi.Strobe[ CC2520_CMD_STXON ]; + STXONCCA = Spi.Strobe[ CC2520_CMD_STXONCCA ]; + SRFOFF = Spi.Strobe [ CC2520_CMD_SRFOFF ]; + SXOSCOFF = Spi.Strobe[ CC2520_CMD_SXOSCOFF ]; + SFLUSHRX = Spi.Strobe[ CC2520_CMD_SFLUSHRX ]; + SFLUSHTX = Spi.Strobe[ CC2520_CMD_SFLUSHTX ]; + SACK = Spi.Strobe[ CC2520_CMD_SACK ]; + SACKPEND = Spi.Strobe[ CC2520_CMD_SACKPEND ]; + //SRXDEC = Spi.Strobe[ CC2520_SRXDEC ]; + //STXENC = Spi.Strobe[ CC2520_STXENC ]; + //SAES = Spi.Strobe[ CC2520_SAES ]; + + // registers + //MAIN = Spi.Reg[ CC2520_MAIN ]; + + MDMCTRL0 = Spi.Reg[ CC2520_MDMCTRL0 ]; + MDMCTRL1 = Spi.Reg[ CC2520_MDMCTRL1 ]; + RSSI = Spi.Reg[ CC2520_RSSI ]; + //SYNCWORD = Spi.Reg[ CC2520_SYNCWORD ]; + //TXCTRL = Spi.Reg[ CC2520_TXCTRL ]; + //RXCTRL0 = Spi.Reg[ CC2520_RXCTRL0 ]; + //RXCTRL1 = Spi.Reg[ CC2520_RXCTRL1 ]; + //FSCTRL = Spi.Reg[ CC2520_FSCTRL ]; + //SECCTRL0 = Spi.Reg[ CC2520_SECCTRL0 ]; + //SECCTRL1 = Spi.Reg[ CC2520_SECCTRL1 ]; + //BATTMON = Spi.Reg[ CC2520_BATTMON ]; + //IOCFG0 = Spi.Reg[ CC2520_IOCFG0 ]; + //IOCFG1 = Spi.Reg[ CC2520_IOCFG1 ]; + //MANFIDL = Spi.Reg[ CC2520_MANFIDL ]; + //MANFIDH = Spi.Reg[ CC2520_MANFIDH ]; + //FSMTC = Spi.Reg[ CC2520_FSMTC ]; + //MANAND = Spi.Reg[ CC2520_MANAND ]; + //MANOR = Spi.Reg[ CC2520_MANOR ]; + //AGCCTRL = Spi.Reg[ CC2520_AGCCTRL ]; + RXCTRL = Spi.Reg[ CC2520_RXCTRL ]; + FSCTRL = Spi.Reg[ CC2520_FSCTRL ]; + FSCAL1 = Spi.Reg[ CC2520_FSCAL1 ]; + TXPOWER = Spi.Reg[ CC2520_TXPOWER ]; + FREQCTRL = Spi.Reg[ CC2520_FREQCTRL ]; + ADCTEST0 = Spi.Reg[ CC2520_ADCTEST0 ]; + ADCTEST1 = Spi.Reg[ CC2520_ADCTEST1 ]; + ADCTEST2 = Spi.Reg[ CC2520_ADCTEST2 ]; + FRMCTRL0 = Spi.Reg[ CC2520_FRMCTRL0 ]; + + + FRMCTRL1 = Spi.Reg[ CC2520_FRMCTRL1 ]; + RXENABLE1 = Spi.Reg[ CC2520_RXENABLE1 ]; + + + + CCACTRL0 = Spi.Reg[ CC2520_CCACTRL0 ]; + AGCCTRL1 = Spi.Reg[ CC2520_AGCCTRL1 ]; + + EXTCLOCK = Spi.Reg[ CC2520_EXTCLOCK ]; + GPIOCTRL0 = Spi.Reg[ CC2520_GPIOCTRL0 ]; + GPIOCTRL1 = Spi.Reg[ CC2520_GPIOCTRL1 ]; + GPIOCTRL2 = Spi.Reg[ CC2520_GPIOCTRL2 ]; + GPIOCTRL3 = Spi.Reg[ CC2520_GPIOCTRL3 ]; + GPIOCTRL4 = Spi.Reg[ CC2520_GPIOCTRL4 ]; + GPIOCTRL5 = Spi.Reg[ CC2520_GPIOCTRL5 ]; + // newly Added + GPIOPOLARITY = Spi.Reg[ CC2520_GPIOPOLARITY];//CC2520_GPIOPOLARITY ]; + FRMFILT0 = Spi.Reg[ CC2520_FRMFILT0]; + FRMFILT1 = Spi.Reg[ CC2520_FRMFILT1]; + FIFOPCTRL = Spi.Reg[ CC2520_FIFOPCTRL]; + + + EXCFLAG0 = Spi.Reg[ CC2520_EXCFLAG0]; + EXCFLAG1 = Spi.Reg[ CC2520_EXCFLAG1]; + EXCFLAG2 = Spi.Reg[ CC2520_EXCFLAG2]; + FSMSTAT1 = Spi.Reg[ CC2520_FSMSTAT1]; + // ram + IEEEADR = Spi.Ram[ CC2520_RAM_IEEEADR ]; + PANID = Spi.Ram[ CC2520_RAM_PANID ]; + SHORTADR = Spi.Ram[ CC2520_RAM_SHORTADR ]; + TXFIFO_RAM = Spi.Ram[ CC2520_RAM_TXFIFO]; + + #ifdef CC2520_HW_SECURITY + //Security + KEY = Spi.Ram[ CC2520_RAM_KEY0]; + TXNONCE = Spi.Ram[ CC2520_RAM_TXNONCE]; + RXNONCE = Spi.Ram[ CC2520_RAM_RXNONCE]; + RXFRAME = Spi.Ram[ CC2520_RAM_RXFRAME]; + TXFRAME = Spi.Ram[ CC2520_RAM_TXFRAME]; + #endif + + // fifos + RXFIFO = Spi.Fifo[ CC2520_CMD_RXBUF ]; + TXFIFO = Spi.Fifo[ CC2520_CMD_TXBUF ]; + + +} + diff --git a/cc2520/spi/CC2520SpiP.nc b/cc2520/spi/CC2520SpiP.nc new file mode 100644 index 0000000000..291587d6bd --- /dev/null +++ b/cc2520/spi/CC2520SpiP.nc @@ -0,0 +1,449 @@ +/* + * 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 + */ +// The actual Spi files are located in Msp430SpiNoDmaBP.nc & HplMsp430UsciB0P.nc--- Lijo +/** + * @author Jonathan Hui + * @author David Moss + * @author Roman Lim + * @author Razvan Musaloie-E. + * @author Jeonggil Ko + * @version $Revision: 1.4 $ $Date: 2008/06/23 20:25:15 $ + */ + + +#define HI_UINT16(a) (((int)(a) >> 8) & 0xFF) +#define LO_UINT16(a) ((int)(a) & 0xFF) + +module CC2520SpiP @safe() { + + provides { + interface ChipSpiResource; + interface Resource[ uint8_t id ]; + interface CC2520Fifo as Fifo[ uint8_t id ]; + interface CC2520Ram as Ram[ uint16_t id ]; + interface CC2520Register as Reg[ uint8_t id ]; + interface CC2520Strobe 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( "CC2520Spi.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 cc2520_status_t Fifo.beginRead[ uint8_t addr ]( uint8_t* data, + uint8_t len ) { + + cc2520_status_t status = 0; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + + // m_addr = addr | 0x40; + //printf("\n Fifo Read"); + //m_addr = addr; + + m_addr = CC2520_CMD_RXBUF; + status = call SpiByte.write( m_addr ); + m_addr = addr | 0x40; // For Reading ...used in SpiPacket.sendDone + 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 cc2520_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 = CC2520_CMD_TXBUF ; //addr; // CC2520_CMD_TXBUF + + status = call SpiByte.write( m_addr ); + call SpiPacket.send( data, NULL, len ); + + return status; + + } + + /***************** RAM Commands ****************/ + async command cc2520_status_t Ram.read[ uint16_t addr ]( uint8_t offset, + uint8_t* data, + uint8_t len ) { + + cc2520_status_t status = 0; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + + call SpiByte.write(CC2520_CMD_MEMORY_READ | (HI_UINT16(addr))); + addr = LO_UINT16(addr); + status = call SpiByte.write( addr ); // Edited by Lijo + for ( ; len; len-- ) { + *data++ = call SpiByte.write( 0 ); + } + + return status; + + } + + + async command cc2520_status_t Ram.write[ uint16_t addr ]( uint8_t offset, + uint8_t* data, + uint8_t len ) { + + cc2520_status_t status = 0; + uint8_t tmpLen = len; + uint8_t * COUNT(tmpLen) tmpData = (uint8_t * COUNT(tmpLen))data; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + call SpiByte.write(CC2520_CMD_MEMORY_WRITE | (HI_UINT16(addr))); + addr = LO_UINT16(addr); + status = call SpiByte.write( addr ); // Edited by Lijo + for ( ; len; len-- ) { + call SpiByte.write( tmpData[tmpLen-len] ); + // call SpiByte.write( tmpData[len-1] ); //Jamal:Writing in reverse order + } + + return status; + + } + + /***************** Register Commands ****************/ + async command cc2520_status_t Reg.read[ uint8_t addr ]( uint16_t* data ) { + + cc2520_status_t status = 0; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + + //call SpiByte.write( CC2520_CMD_MEMORY_READ | (HI_UINT16(addr)) ); + //call SpiByte.write( LO_UINT16(addr) ); + //status = call SpiByte.write( addr | 0x40 ); + //printf("Memory Read: %x , Register Address : %x \n", CC2520_CMD_MEMORY_WRITE,addr); + call SpiByte.write( CC2520_CMD_MEMORY_READ ); + call SpiByte.write(addr); + //printf("Value: %x \n", call SpiByte.write( 0x00 )); + //call SpiByte.write( 0x00 ); + + //printf("CC2520 Status: %x \n", call SpiByte.write( 0x00 )); + + *data = (uint16_t)call SpiByte.write( 0 ) << 8; + *data |= call SpiByte.write( 0 ); + + //*data =0; + + + return status; + + } + + async command cc2520_status_t Reg.write[ uint8_t addr ]( uint16_t data ) { + + atomic { + if(call WorkingState.isIdle()) { + return 0; + } + } + + if(addr <= CC2520_FREG_MASK) + { + // we can use 1 byte less to write this register using the + // register write command + + //ASSERT( addr == (addr & CC2520_FREG_MASK) ); + addr = (addr & CC2520_FREG_MASK); + //printf(" Register Address : %x , Data : %x\n", (CC2520_CMD_MEMORY_WRITE ),addr); + + //status.value = call SpiByte.write(CC2520_CMD_REGISTER_WRITE | reg); + //call SpiByte.write(CC2520_CMD_REGISTER_WRITE | addr); + call SpiByte.write(CC2520_CMD_MEMORY_WRITE); + call SpiByte.write(addr); + + } + else + { + // we have to use the memory write command as the register is in + // SREG + + //ASSERT( addr == (addr & CC2520_SREG_MASK) ); + addr = (addr & CC2520_SREG_MASK); + // printf(" Register Address : %x , Data : %x\n", (addr),data); + // the register has to be below the 0x100 memory address. Thus, we + // don't have to add anything to the MEMORY_WRITE command. + call SpiByte.write(CC2520_CMD_MEMORY_WRITE); + call SpiByte.write(addr); + + } + + + //call SpiByte.write( addr ); + //call SpiByte.write( data >> 8 ); + //return call SpiByte.write( data & 0xff ); + //call SpiByte.write( CC2520_CMD_MEMORY_WRITE ); + //call SpiByte.write(addr); + // call SpiByte.write( data ); + + // printf("Memory Write: %x , Register Address : %x , Data : %x\n", CC2520_CMD_MEMORY_WRITE,addr,data); + //printf("Value 0: %x Value1: %x \n", *(data+0),*(data+1)); + //call SpiByte.write( CC2520_CMD_MEMORY_WRITE | (HI_UINT16(addr)) ); + //call SpiByte.write( LO_UINT16(addr) ); + //return call SpiByte.write( 0x32 ); + + return call SpiByte.write((data & 0xFF)); // Edited by Lijo + } + + + + + /***************** Strobe Commands ****************/ + async command cc2520_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/cc2520/spi/CC2520SpiP_edited.nc b/cc2520/spi/CC2520SpiP_edited.nc new file mode 100644 index 0000000000..b3830713d9 --- /dev/null +++ b/cc2520/spi/CC2520SpiP_edited.nc @@ -0,0 +1,459 @@ +/* + * 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 + */ +// The actual Spi files are located in Msp430SpiNoDmaBP.nc & HplMsp430UsciB0P.nc--- Lijo +/** + * @author Jonathan Hui + * @author David Moss + * @author Roman Lim + * @author Razvan Musaloie-E. + * @author Jeonggil Ko + * @version $Revision: 1.4 $ $Date: 2008/06/23 20:25:15 $ + */ + + +#define HI_UINT16(a) (((int)(a) >> 8) & 0xFF) +#define LO_UINT16(a) ((int)(a) & 0xFF) +#include "printf.h" +module CC2520SpiP @safe() { + + provides { + interface ChipSpiResource; + interface Resource[ uint8_t id ]; + interface CC2520Fifo as Fifo[ uint8_t id ]; + interface CC2520Ram as Ram[ uint16_t id ]; + interface CC2520Register as Reg[ uint8_t id ]; + interface CC2520Strobe 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( "CC2520Spi.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 cc2520_status_t Fifo.beginRead[ uint8_t addr ]( uint8_t* data, + uint8_t len ) { + + cc2520_status_t status = 0; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + + // m_addr = addr | 0x40; + //printf("\n Fifo Read"); + //m_addr = addr; + + m_addr = CC2520_CMD_RXBUF; + status = call SpiByte.write( m_addr ); + m_addr = addr | 0x40; // For Reading ...used in SpiPacket.sendDone + 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 cc2520_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 = CC2520_CMD_TXBUF ; //addr; // CC2520_CMD_TXBUF + + status = call SpiByte.write( m_addr ); + call SpiPacket.send( data, NULL, len ); + + return status; + + } + + /***************** RAM Commands ****************/ + async command cc2520_status_t Ram.read[ uint16_t addr ]( uint8_t offset, + uint8_t* data, + uint8_t len ) { + + cc2520_status_t status = 0; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + + call SpiByte.write(CC2520_CMD_MEMORY_READ | (HI_UINT16(addr))); + + addr = LO_UINT16(addr); + addr += offset; + + //status = call SpiByte.write( addr | 0x80 ); + status = call SpiByte.write( addr ); // Edited by Lijo + //call SpiByte.write( ( ( addr >> 1 ) & 0xC0 ) | 0x20 ); + for ( ; len; len-- ) { + *data++ = call SpiByte.write( 0 ); + } + + return status; + + } + + + async command cc2520_status_t Ram.write[ uint16_t addr ]( uint8_t offset, + uint8_t* data, + uint8_t len ) { + + cc2520_status_t status = 0; + uint8_t tmpLen = len; + uint8_t * COUNT(tmpLen) tmpData = (uint8_t * COUNT(tmpLen))data; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + //printf("\n SpiP_Ram_Write"); + + //printf("\n Ram_rt : %x",call SpiByte.write(CC2520_CMD_MEMORY_WRITE | (HI_UINT16(addr)))); + call SpiByte.write(CC2520_CMD_MEMORY_WRITE | (HI_UINT16(addr))); + + addr = LO_UINT16(addr); + addr += offset; + + status = call SpiByte.write( addr ); // Edited by Lijo + // printf("\n Ram_rt : %x",call SpiByte.write( addr )); + //status = call SpiByte.write( addr | 0x80 ); + //call SpiByte.write( ( addr >> 1 ) & 0xc0 ); + for ( ; len; len-- ) { + // printf("\n Ram_rt : %x",); + (call SpiByte.write( tmpData[tmpLen-len] )); + } + + return status; + + } + + /***************** Register Commands ****************/ + async command cc2520_status_t Reg.read[ uint8_t addr ]( uint16_t* data ) { + + cc2520_status_t status = 0; + + atomic { + if(call WorkingState.isIdle()) { + return status; + } + } + + //call SpiByte.write( CC2520_CMD_MEMORY_READ | (HI_UINT16(addr)) ); + //call SpiByte.write( LO_UINT16(addr) ); + //status = call SpiByte.write( addr | 0x40 ); + //printf("Memory Read: %x , Register Address : %x \n", CC2520_CMD_MEMORY_WRITE,addr); + call SpiByte.write( CC2520_CMD_MEMORY_READ ); + call SpiByte.write(addr); + call SpiByte.write( 0x00 ); + //printf("CC2520 Status: %x \n", call SpiByte.write( 0x00 )); + + /**data = (uint16_t)call SpiByte.write( 0 ) << 8; + *data |= call SpiByte.write( 0 );*/ + + *data =0; + + + return status; + + } + + async command cc2520_status_t Reg.write[ uint8_t addr ]( uint16_t data ) { + + atomic { + if(call WorkingState.isIdle()) { + return 0; + } + } + + if(addr <= CC2520_FREG_MASK) + { + // we can use 1 byte less to write this register using the + // register write command + + //ASSERT( addr == (addr & CC2520_FREG_MASK) ); + addr = (addr & CC2520_FREG_MASK); + //printf(" Register Address : %x , Data : %x\n", (CC2520_CMD_MEMORY_WRITE ),addr); + + //status.value = call SpiByte.write(CC2520_CMD_REGISTER_WRITE | reg); + //call SpiByte.write(CC2520_CMD_REGISTER_WRITE | addr); + call SpiByte.write(CC2520_CMD_MEMORY_WRITE); + call SpiByte.write(addr); + + } + else + { + // we have to use the memory write command as the register is in + // SREG + + //ASSERT( addr == (addr & CC2520_SREG_MASK) ); + addr = (addr & CC2520_SREG_MASK); + // printf(" Register Address : %x , Data : %x\n", (addr),data); + // the register has to be below the 0x100 memory address. Thus, we + // don't have to add anything to the MEMORY_WRITE command. + call SpiByte.write(CC2520_CMD_MEMORY_WRITE); + call SpiByte.write(addr); + + } + + + //call SpiByte.write( addr ); + //call SpiByte.write( data >> 8 ); + //return call SpiByte.write( data & 0xff ); + //call SpiByte.write( CC2520_CMD_MEMORY_WRITE ); + //call SpiByte.write(addr); + // call SpiByte.write( data ); + + // printf("Memory Write: %x , Register Address : %x , Data : %x\n", CC2520_CMD_MEMORY_WRITE,addr,data); + //printf("Value 0: %x Value1: %x \n", *(data+0),*(data+1)); + //call SpiByte.write( CC2520_CMD_MEMORY_WRITE | (HI_UINT16(addr)) ); + //call SpiByte.write( LO_UINT16(addr) ); + //return call SpiByte.write( 0x32 ); + + return call SpiByte.write((data & 0xFF)); // Edited by Lijo + } + + + /***************** Strobe Commands ****************/ + async command cc2520_status_t Strobe.strobe[ uint8_t addr ]() { + atomic { + if(call WorkingState.isIdle()) { + return 0; + } + } + if(addr == CC2520_CMD_SRFOFF ) + 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/cc2520/spi/CC2520SpiWireC.nc b/cc2520/spi/CC2520SpiWireC.nc new file mode 100644 index 0000000000..575a72dbc8 --- /dev/null +++ b/cc2520/spi/CC2520SpiWireC.nc @@ -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 + * @version $Revision: 1.1 $ $Date: 2007/07/04 00:37:16 $ + */ + +configuration CC2520SpiWireC { + + provides interface Resource[ uint8_t id ]; + provides interface ChipSpiResource; + provides interface CC2520Fifo as Fifo[ uint8_t id ]; + provides interface CC2520Ram as Ram[ uint16_t id ]; + provides interface CC2520Register as Reg[ uint8_t id ]; + provides interface CC2520Strobe as Strobe[ uint8_t id ]; + +} + +implementation { + + components CC2520SpiP as SpiP; + Resource = SpiP; + Fifo = SpiP; + Ram = SpiP; + Reg = SpiP; + Strobe = SpiP; + ChipSpiResource = SpiP; + + components new StateC() as WorkingStateC; + SpiP.WorkingState -> WorkingStateC; + + components new HplCC2520SpiC(); + SpiP.SpiResource -> HplCC2520SpiC; + SpiP.SpiByte -> HplCC2520SpiC; + SpiP.SpiPacket -> HplCC2520SpiC; + + components LedsC; + SpiP.Leds -> LedsC; + +} diff --git a/cc2520/transmit/CC2520TransmitC.nc b/cc2520/transmit/CC2520TransmitC.nc new file mode 100644 index 0000000000..ac09fdca79 --- /dev/null +++ b/cc2520/transmit/CC2520TransmitC.nc @@ -0,0 +1,119 @@ +/* + * 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 CC2520 radio. + * + * @author Jonathan Hui + * @version $Revision: 1.2 $ $Date: 2008/06/17 07:28:24 $ + */ + +#include "IEEE802154.h" + +configuration CC2520TransmitC { + + provides { + interface StdControl; + interface CC2520Transmit; + interface RadioBackoff; + interface ReceiveIndicator as EnergyIndicator; + interface ReceiveIndicator as ByteIndicator; + } +} + +implementation { + + components CC2520TransmitP; + StdControl = CC2520TransmitP; + CC2520Transmit = CC2520TransmitP; + RadioBackoff = CC2520TransmitP; + EnergyIndicator = CC2520TransmitP.EnergyIndicator; + ByteIndicator = CC2520TransmitP.ByteIndicator; + + components MainC; + MainC.SoftwareInit -> CC2520TransmitP; + MainC.SoftwareInit -> Alarm; + + components AlarmMultiplexC as Alarm; + CC2520TransmitP.BackoffTimer -> Alarm; + + components HplCC2520PinsC as Pins; + CC2520TransmitP.CCA -> Pins.CCA; + CC2520TransmitP.CSN -> Pins.CSN; + CC2520TransmitP.SFD -> Pins.SFD; + + components HplCC2520InterruptsC as Interrupts; + CC2520TransmitP.CaptureSFD -> Interrupts.CaptureSFD; + + components new CC2520SpiC() as Spi; + CC2520TransmitP.SpiResource -> Spi; + CC2520TransmitP.ChipSpiResource -> Spi; + CC2520TransmitP.SNOP -> Spi.SNOP; + CC2520TransmitP.STXON -> Spi.STXON; + CC2520TransmitP.STXONCCA -> Spi.STXONCCA; + CC2520TransmitP.SFLUSHTX -> Spi.SFLUSHTX; + CC2520TransmitP.TXPOWER -> Spi.TXPOWER; + CC2520TransmitP.EXCFLAG1 -> Spi.EXCFLAG1; + CC2520TransmitP.TXFIFO -> Spi.TXFIFO; + CC2520TransmitP.TXFIFO_RAM -> Spi.TXFIFO_RAM; +#ifdef CC2520_HW_SECURITY + CC2520TransmitP.TXFRAME -> Spi.TXFRAME; + CC2520TransmitP.TXNonce -> Spi.TXNONCE; + + components new HplCC2520SpiC(); + CC2520TransmitP.SpiByte -> HplCC2520SpiC; + + components CC2520KeyC; + CC2520TransmitP.CC2520Key -> CC2520KeyC; + + +#endif + // CC2520TransmitP.MDMCTRL1 -> Spi.MDMCTRL1; + + components CC2520ReceiveC; + CC2520TransmitP.CC2520Receive -> CC2520ReceiveC; + + components CC2520PacketC; + CC2520TransmitP.CC2520Packet -> CC2520PacketC; + CC2520TransmitP.CC2520PacketBody -> CC2520PacketC; + CC2520TransmitP.PacketTimeStamp -> CC2520PacketC; + CC2520TransmitP.PacketTimeSyncOffset -> CC2520PacketC; + + + components LedsC; + CC2520TransmitP.Leds -> LedsC; + + #if defined(LCD_DEBUG) + components LcdC; + CC2520TransmitP.Lcd -> LcdC; + #endif + +} diff --git a/cc2520/transmit/CC2520TransmitP.nc b/cc2520/transmit/CC2520TransmitP.nc new file mode 100644 index 0000000000..b56820542f --- /dev/null +++ b/cc2520/transmit/CC2520TransmitP.nc @@ -0,0 +1,932 @@ +/* + * 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 + * @author David Moss + * @author Jung Il Choi Initial SACK implementation + * @version $Revision: 1.9 $ $Date: 2008/07/11 19:21:23 $ + */ + +#include "CC2520.h" +#include "CC2520TimeSyncMessage.h" +#include "crc.h" +#include "message.h" + +#ifdef CC2520_HW_SECURITY + #define LOW_PRIORITY 0 + #define HIGH_PRIORITY 1 +#endif + +module CC2520TransmitP @safe() { + + provides interface Init; + provides interface StdControl; + provides interface CC2520Transmit as Send; + provides interface RadioBackoff; + provides interface ReceiveIndicator as EnergyIndicator; + provides interface ReceiveIndicator as ByteIndicator; + + uses interface Alarm as BackoffTimer; + uses interface CC2520Packet; + uses interface CC2520PacketBody; + uses interface PacketTimeStamp; + uses interface PacketTimeSyncOffset; + 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 CC2520Fifo as TXFIFO; + uses interface CC2520Ram as TXFIFO_RAM; +#ifdef CC2520_HW_SECURITY + uses interface CC2520Ram as TXFRAME; + uses interface SpiByte; + uses interface CC2520Key; + uses interface CC2520Ram as TXNonce; +#endif + uses interface CC2520Register as TXPOWER; + uses interface CC2520Register as EXCFLAG1; + uses interface CC2520Strobe as SNOP; + uses interface CC2520Strobe as STXON; + uses interface CC2520Strobe as STXONCCA; + uses interface CC2520Strobe as SFLUSHTX; + //uses interface CC2520Register as MDMCTRL1; + + uses interface CC2520Receive; + uses interface Leds; + +#if defined(LCD_DEBUG) + uses interface Lcd; +#endif +} + +implementation { + + typedef enum { + S_STOPPED, + S_STARTED, + S_LOAD, + S_SAMPLE_CCA, + S_BEGIN_TRANSMIT, + S_SFD, + S_EFD, + S_ACK_WAIT, + S_CANCEL, + } cc2520_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 { + CC2520_ABORT_PERIOD = 200 //320 + }; + + norace message_t * ONE_NOK m_msg; + + norace bool m_cca; + + norace uint8_t m_tx_power; + + cc2520_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; + + #ifdef CC2520_HW_SECURITY + uint8_t read_memory[60]; + void encryptTXFIFO(void); + uint8_t getMICLength(uint8_t SecurityLevel) ; +#endif + + + /***************** Prototypes ****************/ + error_t send( message_t * ONE 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; + //if(PRINTF_ENABLED) + + } + 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(); + //if(PRINTF_ENABLED) + //printf("\n Transmit stoped.."); + } + return SUCCESS; + } + + + /**************** Send Commands ****************/ + async command error_t Send.send( message_t* ONE p_msg, bool useCca ) { + //if(PRINTF_ENABLED) + //printf("\n Send_TransmitP");printfflush(); + //return send( p_msg, useCca ); + return send(p_msg,useCca); + } + + async command error_t Send.resend(bool useCca) { + //if(PRINTF_ENABLED) + //printf("\n Resend_TransmitP"); + return resend( useCca ); + } + + async command error_t Send.cancel() { + atomic { + switch( m_state ) { + case S_LOAD: + case S_SAMPLE_CCA: + case S_BEGIN_TRANSMIT: + m_state = S_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(); + //if(PRINTF_ENABLED) + //printf("\n Send.modify"); + 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) { + } + + + inline uint32_t time16to32(uint16_t time, uint32_t recent_time) + { + if ((recent_time&0xFFFF)data + (call PacketTimeSyncOffset.get(m_msg) - sizeof(cc2520_header_t)); + timesync_radio_t *timesync = (timesync_radio_t*)taddr; + // set timesync event time as the offset between the event time and the SFD interrupt time (TEP 133) + *timesync -= time32; + call CSN.clr(); + call TXFIFO_RAM.write( call PacketTimeSyncOffset.get(m_msg), (uint8_t*)timesync, sizeof(timesync_radio_t) ); + call CSN.set(); + // if(PRINTF_ENABLED) + //printf("\n S_SFD2"); + } + + if ( (call CC2520PacketBody.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(); + //if(PRINTF_ENABLED) + //printf("\n Backoff Timer Stoped"); + call BackoffTimer.stop(); + + + if ( ( ( (call CC2520PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) { + call PacketTimeStamp.set(m_msg, time32); + } + + if ( call SFD.get() ) { + //if(PRINTF_ENABLED) + // printf("\n SFD.get1"); + break; + } + /** Fall Through because the next interrupt was already received */ + + case S_EFD: + sfdHigh = FALSE; + call CaptureSFD.captureRisingEdge(); + + //printf("\n S_EFD"); + if ( (call CC2520PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) { + m_state = S_ACK_WAIT; + call BackoffTimer.start( CC2520_ACK_WAIT_DELAY ); + } else { +// call Leds.led0Toggle(); + signalDone(SUCCESS); + } + //if(PRINTF_ENABLED) + //printf("\n S_EFD.get2"); + if ( !call SFD.get() ) { + break; + } + /** Fall Through because the next interrupt was already received */ + + default: + if ( !m_receiving ) { + sfdHigh = TRUE; + call CaptureSFD.captureFallingEdge(); + call CC2520Receive.sfd( time32 ); + m_receiving = TRUE; + m_prev_time = time; + //if(PRINTF_ENABLED) + //printf("\n Sfd default"); + if ( call SFD.get() ) { + // wait for the next interrupt before moving on + return; + } + } + //if(PRINTF_ENABLED) + // printf("\n Sfd default1"); + sfdHigh = FALSE; + call CaptureSFD.captureRisingEdge(); + m_receiving = FALSE; + if ( time - m_prev_time < 10 ) { + call CC2520Receive.sfd_dropped(); + if (m_msg) + call PacketTimeStamp.clear(m_msg); + } + 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 CC2520Receive.receive( uint8_t type, message_t* ack_msg ) { + cc2520_header_t* ack_header; + cc2520_header_t* msg_header; + cc2520_metadata_t* msg_metadata; + uint8_t* ack_buf; + uint8_t length; + //if(PRINTF_ENABLED) + //printf("\n cc2520 receive_Tx"); + if ( type == IEEE154_TYPE_ACK && m_msg) { + ack_header = call CC2520PacketBody.getHeader( ack_msg ); + msg_header = call CC2520PacketBody.getHeader( m_msg ); + + + if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) { + call BackoffTimer.stop(); + + msg_metadata = call CC2520PacketBody.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; + //printf("\n spi granted");printfflush(); + atomic { + cur_state = m_state; + } + + switch( cur_state ) { + case S_LOAD: + loadTXFIFO(); + break; + + case S_BEGIN_TRANSMIT: + attemptSend(); + break; + + case S_CANCEL: + call CSN.clr(); + call SFLUSHTX.strobe(); + call CSN.set(); + releaseSpiResource(); + atomic { + m_state = S_STARTED; + } + signal Send.sendDone( m_msg, ECANCEL ); + 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 ) { + // printf("\n TXFIFO writeDone");printfflush(); + call CSN.set(); + + if ( m_state == S_CANCEL ) { + atomic { + call CSN.clr(); + call SFLUSHTX.strobe(); + call CSN.set(); + //printf("\n TX FIFO SFLUSH"); + } + + releaseSpiResource(); + m_state = S_STARTED; + //printf("\n State Started"); + signal Send.sendDone( m_msg, ECANCEL ); + + } else if ( !m_cca ) { + + atomic { + m_state = S_BEGIN_TRANSMIT; + //printf("\n State Begin"); + + } + + attemptSend(); + //printf("\n TX FIFO attempt send"); + //printfflush(); + } else { + + releaseSpiResource(); + atomic { + m_state = S_SAMPLE_CCA; + //printf("\n State CCA"); + } + + signal RadioBackoff.requestInitialBackoff(m_msg); + + call BackoffTimer.start(myInitialBackoff); + //printf("\n TX FIFO back offTimer"); + //printfflush(); + } + } + + + 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( CC2520_TIME_ACK_TURNAROUND ); + // printf("\nbackoff_Timer"); + } else { + + congestionBackoff(); + //printf("\n CCA Congestion"); + } + break; + + case S_BEGIN_TRANSMIT: + case S_CANCEL: + if ( acquireSpiResource() == SUCCESS ) { + attemptSend(); + + //printf("\n backoff_Send"); + }else{ + //printf("\n failed to get the resource"); + //printfflush(); + } + break; + + case S_ACK_WAIT: + + signalDone( SUCCESS ); + //printf("\n attempt Sucess"); printfflush(); + 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 ); + //printf("\n S_SFD"); printfflush(); + 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* ONE p_msg, bool cca ) { + atomic { + if (m_state == S_CANCEL) { + //printf("\n ECANCEL"); + + return ECANCEL; + } + + if ( m_state != S_STARTED ) { + //printf("\n FAIL"); + + return FAIL; + } + + m_state = S_LOAD; + m_cca = cca; + m_msg = p_msg; + totalCcaChecks = 0; + } + + + if ( acquireSpiResource() == SUCCESS ) { + + #ifdef CC2520_HW_SECURITY + encryptTXFIFO(); + #endif + loadTXFIFO(); + + + }else{ + } + + 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_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; + //printf("\n ReSend"); + atomic { + if (m_state == S_CANCEL) { + call CSN.set(); + call CSN.clr(); + call SFLUSHTX.strobe(); + releaseSpiResource(); + call CSN.set(); + m_state = S_STARTED; + // printf("\n S_CANCEL"); + signal Send.sendDone( m_msg, ECANCEL ); + return; + } + // printf("\n STXONCCA"); + call CSN.set(); + call CSN.clr(); + + status = m_cca ? call STXONCCA.strobe() : call STXON.strobe(); + call CSN.set(); + call CSN.clr(); + if ( !( status & CC2520_STATUS_TX_ACTIVE ) ) { + + status = call SNOP.strobe(); + if ( status & CC2520_STATUS_TX_ACTIVE ) { + + congestion = FALSE; + } + } + + m_state = congestion ? S_SAMPLE_CCA : S_SFD; + call CSN.set(); + } + + call CSN.clr(); + //printf("\n Tx status: %x",(call SNOP.strobe()));printfflush(); + call CSN.set(); + if ( congestion ) { + totalCcaChecks = 0; + releaseSpiResource(); + congestionBackoff(); + + } else { + call BackoffTimer.start(CC2520_ABORT_PERIOD); + //printf("\n Start BackoffTimer");printfflush(); + } + } + + + /** + * 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 ) { + // printf("\nspi error:%d",error);printfflush(); + call SpiResource.request(); + } + return error; + } + + error_t releaseSpiResource() { + call SpiResource.release(); + return SUCCESS; + } + + #ifdef CC2520_HW_SECURITY + + uint8_t getMICLength(uint8_t securityLevel) { + + if(securityLevel == SEC_MIC_32 || securityLevel == SEC_ENC_MIC_32) + return 4; + else if(securityLevel == SEC_MIC_64 || securityLevel == SEC_ENC_MIC_64) + return 8; + else if(securityLevel == SEC_ENC_MIC_128 || securityLevel == SEC_ENC_MIC_128) + return 16; + return 0; + } + + + void reverseArray(uint8_t *ptr,uint8_t length) + { + uint8_t i,tmp; + for(i=0; i< length/2;i++) + { + tmp = ptr[i]; + ptr[i] = ptr[length -i]; + ptr[length-i] = tmp; + } + } + + void readFrame() + { + uint8_t i; + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_msg ); + memset(read_memory,0,sizeof(read_memory)); + call CSN.clr(); + call TXFRAME.read(0, read_memory, header->length); + call CSN.set(); + //printf("Packet After Encryption\n"); + //for(i=0;ilength;i++) + // printf("%x\t",read_memory[i]); + //printfflush(); + } + + + + void encryptTXFIFO(void) { + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_msg ); + uint8_t *ptr = (uint8_t *)header; + //uint32_t frame_counter = header->secHdr.frameCounter; + uint8_t micLength = getMICLength(header->secHdr.secLevel); + uint8_t encryptLength = header->length - CC2520_SIZE - micLength; + uint8_t authLength = CC2520_SIZE - MAC_FOOTER_SIZE; + + /* + * Step1 : Load the frame in the CC2520 RAM with MEMWR instructions + */ + + call CSN.clr(); + call TXFRAME.write(0, ptr,header->length-micLength-1); + call CSN.set(); + + /*Step 2: Perform the CCM operation on the address the frame was loaded to +1(excluding the length byte)*/ + /* + * CCM Instruction: + * + * CCM(uint8_t p, uint8_t k, uint8_t c, uint8_t n, uint16_t a,uint16_t e, + * uint8_t f, uint8_t m) + * + * p --> priority (Either 0 or 1) + * k --> Pointer to 128 bit Key Address. The key is stored in reversed byte + * order starting at address 16 * k + * c --> Number of bytes to authenticate and encrypt, typically the frame + * payload. Encrypt and authenticate c bytes starting at address a+f. * If c = 0 it will only authenticate, no encryption is + * performed + * n --> Pointer to 128 bit concatenation of flags,nonce and counter.Note + * that this value is stored in reverse byte order.value = addr/16 + * + * a --> Frame buffer,the whole frame except the length field + * + * e --> Pointer to start of output data.set to 0 for inline authentication/ + * encryption + * + * f --> Authenticate F bytes of plaintext starting at address A.This + * parameter is also used to calculate the starting address of the c * bytes that will be both encrypted and authenticated + * m --> Mic length + * + */ + call CSN.clr(); + call SpiByte.write(CC2520_CMD_CCM | HIGH_PRIORITY); + call SpiByte.write(CC2520_RAM_KEY0/16); + call SpiByte.write(encryptLength); + call SpiByte.write(CC2520_RAM_TXNONCE/16); + call SpiByte.write((HI_UINT16(CC2520_RAM_TXFRAME+1)<<4)|HI_UINT16(0)); + call SpiByte.write(LO_UINT16(CC2520_RAM_TXFRAME+1)); + call SpiByte.write(LO_UINT16(0)); //For Inline Security + call SpiByte.write(authLength); + call SpiByte.write(micLength); + call CSN.set(); + call CSN.clr(); + while(call SNOP.strobe() & 0x08); + call CSN.set(); + + call CSN.clr(); + call TXFRAME.read(0, (uint8_t *)header, header->length-1); + call CSN.set(); + + /*Step3 :Move the frame to the TXFIFO with the TXBUFCP Instruction*/ + /* Not working this instruction so we are reading directly from RAM + and writing into FIFO */ + /*call CSN.clr(); + call SpiByte.write(CC2520_CMD_TXBUFCP | HIGH_PRIORITY); + call SpiByte.write(header->length-1); + call SpiByte.write(HI_UINT16(CC2520_RAM_TXFRAME)); + call SpiByte.write(LO_UINT16(CC2520_RAM_TXFRAME)); + call CSN.set();*/ + /* Wait for the instruction to execute*/ + /* + call CSN.clr(); + while(call SNOP.strobe() & 0x08); + call CSN.set(); + */ + } + + event void CC2520Key.setKeyDone(uint8_t status) + { + } + + event void CC2520Key.getKeyDone(uint8_t status, uint8_t *ptr) + { + } + + #endif + /** + * 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() { + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_msg ); + uint8_t tx_power = (call CC2520PacketBody.getMetadata( m_msg ))->tx_power; + //printf("\n Transmit Power 0 : %x",tx_power ); + if ( !tx_power ) { + tx_power = CC2520_DEF_RFPOWER; + + // printf("\n Defined Power 0 : %x",CC2520_DEF_RFPOWER ); + } + + call CSN.clr(); + + if ( m_tx_power != tx_power ) { + /* call TXPOWER.write( ( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) | + ( 3 << CC2420_TXCTRL_PA_CURRENT ) | + ( 1 << CC2420_TXCTRL_RESERVED ) | + ( (tx_power & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) );*/ + //call TXPOWER.write( (tx_power)); + //printf("\n Transmit Power 1 : %x",CC2520_DEF_RFPOWER ); + //printf("\n M Transmit Power 2 : %x",m_tx_power ); + } + //printf("\n Transmit Power 3 : %x",tx_power ); + //printf("\n M Transmit Power 4 : %x",m_tx_power ); + + m_tx_power = tx_power; + + { + uint8_t tmpLen __DEPUTY_UNUSED__ = header->length - 1; + call TXFIFO.write(TCAST(uint8_t * COUNT(tmpLen), header), header->length - 1); + //printf("\n write in the txfifo");printfflush(); + } + } + + void signalDone( error_t err ) { + atomic m_state = S_STARTED; + abortSpiRelease = FALSE; + // printf("\n attempting to release chipspi");printfflush(); + call ChipSpiResource.attemptRelease(); + signal Send.sendDone( m_msg, err ); + } +} + diff --git a/cc2520/transmit/CC2520TransmitP2.nc b/cc2520/transmit/CC2520TransmitP2.nc new file mode 100644 index 0000000000..14442af26f --- /dev/null +++ b/cc2520/transmit/CC2520TransmitP2.nc @@ -0,0 +1,723 @@ +/* + * 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 + * @author David Moss + * @author Jung Il Choi Initial SACK implementation + * @version $Revision: 1.9 $ $Date: 2008/07/11 19:21:23 $ + */ + +#include "CC2520.h" +#include "CC2520TimeSyncMessage.h" +#include "crc.h" +#include "message.h" +#include "printf.h" + +module CC2520TransmitP @safe() { + + provides interface Init; + provides interface StdControl; + provides interface CC2520Transmit as Send; + provides interface RadioBackoff; + provides interface ReceiveIndicator as EnergyIndicator; + provides interface ReceiveIndicator as ByteIndicator; + + uses interface Alarm as BackoffTimer; + uses interface CC2520Packet; + uses interface CC2520PacketBody; + uses interface PacketTimeStamp; + uses interface PacketTimeSyncOffset; + 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 CC2520Fifo as TXFIFO; + uses interface CC2520Ram as TXFIFO_RAM; + uses interface CC2520Register as TXPOWER; + uses interface CC2520Strobe as SNOP; + uses interface CC2520Strobe as STXON; + uses interface CC2520Strobe as STXONCCA; + uses interface CC2520Strobe as SFLUSHTX; + //uses interface CC2520Register as MDMCTRL1; + + uses interface CC2520Receive; + +} + +implementation { + + typedef enum { + S_STOPPED, + S_STARTED, + S_LOAD, + S_SAMPLE_CCA, + S_BEGIN_TRANSMIT, + S_SFD, + S_EFD, + S_ACK_WAIT, + S_CANCEL, + } cc2520_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 { + CC2520_ABORT_PERIOD = 320 + }; + + norace message_t * ONE_NOK m_msg; + + norace bool m_cca; + + norace uint8_t m_tx_power; + + cc2520_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 * ONE 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; + printf("\n Transmit init.."); + } + 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(); + printf("\n Transmit stoped.."); + } + return SUCCESS; + } + + + /**************** Send Commands ****************/ + async command error_t Send.send( message_t* ONE 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: + case S_SAMPLE_CCA: + case S_BEGIN_TRANSMIT: + m_state = S_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(); + printf("\n Send.modify"); + 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) { + } + + + inline uint32_t time16to32(uint16_t time, uint32_t recent_time) + { + if ((recent_time&0xFFFF)data + (call PacketTimeSyncOffset.get(m_msg) - sizeof(cc2520_header_t)); + timesync_radio_t *timesync = (timesync_radio_t*)taddr; + // set timesync event time as the offset between the event time and the SFD interrupt time (TEP 133) + *timesync -= time32; + call CSN.clr(); + call TXFIFO_RAM.write( call PacketTimeSyncOffset.get(m_msg), (uint8_t*)timesync, sizeof(timesync_radio_t) ); + call CSN.set(); + printf("\n S_SFD"); + } + + if ( (call CC2520PacketBody.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(); + printf("\n Stop Backoff Timer"); + call BackoffTimer.stop(); + + + if ( ( ( (call CC2520PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) { + call PacketTimeStamp.set(m_msg, time32); + } + + if ( call SFD.get() ) { + printf("\n S_SFD1"); + break; + } + /** Fall Through because the next interrupt was already received */ + + case S_EFD: + sfdHigh = FALSE; + call CaptureSFD.captureRisingEdge(); + + if ( (call CC2520PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) { + m_state = S_ACK_WAIT; + call BackoffTimer.start( CC2520_ACK_WAIT_DELAY ); + } else { + signalDone(SUCCESS); + } + printf("\n S_EFD.get1"); + if ( !call SFD.get() ) { + break; + } + /** Fall Through because the next interrupt was already received */ + + default: + if ( !m_receiving ) { + sfdHigh = TRUE; + call CaptureSFD.captureFallingEdge(); + call CC2520Receive.sfd( time32 ); + m_receiving = TRUE; + m_prev_time = time; + printf("\n Sfd default"); + 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 CC2520Receive.sfd_dropped(); + if (m_msg) + call PacketTimeStamp.clear(m_msg); + } + 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 CC2520Receive.receive( uint8_t type, message_t* ack_msg ) { + cc2520_header_t* ack_header; + cc2520_header_t* msg_header; + cc2520_metadata_t* msg_metadata; + uint8_t* ack_buf; + uint8_t length; + + if ( type == IEEE154_TYPE_ACK && m_msg) { + ack_header = call CC2520PacketBody.getHeader( ack_msg ); + msg_header = call CC2520PacketBody.getHeader( m_msg ); + + + if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) { + call BackoffTimer.stop(); + + msg_metadata = call CC2520PacketBody.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_CANCEL: + call CSN.clr(); + call SFLUSHTX.strobe(); + call CSN.set(); + releaseSpiResource(); + atomic { + m_state = S_STARTED; + } + + signal Send.sendDone( m_msg, ECANCEL ); + 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 ) { + printf("\n TXFIFO writeDone"); + call CSN.set(); + if ( m_state == S_CANCEL ) { + atomic { + call CSN.clr(); + call SFLUSHTX.strobe(); + call CSN.set(); + printf("\n TX FIFO SFLUSH"); + } + releaseSpiResource(); + m_state = S_STARTED; + signal Send.sendDone( m_msg, ECANCEL ); + + } else if ( !m_cca ) { + atomic { + m_state = S_BEGIN_TRANSMIT; + } + attemptSend(); + printf("\n TX FIFO attempt send"); + + } else { + releaseSpiResource(); + atomic { + m_state = S_SAMPLE_CCA; + } + + signal RadioBackoff.requestInitialBackoff(m_msg); + printf("\n TX FIFO back offTimer"); + 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( CC2520_TIME_ACK_TURNAROUND ); + printf("\n Backoff Timer"); + } else { + congestionBackoff(); + } + break; + + case S_BEGIN_TRANSMIT: + case S_CANCEL: + if ( acquireSpiResource() == SUCCESS ) { + attemptSend(); + printf("\n backoff_attempt Send"); + } + break; + + case S_ACK_WAIT: + signalDone( SUCCESS ); + printf("\n attempt Sucess"); + 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 ); + printf("\n Backoff S_SFD"); + 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* ONE p_msg, bool cca ) { + atomic { + if (m_state == S_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 ) { + + printf("\n LoadTXFIFO"); + 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_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; + printf("\n void attemptSend"); + atomic { + if (m_state == S_CANCEL) { + call CSN.set(); + call CSN.clr(); + call SFLUSHTX.strobe(); + releaseSpiResource(); + call CSN.set(); + m_state = S_STARTED; + printf("\n S_CANCEL"); + signal Send.sendDone( m_msg, ECANCEL ); + return; + } + + + call CSN.clr(); + + status = m_cca ? call STXONCCA.strobe() : call STXON.strobe(); + call CSN.set(); + call CSN.clr(); + if ( !( status & CC2520_STATUS_TX_ACTIVE ) ) { + status = call SNOP.strobe(); + if ( status & CC2520_STATUS_TX_ACTIVE ) { + congestion = FALSE; + } + } + + m_state = congestion ? S_SAMPLE_CCA : S_SFD; + call CSN.set(); + } + + call CSN.clr(); + printf("\n Tx status: %x",(call SNOP.strobe())); + call CSN.set(); + if ( congestion ) { + totalCcaChecks = 0; + releaseSpiResource(); + congestionBackoff(); + } else { + call BackoffTimer.start(CC2520_ABORT_PERIOD); + printf("\n Start BackoffTimer"); + } + } + + + /** + * 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() { + cc2520_header_t* header = call CC2520PacketBody.getHeader( m_msg ); + uint8_t tx_power = (call CC2520PacketBody.getMetadata( m_msg ))->tx_power; + + if ( !tx_power ) { + tx_power = CC2520_DEF_RFPOWER; + } + + call CSN.clr(); + + if ( m_tx_power != tx_power ) { + /* call TXPOWER.write( ( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) | + ( 3 << CC2420_TXCTRL_PA_CURRENT ) | + ( 1 << CC2420_TXCTRL_RESERVED ) | + ( (tx_power & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) );*/ + call TXPOWER.write( (tx_power)); + printf("\n Transmit Power : %x",tx_power ); + } + + m_tx_power = tx_power; + + { + uint8_t tmpLen __DEPUTY_UNUSED__ = header->length - 1; + call TXFIFO.write(TCAST(uint8_t * COUNT(tmpLen), header), header->length - 1); + } + } + + void signalDone( error_t err ) { + atomic m_state = S_STARTED; + abortSpiRelease = FALSE; + + call ChipSpiResource.attemptRelease(); + printf("\n msg" ); + signal Send.sendDone( m_msg, err ); + } +} + diff --git a/cc2520/unique/UniqueReceiveC.nc b/cc2520/unique/UniqueReceiveC.nc new file mode 100644 index 0000000000..cd92064b5f --- /dev/null +++ b/cc2520/unique/UniqueReceiveC.nc @@ -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, + CC2520PacketC, + MainC; + + Receive = UniqueReceiveP.Receive; + DuplicateReceive = UniqueReceiveP.DuplicateReceive; + SubReceive = UniqueReceiveP.SubReceive; + + MainC.SoftwareInit -> UniqueReceiveP; + + UniqueReceiveP.CC2520PacketBody -> CC2520PacketC; + +} + diff --git a/cc2520/unique/UniqueReceiveP.nc b/cc2520/unique/UniqueReceiveP.nc new file mode 100644 index 0000000000..0e17dfa14e --- /dev/null +++ b/cc2520/unique/UniqueReceiveP.nc @@ -0,0 +1,162 @@ +/* + * 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 "CC2520.h" + +module UniqueReceiveP @safe() { + provides { + interface Receive; + interface Receive as DuplicateReceive; + interface Init; + } + + uses { + interface Receive as SubReceive; + interface CC2520PacketBody; + } +} + +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); + + /***************** SubReceive Events *****************/ + event message_t *SubReceive.receive(message_t* msg, void* payload, + uint8_t len) { + uint16_t msgSource = (call CC2520PacketBody.getHeader(msg))->src; + uint8_t msgDsn = (call CC2520PacketBody.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/cc2520/unique/UniqueSendC.nc b/cc2520/unique/UniqueSendC.nc new file mode 100644 index 0000000000..061525c57c --- /dev/null +++ b/cc2520/unique/UniqueSendC.nc @@ -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, + CC2520PacketC, + MainC; + + Send = UniqueSendP.Send; + SubSend = UniqueSendP.SubSend; + + MainC.SoftwareInit -> UniqueSendP; + + UniqueSendP.State -> StateC; + UniqueSendP.Random -> RandomC; + UniqueSendP.CC2520PacketBody -> CC2520PacketC; + +} + diff --git a/cc2520/unique/UniqueSendP.nc b/cc2520/unique/UniqueSendP.nc new file mode 100644 index 0000000000..2a8b5ba1f3 --- /dev/null +++ b/cc2520/unique/UniqueSendP.nc @@ -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 @safe() { + provides { + interface Send; + interface Init; + } + + uses { + interface Send as SubSend; + interface State; + interface Random; + interface CC2520PacketBody; + } +} + +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 CC2520PacketBody.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, uint8_t len) { + return call SubSend.getPayload(msg, len); + } + + /***************** SubSend Events ****************/ + event void SubSend.sendDone(message_t *msg, error_t error) { + call State.toIdle(); + signal Send.sendDone(msg, error); + } + +} + diff --git a/tos/lib/printf/debug.h b/tos/lib/printf/debug.h new file mode 100644 index 0000000000..d619adf2d1 --- /dev/null +++ b/tos/lib/printf/debug.h @@ -0,0 +1,49 @@ + +#ifndef DEBUG_H +#define DEBUG_H + + +#ifndef DEFAULT_LOG_LEVEL +#define DEFAULT_LOG_LEVEL 5 +#endif + +#define NOP (void)0 + + +#define print(log_level, ...) (log_level > DEFAULT_LOG_LEVEL) ? NOP : printf(__VA_ARGS__) + +#define pr_emergency(...) print(EMERGENCY, __VA_ARGS__) + +#define pr_alert(...) print(ALERT, __VA_ARGS__) + +#define pr_critical(...) print(CRITICAL, __VA_ARGS__) + +#define pr_error(...) print(ERROR, __VA_ARGS__) + +#define pr_warning(...) print(WARNING, __VA_ARGS__) + +#define pr_info(...) print(INFO, __VA_ARGS__) + +#define pr_debug(...) print(DEBUG, __VA_ARGS__) + + + + + +//Various Log Levels: (Names copied from kernel logging levels) + + +enum { + EMERGENCY = 0, //System is about to crash or is unstable + ALERT = 1, //Something bad happened and action must be taken immediately + CRITICAL = 2, //Critical condition occured like serious hardware/software issue + ERROR = 3, //Often used to indicate difficulties with the hardware + WARNING = 4, //Nothing serious by itself but might indicate problems + INFO = 5, //Informational Messages,e.g: startup information + DEBUG = 6, //Debug Information +}; + + + + +#endif diff --git a/tos/lib/printf/printf.h b/tos/lib/printf/printf.h index 10f7bc8e45..9f114dcca9 100644 --- a/tos/lib/printf/printf.h +++ b/tos/lib/printf/printf.h @@ -69,6 +69,7 @@ #undef putchar #include "message.h" +#include "debug.h" int printfflush(); #ifndef PRINTF_MSG_LENGTH @@ -82,5 +83,8 @@ enum { AM_PRINTF_MSG = 100, }; + + + #endif //PRINTF_H