]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/cc1000/CC1000CsmaP.nc
LPL interface changes
[tinyos-2.x.git] / tos / chips / cc1000 / CC1000CsmaP.nc
index 8449652e9f1ddad82190fae084370ba81a2d3233..698ab8cbd205f359ad79079c6cbb7da2718ffba4 100644 (file)
@@ -1,6 +1,6 @@
 // $Id$
 
-/*                                                                     tab:4
+/*
  * "Copyright (c) 2000-2005 The Regents of the University  of California.  
  * All rights reserved.
  *
@@ -50,7 +50,7 @@
  * @author David Gay
  */
   
-module CC1000CsmaP {
+module CC1000CsmaP @safe() {
   provides {
     interface Init;
     interface SplitControl;
@@ -101,13 +101,16 @@ implementation
 
   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;
@@ -153,24 +156,11 @@ implementation
   }
 
   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 */
   /*--------------------------------------*/
@@ -200,8 +190,6 @@ implementation
          call ByteRadioControl.start();
          enterIdleStateSetWakeup();
          f.txPending = FALSE;
-         setPreambleLength();
-         setSleepTime();
        }
       else
        return SUCCESS;
@@ -234,11 +222,13 @@ implementation
       {
       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
@@ -304,7 +294,7 @@ implementation
     bool turnOn = FALSE;
 
     atomic
-      if (f.txPending)
+      if (f.txPending || !sleepTime)
        {
          if (radioState == PULSECHECK_STATE || radioState == POWERDOWN_STATE)
            {
@@ -312,8 +302,7 @@ implementation
              turnOn = TRUE;
            }
        }
-      else if (lplRxPower > 0 && call CC1000Squelch.settled() &&
-              !call ByteRadio.syncing())
+      else if (call CC1000Squelch.settled() && !call ByteRadio.syncing())
        {
          radioOff();
          enterPowerDownState();
@@ -341,6 +330,7 @@ implementation
     */
     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))
          {
@@ -348,7 +338,6 @@ implementation
            rssiForSquelch = data;
            post adjustSquelch();
          }
-       post sleepCheck();
       }
     else if (count++ > 5)
       {
@@ -366,7 +355,7 @@ implementation
   /* CSMA */
   /*------*/
 
-  event void ByteRadio.rts() {
+  event void ByteRadio.rts(message_t * ONE msg) {
     atomic
       {
        f.txPending = TRUE;
@@ -377,6 +366,8 @@ implementation
          macDelay = signal CsmaBackoff.initial(call ByteRadio.getTxMessage());
        else
          macDelay = 1;
+
+       setPreambleLength(msg);
       }
   }
 
@@ -477,73 +468,83 @@ implementation
     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);
   }
 }