+++ /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
- * Module to duty cycle the radio on and off, performing CCA receive checks.\r
- * When a carrier is sensed, this will leave the radio on. It is then up\r
- * to higher layers to turn the radio off again. Once the radio is turned\r
- * off, this module will automatically continue duty cycling and looking for\r
- * a modulated signal.\r
- *\r
- * @author David Moss\r
- */\r
- \r
-#include "CC2420DutyCycle.h"\r
-\r
-module CC2420DutyCycleP {\r
- provides {\r
- interface CC2420DutyCycle;\r
- interface Init;\r
- interface SplitControl;\r
- }\r
-\r
- uses {\r
- interface Timer<TMilli> as OnTimer;\r
- interface SplitControl as SubControl;\r
- interface State as RadioPowerState;\r
- interface State as DutyCycleState;\r
- interface State as SplitControlState;\r
- interface State as CheckState;\r
- interface Leds;\r
- interface CC2420Cca;\r
- interface Random;\r
- }\r
-}\r
-\r
-implementation {\r
- \r
- /** The current period of the duty cycle, equivalent of wakeup interval */\r
- uint16_t sleepInterval;\r
- \r
- /** The number of times the CCA has been sampled in this wakeup period */\r
- uint8_t ccaChecks;\r
- \r
- /**\r
- * Radio Power, Check State, and Duty Cycling State\r
- */\r
- enum {\r
- S_OFF, // off by default\r
- S_ON,\r
- };\r
- \r
- \r
- /***************** Prototypes ****************/\r
- task void stopRadio();\r
- task void startRadio();\r
- task void getCca();\r
- \r
- /***************** Init Commands ****************/\r
- command error_t Init.init() {\r
- sleepInterval = DEFAULT_DUTY_PERIOD;\r
- return SUCCESS;\r
- }\r
- \r
- /***************** CC2420DutyCycle Commands ****************/\r
- /**\r
- * Set the sleep interval, in binary milliseconds\r
- * @param sleepIntervalMs the sleep interval in [ms]\r
- */\r
- command void CC2420DutyCycle.setSleepInterval(uint16_t sleepIntervalMs) {\r
- sleepInterval = sleepIntervalMs;\r
- \r
- if(sleepInterval == 0 && call DutyCycleState.getState() == S_ON) {\r
- call DutyCycleState.forceState(S_OFF);\r
- call CheckState.toIdle();\r
- \r
- /*\r
- * Leave the radio on permanently if sleepInterval == 0 and the radio is \r
- * supposed to be enabled\r
- */\r
- if(call RadioPowerState.getState() == S_OFF) {\r
- call SubControl.start();\r
- }\r
- }\r
- }\r
- \r
- /**\r
- * @return the sleep interval in [ms]\r
- */\r
- command uint16_t CC2420DutyCycle.getSleepInterval() {\r
- return sleepInterval;\r
- }\r
- \r
- /***************** SplitControl Commands ****************/\r
- command error_t SplitControl.start() {\r
- call SplitControlState.forceState(S_ON);\r
- \r
- if(sleepInterval > 0) {\r
- // Begin duty cycling\r
- call DutyCycleState.forceState(S_ON);\r
- call CheckState.toIdle();\r
- post stopRadio();\r
- signal SplitControl.startDone(SUCCESS);\r
- \r
- } else {\r
- call DutyCycleState.forceState(S_OFF);\r
- call CheckState.toIdle();\r
- \r
- /*\r
- * Leave the radio on permanently if sleepInterval == 0 and the radio is \r
- * supposed to be enabled\r
- */\r
- if(call RadioPowerState.getState() == S_OFF) {\r
- call SubControl.start();\r
- // Here, SplitControl.startDone is signaled on SubControl.startDone\r
- \r
- } else {\r
- // Radio is already on\r
- signal SplitControl.startDone(SUCCESS);\r
- }\r
- }\r
-\r
- return SUCCESS;\r
- }\r
- \r
- command error_t SplitControl.stop() {\r
- call SplitControlState.forceState(S_OFF);\r
- call DutyCycleState.forceState(S_OFF);\r
- call CheckState.toIdle();\r
- return call SubControl.stop();\r
- \r
- /*\r
- * SubControl.stopDone signals SplitControl.stopDone when \r
- * DutyCycleState is S_OFF\r
- */\r
- }\r
- \r
- /***************** Timer Events ****************/\r
- event void OnTimer.fired() {\r
- if(call DutyCycleState.getState() == S_ON) {\r
- if(call RadioPowerState.getState() == S_OFF) {\r
- call CheckState.forceState(S_ON);\r
- ccaChecks = 0;\r
- \r
- /*\r
- * The MicaZ, running on an external oscillator I think, and\r
- * returning the microcontroller out of a sleep state to immediately\r
- * perform an ADC conversion, sucks. The first ADC conversion out\r
- * of a sleep state lasts about a second. We don't want the radio\r
- * on that long. Like the CC1000 RSSI pulse check implementation\r
- * done in the Rincon CC1000Radio stack, we will perform\r
- * a single ADC conversion and then flip on the radio to check\r
- * the channel.\r
- */\r
- post getCca();\r
- \r
- } else {\r
- // Someone else turned on the radio, try again in awhile\r
- call OnTimer.startOneShot(sleepInterval);\r
- }\r
- }\r
- }\r
- \r
- /***************** SubControl Events ****************/\r
- event void SubControl.startDone(error_t error) {\r
- if(call DutyCycleState.getState() == S_ON && error) {\r
- // My responsibility to try again\r
- post startRadio();\r
- return;\r
- }\r
- \r
- call RadioPowerState.forceState(S_ON);\r
- //call Leds.led2On();\r
- \r
- if(call DutyCycleState.getState() == S_ON) {\r
- if(call CheckState.getState() == S_ON) {\r
- post getCca();\r
- }\r
- \r
- } else {\r
- // Must have turned the radio on manually\r
- signal SplitControl.startDone(SUCCESS);\r
- }\r
- }\r
- \r
- event void SubControl.stopDone(error_t error) {\r
- if(error && call DutyCycleState.getState() == S_ON) {\r
- // My responsibility to try again\r
- post stopRadio();\r
- return;\r
- }\r
- \r
- call RadioPowerState.forceState(S_OFF);\r
- //call Leds.led2Off();\r
- \r
- if(call DutyCycleState.getState() == S_ON) {\r
- call OnTimer.startOneShot(sleepInterval);\r
-\r
- } else {\r
- // Must have turned off the radio manually\r
- signal SplitControl.stopDone(error);\r
- }\r
- \r
- }\r
- \r
- \r
- /***************** Tasks ****************/\r
- task void stopRadio() {\r
- if(call DutyCycleState.getState() == S_ON) {\r
- if(call SubControl.stop() != SUCCESS) {\r
- // Already stopped?\r
- call OnTimer.startOneShot(sleepInterval);\r
- }\r
- }\r
- }\r
- \r
- task void startRadio() {\r
- if(call DutyCycleState.getState() == S_ON) {\r
- if(call SubControl.start() != SUCCESS) {\r
- post startRadio();\r
- }\r
- }\r
- }\r
- \r
- \r
- task void getCca() {\r
- if(call DutyCycleState.getState() == S_ON) {\r
- \r
- ccaChecks++;\r
- if(ccaChecks == 1) {\r
- // Microcontroller is ready, turn on the radio and sample a few times\r
- post startRadio();\r
- return;\r
- } \r
-\r
- if(!call CC2420Cca.isChannelClear()) {\r
- signal CC2420DutyCycle.detected(); \r
- // Leave the radio on for upper layers to perform some transaction\r
- \r
- } else {\r
- if(ccaChecks <= MAX_LPL_CCA_CHECKS) {\r
- post getCca();\r
- return;\r
- \r
- } else {\r
- call CheckState.toIdle();\r
- post stopRadio();\r
- }\r
- }\r
- } \r
- }\r
- \r
- /**************** Defaults ****************/\r
- default event void CC2420DutyCycle.detected() {\r
- }\r
-\r
-}\r
-\r
-\r