// $Id$
-/* tab:4
+/*
* "Copyright (c) 2000-2005 The Regents of the University of California.
* All rights reserved.
*
* @author David Gay
*/
-module CC1000CsmaP {
+module CC1000CsmaP @safe() {
provides {
interface Init;
interface SplitControl;
int16_t macDelay;
- uint8_t lplTxPower, lplRxPower;
uint16_t sleepTime;
uint16_t rssiForSquelch;
task void setWakeupTask();
+ cc1000_metadata_t * ONE getMetadata(message_t * ONE amsg) {
+ return TCAST(cc1000_metadata_t * ONE, (uint8_t*)amsg + offsetof(message_t, footer) + sizeof(cc1000_footer_t));
+ }
+
void enterIdleState() {
call cancelRssi();
radioState = IDLE_STATE;
}
void radioOff() {
- call ByteRadio.off();
call CC1000Control.off();
+ call ByteRadio.off();
}
- /* LPL preamble length and sleep time computation */
-
- void setPreambleLength() {
- uint16_t len =
- (uint16_t)read_uint8_t(&CC1K_LPL_PreambleLength[lplTxPower * 2]) << 8
- | read_uint8_t(&CC1K_LPL_PreambleLength[lplTxPower * 2 + 1]);
- call ByteRadio.setPreambleLength(len);
- }
-
- void setSleepTime() {
- sleepTime =
- (uint16_t)read_uint8_t(&CC1K_LPL_SleepTime[lplRxPower *2 ]) << 8 |
- read_uint8_t(&CC1K_LPL_SleepTime[lplRxPower * 2 + 1]);
- }
+ void setPreambleLength(message_t * ONE msg);
/* Initialisation, startup and stopping */
/*--------------------------------------*/
call ByteRadioControl.start();
enterIdleStateSetWakeup();
f.txPending = FALSE;
- setPreambleLength();
- setSleepTime();
}
else
return SUCCESS;
{
case IDLE_STATE:
/* Timer already running means that we have a noise floor
- measurement scheduled. */
+ measurement scheduled. If we just set a new alarm here, we
+ might indefinitely delay noise floor measurements if we're,
+ e,g, transmitting frequently. */
if (!call WakeupTimer.isRunning())
if (call CC1000Squelch.settled())
{
- if (lplRxPower == 0 || f.txPending)
+ if (sleepTime == 0)
call WakeupTimer.startOneShot(CC1K_SquelchIntervalSlow);
else
// timeout for receiving a message after an lpl check
bool turnOn = FALSE;
atomic
- if (f.txPending)
+ if (f.txPending || !sleepTime)
{
if (radioState == PULSECHECK_STATE || radioState == POWERDOWN_STATE)
{
turnOn = TRUE;
}
}
- else if (lplRxPower > 0 && call CC1000Squelch.settled() &&
- !call ByteRadio.syncing())
+ else if (call CC1000Squelch.settled() && !call ByteRadio.syncing())
{
radioOff();
enterPowerDownState();
*/
if (data > call CC1000Squelch.get() - (call CC1000Squelch.get() >> 2))
{
+ post sleepCheck();
// don't be too agressive (ignore really quiet thresholds).
if (data < call CC1000Squelch.get() + (call CC1000Squelch.get() >> 3))
{
rssiForSquelch = data;
post adjustSquelch();
}
- post sleepCheck();
}
else if (count++ > 5)
{
/* CSMA */
/*------*/
- event void ByteRadio.rts() {
+ event void ByteRadio.rts(message_t * ONE msg) {
atomic
{
f.txPending = TRUE;
macDelay = signal CsmaBackoff.initial(call ByteRadio.getTxMessage());
else
macDelay = 1;
+
+ setPreambleLength(msg);
}
}
return SUCCESS;
}
- async command error_t LowPowerListening.setListeningMode(uint8_t power) {
- if (power >= CC1K_LPL_STATES)
- return FAIL;
+ /* Default MAC backoff parameters */
+ /*--------------------------------*/
- atomic
- {
- if (radioState != DISABLED_STATE)
- return FAIL;
- lplTxPower = power;
- lplRxPower = power;
- }
- return SUCCESS;
+ default async event uint16_t CsmaBackoff.initial(message_t *m) {
+ // initially back off [1,32] bytes (approx 2/3 packet)
+ return (call Random.rand16() & 0x1F) + 1;
}
- async command uint8_t LowPowerListening.getListeningMode() {
- atomic return lplRxPower;
+ default async event uint16_t CsmaBackoff.congestion(message_t *m) {
+ return (call Random.rand16() & 0xF) + 1;
}
- async command error_t LowPowerListening.setTransmitMode(uint8_t power) {
- if (power >= CC1K_LPL_STATES)
- return FAIL;
+ /* LowPowerListening setup */
+ /* ----------------------- */
- atomic
- {
- lplTxPower = power;
- setPreambleLength();
- }
- return SUCCESS;
+ uint16_t validateSleepInterval(uint16_t sleepIntervalMs) {
+ if (sleepIntervalMs < CC1K_LPL_MIN_INTERVAL)
+ return 0;
+ else if (sleepIntervalMs > CC1K_LPL_MAX_INTERVAL)
+ return CC1K_LPL_MAX_INTERVAL;
+ else
+ return sleepIntervalMs;
}
- async command uint8_t LowPowerListening.getTransmitMode() {
- atomic return lplTxPower;
- }
+ uint16_t dutyToSleep(uint16_t dutyCycle) {
+ /* Scaling factors on CC1K_LPL_CHECK_TIME and dutyCycle are identical */
+ uint16_t interval = (1000 * CC1K_LPL_CHECK_TIME) / dutyCycle;
- async command error_t LowPowerListening.setPreambleLength(uint16_t bytes) {
- call ByteRadio.setPreambleLength(bytes);
- return SUCCESS;
+ return interval < CC1K_LPL_MIN_INTERVAL ? 0 : interval;
}
- async command uint16_t LowPowerListening.getPreambleLength() {
- return call ByteRadio.getPreambleLength();
+ uint16_t sleepToDuty(uint16_t sleepInterval) {
+ if (sleepInterval < CC1K_LPL_MIN_INTERVAL)
+ return 10000;
+
+ /* Scaling factors on CC1K_LPL_CHECK_TIME and dutyCycle are identical */
+ return (1000 * CC1K_LPL_CHECK_TIME) / sleepInterval;
}
- async command error_t LowPowerListening.setCheckInterval(uint16_t ms) {
- atomic
- {
- if (lplRxPower == 0)
- return FAIL;
+ command void LowPowerListening.setLocalWakeupInterval(uint16_t s) {
+ sleepTime = validateSleepInterval(s);
+ }
- sleepTime = ms;
- }
- return SUCCESS;
+ command uint16_t LowPowerListening.getLocalWakeupInterval() {
+ return sleepTime;
}
- async command uint16_t LowPowerListening.getCheckInterval() {
- atomic return sleepTime;
+ command void LowPowerListening.setRemoteWakeupInterval(message_t *msg, uint16_t sleepIntervalMs) {
+ cc1000_metadata_t *meta = getMetadata(msg);
+
+ meta->strength_or_preamble = -(int16_t)validateSleepInterval(sleepIntervalMs) - 1;
}
- /* Default MAC backoff parameters */
- /*--------------------------------*/
+ command uint16_t LowPowerListening.getRemoteWakeupInterval(message_t *msg) {
+ cc1000_metadata_t *meta = getMetadata(msg);
- default async event uint16_t CsmaBackoff.initial(message_t *m) {
- // initially back off [1,32] bytes (approx 2/3 packet)
- return (call Random.rand16() & 0x1F) + 1;
+ if (meta->strength_or_preamble >= 0)
+ return sleepTime;
+ else
+ return -(meta->strength_or_preamble + 1);
}
- default async event uint16_t CsmaBackoff.congestion(message_t *m) {
- return (call Random.rand16() & 0xF) + 1;
+ void setPreambleLength(message_t * ONE msg) {
+ cc1000_metadata_t *meta = getMetadata(msg);
+ uint16_t s;
+ uint32_t plen;
+
+ if (meta->strength_or_preamble >= 0)
+ s = sleepTime;
+ else
+ s = -(meta->strength_or_preamble + 1);
+ meta->strength_or_preamble = 0; /* Destroy setting */
+
+ if (s == 0)
+ plen = 6;
+ else
+ plen = ((s * 614UL) >> 8) + 22; /* ~ s * 2.4 + 22 */
+ call ByteRadio.setPreambleLength(plen);
}
}