+++ /dev/null
-/* $Id$\r
- * Copyright (c) 2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-/**\r
- * Radio logic is split between Csma (media-access control, low-power\r
- * listening and general control) and SendReceive (packet reception and\r
- * transmission). This interface specifies the interaction between these\r
- * two components.\r
- *\r
- * @author David Gay\r
- */\r
- \r
-interface ByteRadio\r
-{\r
- /**\r
- * SendReceive wants to send a packet.\r
- * @param msg Message to be sent.\r
- */\r
- event void rts(message_t *msg);\r
-\r
- /**\r
- * Access to the media granted. Start sending. SendReceive must signal\r
- * sendDone when transmission is complete. Note: the media-access-contro\r
- * layer must have enabled listening before calling cts().\r
- */\r
- async command void cts();\r
-\r
- /**\r
- * Between the rts() and sendDone() events, this must return the\r
- * message under transmission.\r
- * @return Message being transmitted.\r
- */\r
- async command message_t *getTxMessage();\r
-\r
- /**\r
- * Transmission complete.\r
- */\r
- async event void sendDone();\r
-\r
- /**\r
- * Set message preamble length.\r
- * @param bytes Preamble length in bytes\r
- */\r
- async command void setPreambleLength(uint16_t bytes);\r
-\r
- /**\r
- * Get message preamble length.\r
- * @return Preamble length in bytes\r
- */\r
- async command uint16_t getPreambleLength();\r
-\r
- /**\r
- * Enable listening for incoming packets.\r
- */\r
- async command void listen();\r
-\r
- /**\r
- * Disable listening for incoming packets.\r
- */\r
- async command void off();\r
-\r
- /**\r
- * SendReceive signals this event for every radio-byte-time while\r
- * listening is enabled and a message isn't being received or\r
- * transmitted.\r
- * @param preamble TRUE if a message preamble byte has been received\r
- */\r
- async event void idleByte(bool preamble);\r
-\r
- /**\r
- * Detect if SendReceive is attempting to sync with an incoming packet.\r
- * During sync, idleByte events are not signaled. If sync is successful,\r
- * an rx() event will be signaled, if it fails, idleByte events will\r
- * resume. If syncing() returns TRUE, the last idleByte() event must\r
- * have had preamble = TRUE.\r
- *\r
- * @return TRUE if a sync attempt is in progress, FALSE if not.\r
- */\r
- async command bool syncing();\r
-\r
- /**\r
- * A message is being received\r
- */\r
- async event void rx();\r
-\r
- /**\r
- * Message reception is complete.\r
- */\r
- async event void rxDone();\r
-}\r
+++ /dev/null
-// $Id$\r
-\r
-/* tab:4\r
- * "Copyright (c) 2004-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2004-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-\r
-/**\r
- *\r
- * The Active Message layer for the CC1000 radio. This configuration\r
- * just layers the AM dispatch (CC1000ActiveMessageM) on top of the\r
- * underlying CC1000 radio packet (CC1000CsmaRadioC), which is\r
- * inherently an AM packet (acknowledgements based on AM destination\r
- * addr and group).\r
- * \r
- * @author Philip Levis\r
- * @date June 19 2005\r
- */\r
-\r
-configuration CC1000ActiveMessageC {\r
- provides {\r
- interface SplitControl;\r
- interface AMSend[am_id_t id];\r
- interface Receive[am_id_t id];\r
- interface Receive as Snoop[am_id_t id];\r
- interface AMPacket;\r
- interface Packet;\r
- interface PacketAcknowledgements;\r
- interface LowPowerListening;\r
- }\r
-}\r
-implementation {\r
-\r
- components CC1000ActiveMessageP as AM, CC1000CsmaRadioC as Radio;\r
- components ActiveMessageAddressC as Address;\r
- components CC1000LowPowerListeningC as Lpl;\r
- \r
- SplitControl = Radio;\r
- Packet = Radio;\r
- PacketAcknowledgements = Radio;\r
- LowPowerListening = Radio;\r
-\r
- AMSend = AM;\r
- Receive = AM.Receive;\r
- Snoop = AM.Snoop;\r
- AMPacket = AM;\r
-\r
- AM.SubSend -> Lpl.Send;\r
- AM.SubReceive -> Lpl.Receive;\r
- AM.amAddress -> Address;\r
- AM.Packet -> Radio;\r
-}\r
+++ /dev/null
-// $Id$\r
-\r
-/* tab:4\r
- * "Copyright (c) 2004-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2004-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-/**\r
- * Implementation component for CC1000ActiveMessageC.\r
- *\r
- * @author Philip Levis\r
- * @date June 19 2006\r
- */\r
-\r
-module CC1000ActiveMessageP {\r
- provides {\r
- interface AMSend[am_id_t id];\r
- interface Receive[am_id_t id];\r
- interface Receive as Snoop[am_id_t id];\r
- interface AMPacket;\r
- }\r
- uses {\r
- interface Send as SubSend;\r
- interface Receive as SubReceive;\r
- interface Packet as Packet;\r
- command am_addr_t amAddress();\r
- }\r
-}\r
-implementation {\r
-\r
- cc1000_header_t* getHeader(message_t* amsg) {\r
- return (cc1000_header_t*)(amsg->data - sizeof(cc1000_header_t));\r
- }\r
-\r
- cc1000_footer_t *getFooter(message_t *amsg) {\r
- return (cc1000_footer_t *)(amsg->footer);\r
- }\r
-\r
- command error_t AMSend.send[am_id_t id](am_addr_t addr,\r
- message_t* amsg,\r
- uint8_t len) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- header->type = id;\r
- header->dest = addr;\r
- header->source = call AMPacket.address();\r
- header->group = TOS_AM_GROUP;\r
- return call SubSend.send(amsg, len);\r
- }\r
-\r
- command error_t AMSend.cancel[am_id_t id](message_t* msg) {\r
- return call SubSend.cancel(msg);\r
- }\r
-\r
- event void SubSend.sendDone(message_t* msg, error_t result) {\r
- signal AMSend.sendDone[call AMPacket.type(msg)](msg, result);\r
- }\r
-\r
- command uint8_t AMSend.maxPayloadLength[am_id_t id]() {\r
- return call Packet.maxPayloadLength();\r
- }\r
-\r
- command void* AMSend.getPayload[am_id_t id](message_t* m) {\r
- return call Packet.getPayload(m, NULL);\r
- }\r
-\r
- /* Receiving a packet */\r
-\r
- event message_t* SubReceive.receive(message_t* msg, void* payload, uint8_t len) {\r
- cc1000_footer_t* msg_footer = getFooter(msg);\r
- if(msg_footer->crc == 1) {\r
- if (call AMPacket.isForMe(msg)) {\r
- return signal Receive.receive[call AMPacket.type(msg)](msg, payload, len);\r
- }\r
- else {\r
- return signal Snoop.receive[call AMPacket.type(msg)](msg, payload, len);\r
- }\r
- }\r
- return msg;\r
- }\r
- \r
- command void* Receive.getPayload[am_id_t id](message_t* m, uint8_t* len) {\r
- return call Packet.getPayload(m, len);\r
- }\r
-\r
- command uint8_t Receive.payloadLength[am_id_t id](message_t* m) {\r
- return call Packet.payloadLength(m);\r
- }\r
- \r
- command void* Snoop.getPayload[am_id_t id](message_t* m, uint8_t* len) {\r
- return call Packet.getPayload(m, len);\r
- }\r
-\r
- command uint8_t Snoop.payloadLength[am_id_t id](message_t* m) {\r
- return call Packet.payloadLength(m);\r
- }\r
-\r
- command am_addr_t AMPacket.address() {\r
- return call amAddress();\r
- }\r
- \r
- command am_addr_t AMPacket.destination(message_t* amsg) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- return header->dest;\r
- }\r
-\r
- command am_addr_t AMPacket.source(message_t* amsg) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- return header->source;\r
- }\r
-\r
- command void AMPacket.setDestination(message_t* amsg, am_addr_t addr) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- header->dest = addr;\r
- }\r
-\r
- command void AMPacket.setSource(message_t* amsg, am_addr_t addr) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- header->source = addr;\r
- }\r
- \r
- command bool AMPacket.isForMe(message_t* amsg) {\r
- return (call AMPacket.destination(amsg) == call AMPacket.address() ||\r
- call AMPacket.destination(amsg) == AM_BROADCAST_ADDR);\r
- }\r
-\r
- command am_id_t AMPacket.type(message_t* amsg) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- return header->type;\r
- }\r
-\r
- command void AMPacket.setType(message_t* amsg, am_id_t type) {\r
- cc1000_header_t* header = getHeader(amsg);\r
- header->type = type;\r
- }\r
-\r
- command void AMPacket.setGroup(message_t* msg, am_group_t group) {\r
- cc1000_header_t* header = getHeader(msg);\r
- header->group = group;\r
- }\r
-\r
- command am_group_t AMPacket.group(message_t* msg) {\r
- cc1000_header_t* header = getHeader(msg);\r
- return header->group;\r
- }\r
-\r
- command am_group_t AMPacket.localGroup() {\r
- return TOS_AM_GROUP;\r
- }\r
-\r
- default event message_t* Receive.receive[am_id_t id](message_t* msg, void* payload, uint8_t len) {\r
- return msg;\r
- }\r
- \r
- default event message_t* Snoop.receive[am_id_t id](message_t* msg, void* payload, uint8_t len) {\r
- return msg;\r
- }\r
-\r
- default event void AMSend.sendDone[uint8_t id](message_t* msg, error_t err) {\r
- return;\r
- }\r
-\r
- \r
-\r
-}\r
+++ /dev/null
-// $Id$\r
-\r
-/* -*- Mode: C; c-basic-indent: 2; indent-tabs-mode: nil -*- */ \r
-/* tab:4\r
- * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By\r
- * downloading, copying, installing or using the software you agree to\r
- * this license. If you do not agree to this license, do not download,\r
- * install, copy or use the software.\r
- *\r
- * Intel Open Source License \r
- *\r
- * Copyright (c) 2002 Intel Corporation \r
- * All rights reserved. \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are\r
- * met:\r
- * \r
- * Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- * Neither the name of the Intel Corporation nor the names of its\r
- * contributors may be used to endorse or promote products derived from\r
- * this software without specific prior written permission.\r
- * \r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\r
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS\r
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * \r
- */\r
-\r
-/*\r
- * Constants for CC1000 radio\r
- *\r
- * @author Phil Buonadonna\r
- */\r
-\r
-#ifndef CC1000CONST_H\r
-#define CC1000CONST_H\r
-\r
-/* Constants defined for CC1K */\r
-/* Register addresses */\r
-\r
-enum {\r
- CC1K_MAIN = 0x00,\r
- CC1K_FREQ_2A = 0x01,\r
- CC1K_FREQ_1A = 0x02,\r
- CC1K_FREQ_0A = 0x03,\r
- CC1K_FREQ_2B = 0x04,\r
- CC1K_FREQ_1B = 0x05,\r
- CC1K_FREQ_0B = 0x06,\r
- CC1K_FSEP1 = 0x07,\r
- CC1K_FSEP0 = 0x08,\r
- CC1K_CURRENT = 0x09,\r
- CC1K_FRONT_END = 0x0A, //10\r
- CC1K_PA_POW = 0x0B, //11\r
- CC1K_PLL = 0x0C, //12\r
- CC1K_LOCK = 0x0D, //13\r
- CC1K_CAL = 0x0E, //14\r
- CC1K_MODEM2 = 0x0F, //15\r
- CC1K_MODEM1 = 0x10, //16\r
- CC1K_MODEM0 = 0x11, //17\r
- CC1K_MATCH = 0x12, //18\r
- CC1K_FSCTRL = 0x13, //19\r
- CC1K_FSHAPE7 = 0x14, //20\r
- CC1K_FSHAPE6 = 0x15, //21\r
- CC1K_FSHAPE5 = 0x16, //22\r
- CC1K_FSHAPE4 = 0x17, //23\r
- CC1K_FSHAPE3 = 0x18, //24\r
- CC1K_FSHAPE2 = 0x19, //25\r
- CC1K_FSHAPE1 = 0x1A, //26\r
- CC1K_FSDELAY = 0x1B, //27\r
- CC1K_PRESCALER = 0x1C, //28\r
- CC1K_TEST6 = 0x40, //64\r
- CC1K_TEST5 = 0x41, //66\r
- CC1K_TEST4 = 0x42, //67\r
- CC1K_TEST3 = 0x43, //68\r
- CC1K_TEST2 = 0x44, //69\r
- CC1K_TEST1 = 0x45, //70\r
- CC1K_TEST0 = 0x46, //71\r
-\r
- // MAIN Register Bit Posititions\r
- CC1K_RXTX = 7,\r
- CC1K_F_REG = 6,\r
- CC1K_RX_PD = 5,\r
- CC1K_TX_PD = 4,\r
- CC1K_FS_PD = 3,\r
- CC1K_CORE_PD = 2,\r
- CC1K_BIAS_PD = 1,\r
- CC1K_RESET_N = 0,\r
-\r
- // CURRENT Register Bit Positions\r
- CC1K_VCO_CURRENT = 4,\r
- CC1K_LO_DRIVE = 2,\r
- CC1K_PA_DRIVE = 0,\r
-\r
- // FRONT_END Register Bit Positions\r
- CC1K_BUF_CURRENT = 5,\r
- CC1K_LNA_CURRENT = 3,\r
- CC1K_IF_RSSI = 1,\r
- CC1K_XOSC_BYPASS = 0,\r
-\r
- // PA_POW Register Bit Positions\r
- CC1K_PA_HIGHPOWER = 4,\r
- CC1K_PA_LOWPOWER = 0,\r
-\r
- // PLL Register Bit Positions\r
- CC1K_EXT_FILTER = 7,\r
- CC1K_REFDIV = 3,\r
- CC1K_ALARM_DISABLE = 2,\r
- CC1K_ALARM_H = 1,\r
- CC1K_ALARM_L = 0,\r
-\r
- // LOCK Register Bit Positions\r
- CC1K_LOCK_SELECT = 4,\r
- CC1K_PLL_LOCK_ACCURACY = 3,\r
- CC1K_PLL_LOCK_LENGTH = 2,\r
- CC1K_LOCK_INSTANT = 1,\r
- CC1K_LOCK_CONTINUOUS = 0,\r
-\r
- // CAL Register Bit Positions\r
- CC1K_CAL_START = 7,\r
- CC1K_CAL_DUAL = 6,\r
- CC1K_CAL_WAIT = 5,\r
- CC1K_CAL_CURRENT = 4,\r
- CC1K_CAL_COMPLETE = 3,\r
- CC1K_CAL_ITERATE = 0,\r
-\r
- // MODEM2 Register Bit Positions\r
- CC1K_PEAKDETECT = 7,\r
- CC1K_PEAK_LEVEL_OFFSET = 0,\r
-\r
- // MODEM1 Register Bit Positions\r
- CC1K_MLIMIT = 5,\r
- CC1K_LOCK_AVG_IN = 4,\r
- CC1K_LOCK_AVG_MODE = 3,\r
- CC1K_SETTLING = 1,\r
- CC1K_MODEM_RESET_N = 0,\r
-\r
- // MODEM0 Register Bit Positions\r
- CC1K_BAUDRATE = 4,\r
- CC1K_DATA_FORMAT = 2,\r
- CC1K_XOSC_FREQ = 0,\r
-\r
- // MATCH Register Bit Positions\r
- CC1K_RX_MATCH = 4,\r
- CC1K_TX_MATCH = 0,\r
-\r
- // FSCTLR Register Bit Positions\r
- CC1K_DITHER1 = 3,\r
- CC1K_DITHER0 = 2,\r
- CC1K_SHAPE = 1,\r
- CC1K_FS_RESET_N = 0,\r
-\r
- // PRESCALER Register Bit Positions\r
- CC1K_PRE_SWING = 6,\r
- CC1K_PRE_CURRENT = 4,\r
- CC1K_IF_INPUT = 3,\r
- CC1K_IF_FRONT = 2,\r
-\r
- // TEST6 Register Bit Positions\r
- CC1K_LOOPFILTER_TP1 = 7,\r
- CC1K_LOOPFILTER_TP2 = 6,\r
- CC1K_CHP_OVERRIDE = 5,\r
- CC1K_CHP_CO = 0,\r
-\r
- // TEST5 Register Bit Positions\r
- CC1K_CHP_DISABLE = 5,\r
- CC1K_VCO_OVERRIDE = 4,\r
- CC1K_VCO_AO = 0,\r
-\r
- // TEST3 Register Bit Positions\r
- CC1K_BREAK_LOOP = 4,\r
- CC1K_CAL_DAC_OPEN = 0,\r
-\r
-\r
- /* \r
- * CC1K Register Parameters Table\r
- *\r
- * This table follows the same format order as the CC1K register \r
- * set EXCEPT for the last entry in the table which is the \r
- * CURRENT register value for TX mode.\r
- * \r
- * NOTE: To save RAM space, this table resides in program memory (flash). \r
- * This has two important implications:\r
- * 1) You can't write to it (duh!)\r
- * 2) You must read it using the PRG_RDB(addr) macro. IT CANNOT BE ACCESSED AS AN ORDINARY C ARRAY. \r
- * \r
- * Add/remove individual entries below to suit your RF tastes.\r
- * \r
- */\r
- CC1K_433_002_MHZ = 0x00,\r
- CC1K_915_998_MHZ = 0x01,\r
- CC1K_434_845_MHZ = 0x02,\r
- CC1K_914_077_MHZ = 0x03,\r
- CC1K_315_178_MHZ = 0x04,\r
-\r
- //#define CC1K_SquelchInit 0x02F8 // 0.90V using the bandgap reference\r
- CC1K_SquelchInit = 0x120,\r
- CC1K_SquelchTableSize = 9,\r
- CC1K_MaxRSSISamples = 5,\r
- CC1K_Settling = 1,\r
- CC1K_ValidPrecursor = 2,\r
- CC1K_SquelchIntervalFast = 128,\r
- CC1K_SquelchIntervalSlow = 2560,\r
- CC1K_SquelchCount = 30,\r
- CC1K_SquelchBuffer = 12,\r
-\r
- CC1K_LPL_PACKET_TIME = 16,\r
-\r
- CC1K_LPL_CHECK_TIME = 16, /* In tenth's of milliseconds, this should\r
- be an approximation of the on-time for\r
- a LPL check rather than the total check\r
- time. */\r
- CC1K_LPL_MIN_INTERVAL = 5, /* In milliseconds, the minimum interval\r
- between low-power-listening checks */\r
- CC1K_LPL_MAX_INTERVAL = 10000, /* In milliseconds, the maximum interval\r
- between low-power-listening checks.\r
- Arbitrary value, but must be at\r
- most 32767 because of the way\r
- sleep interval is stored in outgoing\r
- messages */\r
- \r
- CC1000_MIN_BACKOFF = 2,\r
- CC1000_BACKOFF_PERIOD = 2,\r
-};\r
-\r
-#ifdef CC1K_DEFAULT_FREQ\r
-#define CC1K_DEF_PRESET (CC1K_DEFAULT_FREQ)\r
-#endif\r
-#ifdef CC1K_MANUAL_FREQ\r
-#define CC1K_DEF_FREQ (CC1K_MANUAL_FREQ)\r
-#endif\r
-\r
-#ifndef CC1K_DEF_PRESET\r
-#define CC1K_DEF_PRESET (CC1K_434_845_MHZ)\r
-#endif \r
-\r
-static const_uint8_t CC1K_Params[6][20] = {\r
- // (0) 433.002 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO\r
- { // MAIN 0x00\r
- 0x31,\r
- // FREQ2A,FREQ1A,FREQ0A 0x01-0x03\r
- 0x58,0x00,0x00, \r
- // FREQ2B,FREQ1B,FREQ0B 0x04-0x06\r
- 0x57,0xf6,0x85, //XBOW\r
- // FSEP1, FSEP0 0x07-0x08\r
- 0X03,0x55,\r
- // CURRENT RX MODE VALUE 0x09 also see below\r
- 4 << CC1K_VCO_CURRENT | 1 << CC1K_LO_DRIVE, \r
- // FRONT_END 0x0a\r
- 1 << CC1K_IF_RSSI,\r
- // PA_POW 0x0b\r
- 0x0 << CC1K_PA_HIGHPOWER | 0xf << CC1K_PA_LOWPOWER, \r
- // PLL 0x0c\r
- 12 << CC1K_REFDIV, \r
- // LOCK 0x0d\r
- 0xe << CC1K_LOCK_SELECT,\r
- // CAL 0x0e\r
- 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE, \r
- // MODEM2 0x0f\r
- 0 << CC1K_PEAKDETECT | 28 << CC1K_PEAK_LEVEL_OFFSET,\r
- // MODEM1 0x10\r
- 3 << CC1K_MLIMIT | 1 << CC1K_LOCK_AVG_MODE | CC1K_Settling << CC1K_SETTLING | 1 << CC1K_MODEM_RESET_N, \r
- // MODEM0 0x11\r
- 5 << CC1K_BAUDRATE | 1 << CC1K_DATA_FORMAT | 1 << CC1K_XOSC_FREQ,\r
- // MATCH 0x12\r
- 0x7 << CC1K_RX_MATCH | 0x0 << CC1K_TX_MATCH,\r
- // tx current (extra)\r
- 8 << CC1K_VCO_CURRENT | 1 << CC1K_PA_DRIVE,\r
- },\r
-\r
- // 1 915.9988 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO\r
- { // MAIN 0x00 \r
- 0x31,\r
- // FREQ2A,FREQ1A,FREQ0A 0x01-0x03\r
- 0x7c,0x00,0x00, \r
- // FREQ2B,FREQ1B,FREQ0B 0x04-0x06\r
- 0x7b,0xf9,0xae, \r
- // FSEP1, FSEP0 0x07-0x8\r
- 0x02,0x38,\r
- // CURRENT RX MODE VALUE 0x09 also see below\r
- 8 << CC1K_VCO_CURRENT | 3 << CC1K_LO_DRIVE,\r
- //0x8C, \r
- // FRONT_END 0x0a\r
- 1 << CC1K_BUF_CURRENT | 2 << CC1K_LNA_CURRENT | 1 << CC1K_IF_RSSI,\r
- //0x32,\r
- // PA_POW 0x0b\r
- 0x8 << CC1K_PA_HIGHPOWER | 0x0 << CC1K_PA_LOWPOWER, \r
- //0xff,\r
- // PLL 0xc\r
- 8 << CC1K_REFDIV, \r
- //0x40,\r
- // LOCK 0xd\r
- 0x1 << CC1K_LOCK_SELECT,\r
- //0x10,\r
- // CAL 0xe\r
- 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE, \r
- //0x26,\r
- // MODEM2 0xf\r
- 1 << CC1K_PEAKDETECT | 33 << CC1K_PEAK_LEVEL_OFFSET,\r
- //0xA1,\r
- // MODEM1 0x10\r
- 3 << CC1K_MLIMIT | 1 << CC1K_LOCK_AVG_MODE | CC1K_Settling << CC1K_SETTLING | 1 << CC1K_MODEM_RESET_N, \r
- //0x6f, \r
- // MODEM0 0x11\r
- 5 << CC1K_BAUDRATE | 1 << CC1K_DATA_FORMAT | 1 << CC1K_XOSC_FREQ,\r
- //0x55,\r
- // MATCH 0x12\r
- 0x1 << CC1K_RX_MATCH | 0x0 << CC1K_TX_MATCH,\r
- // tx current (extra)\r
- 15 << CC1K_VCO_CURRENT | 3 << CC1K_PA_DRIVE,\r
- },\r
-\r
- // 2 434.845200 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO\r
- { // MAIN 0x00\r
- 0x31,\r
- // FREQ2A,FREQ1A,FREQ0A 0x01-0x03\r
- 0x51,0x00,0x00, \r
- // FREQ2B,FREQ1B,FREQ0B 0x04-0x06\r
- 0x50,0xf7,0x4F, //XBOW\r
- // FSEP1, FSEP0 0x07-0x08\r
- 0X03,0x0E,\r
- // CURRENT RX MODE VALUE 0x09 also see below\r
- 4 << CC1K_VCO_CURRENT | 1 << CC1K_LO_DRIVE, \r
- // FRONT_END 0x0a\r
- 1 << CC1K_IF_RSSI,\r
- // PA_POW 0x0b\r
- 0x0 << CC1K_PA_HIGHPOWER | 0xf << CC1K_PA_LOWPOWER, \r
- // PLL 0x0c\r
- 11 << CC1K_REFDIV, \r
- // LOCK 0x0d\r
- 0xe << CC1K_LOCK_SELECT,\r
- // CAL 0x0e\r
- 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE, \r
- // MODEM2 0x0f\r
- 1 << CC1K_PEAKDETECT | 33 << CC1K_PEAK_LEVEL_OFFSET,\r
- // MODEM1 0x10\r
- 3 << CC1K_MLIMIT | 1 << CC1K_LOCK_AVG_MODE | CC1K_Settling << CC1K_SETTLING | 1 << CC1K_MODEM_RESET_N, \r
- // MODEM0 0x11\r
- 5 << CC1K_BAUDRATE | 1 << CC1K_DATA_FORMAT | 1 << CC1K_XOSC_FREQ,\r
- // MATCH 0x12\r
- 0x7 << CC1K_RX_MATCH | 0x0 << CC1K_TX_MATCH,\r
- // tx current (extra)\r
- 8 << CC1K_VCO_CURRENT | 1 << CC1K_PA_DRIVE,\r
- },\r
-\r
- \r
- // 3 914.077 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO\r
- { // MAIN 0x00 \r
- 0x31,\r
- // FREQ2A,FREQ1A,FREQ0A 0x01-0x03\r
- 0x5c,0xe0,0x00, \r
- // FREQ2B,FREQ1B,FREQ0B 0x04-0x06\r
- 0x5c,0xdb,0x42, \r
- // FSEP1, FSEP0 0x07-0x8\r
- 0x01,0xAA,\r
- // CURRENT RX MODE VALUE 0x09 also see below\r
- 8 << CC1K_VCO_CURRENT | 3 << CC1K_LO_DRIVE,\r
- //0x8C, \r
- // FRONT_END 0x0a\r
- 1 << CC1K_BUF_CURRENT | 2 << CC1K_LNA_CURRENT | 1 << CC1K_IF_RSSI,\r
- //0x32,\r
- // PA_POW 0x0b\r
- 0x8 << CC1K_PA_HIGHPOWER | 0x0 << CC1K_PA_LOWPOWER, \r
- //0xff,\r
- // PLL 0xc\r
- 6 << CC1K_REFDIV, \r
- //0x40,\r
- // LOCK 0xd\r
- 0x1 << CC1K_LOCK_SELECT,\r
- //0x10,\r
- // CAL 0xe\r
- 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE, \r
- //0x26,\r
- // MODEM2 0xf\r
- 1 << CC1K_PEAKDETECT | 33 << CC1K_PEAK_LEVEL_OFFSET,\r
- //0xA1,\r
- // MODEM1 0x10\r
- 3 << CC1K_MLIMIT | 1 << CC1K_LOCK_AVG_MODE | CC1K_Settling << CC1K_SETTLING | 1 << CC1K_MODEM_RESET_N, \r
- //0x6f, \r
- // MODEM0 0x11\r
- 5 << CC1K_BAUDRATE | 1 << CC1K_DATA_FORMAT | 1 << CC1K_XOSC_FREQ,\r
- //0x55,\r
- // MATCH 0x12\r
- 0x1 << CC1K_RX_MATCH | 0x0 << CC1K_TX_MATCH,\r
- // tx current (extra)\r
- 15 << CC1K_VCO_CURRENT | 3 << CC1K_PA_DRIVE,\r
- },\r
-\r
- // 4 315.178985 MHz channel, 38.4 Kbps data, Manchester Encoding, High Side LO\r
- { // MAIN 0x00\r
- 0x31,\r
- // FREQ2A,FREQ1A,FREQ0A 0x01-0x03\r
- 0x45,0x60,0x00, \r
- // FREQ2B,FREQ1B,FREQ0B 0x04-0x06\r
- 0x45,0x55,0xBB,\r
- // FSEP1, FSEP0 0x07-0x08\r
- 0X03,0x9C,\r
- // CURRENT RX MODE VALUE 0x09 also see below\r
- 8 << CC1K_VCO_CURRENT | 0 << CC1K_LO_DRIVE, \r
- // FRONT_END 0x0a\r
- 1 << CC1K_IF_RSSI,\r
- // PA_POW 0x0b\r
- 0x0 << CC1K_PA_HIGHPOWER | 0xf << CC1K_PA_LOWPOWER, \r
- // PLL 0x0c\r
- 13 << CC1K_REFDIV, \r
- // LOCK 0x0d\r
- 0xe << CC1K_LOCK_SELECT,\r
- // CAL 0x0e\r
- 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE, \r
- // MODEM2 0x0f\r
- 1 << CC1K_PEAKDETECT | 33 << CC1K_PEAK_LEVEL_OFFSET,\r
- // MODEM1 0x10\r
- 3 << CC1K_MLIMIT | 1 << CC1K_LOCK_AVG_MODE | CC1K_Settling << CC1K_SETTLING | 1 << CC1K_MODEM_RESET_N, \r
- // MODEM0 0x11\r
- 5 << CC1K_BAUDRATE | 1 << CC1K_DATA_FORMAT | 0 << CC1K_XOSC_FREQ,\r
- // MATCH 0x12\r
- 0x7 << CC1K_RX_MATCH | 0x0 << CC1K_TX_MATCH,\r
- // tx current (extra)\r
- 8 << CC1K_VCO_CURRENT | 1 << CC1K_PA_DRIVE,\r
- },\r
-\r
- // 5 Spare\r
- { // MAIN 0x00\r
- 0x31,\r
- // FREQ2A,FREQ1A,FREQ0A 0x01-0x03\r
- 0x58,0x00,0x00, \r
- // FREQ2B,FREQ1B,FREQ0B 0x04-0x06\r
- 0x57,0xf6,0x85, //XBOW\r
- // FSEP1, FSEP0 0x07-0x08\r
- 0X03,0x55,\r
- // CURRENT RX MODE VALUE 0x09 also see below\r
- 8 << CC1K_VCO_CURRENT | 4 << CC1K_LO_DRIVE, \r
- // FRONT_END 0x0a\r
- 1 << CC1K_IF_RSSI,\r
- // PA_POW 0x0b\r
- 0x0 << CC1K_PA_HIGHPOWER | 0xf << CC1K_PA_LOWPOWER, \r
- // PLL 0x0c\r
- 12 << CC1K_REFDIV, \r
- // LOCK 0x0d\r
- 0xe << CC1K_LOCK_SELECT,\r
- // CAL 0x0e\r
- 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE, \r
- // MODEM2 0x0f\r
- 1 << CC1K_PEAKDETECT | 33 << CC1K_PEAK_LEVEL_OFFSET,\r
- // MODEM1 0x10\r
- 3 << CC1K_MLIMIT | 1 << CC1K_LOCK_AVG_MODE | CC1K_Settling << CC1K_SETTLING | 1 << CC1K_MODEM_RESET_N, // MODEM0 0x11\r
- 5 << CC1K_BAUDRATE | 1 << CC1K_DATA_FORMAT | 1 << CC1K_XOSC_FREQ,\r
- // MATCH 0x12\r
- 0x7 << CC1K_RX_MATCH | 0x0 << CC1K_TX_MATCH,\r
- // tx current (extra)\r
- 8 << CC1K_VCO_CURRENT | 1 << CC1K_PA_DRIVE,\r
- },\r
-};\r
-\r
-#define UQ_CC1000_RSSI "CC1000RssiP.Rssi"\r
-\r
-#endif /* CC1000CONST_H */\r
+++ /dev/null
-/* $Id$\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-/**\r
- * CC1000 internal radio control interface.\r
- * @author Philip Buonadonna\r
- * @aythor Jaein Jeong\r
- */\r
-interface CC1000Control\r
-{\r
- /**\r
- * Initialise the radio to its default state.\r
- */\r
- command void init();\r
-\r
- /**\r
- * Tune the radio to one of the frequencies available in the CC1K_Params\r
- * table. Calling Tune will allso reset the rfpower and LockVal\r
- * selections to the table values.\r
- * \r
- * @param freq The index into the CC1K_Params table that holds the\r
- * desired preset frequency parameters.\r
- */\r
- command void tunePreset(uint8_t freq); \r
-\r
- /**\r
- * Tune the radio to a given frequency. Since the CC1000 uses a digital\r
- * frequency synthesizer, it cannot tune to just an arbitrary frequency.\r
- * This routine will determine the closest achievable channel, compute\r
- * the necessary parameters and tune the radio.\r
- * \r
- * @param The desired channel frequency, in Hz.\r
- * \r
- * @return The actual computed channel frequency, in Hz. A return value\r
- * of '0' indicates that no frequency was computed and the radio was not\r
- * tuned.\r
- */\r
- command uint32_t tuneManual(uint32_t DesiredFreq);\r
-\r
- /**\r
- * Turn the CC1000 off\r
- */\r
- async command void off();\r
-\r
- /**\r
- * Shift the CC1000 Radio into transmit mode.\r
- */\r
- async command void txMode();\r
-\r
- /**\r
- * Shift the CC1000 Radio in receive mode.\r
- */\r
- async command void rxMode();\r
-\r
- /**\r
- * Turn off the bias power on the CC1000 radio, but leave the core and\r
- * crystal oscillator powered. This will result in approximately a 750\r
- * uA power savings.\r
- */\r
- async command void coreOn(); \r
-\r
- /**\r
- * Turn the bias power on. This function must be followed by a call to\r
- * either rxMode() or txMode() to place the radio in a recieve/transmit\r
- * state respectively. There is approximately a 200us delay when\r
- * restoring bias power.\r
- */\r
- async command void biasOn();\r
-\r
- /**\r
- * Set the transmit RF power value. The input value is simply an\r
- * arbitrary index that is programmed into the CC1000 registers. Consult\r
- * the CC1000 datasheet for the resulting power output/current\r
- * consumption values.\r
- *\r
- * @param power A power index between 1 and 255.\r
- */\r
- command void setRFPower(uint8_t power); \r
-\r
- /**\r
- * Get the present RF power index.\r
- *\r
- * @return The power index value.\r
- */\r
- command uint8_t getRFPower(); \r
-\r
- /** \r
- * Select the signal to monitor at the CHP_OUT pin of the CC1000. See\r
- * the CC1000 data sheet for the available signals.\r
- * \r
- * @param LockVal The index of the signal to monitor at the CHP_OUT pin\r
- */\r
- command void selectLock(uint8_t LockVal); \r
-\r
- /**\r
- * Get the binary value from the CHP_OUT pin. Analog signals cannot be\r
- * read using function.\r
- *\r
- * @return 1 - Pin is high or 0 - Pin is low\r
- */\r
- command uint8_t getLock();\r
-\r
- /**\r
- * Returns whether the present frequency set is using high-side LO\r
- * injection or not. This information is used to determine if the data\r
- * from the CC1000 needs to be inverted or not.\r
- *\r
- * @return TRUE if high-side LO injection is being used (i.e. data does NOT need to be inverted\r
- * at the receiver.\r
- */\r
- command bool getLOStatus();\r
-}\r
+++ /dev/null
-/* $Id$
- * "Copyright (c) 2000-2005 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice, the following
- * two paragraphs and the author appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
- *
- * Copyright (c) 2002-2005 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 "CC1000Const.h"
-#include "Timer.h"
-
-/**
- * This module provides the CONTROL functionality for the Chipcon1000
- * series radio. It exports a custom interface to control CC1000
- * operation.
- *
- * @author Philip Buonadonna
- * @author Jaein Jeong
- * @author David Gay
- */
-module CC1000ControlP {
- provides {
- interface CC1000Control;
- }
- uses {
- interface HplCC1000 as CC;
- interface BusyWait<TMicro, uint16_t>;
- }
-}
-implementation
-{
- uint8_t txCurrent, rxCurrent, power;
-
- enum {
- IF = 150000,
- FREQ_MIN = 4194304,
- FREQ_MAX = 16751615
- };
-
- const_uint32_t fRefTbl[9] = {2457600,
- 2106514,
- 1843200,
- 1638400,
- 1474560,
- 1340509,
- 1228800,
- 1134277,
- 1053257};
-
- const_uint16_t corTbl[9] = {1213,
- 1416,
- 1618,
- 1820,
- 2022,
- 2224,
- 2427,
- 2629,
- 2831};
-
- const_uint16_t fSepTbl[9] = {0x1AA,
- 0x1F1,
- 0x238,
- 0x280,
- 0x2C7,
- 0x30E,
- 0x355,
- 0x39C,
- 0x3E3};
-
- void calibrateNow() {
- // start cal
- call CC.write(CC1K_CAL,
- 1 << CC1K_CAL_START |
- 1 << CC1K_CAL_WAIT |
- 6 << CC1K_CAL_ITERATE);
- while ((call CC.read(CC1K_CAL) & 1 << CC1K_CAL_COMPLETE) == 0)
- ;
-
- //exit cal mode
- call CC.write(CC1K_CAL, 1 << CC1K_CAL_WAIT | 6 << CC1K_CAL_ITERATE);
- }
-
- void calibrate() {
- call CC.write(CC1K_PA_POW, 0x00); // turn off rf amp
- call CC.write(CC1K_TEST4, 0x3f); // chip rate >= 38.4kb
-
- // RX - configure main freq A
- call CC.write(CC1K_MAIN, 1 << CC1K_TX_PD | 1 << CC1K_RESET_N);
-
- calibrateNow();
-
- // TX - configure main freq B
- call CC.write(CC1K_MAIN,
- 1 << CC1K_RXTX |
- 1 << CC1K_F_REG |
- 1 << CC1K_RX_PD |
- 1 << CC1K_RESET_N);
- // Set TX current
- call CC.write(CC1K_CURRENT, txCurrent);
- call CC.write(CC1K_PA_POW, 0);
-
- calibrateNow();
-
- call CC1000Control.rxMode();
- }
-
- /*
- * cc1000ComputeFreq(uint32_t desiredFreq);
- *
- * Compute an achievable frequency and the necessary CC1K parameters from
- * a given desired frequency (Hz). The function returns the actual achieved
- * channel frequency in Hz.
- *
- * This routine assumes the following:
- * - Crystal Freq: 14.7456 MHz
- * - LO Injection: High
- * - Separation: 64 KHz
- * - IF: 150 KHz
- *
- * Approximate costs for this function:
- * - ~870 bytes FLASH
- * - ~32 bytes RAM
- * - 9400 cycles
- */
- uint32_t cc1000SetFrequency(uint32_t desiredFreq) {
- uint32_t ActualChannel = 0;
- uint32_t RXFreq = 0, TXFreq = 0;
- int32_t Offset = 0x7fffffff;
- uint16_t FSep = 0;
- uint8_t RefDiv = 0;
- uint8_t i, match, frontend;
-
- for (i = 0; i < 9; i++)
- {
- uint32_t NRef = desiredFreq + IF;
- uint32_t FRef = read_uint32_t(&fRefTbl[i]);
- uint32_t Channel = 0;
- uint32_t RXCalc = 0, TXCalc = 0;
- int32_t diff;
-
- NRef = ((desiredFreq + IF) << 2) / FRef;
- if (NRef & 0x1)
- NRef++;
-
- if (NRef & 0x2)
- {
- RXCalc = 16384 >> 1;
- Channel = FRef >> 1;
- }
-
- NRef >>= 2;
-
- RXCalc += (NRef * 16384) - 8192;
- if ((RXCalc < FREQ_MIN) || (RXCalc > FREQ_MAX))
- continue;
-
- TXCalc = RXCalc - read_uint16_t(&corTbl[i]);
- if (TXCalc < FREQ_MIN || TXCalc > FREQ_MAX)
- continue;
-
- Channel += NRef * FRef;
- Channel -= IF;
-
- diff = Channel - desiredFreq;
- if (diff < 0)
- diff = -diff;
-
- if (diff < Offset)
- {
- RXFreq = RXCalc;
- TXFreq = TXCalc;
- ActualChannel = Channel;
- FSep = read_uint16_t(&fSepTbl[i]);
- RefDiv = i + 6;
- Offset = diff;
- }
- }
-
- if (RefDiv != 0)
- {
- call CC.write(CC1K_FREQ_0A, RXFreq);
- call CC.write(CC1K_FREQ_1A, RXFreq >> 8);
- call CC.write(CC1K_FREQ_2A, RXFreq >> 16);
-
- call CC.write(CC1K_FREQ_0B, TXFreq);
- call CC.write(CC1K_FREQ_1B, TXFreq >> 8);
- call CC.write(CC1K_FREQ_2B, TXFreq >> 16);
-
- call CC.write(CC1K_FSEP0, FSep);
- call CC.write(CC1K_FSEP1, FSep >> 8);
-
- if (ActualChannel < 500000000)
- {
- if (ActualChannel < 400000000)
- {
- rxCurrent = 8 << CC1K_VCO_CURRENT | 1 << CC1K_LO_DRIVE;
- txCurrent = 9 << CC1K_VCO_CURRENT | 1 << CC1K_PA_DRIVE;
- }
- else
- {
- rxCurrent = 4 << CC1K_VCO_CURRENT | 1 << CC1K_LO_DRIVE;
- txCurrent = 8 << CC1K_VCO_CURRENT | 1 << CC1K_PA_DRIVE;
- }
- frontend = 1 << CC1K_IF_RSSI;
- match = 7 << CC1K_RX_MATCH;
- }
- else
- {
- rxCurrent = 8 << CC1K_VCO_CURRENT | 3 << CC1K_LO_DRIVE;
- txCurrent = 15 << CC1K_VCO_CURRENT | 3 << CC1K_PA_DRIVE;
-
- frontend =
- 1 << CC1K_BUF_CURRENT | 2 << CC1K_LNA_CURRENT |
- 1 << CC1K_IF_RSSI;
- match = 2 << CC1K_RX_MATCH; // datasheet says to use 1...
- }
- call CC.write(CC1K_CURRENT, rxCurrent);
- call CC.write(CC1K_MATCH, match);
- call CC.write(CC1K_FRONT_END, frontend);
- call CC.write(CC1K_PLL, RefDiv << CC1K_REFDIV);
- }
-
- return ActualChannel;
- }
-
- command void CC1000Control.init() {
- call CC.init();
-
- // wake up xtal and reset unit
- call CC.write(CC1K_MAIN,
- 1 << CC1K_RX_PD | 1 << CC1K_TX_PD |
- 1 << CC1K_FS_PD | 1 << CC1K_BIAS_PD);
- // clear reset.
- call CC1000Control.coreOn();
- call BusyWait.wait(2000);
-
- // Set default parameter values
- // POWER: 0dbm (~900MHz), 6dbm (~430MHz)
- power = 8 << CC1K_PA_HIGHPOWER | 0 << CC1K_PA_LOWPOWER;
- call CC.write(CC1K_PA_POW, power);
-
- // select Manchester Violation for CHP_OUT
- call CC.write(CC1K_LOCK_SELECT, 9 << CC1K_LOCK_SELECT);
-
- // Default modem values = 19.2 Kbps (38.4 kBaud), Manchester encoded
- call CC.write(CC1K_MODEM2, 0);
- call CC.write(CC1K_MODEM1,
- 3 << CC1K_MLIMIT |
- 1 << CC1K_LOCK_AVG_MODE |
- 3 << CC1K_SETTLING |
- 1 << CC1K_MODEM_RESET_N);
- call CC.write(CC1K_MODEM0,
- 5 << CC1K_BAUDRATE |
- 1 << CC1K_DATA_FORMAT |
- 1 << CC1K_XOSC_FREQ);
-
- call CC.write(CC1K_FSCTRL, 1 << CC1K_FS_RESET_N);
-
-#ifdef CC1K_DEF_FREQ
- call CC1000Control.tuneManual(CC1K_DEF_FREQ);
-#else
- call CC1000Control.tunePreset(CC1K_DEF_PRESET);
-#endif
- call CC1000Control.off();
- }
-
- command void CC1000Control.tunePreset(uint8_t freq) {
- int i;
-
- // FREQA, FREQB, FSEP, CURRENT(RX), FRONT_END, POWER, PLL
- for (i = CC1K_FREQ_2A; i <= CC1K_PLL; i++)
- call CC.write(i, read_uint8_t(&CC1K_Params[freq][i]));
- call CC.write(CC1K_MATCH, read_uint8_t(&CC1K_Params[freq][CC1K_MATCH]));
- rxCurrent = read_uint8_t(&CC1K_Params[freq][CC1K_CURRENT]);
- txCurrent = read_uint8_t(&CC1K_Params[freq][CC1K_MATCH + 1]);
- power = read_uint8_t(&CC1K_Params[freq][CC1K_PA_POW]);
-
- calibrate();
- }
-
- command uint32_t CC1000Control.tuneManual(uint32_t DesiredFreq) {
- uint32_t actualFreq;
-
- actualFreq = cc1000SetFrequency(DesiredFreq);
-
- calibrate();
-
- return actualFreq;
- }
-
- async command void CC1000Control.txMode() {
- // MAIN register to TX mode
- call CC.write(CC1K_MAIN,
- 1 << CC1K_RXTX |
- 1 << CC1K_F_REG |
- 1 << CC1K_RX_PD |
- 1 << CC1K_RESET_N);
- // Set the TX mode VCO Current
- call CC.write(CC1K_CURRENT, txCurrent);
- call BusyWait.wait(250);
- call CC.write(CC1K_PA_POW, power);
- call BusyWait.wait(20);
- }
-
- async command void CC1000Control.rxMode() {
- // MAIN register to RX mode
- // Powerup Freqency Synthesizer and Receiver
- call CC.write(CC1K_CURRENT, rxCurrent);
- call CC.write(CC1K_PA_POW, 0); // turn off power amp
- call CC.write(CC1K_MAIN, 1 << CC1K_TX_PD | 1 << CC1K_RESET_N);
- call BusyWait.wait(125);
- }
-
- async command void CC1000Control.coreOn() {
- // MAIN register to SLEEP mode
- call CC.write(CC1K_MAIN,
- 1 << CC1K_RX_PD |
- 1 << CC1K_TX_PD |
- 1 << CC1K_FS_PD |
- 1 << CC1K_BIAS_PD |
- 1 << CC1K_RESET_N);
- }
-
- async command void CC1000Control.biasOn() {
- call CC.write(CC1K_MAIN,
- 1 << CC1K_RX_PD |
- 1 << CC1K_TX_PD |
- 1 << CC1K_FS_PD |
- 1 << CC1K_RESET_N);
- }
-
-
- async command void CC1000Control.off() {
- // MAIN register to power down mode. Shut everything off
- call CC.write(CC1K_MAIN,
- 1 << CC1K_RX_PD |
- 1 << CC1K_TX_PD |
- 1 << CC1K_FS_PD |
- 1 << CC1K_CORE_PD |
- 1 << CC1K_BIAS_PD |
- 1 << CC1K_RESET_N);
- call CC.write(CC1K_PA_POW, 0); // turn off rf amp
- }
-
- command void CC1000Control.setRFPower(uint8_t newPower) {
- power = newPower;
- }
-
- command uint8_t CC1000Control.getRFPower() {
- return power;
- }
-
- command void CC1000Control.selectLock(uint8_t fn) {
- // Select function of CHP_OUT pin (readable via getLock)
- call CC.write(CC1K_LOCK, fn << CC1K_LOCK_SELECT);
- }
-
- command uint8_t CC1000Control.getLock() {
- return call CC.getLOCK();
- }
-
- command bool CC1000Control.getLOStatus() {
- // We use a high-side LO (local oscillator) frequency -> data will be
- // inverted. See cc1000ComputeFreq and CC1000 datasheet p.23.
- return TRUE;
- }
-}
+++ /dev/null
-// $Id$\r
-\r
-/* tab:4\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-\r
-#include "message.h"\r
-#include "crc.h"\r
-#include "CC1000Const.h"\r
-#include "Timer.h"\r
-\r
-/**\r
- * A rewrite of the low-power-listening CC1000 radio stack.\r
- * This file contains the CSMA and low-power listening logic. Actual\r
- * packet transmission and reception is in SendReceive.\r
- * <p>\r
- * This code has some degree of platform-independence, via the\r
- * CC1000Control, RSSIADC and SpiByteFifo interfaces which must be provided\r
- * by the platform. However, these interfaces may still reflect some\r
- * particularities of the mica2 hardware implementation.\r
- *\r
- * @author Philip Buonadonna\r
- * @author Jaein Jeong\r
- * @author Joe Polastre\r
- * @author David Gay\r
- */\r
- \r
-module CC1000CsmaP {\r
- provides {\r
- interface Init;\r
- interface SplitControl;\r
- interface CsmaControl;\r
- interface CsmaBackoff;\r
- interface LowPowerListening;\r
- }\r
- uses {\r
- interface Init as ByteRadioInit;\r
- interface StdControl as ByteRadioControl;\r
- interface ByteRadio;\r
-\r
- //interface PowerManagement;\r
- interface CC1000Control;\r
- interface CC1000Squelch;\r
- interface Random;\r
- interface Timer<TMilli> as WakeupTimer;\r
- interface BusyWait<TMicro, uint16_t>;\r
-\r
- interface ReadNow<uint16_t> as RssiNoiseFloor;\r
- interface ReadNow<uint16_t> as RssiCheckChannel;\r
- interface ReadNow<uint16_t> as RssiPulseCheck;\r
- async command void cancelRssi();\r
- }\r
-}\r
-implementation \r
-{\r
- enum {\r
- DISABLED_STATE,\r
- IDLE_STATE,\r
- RX_STATE,\r
- TX_STATE,\r
- POWERDOWN_STATE,\r
- PULSECHECK_STATE\r
- };\r
-\r
- enum {\r
- TIME_AFTER_CHECK = 30,\r
- };\r
-\r
- uint8_t radioState = DISABLED_STATE;\r
- struct {\r
- uint8_t ccaOff : 1;\r
- uint8_t txPending : 1;\r
- } f; // f for flags\r
- uint8_t count;\r
- uint8_t clearCount;\r
-\r
- int16_t macDelay;\r
-\r
- uint16_t sleepTime;\r
-\r
- uint16_t rssiForSquelch;\r
-\r
- task void setWakeupTask();\r
-\r
- cc1000_metadata_t *getMetadata(message_t *amsg) {\r
- return (cc1000_metadata_t *)((uint8_t *)amsg->footer + sizeof(cc1000_footer_t));\r
- }\r
- \r
- void enterIdleState() {\r
- call cancelRssi();\r
- radioState = IDLE_STATE;\r
- }\r
-\r
- void enterIdleStateSetWakeup() {\r
- enterIdleState();\r
- post setWakeupTask();\r
- }\r
-\r
- void enterDisabledState() {\r
- call cancelRssi();\r
- radioState = DISABLED_STATE;\r
- }\r
-\r
- void enterPowerDownState() {\r
- call cancelRssi();\r
- radioState = POWERDOWN_STATE;\r
- }\r
-\r
- void enterPulseCheckState() {\r
- radioState = PULSECHECK_STATE;\r
- count = 0;\r
- }\r
-\r
- void enterRxState() {\r
- call cancelRssi();\r
- radioState = RX_STATE;\r
- }\r
-\r
- void enterTxState() {\r
- radioState = TX_STATE;\r
- }\r
-\r
- /* Basic radio power control */\r
-\r
- void radioOn() {\r
- call CC1000Control.coreOn();\r
- call BusyWait.wait(2000);\r
- call CC1000Control.biasOn();\r
- call BusyWait.wait(200);\r
- atomic call ByteRadio.listen();\r
- }\r
-\r
- void radioOff() {\r
- call CC1000Control.off();\r
- call ByteRadio.off();\r
- }\r
-\r
- void setPreambleLength(message_t *msg);\r
-\r
- /* Initialisation, startup and stopping */\r
- /*--------------------------------------*/\r
-\r
- command error_t Init.init() {\r
- call ByteRadioInit.init();\r
- call CC1000Control.init();\r
-\r
- return SUCCESS;\r
- }\r
-\r
- task void startStopDone() {\r
- uint8_t s;\r
-\r
- // Save a byte of RAM by sharing start/stopDone task\r
- atomic s = radioState;\r
- if (s == DISABLED_STATE)\r
- signal SplitControl.stopDone(SUCCESS);\r
- else\r
- signal SplitControl.startDone(SUCCESS);\r
- }\r
-\r
- command error_t SplitControl.start() {\r
- atomic \r
- if (radioState == DISABLED_STATE)\r
- {\r
- call ByteRadioControl.start();\r
- enterIdleStateSetWakeup();\r
- f.txPending = FALSE;\r
- }\r
- else\r
- return SUCCESS;\r
-\r
- radioOn();\r
-\r
- post startStopDone();\r
-\r
- return SUCCESS;\r
- }\r
-\r
- command error_t SplitControl.stop() {\r
- atomic \r
- {\r
- call ByteRadioControl.stop();\r
- enterDisabledState();\r
- radioOff();\r
- }\r
- call WakeupTimer.stop();\r
- post startStopDone();\r
- return SUCCESS;\r
- }\r
-\r
- /* Wakeup timer */\r
- /*-------------*/\r
-\r
- /* All timer setting code is placed in setWakeup, for consistency. */\r
- void setWakeup() {\r
- switch (radioState)\r
- {\r
- case IDLE_STATE:\r
- /* Timer already running means that we have a noise floor\r
- measurement scheduled. If we just set a new alarm here, we\r
- might indefinitely delay noise floor measurements if we're,\r
- e,g, transmitting frequently. */\r
- if (!call WakeupTimer.isRunning())\r
- if (call CC1000Squelch.settled())\r
- {\r
- if (sleepTime == 0)\r
- call WakeupTimer.startOneShot(CC1K_SquelchIntervalSlow);\r
- else\r
- // timeout for receiving a message after an lpl check\r
- // indicates channel activity.\r
- call WakeupTimer.startOneShot(TIME_AFTER_CHECK);\r
- }\r
- else\r
- call WakeupTimer.startOneShot(CC1K_SquelchIntervalFast);\r
- break;\r
- case PULSECHECK_STATE:\r
- // Radio warm-up time.\r
- call WakeupTimer.startOneShot(1);\r
- break;\r
- case POWERDOWN_STATE:\r
- // low-power listening check interval\r
- call WakeupTimer.startOneShot(sleepTime);\r
- break;\r
- }\r
- }\r
-\r
- task void setWakeupTask() {\r
- atomic setWakeup();\r
- }\r
-\r
- event void WakeupTimer.fired() {\r
- atomic \r
- {\r
- switch (radioState)\r
- {\r
- case IDLE_STATE:\r
- /* If we appear to be receiving a packet we don't check the\r
- noise floor. For LPL, this means that going to sleep will\r
- be delayed by another TIME_AFTER_CHECK ms. */\r
- if (!call ByteRadio.syncing())\r
- {\r
- call cancelRssi();\r
- call RssiNoiseFloor.read();\r
- }\r
- break;\r
-\r
- case POWERDOWN_STATE:\r
- // Turn radio on, wait for 1ms\r
- enterPulseCheckState();\r
- call CC1000Control.biasOn();\r
- break;\r
-\r
- case PULSECHECK_STATE:\r
- // Switch to RX mode and get RSSI output\r
- call CC1000Control.rxMode();\r
- call RssiPulseCheck.read();\r
- call BusyWait.wait(80);\r
- return; // don't set wakeup timer\r
- }\r
- setWakeup();\r
- }\r
- }\r
-\r
- /* Low-power listening stuff */\r
- /*---------------------------*/\r
-\r
- /* Should we go to sleep, or turn the radio fully on? */\r
- task void sleepCheck() {\r
- bool turnOn = FALSE;\r
-\r
- atomic\r
- if (f.txPending || !sleepTime)\r
- {\r
- if (radioState == PULSECHECK_STATE || radioState == POWERDOWN_STATE)\r
- {\r
- enterIdleStateSetWakeup();\r
- turnOn = TRUE;\r
- }\r
- }\r
- else if (call CC1000Squelch.settled() && !call ByteRadio.syncing())\r
- {\r
- radioOff();\r
- enterPowerDownState();\r
- setWakeup();\r
- }\r
-\r
- if (turnOn)\r
- radioOn();\r
- }\r
-\r
- task void adjustSquelch();\r
-\r
- async event void RssiPulseCheck.readDone(error_t result, uint16_t data) {\r
- if (result != SUCCESS)\r
- {\r
- /* Just give up on this interval. */\r
- post sleepCheck();\r
- return;\r
- }\r
-\r
- /* We got some RSSI data for our LPL check. Decide whether to:\r
- - go back to sleep (quiet)\r
- - wake up (channel active)\r
- - get more RSSI data\r
- */\r
- if (data > call CC1000Squelch.get() - (call CC1000Squelch.get() >> 2))\r
- {\r
- post sleepCheck();\r
- // don't be too agressive (ignore really quiet thresholds).\r
- if (data < call CC1000Squelch.get() + (call CC1000Squelch.get() >> 3))\r
- {\r
- // adjust the noise floor level, go back to sleep.\r
- rssiForSquelch = data;\r
- post adjustSquelch();\r
- }\r
- }\r
- else if (count++ > 5)\r
- {\r
- //go to the idle state since no outliers were found\r
- enterIdleStateSetWakeup();\r
- call ByteRadio.listen();\r
- }\r
- else\r
- {\r
- call RssiPulseCheck.read();\r
- call BusyWait.wait(80);\r
- }\r
- }\r
-\r
- /* CSMA */\r
- /*------*/\r
-\r
- event void ByteRadio.rts(message_t *msg) {\r
- atomic\r
- {\r
- f.txPending = TRUE;\r
-\r
- if (radioState == POWERDOWN_STATE)\r
- post sleepCheck();\r
- if (!f.ccaOff)\r
- macDelay = signal CsmaBackoff.initial(call ByteRadio.getTxMessage());\r
- else\r
- macDelay = 1;\r
-\r
- setPreambleLength(msg);\r
- }\r
- }\r
-\r
- async event void ByteRadio.sendDone() {\r
- f.txPending = FALSE;\r
- enterIdleStateSetWakeup();\r
- }\r
-\r
- void congestion() {\r
- macDelay = signal CsmaBackoff.congestion(call ByteRadio.getTxMessage());\r
- }\r
-\r
- async event void ByteRadio.idleByte(bool preamble) {\r
- if (f.txPending)\r
- {\r
- if (!f.ccaOff && preamble)\r
- congestion();\r
- else if (macDelay && !--macDelay)\r
- {\r
- call cancelRssi();\r
- count = 0;\r
- call RssiCheckChannel.read();\r
- }\r
- }\r
- }\r
-\r
- async event void RssiCheckChannel.readDone(error_t result, uint16_t data) {\r
- if (result != SUCCESS)\r
- {\r
- /* We'll retry the transmission at the next SPI event. */\r
- atomic macDelay = 1;\r
- return;\r
- }\r
-\r
- count++;\r
- if (data > call CC1000Squelch.get() + CC1K_SquelchBuffer)\r
- clearCount++;\r
- else\r
- clearCount = 0;\r
-\r
- // if the channel is clear or CCA is disabled, GO GO GO!\r
- if (clearCount >= 1 || f.ccaOff)\r
- {\r
- enterTxState();\r
- call ByteRadio.cts();\r
- }\r
- else if (count == CC1K_MaxRSSISamples)\r
- congestion();\r
- else \r
- call RssiCheckChannel.read();\r
- }\r
-\r
- /* Message being received. We basically just go inactive. */\r
- /*--------------------------------------------------------*/\r
-\r
- async event void ByteRadio.rx() {\r
- enterRxState();\r
- }\r
-\r
- async event void ByteRadio.rxDone() {\r
- if (radioState == RX_STATE)\r
- enterIdleStateSetWakeup();\r
- }\r
-\r
- /* Noise floor */\r
- /*-------------*/\r
-\r
- task void adjustSquelch() {\r
- uint16_t squelchData;\r
-\r
- atomic squelchData = rssiForSquelch;\r
- call CC1000Squelch.adjust(squelchData);\r
- }\r
-\r
- async event void RssiNoiseFloor.readDone(error_t result, uint16_t data) {\r
- if (result != SUCCESS)\r
- {\r
- /* We just ignore failed noise floor measurements */\r
- post sleepCheck();\r
- return;\r
- }\r
-\r
- rssiForSquelch = data;\r
- post adjustSquelch();\r
- post sleepCheck();\r
- }\r
-\r
- /* Options */\r
- /*---------*/\r
-\r
- async command error_t CsmaControl.enableCca() {\r
- atomic f.ccaOff = FALSE;\r
- return SUCCESS;\r
- }\r
-\r
- async command error_t CsmaControl.disableCca() {\r
- atomic f.ccaOff = TRUE;\r
- return SUCCESS;\r
- }\r
-\r
- /* Default MAC backoff parameters */\r
- /*--------------------------------*/\r
-\r
- default async event uint16_t CsmaBackoff.initial(message_t *m) { \r
- // initially back off [1,32] bytes (approx 2/3 packet)\r
- return (call Random.rand16() & 0x1F) + 1;\r
- }\r
-\r
- default async event uint16_t CsmaBackoff.congestion(message_t *m) { \r
- return (call Random.rand16() & 0xF) + 1;\r
- }\r
-\r
- /* LowPowerListening setup */\r
- /* ----------------------- */\r
-\r
- uint16_t validateSleepInterval(uint16_t sleepIntervalMs) {\r
- if (sleepIntervalMs < CC1K_LPL_MIN_INTERVAL)\r
- return 0;\r
- else if (sleepIntervalMs > CC1K_LPL_MAX_INTERVAL)\r
- return CC1K_LPL_MAX_INTERVAL;\r
- else\r
- return sleepIntervalMs;\r
- }\r
-\r
- uint16_t dutyToSleep(uint16_t dutyCycle) {\r
- /* Scaling factors on CC1K_LPL_CHECK_TIME and dutyCycle are identical */\r
- uint16_t interval = (1000 * CC1K_LPL_CHECK_TIME) / dutyCycle;\r
-\r
- return interval < CC1K_LPL_MIN_INTERVAL ? 0 : interval;\r
- }\r
-\r
- uint16_t sleepToDuty(uint16_t sleepInterval) {\r
- if (sleepInterval < CC1K_LPL_MIN_INTERVAL)\r
- return 10000;\r
-\r
- /* Scaling factors on CC1K_LPL_CHECK_TIME and dutyCycle are identical */\r
- return (1000 * CC1K_LPL_CHECK_TIME) / sleepInterval;\r
- }\r
-\r
- command void LowPowerListening.setLocalSleepInterval(uint16_t s) {\r
- sleepTime = validateSleepInterval(s);\r
- }\r
-\r
- command uint16_t LowPowerListening.getLocalSleepInterval() {\r
- return sleepTime;\r
- }\r
-\r
- command void LowPowerListening.setLocalDutyCycle(uint16_t d) {\r
- return call LowPowerListening.setLocalSleepInterval(dutyToSleep(d));\r
- }\r
-\r
- command uint16_t LowPowerListening.getLocalDutyCycle() {\r
- return sleepToDuty(call LowPowerListening.getLocalSleepInterval());\r
- }\r
-\r
- command void LowPowerListening.setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs) {\r
- cc1000_metadata_t *meta = getMetadata(msg);\r
-\r
- meta->strength_or_preamble = -(int16_t)validateSleepInterval(sleepIntervalMs) - 1;\r
- }\r
-\r
- command uint16_t LowPowerListening.getRxSleepInterval(message_t *msg) {\r
- cc1000_metadata_t *meta = getMetadata(msg);\r
-\r
- if (meta->strength_or_preamble >= 0)\r
- return sleepTime;\r
- else\r
- return -(meta->strength_or_preamble + 1);\r
- }\r
-\r
- command void LowPowerListening.setRxDutyCycle(message_t *msg, uint16_t d) {\r
- return call LowPowerListening.setRxSleepInterval(msg, dutyToSleep(d));\r
- }\r
-\r
- command uint16_t LowPowerListening.getRxDutyCycle(message_t *msg) {\r
- return sleepToDuty(call LowPowerListening.getRxSleepInterval(msg));\r
- }\r
-\r
- command uint16_t LowPowerListening.dutyCycleToSleepInterval(uint16_t d) {\r
- return dutyToSleep(d);\r
- }\r
-\r
- command uint16_t LowPowerListening.sleepIntervalToDutyCycle(uint16_t s) {\r
- return sleepToDuty(s);\r
- }\r
-\r
- void setPreambleLength(message_t *msg) {\r
- cc1000_metadata_t *meta = getMetadata(msg);\r
- uint16_t s;\r
- uint32_t plen;\r
-\r
- if (meta->strength_or_preamble >= 0)\r
- s = sleepTime;\r
- else\r
- s = -(meta->strength_or_preamble + 1);\r
- meta->strength_or_preamble = 0; /* Destroy setting */\r
-\r
- if (s == 0)\r
- plen = 6;\r
- else\r
- plen = (((s * 614UL) >> 8) / 6) + 22; \r
- // ~ (s * 2.4)/6 + 22\r
- // TODO remove the divide. It's there so we still have a long preamble, but\r
- // 6 times shorter than the regular preamble. This will increase\r
- // delivery time while modulating the channel long enough to get detected.\r
- \r
- call ByteRadio.setPreambleLength(plen);\r
- }\r
-}\r
+++ /dev/null
-/* $Id$\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-\r
-/**\r
- * A low-power-listening CC1000 radio stack.\r
- *\r
- * Radio logic is split between Csma (media-access control, low-power\r
- * listening and general control) and SendReceive (packet reception and\r
- * transmission). \r
- *\r
- * CC1000RssiP (RSSI sharing), CC1000SquelchP (noise-floor estimation)\r
- * and CC1000ControlP (radio configuration) provide supporting roles.\r
- *\r
- * This code has some degree of platform-independence, via the HplCC1000,\r
- * RssiAdc and HplCC1000Spi interfaces which must be provided by the\r
- * platform. However, these interfaces may still reflect some\r
- * particularities of the mica2 hardware implementation.\r
- *\r
- * @author Joe Polastre\r
- * @author David Gay\r
- */\r
-\r
-#include "CC1000Const.h"\r
-#include "message.h"\r
-\r
-configuration CC1000CsmaRadioC {\r
- provides {\r
- interface SplitControl;\r
- interface Send;\r
- interface Receive;\r
-\r
- interface Packet; \r
- interface CsmaControl;\r
- interface CsmaBackoff;\r
- interface RadioTimeStamping;\r
- interface PacketAcknowledgements;\r
-\r
- interface LowPowerListening;\r
- }\r
-}\r
-implementation {\r
- components CC1000CsmaP as Csma;\r
- components CC1000SendReceiveP as SendReceive;\r
- components CC1000RssiP as Rssi;\r
- components CC1000SquelchP as Squelch;\r
- components CC1000ControlP as Control;\r
- components HplCC1000C as Hpl;\r
- components CC1000LowPowerListeningC;\r
-\r
- components MainC, RandomC, new TimerMilliC(), ActiveMessageAddressC, BusyWaitMicroC;\r
-\r
- MainC.SoftwareInit -> Csma;\r
- MainC.SoftwareInit -> Squelch;\r
-\r
- SplitControl = Csma;\r
- Send = SendReceive;\r
- Receive = SendReceive;\r
- Packet = SendReceive;\r
-\r
- CsmaControl = Csma;\r
- CsmaBackoff = Csma;\r
- LowPowerListening = Csma;\r
- RadioTimeStamping = SendReceive;\r
- PacketAcknowledgements = SendReceive;\r
-\r
- Csma.CC1000Control -> Control;\r
- Csma.Random -> RandomC;\r
- Csma.CC1000Squelch -> Squelch;\r
- Csma.WakeupTimer -> TimerMilliC;\r
- Csma.ByteRadio -> SendReceive;\r
- Csma.ByteRadioInit -> SendReceive;\r
- Csma.ByteRadioControl -> SendReceive;\r
- \r
- SendReceive.CC1000Control -> Control;\r
- SendReceive.HplCC1000Spi -> Hpl;\r
- SendReceive.amAddress -> ActiveMessageAddressC;\r
- SendReceive.RssiRx -> Rssi.Rssi[unique(UQ_CC1000_RSSI)];\r
- \r
- Csma.RssiNoiseFloor -> Rssi.Rssi[unique(UQ_CC1000_RSSI)];\r
- Csma.RssiCheckChannel -> Rssi.Rssi[unique(UQ_CC1000_RSSI)];\r
- Csma.RssiPulseCheck -> Rssi.Rssi[unique(UQ_CC1000_RSSI)];\r
- Csma.cancelRssi -> Rssi;\r
- Csma.BusyWait -> BusyWaitMicroC;\r
-\r
- Rssi.ActualRssi -> Hpl;\r
- Rssi.Resource -> Hpl;\r
- Control.CC -> Hpl;\r
- Control.BusyWait -> BusyWaitMicroC;\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005-2006 Rincon Research Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the\r
- * distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
- \r
- /**\r
- * @author David Moss\r
- */\r
-#ifndef CC1000LOWPOWERLISTENING_H\r
-#define CC1000LOWPOWERLISTENING_H\r
-\r
-/**\r
- * The default duty period is usually 0, which is the equivalent of\r
- * ONE_MESSAGE (below), which tells the node to transmit the message\r
- * one time without expecting receiver duty cycling.\r
- */\r
-#ifndef DEFAULT_TRANSMIT_PERIOD\r
-#define DEFAULT_TRANSMIT_PERIOD 0\r
-#endif\r
-\r
-/**\r
- * Value used to indicate the message being sent should be transmitted\r
- * one time\r
- */\r
-#ifndef ONE_MESSAGE\r
-#define ONE_MESSAGE 0\r
-#endif\r
-\r
-#endif\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005-2006 Rincon Research Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the\r
- * distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
-\r
-/**\r
- * Low Power Listening for the CC1000\r
- * @author David Moss\r
- */\r
- \r
-#include "CC1000LowPowerListening.h"\r
-\r
-configuration CC1000LowPowerListeningC {\r
- provides {\r
- interface Send;\r
- interface Receive;\r
- interface CsmaBackoff[am_id_t amId];\r
- }\r
-}\r
-\r
-implementation {\r
- components MainC,\r
- CC1000ActiveMessageC,\r
- CC1000LowPowerListeningP,\r
- CC1000CsmaRadioC,\r
- RandomC,\r
- new StateC() as SendStateC,\r
- new StateC() as RadioPowerStateC,\r
- new TimerMilliC() as SendDoneTimerC;\r
- \r
- Send = CC1000LowPowerListeningP;\r
- Receive = CC1000LowPowerListeningP;\r
- CsmaBackoff = CC1000LowPowerListeningP;\r
- \r
- MainC.SoftwareInit -> CC1000LowPowerListeningP;\r
- \r
- CC1000LowPowerListeningP.AMPacket -> CC1000ActiveMessageC;\r
- CC1000LowPowerListeningP.Random -> RandomC;\r
- CC1000LowPowerListeningP.SendState -> SendStateC;\r
- CC1000LowPowerListeningP.RadioPowerState -> RadioPowerStateC;\r
- CC1000LowPowerListeningP.SendDoneTimer -> SendDoneTimerC;\r
- CC1000LowPowerListeningP.SubSend -> CC1000CsmaRadioC;\r
- CC1000LowPowerListeningP.SubReceive -> CC1000CsmaRadioC;\r
- CC1000LowPowerListeningP.SubControl -> CC1000CsmaRadioC;\r
- CC1000LowPowerListeningP.PacketAcknowledgements -> CC1000CsmaRadioC;\r
- CC1000LowPowerListeningP.SubBackoff -> CC1000CsmaRadioC;\r
- CC1000LowPowerListeningP.CsmaControl -> CC1000CsmaRadioC;\r
- CC1000LowPowerListeningP.LowPowerListening -> CC1000CsmaRadioC;\r
- \r
-}\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005-2006 Rincon Research Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the\r
- * distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
-\r
-/**\r
- * Low Power Listening for the CC1000\r
- *\r
- * @author David Moss\r
- */\r
-\r
-#include "CC1000LowPowerListening.h"\r
-\r
-module CC1000LowPowerListeningP {\r
- provides {\r
- interface Init;\r
- interface Send;\r
- interface Receive;\r
- interface CsmaBackoff[am_id_t amId];\r
- }\r
- \r
- uses {\r
- interface LowPowerListening;\r
- interface CsmaBackoff as SubBackoff;\r
- interface CsmaControl;\r
- interface Leds;\r
- interface Send as SubSend;\r
- interface Receive as SubReceive;\r
- interface AMPacket;\r
- interface SplitControl as SubControl;\r
- interface PacketAcknowledgements;\r
- interface State as SendState;\r
- interface State as RadioPowerState;\r
- interface Random;\r
- interface Timer<TMilli> as SendDoneTimer;\r
- }\r
-}\r
-\r
-implementation {\r
- \r
- /** The message currently being sent */\r
- message_t *currentSendMsg;\r
- \r
- /** The length of the current send message */\r
- uint8_t currentSendLen;\r
- \r
- /** Tx DSN to ensure multiple transmitted messages get across only once */ \r
- uint8_t txDsn;\r
- \r
- /** The last received broadcast DSN. TODO is this the best way? */\r
- uint8_t lastRxDsn;\r
-\r
- /** TRUE if the first message of the current LPL delivery has been sent */\r
- norace bool firstMessageSent;\r
- \r
- /**\r
- * Radio State\r
- */\r
- enum {\r
- S_OFF,\r
- S_ON,\r
- };\r
- \r
- /**\r
- * Send States\r
- */\r
- enum {\r
- S_IDLE,\r
- S_SENDING,\r
- };\r
- \r
- \r
- /***************** Prototypes ***************/\r
- task void send();\r
- task void startRadio();\r
- task void stopRadio();\r
- \r
- cc1000_header_t *getHeader(message_t *msg);\r
- cc1000_metadata_t *getMetadata(message_t* msg);\r
- uint16_t getActualDutyCycle(uint16_t dutyCycle);\r
- void signalDone(error_t error);\r
- \r
- /***************** Init Commands ***************/\r
- command error_t Init.init() {\r
- txDsn = call Random.rand16();\r
- return SUCCESS;\r
- }\r
- \r
- \r
- /***************** SubBackoff Events ****************/\r
- async event uint16_t SubBackoff.initial(message_t* m) {\r
- if(call SendState.getState() == S_SENDING\r
- && getMetadata(m)->strength_or_preamble > ONE_MESSAGE\r
- && firstMessageSent) {\r
- call CsmaControl.disableCca();\r
- return 1;\r
- \r
- } else {\r
- return signal CsmaBackoff.initial[getHeader(m)->type](m);\r
- }\r
- }\r
-\r
- async event uint16_t SubBackoff.congestion(message_t* m) {\r
- if(call SendState.getState() == S_SENDING\r
- && getMetadata(m)->strength_or_preamble > ONE_MESSAGE\r
- && firstMessageSent) {\r
- call CsmaControl.disableCca();\r
- return 1;\r
- \r
- } else {\r
- return signal CsmaBackoff.congestion[getHeader(m)->type](m);\r
- }\r
- }\r
- \r
- /***************** Send Commands ***************/\r
- /**\r
- * Each call to this send command gives the message a single\r
- * DSN that does not change for every copy of the message\r
- * sent out. For messages that are not acknowledged, such as\r
- * a broadcast address message, the receiving end does not\r
- * signal receive() more than once for that message.\r
- */\r
- command error_t Send.send(message_t *msg, uint8_t len) {\r
- if(call RadioPowerState.getState() == S_OFF) {\r
- // Everything is off right now, start SplitControl and try again\r
- return EOFF;\r
- }\r
- \r
- if(call SendState.requestState(S_SENDING) == SUCCESS) {\r
- currentSendMsg = msg;\r
- currentSendLen = len;\r
- (getHeader(msg))->dsn = ++txDsn;\r
- \r
- firstMessageSent = FALSE;\r
- if(call LowPowerListening.getRxSleepInterval(currentSendMsg) \r
- > ONE_MESSAGE) {\r
- \r
- // Send it repetitively within our transmit window\r
- call PacketAcknowledgements.requestAck(currentSendMsg);\r
- call SendDoneTimer.startOneShot(\r
- call LowPowerListening.getRxSleepInterval(currentSendMsg) * 2);\r
- }\r
- \r
- // If the radio is off, the CC1000Csma will automatically turn it on\r
- post send();\r
- return SUCCESS;\r
- }\r
- \r
- return FAIL;\r
- }\r
-\r
- command error_t Send.cancel(message_t *msg) {\r
- if(currentSendMsg == msg) {\r
- call SendState.toIdle();\r
- return SUCCESS;\r
- }\r
- \r
- return FAIL;\r
- }\r
- \r
- \r
- command uint8_t Send.maxPayloadLength() {\r
- return call SubSend.maxPayloadLength();\r
- }\r
-\r
- command void *Send.getPayload(message_t* msg) {\r
- return call SubSend.getPayload(msg);\r
- }\r
- \r
- /***************** Receive Commands ***************/\r
- command void *Receive.getPayload(message_t* msg, uint8_t* len) {\r
- return call SubReceive.getPayload(msg, len);\r
- }\r
-\r
- command uint8_t Receive.payloadLength(message_t* msg) {\r
- return call SubReceive.payloadLength(msg);\r
- }\r
-\r
- \r
- /***************** SubControl Events ***************/\r
- event void SubControl.startDone(error_t error) {\r
- if(!error) {\r
- call RadioPowerState.forceState(S_ON);\r
- }\r
- }\r
- \r
- event void SubControl.stopDone(error_t error) {\r
- if(!error) {\r
- call RadioPowerState.forceState(S_OFF);\r
- }\r
- }\r
- \r
- /***************** SubSend Events ***************/\r
- event void SubSend.sendDone(message_t* msg, error_t error) {\r
- if(call SendState.getState() == S_SENDING \r
- && call SendDoneTimer.isRunning()) {\r
- if(call PacketAcknowledgements.wasAcked(msg)) {\r
- signalDone(error);\r
- \r
- } else {\r
- post send();\r
- }\r
- \r
- return;\r
- }\r
- \r
- signalDone(error);\r
- }\r
- \r
- /***************** SubReceive Events ***************/\r
- /**\r
- * If the received message is new, we signal the receive event and\r
- * start the off timer. If the last message we received had the same\r
- * DSN as this message, then the chances are pretty good\r
- * that this message should be ignored, especially if the destination address\r
- * as the broadcast address\r
- *\r
- * TODO\r
- * What happens if a unicast Tx doesn't get Rx's ack, and resends that\r
- * message?\r
- */\r
- event message_t *SubReceive.receive(message_t* msg, void* payload, \r
- uint8_t len) {\r
- \r
- if((getHeader(msg))->dsn == lastRxDsn \r
- && call AMPacket.destination(msg) == AM_BROADCAST_ADDR) {\r
- // Already got this broadcast message.\r
- // TODO should we do something similar with unicast messages?\r
- return msg;\r
-\r
- } else {\r
- lastRxDsn = (getHeader(msg))->dsn;\r
- return signal Receive.receive(msg, payload, len);\r
- }\r
- }\r
- \r
- /***************** Timer Events ****************/ \r
- /**\r
- * When this timer is running, that means we're sending repeating messages\r
- * to a node that is receive check duty cycling.\r
- */\r
- event void SendDoneTimer.fired() {\r
- if(call SendState.getState() == S_SENDING) {\r
- // The next time SubSend.sendDone is signaled, send is complete.\r
- call SendState.toIdle();\r
- }\r
- }\r
- \r
- /***************** Tasks ***************/\r
- task void send() {\r
- if(call SubSend.send(currentSendMsg, currentSendLen) != SUCCESS) {\r
- post send();\r
- }\r
- }\r
- \r
- task void startRadio() {\r
- if(call SubControl.start() != SUCCESS) {\r
- post startRadio();\r
- }\r
- }\r
- \r
- task void stopRadio() {\r
- if(call SubControl.stop() != SUCCESS) {\r
- post stopRadio();\r
- }\r
- }\r
- \r
- /***************** Functions ***************/ \r
- /**\r
- * Check the bounds on a given duty cycle\r
- * We're never over 100%, and we're never at 0%\r
- */\r
- uint16_t getActualDutyCycle(uint16_t dutyCycle) {\r
- if(dutyCycle > 10000) {\r
- return 10000;\r
- } else if(dutyCycle == 0) {\r
- return 1;\r
- }\r
- \r
- return dutyCycle;\r
- }\r
- \r
- cc1000_header_t *getHeader(message_t *msg) {\r
- return (cc1000_header_t *)(msg->data - sizeof( cc1000_header_t ));\r
- }\r
- \r
- cc1000_metadata_t *getMetadata(message_t* msg) {\r
- return (cc1000_metadata_t*)msg->metadata;\r
- }\r
- \r
- void signalDone(error_t error) {\r
- call CsmaControl.enableCca();\r
- call SendState.toIdle();\r
- // TODO check for broadcast destination\r
- signal Send.sendDone(currentSendMsg, error);\r
- currentSendMsg = NULL;\r
- }\r
- \r
- \r
- \r
- /***************** Defaults ****************/\r
- default async event uint16_t CsmaBackoff.initial[am_id_t amId](message_t *m) {\r
- return ( call Random.rand16() % (0x1F * CC1000_BACKOFF_PERIOD) \r
- + CC1000_MIN_BACKOFF);\r
- }\r
-\r
- default async event uint16_t CsmaBackoff.congestion[am_id_t amId](message_t *m) {\r
- return ( call Random.rand16() % (0x7 * CC1000_BACKOFF_PERIOD) \r
- + CC1000_MIN_BACKOFF);\r
- }\r
-}\r
-\r
+++ /dev/null
-#ifndef CC1K_RADIO_MSG_H\r
-#define CC1K_RADIO_MSG_H\r
-\r
-#include "AM.h"\r
-\r
-typedef nx_struct CC1KHeader {\r
- nx_am_addr_t dest;\r
- nx_am_addr_t source;\r
- nx_uint8_t length;\r
- nx_am_group_t group;\r
- nx_uint8_t dsn;\r
- nx_am_id_t type;\r
-} cc1000_header_t;\r
-\r
-typedef nx_struct CC1KFooter {\r
- nxle_uint16_t crc; \r
-} cc1000_footer_t;\r
-\r
-typedef nx_struct CC1KMetadata {\r
- nx_int16_t strength_or_preamble; /* negative when used for preamble length */\r
- nx_uint8_t ack;\r
- nx_uint16_t time;\r
- nx_uint8_t sendSecurityMode;\r
- nx_uint8_t receiveSecurityMode; \r
-} cc1000_metadata_t;\r
-\r
-#endif\r
+++ /dev/null
-/* $Id$\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-\r
-/**\r
- * RSSI fun. It's used for lots of things, and a request to read it\r
- * for one purpose may have to be discarded if conditions change. For\r
- * example, if we've initiated a noise-floor measure, but start \r
- * receiving a packet, we have to:<ul>\r
- * <li>cancel the noise-floor measure (we don't know if the value will\r
- * reflect the received packet or the previous idle state)\r
- * <li>start an RSSI measurement so that we can report signal strength\r
- * to the application\r
- * </ul><p>\r
- * This module hides the complexities of cancellation from the rest of\r
- * the stack.\r
- */\r
-\r
-module CC1000RssiP\r
-{\r
- provides {\r
- interface ReadNow<uint16_t> as Rssi[uint8_t reason];\r
- async command void cancel();\r
- }\r
- uses {\r
- interface Resource;\r
- interface ReadNow<uint16_t> as ActualRssi;\r
- }\r
-}\r
-implementation\r
-{\r
- enum {\r
- IDLE = unique(UQ_CC1000_RSSI),\r
- CANCELLED = unique(UQ_CC1000_RSSI)\r
- };\r
-\r
- /* All commands are called within atomic sections */\r
- uint8_t currentOp = IDLE;\r
- uint8_t nextOp;\r
-\r
- async command void cancel() {\r
- if (currentOp != IDLE)\r
- currentOp = CANCELLED;\r
- }\r
-\r
- event void Resource.granted() {\r
- call ActualRssi.read();\r
- }\r
-\r
- async command error_t Rssi.read[uint8_t reason]() {\r
- if (currentOp == IDLE)\r
- {\r
- currentOp = reason;\r
- if (call Resource.immediateRequest() == SUCCESS)\r
- call ActualRssi.read();\r
- else\r
- call Resource.request();\r
- }\r
- else\r
- nextOp = reason;\r
- return SUCCESS;\r
- }\r
-\r
- void startNextOp() {\r
- currentOp = nextOp;\r
- if (nextOp != IDLE)\r
- {\r
- nextOp = IDLE;\r
- call ActualRssi.read();\r
- }\r
- else\r
- call Resource.release();\r
- }\r
-\r
- async event void ActualRssi.readDone(error_t result, uint16_t data) {\r
- atomic\r
- {\r
- /* The RSSI measurements are assumed to be 10-bits */\r
- signal Rssi.readDone[currentOp](result, data);\r
- startNextOp();\r
- }\r
- }\r
-\r
- default async event void Rssi.readDone[uint8_t reason](error_t result, uint16_t data) { }\r
-}\r
+++ /dev/null
-// $Id$\r
-\r
-/* tab:4\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-#include "message.h"\r
-#include "crc.h"\r
-#include "CC1000Const.h"\r
-#include "Timer.h"\r
-\r
-/**\r
- * A rewrite of the low-power-listening CC1000 radio stack.\r
- * This file contains the send and receive logic for the CC1000 radio.\r
- * It does not do any media-access control. It requests the channel\r
- * via the ready-to-send event (rts) and starts transmission on reception\r
- * of the clear-to-send command (cts). It listens for packets if the\r
- * listen() command is called, and stops listening when off() is called.\r
- * <p>\r
- * This code has some degree of platform-independence, via the\r
- * CC1000Control, RSSIADC and SpiByteFifo interfaces which must be provided\r
- * by the platform. However, these interfaces may still reflect some\r
- * particularities of the mica2 hardware implementation.\r
- *\r
- * @author Philip Buonadonna\r
- * @author Jaein Jeong\r
- * @author Joe Polastre\r
- * @author David Gay\r
- */\r
- \r
-module CC1000SendReceiveP {\r
- provides {\r
- interface Init;\r
- interface StdControl;\r
- interface Send;\r
- interface Receive;\r
- interface RadioTimeStamping;\r
- interface Packet;\r
- interface ByteRadio;\r
- interface PacketAcknowledgements;\r
- }\r
- uses {\r
- //interface PowerManagement;\r
- interface CC1000Control;\r
- interface HplCC1000Spi;\r
-\r
- interface ReadNow<uint16_t> as RssiRx;\r
- async command am_addr_t amAddress();\r
- }\r
-}\r
-implementation \r
-{\r
- enum {\r
- OFF_STATE,\r
-\r
- INACTIVE_STATE, /* Not listening, but will accept sends */\r
-\r
- LISTEN_STATE, /* Listening for packets */\r
-\r
- /* Reception states */\r
- SYNC_STATE,\r
- RX_STATE,\r
- RECEIVED_STATE,\r
- SENDING_ACK,\r
-\r
- /* Transmission states */\r
- TXPREAMBLE_STATE,\r
- TXSYNC_STATE,\r
- TXDATA_STATE,\r
- TXCRC_STATE,\r
- TXFLUSH_STATE,\r
- TXWAITFORACK_STATE,\r
- TXREADACK_STATE,\r
- TXDONE_STATE,\r
- };\r
-\r
- enum {\r
- SYNC_BYTE1 = 0x33,\r
- SYNC_BYTE2 = 0xcc,\r
- SYNC_WORD = SYNC_BYTE1 << 8 | SYNC_BYTE2,\r
- ACK_BYTE1 = 0xba,\r
- ACK_BYTE2 = 0x83,\r
- ACK_WORD = ACK_BYTE1 << 8 | ACK_BYTE2,\r
- ACK_LENGTH = 16,\r
- MAX_ACK_WAIT = 18\r
- };\r
-\r
- uint8_t radioState;\r
- struct {\r
- uint8_t ack : 1; /* acks enabled? */\r
- uint8_t txBusy : 1; /* send pending? */\r
- uint8_t invert : 1; /* data inverted? (see cc1000 datasheet) */\r
- uint8_t rxBitOffset : 3; /* bit-offset of received bytes */\r
- } f; // f for flags\r
- uint16_t count;\r
- uint16_t runningCrc;\r
-\r
- uint16_t rxShiftBuf;\r
- message_t rxBuf;\r
- message_t *rxBufPtr = &rxBuf;\r
-\r
- uint16_t preambleLength;\r
- message_t *txBufPtr;\r
- uint8_t nextTxByte;\r
-\r
- const_uint8_t ackCode[5] = { 0xab, ACK_BYTE1, ACK_BYTE2, 0xaa, 0xaa };\r
-\r
- /* Packet structure accessor functions. Note that everything is\r
- * relative to the data field. */\r
- cc1000_header_t *getHeader(message_t *amsg) {\r
- return (cc1000_header_t *)(amsg->data - sizeof(cc1000_header_t));\r
- }\r
-\r
- cc1000_footer_t *getFooter(message_t *amsg) {\r
- return (cc1000_footer_t *)(amsg->footer);\r
- }\r
- \r
- cc1000_metadata_t *getMetadata(message_t *amsg) {\r
- return (cc1000_metadata_t *)((uint8_t *)amsg->footer + sizeof(cc1000_footer_t));\r
- }\r
- \r
- /* State transition functions */\r
- /*----------------------------*/\r
-\r
- void enterOffState() {\r
- radioState = OFF_STATE;\r
- }\r
-\r
- void enterInactiveState() {\r
- radioState = INACTIVE_STATE;\r
- }\r
-\r
- void enterListenState() {\r
- radioState = LISTEN_STATE;\r
- count = 0;\r
- }\r
-\r
- void enterSyncState() {\r
- radioState = SYNC_STATE;\r
- count = 0;\r
- rxShiftBuf = 0;\r
- }\r
-\r
- void enterRxState() {\r
- cc1000_header_t *header = getHeader(rxBufPtr);\r
- radioState = RX_STATE;\r
- header->length = sizeof rxBufPtr->data;\r
- count = sizeof(message_header_t) - sizeof(cc1000_header_t);\r
- runningCrc = 0;\r
- }\r
-\r
- void enterReceivedState() {\r
- radioState = RECEIVED_STATE;\r
- }\r
-\r
- void enterAckState() {\r
- radioState = SENDING_ACK;\r
- count = 0;\r
- }\r
-\r
- void enterTxPreambleState() {\r
- radioState = TXPREAMBLE_STATE;\r
- count = 0;\r
- runningCrc = 0;\r
- nextTxByte = 0xaa;\r
- }\r
-\r
- void enterTxSyncState() {\r
- radioState = TXSYNC_STATE;\r
- }\r
-\r
- void enterTxDataState() {\r
- radioState = TXDATA_STATE;\r
- // The count increment happens before the first byte is read from the\r
- // packet, so we subtract one from the real packet start point to\r
- // compensate.\r
- count = (sizeof(message_header_t) - sizeof(cc1000_header_t)) -1; \r
- }\r
-\r
- void enterTxCrcState() {\r
- radioState = TXCRC_STATE;\r
- }\r
- \r
- void enterTxFlushState() {\r
- radioState = TXFLUSH_STATE;\r
- count = 0;\r
- }\r
- \r
- void enterTxWaitForAckState() {\r
- radioState = TXWAITFORACK_STATE;\r
- count = 0;\r
- }\r
- \r
- void enterTxReadAckState() {\r
- radioState = TXREADACK_STATE;\r
- rxShiftBuf = 0;\r
- count = 0;\r
- }\r
- \r
- void enterTxDoneState() {\r
- radioState = TXDONE_STATE;\r
- }\r
-\r
- command error_t Init.init() {\r
- f.ack = TRUE; /* We always ack, for now at least */\r
- call HplCC1000Spi.initSlave();\r
- return SUCCESS;\r
- }\r
-\r
- command error_t StdControl.start() {\r
- atomic \r
- {\r
- enterInactiveState();\r
- f.txBusy = FALSE;\r
- f.invert = call CC1000Control.getLOStatus();\r
- }\r
- return SUCCESS;\r
- }\r
-\r
- command error_t StdControl.stop() {\r
- atomic enterOffState();\r
- return SUCCESS;\r
- }\r
-\r
- /* Send side. Outside requests, SPI handlers for each state */\r
- /*----------------------------------------------------------*/\r
-\r
- command error_t Send.send(message_t *msg, uint8_t len) {\r
- atomic\r
- {\r
- if (f.txBusy || radioState == OFF_STATE)\r
- return FAIL;\r
- else {\r
- cc1000_header_t *header = getHeader(msg);\r
-\r
- f.txBusy = TRUE;\r
- header->length = len;\r
- txBufPtr = msg;\r
- }\r
- }\r
- signal ByteRadio.rts(msg);\r
-\r
- return SUCCESS;\r
- }\r
-\r
- async command void ByteRadio.cts() {\r
- /* We're set to go! Start with our exciting preamble... */\r
- enterTxPreambleState();\r
- call HplCC1000Spi.writeByte(0xaa);\r
- call CC1000Control.txMode();\r
- call HplCC1000Spi.txMode();\r
- }\r
-\r
- command error_t Send.cancel(message_t *msg) {\r
- /* We simply ignore cancellations. */\r
- return FAIL;\r
- }\r
-\r
- void sendNextByte() {\r
- call HplCC1000Spi.writeByte(nextTxByte);\r
- count++;\r
- }\r
-\r
- void txPreamble() {\r
- sendNextByte();\r
- if (count >= preambleLength)\r
- {\r
- nextTxByte = SYNC_BYTE1;\r
- enterTxSyncState();\r
- }\r
- }\r
-\r
- void txSync() {\r
- sendNextByte();\r
- nextTxByte = SYNC_BYTE2;\r
- enterTxDataState();\r
- signal RadioTimeStamping.transmittedSFD(0, txBufPtr); \r
- }\r
-\r
- void txData() {\r
- cc1000_header_t *txHeader = getHeader(txBufPtr);\r
- sendNextByte();\r
- \r
- if (count < txHeader->length + sizeof(message_header_t))\r
- {\r
- nextTxByte = ((uint8_t *)txBufPtr)[count];\r
- runningCrc = crcByte(runningCrc, nextTxByte);\r
- }\r
- else\r
- {\r
- nextTxByte = runningCrc;\r
- enterTxCrcState();\r
- }\r
- }\r
-\r
- void txCrc() {\r
- sendNextByte();\r
- nextTxByte = runningCrc >> 8;\r
- enterTxFlushState();\r
- }\r
-\r
- void txFlush() {\r
- sendNextByte();\r
- if (count > 3)\r
- if (f.ack)\r
- enterTxWaitForAckState();\r
- else\r
- {\r
- call HplCC1000Spi.rxMode();\r
- call CC1000Control.rxMode();\r
- enterTxDoneState();\r
- }\r
- }\r
-\r
- void txWaitForAck() {\r
- sendNextByte();\r
- if (count == 1)\r
- {\r
- call HplCC1000Spi.rxMode();\r
- call CC1000Control.rxMode();\r
- }\r
- else if (count > 3)\r
- enterTxReadAckState();\r
- }\r
-\r
- void txReadAck(uint8_t in) {\r
- uint8_t i;\r
-\r
- sendNextByte();\r
-\r
- for (i = 0; i < 8; i ++)\r
- {\r
- rxShiftBuf <<= 1;\r
- if (in & 0x80)\r
- rxShiftBuf |= 0x1;\r
- in <<= 1;\r
-\r
- if (rxShiftBuf == ACK_WORD)\r
- {\r
- getMetadata(txBufPtr)->ack = 1;\r
- enterTxDoneState();\r
- return;\r
- }\r
- }\r
- if (count >= MAX_ACK_WAIT)\r
- {\r
- getMetadata(txBufPtr)->ack = 0;\r
- enterTxDoneState();\r
- }\r
- }\r
-\r
- task void signalPacketSent() {\r
- message_t *pBuf;\r
-\r
- atomic\r
- {\r
- pBuf = txBufPtr;\r
- f.txBusy = FALSE;\r
- enterListenState();\r
- }\r
- signal Send.sendDone(pBuf, SUCCESS);\r
- }\r
-\r
- void txDone() {\r
- post signalPacketSent();\r
- signal ByteRadio.sendDone();\r
- }\r
-\r
- /* Receive */\r
- /*---------*/\r
-\r
- void packetReceived();\r
- void packetReceiveDone();\r
-\r
- async command void ByteRadio.listen() {\r
- enterListenState();\r
- call CC1000Control.rxMode();\r
- call HplCC1000Spi.rxMode();\r
- call HplCC1000Spi.enableIntr();\r
- }\r
-\r
- async command void ByteRadio.off() {\r
- enterInactiveState();\r
- call HplCC1000Spi.disableIntr();\r
- }\r
-\r
- void listenData(uint8_t in) {\r
- bool preamble = in == 0xaa || in == 0x55;\r
-\r
- // Look for enough preamble bytes\r
- if (preamble)\r
- {\r
- count++;\r
- if (count > CC1K_ValidPrecursor)\r
- enterSyncState();\r
- }\r
- else\r
- count = 0;\r
-\r
- signal ByteRadio.idleByte(preamble);\r
- }\r
-\r
- void syncData(uint8_t in) {\r
- // draw in the preamble bytes and look for a sync byte\r
- // save the data in a short with last byte received as msbyte\r
- // and current byte received as the lsbyte.\r
- // use a bit shift compare to find the byte boundary for the sync byte\r
- // retain the shift value and use it to collect all of the packet data\r
- // check for data inversion, and restore proper polarity \r
- // XXX-PB: Don't do this.\r
-\r
- if (in == 0xaa || in == 0x55)\r
- // It is actually possible to have the LAST BIT of the incoming\r
- // data be part of the Sync Byte. SO, we need to store that\r
- // However, the next byte should definitely not have this pattern.\r
- // XXX-PB: Do we need to check for excessive preamble?\r
- rxShiftBuf = in << 8;\r
- else if (count++ == 0)\r
- rxShiftBuf |= in;\r
- else if (count <= 6)\r
- {\r
- // TODO: Modify to be tolerant of bad bits in the preamble...\r
- uint16_t tmp;\r
- uint8_t i;\r
-\r
- // bit shift the data in with previous sample to find sync\r
- tmp = rxShiftBuf;\r
- rxShiftBuf = rxShiftBuf << 8 | in;\r
-\r
- for(i = 0; i < 8; i++)\r
- {\r
- tmp <<= 1;\r
- if (in & 0x80)\r
- tmp |= 0x1;\r
- in <<= 1;\r
- // check for sync bytes\r
- if (tmp == SYNC_WORD)\r
- {\r
- enterRxState();\r
- signal ByteRadio.rx();\r
- f.rxBitOffset = 7 - i;\r
- signal RadioTimeStamping.receivedSFD(0);\r
- call RssiRx.read();\r
- }\r
- }\r
- }\r
- else // We didn't find it after a reasonable number of tries, so....\r
- enterListenState();\r
- }\r
- \r
- async event void RssiRx.readDone(error_t result, uint16_t data) {\r
- cc1000_metadata_t *rxMetadata = getMetadata(rxBufPtr);\r
-\r
- if (result != SUCCESS)\r
- rxMetadata->strength_or_preamble = 0;\r
- else\r
- rxMetadata->strength_or_preamble = data;\r
- }\r
-\r
- void rxData(uint8_t in) {\r
- uint8_t nextByte;\r
- cc1000_header_t *rxHeader = getHeader(rxBufPtr);\r
- uint8_t rxLength = rxHeader->length;\r
-\r
- // Reject invalid length packets\r
- if (rxLength > TOSH_DATA_LENGTH)\r
- {\r
- // The packet's screwed up, so just dump it\r
- enterListenState();\r
- signal ByteRadio.rxDone();\r
- return;\r
- }\r
-\r
- rxShiftBuf = rxShiftBuf << 8 | in;\r
- nextByte = rxShiftBuf >> f.rxBitOffset;\r
- ((uint8_t *)rxBufPtr)[count++] = nextByte;\r
-\r
- // Adjust rxLength to correspond to the corresponding offset in message_t\r
- rxLength += offsetof(message_t, data);\r
- if (count <= rxLength)\r
- runningCrc = crcByte(runningCrc, nextByte);\r
-\r
- // Jump to CRC when we reach the end of data\r
- if (count == rxLength) {\r
- count = offsetof(message_t, footer) + offsetof(cc1000_footer_t, crc);\r
- }\r
-\r
- if (count == (offsetof(message_t, footer) + sizeof(cc1000_footer_t)))\r
- packetReceived();\r
- }\r
-\r
- void packetReceived() {\r
- cc1000_footer_t *rxFooter = getFooter(rxBufPtr);\r
- cc1000_header_t *rxHeader = getHeader(rxBufPtr);\r
- // Packet filtering based on bad CRC's is done at higher layers.\r
- // So sayeth the TOS weenies.\r
- rxFooter->crc = (rxFooter->crc == runningCrc);\r
-\r
- if (f.ack &&\r
- rxFooter->crc &&\r
- rxHeader->dest == call amAddress())\r
- {\r
- enterAckState();\r
- call CC1000Control.txMode();\r
- call HplCC1000Spi.txMode();\r
- call HplCC1000Spi.writeByte(0xaa);\r
- }\r
- else\r
- packetReceiveDone();\r
- }\r
-\r
- void ackData(uint8_t in) {\r
- if (++count >= ACK_LENGTH)\r
- { \r
- call CC1000Control.rxMode();\r
- call HplCC1000Spi.rxMode();\r
- packetReceiveDone();\r
- }\r
- else if (count >= ACK_LENGTH - sizeof ackCode)\r
- call HplCC1000Spi.writeByte(read_uint8_t(&ackCode[count + sizeof ackCode - ACK_LENGTH]));\r
- }\r
-\r
- task void signalPacketReceived() {\r
- message_t *pBuf;\r
- cc1000_header_t *pHeader;\r
- atomic\r
- {\r
- if (radioState != RECEIVED_STATE)\r
- return;\r
-\r
- pBuf = rxBufPtr;\r
- }\r
- pHeader = getHeader(pBuf);\r
- pBuf = signal Receive.receive(pBuf, pBuf->data, pHeader->length);\r
- atomic\r
- {\r
- if (pBuf) \r
- rxBufPtr = pBuf;\r
- if (radioState == RECEIVED_STATE) // receiver might've done something\r
- enterListenState();\r
- signal ByteRadio.rxDone();\r
- }\r
- }\r
-\r
- void packetReceiveDone() {\r
- post signalPacketReceived();\r
- enterReceivedState();\r
- }\r
-\r
- async event void HplCC1000Spi.dataReady(uint8_t data) {\r
- if (f.invert)\r
- data = ~data;\r
-\r
- switch (radioState)\r
- {\r
- default: break;\r
- case TXPREAMBLE_STATE: txPreamble(); break;\r
- case TXSYNC_STATE: txSync(); break;\r
- case TXDATA_STATE: txData(); break;\r
- case TXCRC_STATE: txCrc(); break;\r
- case TXFLUSH_STATE: txFlush(); break;\r
- case TXWAITFORACK_STATE: txWaitForAck(); break;\r
- case TXREADACK_STATE: txReadAck(data); break;\r
- case TXDONE_STATE: txDone(); break;\r
-\r
- case LISTEN_STATE: listenData(data); break;\r
- case SYNC_STATE: syncData(data); break;\r
- case RX_STATE: rxData(data); break;\r
- case SENDING_ACK: ackData(data); break;\r
- }\r
- }\r
-\r
- /* Interaction with rest of stack */\r
- /*--------------------------------*/\r
-\r
- async command void ByteRadio.setPreambleLength(uint16_t bytes) {\r
- atomic preambleLength = bytes;\r
- }\r
-\r
- async command uint16_t ByteRadio.getPreambleLength() {\r
- atomic return preambleLength;\r
- }\r
-\r
- async command message_t *ByteRadio.getTxMessage() {\r
- return txBufPtr;\r
- }\r
-\r
- async command bool ByteRadio.syncing() {\r
- return radioState == SYNC_STATE;\r
- }\r
-\r
- /* Abstract packet layout */\r
-\r
- command void Packet.clear(message_t *msg) {\r
- memset(msg, 0, sizeof(message_t));\r
- }\r
-\r
- command uint8_t Packet.payloadLength(message_t *msg) {\r
- cc1000_header_t *header = getHeader(msg);\r
- return header->length;\r
- }\r
- \r
- command void Packet.setPayloadLength(message_t *msg, uint8_t len) {\r
- getHeader(msg)->length = len;\r
- }\r
- \r
- command uint8_t Packet.maxPayloadLength() {\r
- return TOSH_DATA_LENGTH;\r
- }\r
-\r
- command void* Packet.getPayload(message_t *msg, uint8_t *len) {\r
- if (len != NULL) {\r
- cc1000_header_t *header = getHeader(msg);\r
-\r
- *len = header->length;\r
- }\r
- return (void*)msg->data;\r
- }\r
-\r
- async command error_t PacketAcknowledgements.requestAck(message_t *msg) {\r
- return SUCCESS; /* We always ack. */\r
- }\r
-\r
- async command error_t PacketAcknowledgements.noAck(message_t *msg) {\r
- return FAIL; /* We always ack */\r
- }\r
-\r
- command void* Receive.getPayload(message_t *m, uint8_t *len) {\r
- return call Packet.getPayload(m, len);\r
- }\r
-\r
- command uint8_t Receive.payloadLength(message_t *m) {\r
- return call Packet.payloadLength(m);\r
- }\r
-\r
- command uint8_t Send.maxPayloadLength() {\r
- return call Packet.maxPayloadLength();\r
- }\r
-\r
- command void* Send.getPayload(message_t *m) {\r
- return call Packet.getPayload(m, NULL);\r
- }\r
-\r
- async command bool PacketAcknowledgements.wasAcked(message_t *msg) {\r
- return getMetadata(msg)->ack;\r
- }\r
- // Default events for radio send/receive coordinators do nothing.\r
- // Be very careful using these, or you'll break the stack.\r
- default async event void RadioTimeStamping.transmittedSFD(uint16_t time, message_t *msgBuff) { }\r
- default async event void RadioTimeStamping.receivedSFD(uint16_t time) { }\r
-}\r
+++ /dev/null
-/* $Id$\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-\r
-/**\r
- * CC1000 internal noise floor (aka squelch value) interface\r
- * @author David Gay\r
- */\r
-interface CC1000Squelch\r
-{\r
- /**\r
- * Adjust noise floor based on new noise measurement\r
- * @param data noise measurement\r
- */\r
- command void adjust(uint16_t data);\r
-\r
- /**\r
- * Return current estimated noise floor\r
- * @return Noise floor value\r
- */\r
- async command uint16_t get();\r
-\r
- /**\r
- * Check if noise floor estimate is considered stable (typically after\r
- * some number of measurements)\r
- * @return TRUE if noise floor estimate considered stable, FALSE otherwise\r
- */\r
- command bool settled();\r
-}\r
+++ /dev/null
-/* $Id$\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-#include "CC1000Const.h"\r
-\r
-/**\r
- * Clear threshold estimation based on RSSI measurements.\r
- *\r
- * @author Philip Buonadonna\r
- * @author Jaein Jeong\r
- * @author Joe Polastre\r
- * @author David Gay\r
- */\r
- \r
-module CC1000SquelchP\r
-{\r
- provides {\r
- interface Init;\r
- interface CC1000Squelch;\r
- }\r
-}\r
-implementation\r
-{\r
- uint16_t clearThreshold = CC1K_SquelchInit;\r
- uint16_t squelchTable[CC1K_SquelchTableSize];\r
- uint8_t squelchIndex, squelchCount;\r
-\r
- command error_t Init.init() {\r
- uint8_t i;\r
-\r
- for (i = 0; i < CC1K_SquelchTableSize; i++)\r
- squelchTable[i] = CC1K_SquelchInit;\r
-\r
- return SUCCESS;\r
- }\r
-\r
- command void CC1000Squelch.adjust(uint16_t data) {\r
- uint16_t squelchTab[CC1K_SquelchTableSize];\r
- uint8_t i, j, min; \r
- uint32_t newThreshold;\r
-\r
- squelchTable[squelchIndex++] = data;\r
- if (squelchIndex >= CC1K_SquelchTableSize)\r
- squelchIndex = 0;\r
- if (squelchCount <= CC1K_SquelchCount)\r
- squelchCount++; \r
-\r
- // Find 3rd highest (aka lowest signal strength) value\r
- memcpy(squelchTab, squelchTable, sizeof squelchTable);\r
- for (j = 0; ; j++)\r
- {\r
- min = 0;\r
- for (i = 1; i < CC1K_SquelchTableSize; i++)\r
- if (squelchTab[i] > squelchTab[min])\r
- min = i;\r
- if (j == 3)\r
- break;\r
- squelchTab[min] = 0;\r
- }\r
-\r
- newThreshold = ((uint32_t)clearThreshold << 5) +\r
- ((uint32_t)squelchTab[min] << 1);\r
- atomic clearThreshold = newThreshold / 34;\r
- }\r
-\r
- async command uint16_t CC1000Squelch.get() {\r
- return clearThreshold;\r
- }\r
-\r
- command bool CC1000Squelch.settled() {\r
- return squelchCount > CC1K_SquelchCount;\r
- }\r
-}\r
+++ /dev/null
-/* tab:4\r
- * "Copyright (c) 2000-2005 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- */\r
-/**\r
- * Interface for activating/deactivating congestion control.\r
- *\r
- * @author Philip Levis\r
- * @author Joe Polastre\r
- * @date August 31 2005\r
- */\r
-interface CsmaControl {\r
- /**\r
- * Enable congestion control.\r
- * @return SUCCESS if congestion control enabled, FAIL otherwise.\r
- */\r
- async command error_t enableCca();\r
-\r
- /**\r
- * Disable congestion control.\r
- * @return SUCCESS if congestion control disabled, FAIL otherwise.\r
- */\r
- async command error_t disableCca();\r
-}\r
+++ /dev/null
-// $Id$\r
-\r
-/* tab:4\r
- * "Copyright (c) 2000-2003 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2003 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-/*\r
- * Authors: Jason Hill, David Gay, Philip Levis\r
- * Date last modified: 6/25/02\r
- *\r
- *\r
- */\r
-\r
-/**\r
- * Low-level CC1000 radio-access operations that must be provided by a\r
- * platform wishing to use this CC1000 implementation.\r
- *\r
- * @author Jason Hill\r
- * @author David Gay\r
- * @author Philip Levis\r
- */\r
-\r
-\r
-interface HplCC1000 {\r
- /**\r
- * Initialize CC1K pins\r
- */\r
- command void init();\r
-\r
- /**\r
- * Write a value to a CC1000 register.\r
- * @param addr Which CC1000 register\r
- * @param data Value to write\r
- */\r
- async command void write(uint8_t addr, uint8_t data);\r
-\r
- /**\r
- * Read a value from a CC1000 register.\r
- * @param addr Which CC1000 register\r
- * @return Value of register\r
- */\r
- async command uint8_t read(uint8_t addr);\r
-\r
- /**\r
- * Read the state of the CHP_OUT pin\r
- * @return State of CHP_OUT as a boolean (TRUE for high)\r
- */\r
- async command bool getLOCK();\r
-}\r
+++ /dev/null
-// $Id$\r
-\r
-/* tab:4\r
- * "Copyright (c) 2000-2003 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2003 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- */\r
-/**\r
- * Interface to the CC1000 chip's serial bus. This isn't really an SPI,\r
- * but the mica2 interface was done using the Atmega128 SPI hardware. Hence\r
- * the name.\r
- *\r
- * @author Jaein Jeong\r
- * @author Philip buonadonna\r
- */\r
-interface HplCC1000Spi\r
-{\r
- /**\r
- * Write a byte to the CC1000 bus.\r
- * @param data Byte to write.\r
- */\r
- async command void writeByte(uint8_t data);\r
-\r
- /**\r
- * Is write buffer busy with the last transmission?\r
- * @return TRUE if the buffer is busy, FALSE otherwise.\r
- */\r
- async command bool isBufBusy();\r
-\r
- /**\r
- * Get the last byte received from the CC1000 bus.\r
- * @return Last byte received.\r
- */\r
- async command uint8_t readByte();\r
-\r
- /**\r
- * Enable dataReady events on every byte sent or received from the CC1000\r
- * bus. After this is called, dataReady events will be signaled every\r
- * 8 CC1000 data clocks.\r
- */\r
- async command void enableIntr();\r
-\r
- /**\r
- * Disable CC1000 bus interrupts.\r
- */\r
- async command void disableIntr();\r
-\r
- /**\r
- * Initialise the interface to the CC1000 bus.\r
- */\r
- async command void initSlave();\r
-\r
- /**\r
- * Switch the interface to the CC1000 bus "transmit" mode.\r
- */\r
- async command void txMode();\r
-\r
- /**\r
- * Switch the interface to the CC1000 bus to "receive" mode.\r
- */\r
- async command void rxMode();\r
-\r
- /**\r
- * If enableIntr() is called, this event will be signaled every 8 CC1000\r
- * data clocks. \r
- * @param data In "receive" mode, the last value received from the CC1000 \r
- * bus.\r
- */\r
- async event void dataReady(uint8_t data);\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005-2006 Rincon Research Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the\r
- * distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
- \r
-/**\r
- * Low Power Listening interface\r
- *\r
- * @author David Moss\r
- * @author Jonathan Hui\r
- */\r
- \r
-#include <message.h>\r
- \r
-interface LowPowerListening {\r
-\r
- /**\r
- * Set this this node's radio sleep interval, in milliseconds.\r
- * Once every interval, the node will sleep and perform an Rx check \r
- * on the radio. Setting the sleep interval to 0 will keep the radio\r
- * always on.\r
- *\r
- * This is the equivalent of setting the local duty cycle rate.\r
- *\r
- * @param sleepIntervalMs the length of this node's Rx check interval, in [ms]\r
- */\r
- command void setLocalSleepInterval(uint16_t sleepIntervalMs);\r
- \r
- /**\r
- * @return the local node's sleep interval, in [ms]\r
- */\r
- command uint16_t getLocalSleepInterval();\r
- \r
- /**\r
- * Set this node's radio duty cycle rate, in units of [percentage*100].\r
- * For example, to get a 0.05% duty cycle,\r
- * <code>\r
- * call LowPowerListening.setDutyCycle(5); // or equivalently...\r
- * call LowPowerListening.setDutyCycle(00005); // for better readability?\r
- * </code>\r
- *\r
- * For a 100% duty cycle (always on),\r
- * <code>\r
- * call LowPowerListening.setDutyCycle(10000);\r
- * </code>\r
- *\r
- * This is the equivalent of setting the local sleep interval explicitly.\r
- * \r
- * @param dutyCycle The duty cycle percentage, in units of [percentage*100]\r
- */\r
- command void setLocalDutyCycle(uint16_t dutyCycle);\r
- \r
- /**\r
- * @return this node's radio duty cycle rate, in units of [percentage*100]\r
- */\r
- command uint16_t getLocalDutyCycle();\r
- \r
- \r
- /**\r
- * Configure this outgoing message so it can be transmitted to a neighbor mote\r
- * with the specified Rx sleep interval.\r
- * @param msg Pointer to the message that will be sent\r
- * @param sleepInterval The receiving node's sleep interval, in [ms]\r
- */\r
- command void setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs);\r
- \r
- /**\r
- * @return the destination node's sleep interval configured in this message\r
- */\r
- command uint16_t getRxSleepInterval(message_t *msg);\r
- \r
- /**\r
- * Configure this outgoing message so it can be transmitted to a neighbor mote\r
- * with the specified Rx duty cycle rate.\r
- * Duty cycle is in units of [percentage*100], i.e. 0.25% duty cycle = 25.\r
- * \r
- * @param msg Pointer to the message that will be sent\r
- * @param dutyCycle The duty cycle of the receiving mote, in units of \r
- * [percentage*100]\r
- */\r
- command void setRxDutyCycle(message_t *msg, uint16_t dutyCycle);\r
- \r
- /**\r
- * @return the destination node's duty cycle configured in this message\r
- * in units of [percentage*100]\r
- */\r
- command uint16_t getRxDutyCycle(message_t *msg);\r
- \r
- /**\r
- * Convert a duty cycle, in units of [percentage*100], to\r
- * the sleep interval of the mote in milliseconds\r
- * @param dutyCycle The duty cycle in units of [percentage*100]\r
- * @return The equivalent sleep interval, in units of [ms]\r
- */\r
- command uint16_t dutyCycleToSleepInterval(uint16_t dutyCycle);\r
- \r
- /**\r
- * Convert a sleep interval, in units of [ms], to a duty cycle\r
- * in units of [percentage*100]\r
- * @param sleepInterval The sleep interval in units of [ms]\r
- * @return The duty cycle in units of [percentage*100]\r
- */\r
- command uint16_t sleepIntervalToDutyCycle(uint16_t sleepInterval);\r
- \r
-}\r