]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/mac/tkn154/BeaconSynchronizeP.nc
- re-designed the radio driver interfaces, restructured/improved the CC2420 radio...
[tinyos-2.x.git] / tos / lib / mac / tkn154 / BeaconSynchronizeP.nc
index eadfc4bc3c0c3e0dd0d2db69c284bd0664ee5eed..87412974b2455f949e18ea78d91804cc64714a96 100644 (file)
  * ========================================================================
  */
 
+/** 
+ * This module is responsible for periodic beacon tracking in a 
+ * beacon-enabled PAN.
+ */
 
 #include "TKN154_MAC.h"
-#include "TKN154_DEBUG.h"
 
 module BeaconSynchronizeP
 {
@@ -45,33 +48,19 @@ module BeaconSynchronizeP
     interface MLME_SYNC;
     interface MLME_BEACON_NOTIFY;
     interface MLME_SYNC_LOSS;
+    interface SuperframeStructure as IncomingSF;
     interface GetNow<bool> as IsTrackingBeacons;
-    interface GetNow<uint32_t> as CapStart;
-    interface GetNow<ieee154_reftime_t*> as CapStartRefTime; 
-    interface GetNow<uint32_t> as CapLen;
-    interface GetNow<uint32_t> as CapEnd;
-    interface GetNow<uint32_t> as CfpEnd;
-    interface GetNow<uint32_t> as CfpLen;
-    interface GetNow<uint32_t> as BeaconInterval; 
-    interface GetNow<bool> as IsBLEActive; 
-    interface GetNow<uint16_t> as BLELen; 
-    interface GetNow<uint8_t*> as GtsField;
-    interface GetNow<uint32_t> as SfSlotDuration; 
-    interface GetNow<uint8_t> as FinalCapSlot; 
-    interface GetNow<uint8_t> as NumGtsSlots;
-    interface GetNow<bool> as IsRxBroadcastPending; 
+    interface StdControl as TrackSingleBeacon;
   }
   uses
   {
     interface MLME_GET;
     interface MLME_SET;
     interface FrameUtility;
-    interface Notify<bool> as FindBeacon;
     interface IEEE154BeaconFrame as BeaconFrame;
     interface Alarm<TSymbolIEEE802154,uint32_t> as TrackAlarm;
     interface RadioRx as BeaconRx;
     interface RadioOff;
-    interface GetNow<bool> as IsBeaconEnabledPAN;
     interface DataRequest;
     interface FrameRx as CoordRealignmentRx;
     interface Resource as Token;
@@ -81,56 +70,57 @@ module BeaconSynchronizeP
     interface TimeCalc;
     interface IEEE154Frame as Frame;
     interface Leds;
-    interface Ieee802154Debug as Debug;
   }
 }
 implementation
 {
+  /* state variables */
+  norace bool m_tracking;
+  bool m_stopTracking ;
+  norace uint8_t m_numBeaconsLost;
+  norace uint8_t m_state;
+  norace bool m_bufferBusy;
 
-  enum {
-    S_PREPARE = 0,
-    S_RXNOW = 1,
-    S_RADIO_OFF = 2,
-    S_FIRST_SCAN= 3,
-
-    RX_DURATION = 1000,    // listen for a beacon for RX_DURATION symbols
-    RX_LAG = 100,          // start to listen for a RX_LAG before expected arrival
-  };
-
-  norace bool m_tracking = FALSE;
-  norace bool m_updatePending = FALSE;
+  /* buffers for the parameters of the MLME-SYNC request */
+  norace bool m_updatePending;
   uint8_t m_updateLogicalChannel;
   bool m_updateTrackBeacon;
-  bool m_stopTracking = FALSE;
-  bool m_internalRequest = FALSE;
 
-  norace uint8_t m_numBeaconsLost;
-  message_t m_beaconBuffer;
-  norace message_t *m_beaconBufferPtr = &m_beaconBuffer;
-  norace bool m_beaconSwapBufferReady = TRUE;
+  /* variables that describe the current configuration */
   norace uint32_t m_beaconInterval;
   norace uint32_t m_dt;
   norace uint32_t m_lastBeaconRxTime;
-  norace ieee154_reftime_t m_lastBeaconRxRefTime;
-  norace uint8_t m_state;
+  norace ieee154_timestamp_t m_lastBeaconRxRefTime;
   norace uint8_t m_beaconOrder;
+  message_t m_beacon;
+  norace message_t *m_beaconPtr = &m_beacon;
+
+  /* variables that describe the latest superframe */
   norace uint32_t m_sfSlotDuration;
-  norace uint8_t m_finalCapSlot;
+  norace bool m_framePendingBit;
+  norace uint8_t m_numCapSlots;
   norace uint8_t m_numGtsSlots;
-  norace uint16_t m_BLELen;
-  norace bool m_broadcastPending;
+  norace uint16_t m_battLifeExtDuration;
   uint8_t m_gtsField[1+1+3*7];
+  
+  enum {
+    S_PREPARE = 0,
+    S_RECEIVING = 1,
+    S_RADIO_OFF = 2,
+    S_INITIAL_SCAN= 3,
+
+  };
 
+
+  /* function/task prototypes */
   task void processBeaconTask();
-  void getNextBeacon();
+  void trackNextBeacon();
   task void signalGrantedTask();
 
   command error_t Reset.init()
   {
-    if (call Token.isOwner()){
-      call Leds.led0On(); // internal error
-      return FAIL;
-    }    
+    // reset this component. will only be called 
+    // while we're not owning the token           
     if (m_tracking || m_updatePending)
       signal MLME_SYNC_LOSS.indication(
           IEEE154_BEACON_LOSS,
@@ -142,65 +132,52 @@ implementation
     return SUCCESS;
   }  
 
-/* ----------------------- MLME-SYNC ----------------------- */
-/*
* Allows to synchronize with a coordinator.
- */
+  /* ----------------------- MLME-SYNC ----------------------- */
+  /*
  * Allows to synchronize with the beacons from a coordinator.
  */
 
   command ieee154_status_t MLME_SYNC.request  (
       uint8_t logicalChannel,
       uint8_t channelPage,
       bool trackBeacon)
   {
+    error_t status = IEEE154_SUCCESS;
     uint32_t supportedChannels = IEEE154_SUPPORTED_CHANNELS;
     uint32_t currentChannelBit = 1;
 
     currentChannelBit <<= logicalChannel;
     if (!(currentChannelBit & supportedChannels) || (call MLME_GET.macPANId() == 0xFFFF) ||
-        (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !call IsBeaconEnabledPAN.getNow())
-      return IEEE154_INVALID_PARAMETER;
-
-    call Debug.log(DEBUG_LEVEL_INFO,0, logicalChannel, channelPage, trackBeacon);
-    if (!trackBeacon && m_tracking){
-      // stop tracking after next received beacon
-      m_stopTracking = TRUE;
-    } else {
-      m_stopTracking = FALSE;
-      m_updateLogicalChannel = logicalChannel;
-      m_updateTrackBeacon = trackBeacon;
-      m_internalRequest = FALSE;
-      m_updatePending = TRUE;
-      call Debug.log(DEBUG_LEVEL_INFO,1, 0, 0, 0);
-      atomic {
-        // if we are tracking then we'll get the Token automatically,
-        // otherwise request it now
-        if (!m_tracking && !call Token.isOwner())
-          call Token.request();  
+        (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !IEEE154_BEACON_ENABLED_PAN)
+      status = IEEE154_INVALID_PARAMETER;
+    else {
+      if (!trackBeacon && m_tracking) {
+        // stop tracking after next received beacon
+        m_stopTracking = TRUE;
+      } else {
+        m_stopTracking = FALSE;
+        m_updateLogicalChannel = logicalChannel;
+        m_updateTrackBeacon = trackBeacon;
+        m_updatePending = TRUE;
+        atomic {
+          // if we are tracking then we'll get the Token automatically,
+          // otherwise request it now
+          if (!m_tracking && !call Token.isOwner())
+            call Token.request();  
+        }
       }
     }
-    call Debug.flush();
-    return IEEE154_SUCCESS;
-  }
-
-  event void FindBeacon.notify( bool val )
-  {
-    call Debug.log(DEBUG_LEVEL_IMPORTANT,20, m_tracking, m_updatePending, 0);
-    if (!m_tracking && !m_updatePending && !call Token.isOwner()){
-      // find a single beacon now (treat this like a user request)
-      m_updateLogicalChannel = call MLME_GET.phyCurrentChannel();
-      m_updateTrackBeacon = FALSE;
-      m_updatePending = TRUE;
-      m_internalRequest = TRUE;
-      call Token.request();
-    }
+    dbg_serial("BeaconSynchronizeP", "MLME_SYNC.request -> result: %lu\n", (uint32_t) status);
+    return status;
   }
 
   event void Token.granted()
   {
-    call Debug.log(DEBUG_LEVEL_INFO,2, m_lastBeaconRxTime+m_beaconInterval, 
-        m_beaconInterval, (m_updatePending<<1)+m_tracking);
-    if (m_updatePending){
-      m_state = S_FIRST_SCAN;
+    dbg_serial("BeaconSynchronizeP","Got token, expecting beacon in %lu\n",
+        (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); 
+    if (m_updatePending) {
+      dbg_serial("BeaconSynchronizeP", "Preparing initial scan\n"); 
+      m_state = S_INITIAL_SCAN;
       m_updatePending = FALSE;      
       m_beaconOrder = call MLME_GET.macBeaconOrder();
       if (m_beaconOrder >= 15)
@@ -210,229 +187,234 @@ implementation
       m_beaconInterval = ((uint32_t) 1 << m_beaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; 
       m_dt = m_beaconInterval;
       m_numBeaconsLost = IEEE154_aMaxLostBeacons;  // will be reset when beacon is received
-      call Debug.log(DEBUG_LEVEL_INFO,3, call MLME_GET.macCoordShortAddress(), 
-          call MLME_GET.macPANId(), m_updateLogicalChannel);
     }
-    getNextBeacon();
-    call Debug.flush();
+    trackNextBeacon();
+  }
+
+  async event void TokenTransferred.transferred()
+  {
+    dbg_serial("BeaconSynchronizeP","Token.transferred(), expecting beacon in %lu symbols.\n",
+        (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); 
+    if (call IsTokenRequested.getNow()) {
+      // some other component needs the token - we give it up for now,  
+      // but make another request to get it back later
+      dbg_serial("BeaconSynchronizeP", "Token is requested, releasing it now.\n");
+      call Token.request();
+      call Token.release();
+    } else if (m_updatePending)
+      post signalGrantedTask();
+    else
+      trackNextBeacon();
   }
 
-  void getNextBeacon()
+
+  task void signalGrantedTask()
+  {
+    signal Token.granted();
+  }
+
+  void trackNextBeacon()
   {
     bool missed = FALSE;
-    if (m_state != S_FIRST_SCAN){
+
+    if (m_state != S_INITIAL_SCAN) {
       // we have received at least one previous beacon
       m_state = S_PREPARE;
-      if (!m_tracking){
+      if (!m_tracking) {
         // nothing to do, just give up the token
-        call Debug.log(DEBUG_LEVEL_INFO,4, 0, 0, 0);
+        dbg_serial("BeaconSynchronizeP", "Stop tracking.\n");
         call Token.release();
         return;
       }
-      while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)){ // missed a beacon!
+      while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)) { // missed a beacon!
+        dbg_serial("BeaconSynchronizeP", "Missed a beacon, expected it: %lu, now: %lu\n", 
+            m_lastBeaconRxTime + m_dt, call TrackAlarm.getNow());
         missed = TRUE;
-        call Debug.log(DEBUG_LEVEL_IMPORTANT,5, m_lastBeaconRxTime, m_dt, missed);
         m_dt += m_beaconInterval;
         m_numBeaconsLost++;
       }
-      if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){
-        call Debug.log(DEBUG_LEVEL_IMPORTANT,19, m_numBeaconsLost, m_dt, missed);
+      if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) {
+        dbg_serial("BeaconSynchronizeP", "Missed too many beacons.\n");
         post processBeaconTask();
         return;
       }
-      if (missed){
+      if (missed) {
+        // let other components get a chance to use the radio
         call Token.request();
-        call Debug.log(DEBUG_LEVEL_IMPORTANT,6, m_lastBeaconRxTime, m_dt, missed);
+        dbg_serial("BeaconSynchronizeP", "Allowing other components to get the token.\n");
         call Token.release();
         return;
       }
     }
-    if (!call RadioOff.isOff())
-      call RadioOff.off();
-    else
+    if (call RadioOff.isOff())
       signal RadioOff.offDone();
-  }
-
-  async event void TokenTransferred.transferred()
-  {
-    if (call IsTokenRequested.getNow()){
-      // some other component needs the token - we give it up for now,  
-      // but make another request to get it back later
-      call Token.request();
-      call Token.release();
-    } else if (m_updatePending)
-      post signalGrantedTask();
     else
-      getNextBeacon();
+      ASSERT(call RadioOff.off() == SUCCESS);
   }
 
-  task void signalGrantedTask()
+  async event void RadioOff.offDone()
   {
-    signal Token.granted();
+    uint32_t delay = IEEE154_RADIO_RX_DELAY + IEEE154_MAX_BEACON_JITTER(m_beaconOrder);
+
+    if (m_state == S_INITIAL_SCAN) {
+      // initial scan
+      call BeaconRx.enableRx(0, 0);
+    } else if (m_state == S_PREPARE) {
+      if (!call TimeCalc.hasExpired(m_lastBeaconRxTime - delay, m_dt))
+        call TrackAlarm.startAt(m_lastBeaconRxTime - delay, m_dt);
+      else
+        signal TrackAlarm.fired();
+    } else {
+      post processBeaconTask();
+    }
   }
 
-  async event void TrackAlarm.fired()
+  async event void BeaconRx.enableRxDone()
   {
-    call Debug.log(DEBUG_LEVEL_INFO,7, m_state,m_lastBeaconRxTime,m_dt);
     switch (m_state)
     {
+      case S_INITIAL_SCAN: 
+        m_state = S_RECEIVING;
+        call TrackAlarm.start((((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) * 
+          (uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons);
+        break;
       case S_PREPARE:
-        call BeaconRx.prepare();
+        m_state = S_RECEIVING;
+        dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon in %lu symbols.\n",
+            (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); 
+        call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + IEEE154_MAX_BEACON_LISTEN_TIME(m_beaconOrder));
         break;
-      case S_RADIO_OFF: 
-        call RadioOff.off(); 
+      default:
+        ASSERT(0);
         break;
     }
   }
 
-  async event void BeaconRx.prepareDone()
+  async event void TrackAlarm.fired()
   {
-    error_t result;
-    if (m_state == S_FIRST_SCAN){
-      m_state = S_RADIO_OFF;
-      atomic {
-        call BeaconRx.receive(NULL, 0);
-        call TrackAlarm.start((((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) * 
-            (uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons);
-      }
+    if (m_state == S_PREPARE) {
+      uint32_t maxBeaconJitter = IEEE154_MAX_BEACON_JITTER(m_beaconOrder);
+      if (maxBeaconJitter > m_dt)
+        maxBeaconJitter = m_dt; // receive immediately
+      call BeaconRx.enableRx(m_lastBeaconRxTime, m_dt - maxBeaconJitter);
     } else {
-      m_state = S_RADIO_OFF;
-      result = call BeaconRx.receive(&m_lastBeaconRxRefTime, m_dt-RX_LAG);
-      //__nesc_enable_interrupt();
-      call Debug.log(DEBUG_LEVEL_INFO,8, m_lastBeaconRxTime, 0,(m_lastBeaconRxTime+m_dt) - call TrackAlarm.getNow());
-      if (result != SUCCESS)
-        call Debug.log(DEBUG_LEVEL_CRITICAL,9, result, 0, 0);
-      call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + RX_DURATION);
+      ASSERT(m_state == S_RECEIVING && call RadioOff.off() == SUCCESS); 
     }
   }
 
-  event message_t* BeaconRx.received(message_t *frame, ieee154_reftime_t *timestamp)
+  event message_t* BeaconRx.received(message_t *frame, const ieee154_timestamp_t *timestamp)
   {
-    uint8_t *mhr = MHR(frame);
-    call Debug.log(DEBUG_LEVEL_INFO,10,*((nxle_uint32_t*) &mhr[MHR_INDEX_ADDRESS]), 
-        mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK,mhr[MHR_INDEX_SEQNO]);
-    if (!m_beaconSwapBufferReady || !call FrameUtility.isBeaconFromCoord(frame))
+    if (m_bufferBusy || !call FrameUtility.isBeaconFromCoord(frame))
     {
-      call Debug.log(DEBUG_LEVEL_IMPORTANT,11, m_beaconSwapBufferReady, 0, 0);
+      if (m_bufferBusy) {
+        dbg_serial("BeaconSynchronizeP", "Got another beacon, dropping it.\n");}
+      else
+        dbg_serial("BeaconSynchronizeP", "Got a beacon, but not from my coordinator.\n");
       return frame;
     } else {
-      error_t resultOff;
-      message_t *tmp = m_beaconBufferPtr;
-      call TrackAlarm.stop();
-      m_beaconSwapBufferReady = FALSE;
-      m_beaconBufferPtr = frame;
-      resultOff = call RadioOff.off();
-      if (timestamp != NULL){
-        memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_reftime_t));
-        call Debug.log(DEBUG_LEVEL_INFO,23,0, 0, resultOff);
+      message_t *tmp = m_beaconPtr;
+      m_bufferBusy = TRUE;
+      m_beaconPtr = frame;
+      if (timestamp != NULL)
+        memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_timestamp_t));
+      if (m_state == S_RECEIVING) { 
+        call TrackAlarm.stop(); // may fail
+        call RadioOff.off();    // may fail
       }
       return tmp;
     }
   }
 
-  async event void RadioOff.offDone()
-  {
-    if (m_state == S_FIRST_SCAN)
-      call BeaconRx.prepare();
-    else if (m_state == S_PREPARE){
-      if (!call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY))
-        call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY);
-      else
-        signal TrackAlarm.fired();
-    } else {
-      post processBeaconTask();
-    }
-  }
-
   task void processBeaconTask()
   {
-    // valid beacon timestamp is pre-condition for slotted CSMA-CA
-    if (m_beaconSwapBufferReady || !call Frame.isTimestampValid(m_beaconBufferPtr)){
-      // missed a beacon!
-      if (!m_beaconSwapBufferReady)
-        call Debug.log(DEBUG_LEVEL_IMPORTANT, 21,m_numBeaconsLost,m_beaconSwapBufferReady,m_lastBeaconRxTime);
+    // if we received a beacon from our coordinator then it is processed now
+    if (!m_bufferBusy || !call Frame.isTimestampValid(m_beaconPtr)) {
+      // missed a beacon or received a beacon with invalid timestamp
+      if (!m_bufferBusy)
+        dbg_serial("BeaconSynchronizeP", "No beacon received!\n");
       else
-        call Debug.log(DEBUG_LEVEL_IMPORTANT, 12,m_numBeaconsLost,m_beaconSwapBufferReady,m_lastBeaconRxTime);
-      m_sfSlotDuration = 0; // CAP len will be 0
-      m_numBeaconsLost++;
+        dbg_serial("BeaconSynchronizeP", "Beacon has invalid timestamp!\n");
+
+      m_numBeaconsLost += 1;
       m_dt += m_beaconInterval;
-      m_beaconSwapBufferReady = TRUE;
-      if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){
+      m_bufferBusy = FALSE;
+
+      if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) {
+        // lost too many beacons, give up!
         m_tracking = FALSE;
-        call Debug.log(DEBUG_LEVEL_IMPORTANT, 13,m_internalRequest,0,0);
-        call Leds.led2Off();
-        if (m_internalRequest){
-          call TokenToCap.transfer();
-          return;
-        } else
-          signal MLME_SYNC_LOSS.indication(
+        dbg_serial("BeaconSynchronizeP", "MLME_SYNC_LOSS!\n");
+        signal MLME_SYNC_LOSS.indication(
               IEEE154_BEACON_LOSS, 
               call MLME_GET.macPANId(),
               call MLME_GET.phyCurrentChannel(),
               call MLME_GET.phyCurrentPage(), 
-              NULL // security
-              );
+              NULL);
       } else
         call Token.request(); // make another request again (before giving the token up)
-      call Debug.log(DEBUG_LEVEL_INFO,14, 0, 0, 0);
+
       call Token.release();
     } else { 
       // got the beacon!
-      uint8_t *payload = (uint8_t *) m_beaconBufferPtr->data;
+      uint8_t *payload = (uint8_t *) m_beaconPtr->data;
       ieee154_macAutoRequest_t autoRequest = call MLME_GET.macAutoRequest();
       uint8_t pendAddrSpecOffset = 3 + (((payload[2] & 7) > 0) ? 1 + (payload[2] & 7) * 3: 0); // skip GTS
       uint8_t pendAddrSpec = payload[pendAddrSpecOffset];
       uint8_t *beaconPayload = payload + pendAddrSpecOffset + 1;
-      uint8_t beaconPayloadSize = call BeaconFrame.getBeaconPayloadLength(m_beaconBufferPtr);
+      uint8_t beaconPayloadSize = call BeaconFrame.getBeaconPayloadLength(m_beaconPtr);
       uint8_t pendingAddrMode = ADDR_MODE_NOT_PRESENT;
       uint8_t coordBeaconOrder;
-      uint8_t *mhr = MHR(m_beaconBufferPtr);
-      uint8_t frameLen = ((uint8_t*) m_beaconBufferPtr)[0] & FRAMECTL_LENGTH_MASK;
+      uint8_t *mhr = MHR(m_beaconPtr);
+      uint8_t frameLen = ((uint8_t*) m_beaconPtr)[0] & FRAMECTL_LENGTH_MASK;
       uint8_t gtsFieldLength;
-      uint32_t timestamp = call Frame.getTimestamp(m_beaconBufferPtr);
+      uint32_t timestamp = call Frame.getTimestamp(m_beaconPtr);
+
+      dbg_serial("BeaconSynchronizeP", "Got beacon, timestamp: %lu, offset to previous: %lu\n", 
+        (uint32_t) timestamp, (uint32_t) (timestamp - m_lastBeaconRxTime));
 
-      call Debug.log(DEBUG_LEVEL_INFO, 15, m_lastBeaconRxTime, timestamp, mhr[2]);
       m_numGtsSlots = (payload[2] & 7);
       gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
       m_lastBeaconRxTime = timestamp;
-      m_finalCapSlot = (payload[1] & 0x0F);
+      m_numCapSlots = (payload[1] & 0x0F) + 1;
       m_sfSlotDuration = (((uint32_t) 1) << ((payload[0] & 0xF0) >> 4)) * IEEE154_aBaseSlotDuration;
       memcpy(m_gtsField, &payload[2], gtsFieldLength);
 
       // check for battery life extension
-      if (payload[1] & 0x10){
+      if (payload[1] & 0x10) {
         // BLE is active; calculate the time offset from slot0
-        m_BLELen = IEEE154_SHR_DURATION + frameLen * IEEE154_SYMBOLS_PER_OCTET;
+        m_battLifeExtDuration = IEEE154_SHR_DURATION + frameLen * IEEE154_SYMBOLS_PER_OCTET;
         if (frameLen > IEEE154_aMaxSIFSFrameSize)
-          m_BLELen += call MLME_GET.macMinLIFSPeriod();
+          m_battLifeExtDuration += call MLME_GET.macMinLIFSPeriod();
         else
-          m_BLELen += call MLME_GET.macMinSIFSPeriod();
-        m_BLELen = m_BLELen + call MLME_GET.macBattLifeExtPeriods() * 20;
+          m_battLifeExtDuration += call MLME_GET.macMinSIFSPeriod();
+        m_battLifeExtDuration = m_battLifeExtDuration + call MLME_GET.macBattLifeExtPeriods() * 20;
       } else
-        m_BLELen = 0;
-      m_broadcastPending = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE;
+        m_battLifeExtDuration = 0;
+
+      m_framePendingBit = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE;
       coordBeaconOrder = (payload[0] & 0x0F); 
       m_dt = m_beaconInterval = ((uint32_t) 1 << coordBeaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; 
-      if (m_stopTracking){
+
+      if (m_stopTracking) {
         m_tracking = FALSE;
-        call Debug.log(DEBUG_LEVEL_INFO,16, 0, 0, 0);
-        if (m_updatePending) // there is already a new request pending...
+        dbg_serial("BeaconSynchronizeP", "Stop tracking.\n");
+        if (m_updatePending) // there is already a new request ...
           call Token.request();
         call Token.release();
       } else {
-        call Debug.log(DEBUG_LEVEL_INFO,17, 0, 0, 0);
-        call TokenToCap.transfer(); // borrow Token to CAP/CFP module, we'll get it back afterwards
+        dbg_serial("BeaconSynchronizeP", "Handing over to CAP.\n");
+        call TokenToCap.transfer(); 
       }
       
       if (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK)
         beaconPayload += (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK) * 2;
       if (pendAddrSpec & PENDING_ADDRESS_EXT_MASK)
         beaconPayload += ((pendAddrSpec & PENDING_ADDRESS_EXT_MASK) >> 4) * 8;
+
       // check for pending data (once we signal MLME_BEACON_NOTIFY we cannot
-      // touch the frame anymore)
+      // touch this frame anymore!)
       if (autoRequest)
-        pendingAddrMode = call BeaconFrame.isLocalAddrPending(m_beaconBufferPtr);
-      if (pendingAddrMode != ADDR_MODE_NOT_PRESENT){
+        pendingAddrMode = call BeaconFrame.isLocalAddrPending(m_beaconPtr);
+      if (pendingAddrMode != ADDR_MODE_NOT_PRESENT) {
         // the coord has pending data
         uint8_t CoordAddrMode;
         uint16_t CoordPANId;
@@ -446,55 +428,98 @@ implementation
         CoordPANId = *((nxle_uint16_t*) &(mhr[MHR_INDEX_ADDRESS]));
         call DataRequest.poll(CoordAddrMode, CoordPANId, CoordAddress, SrcAddrMode);
       }
+
       // Beacon Tracking: update state
-      call Debug.log(DEBUG_LEVEL_INFO, 18, m_lastBeaconRxTime, m_beaconInterval, 0);
       m_numBeaconsLost = 0;
       // TODO: check PAN ID conflict here?
       if (!autoRequest || beaconPayloadSize)
-        m_beaconBufferPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconBufferPtr);
-      m_beaconSwapBufferReady = TRUE;
+        m_beaconPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconPtr);
+      m_bufferBusy = FALSE;
     }
+    dbg_serial_flush();
   }
 
-  async command bool IsTrackingBeacons.getNow(){ return m_tracking;}
-
-  default event message_t* MLME_BEACON_NOTIFY.indication (message_t* frame){return frame;}
+  command error_t TrackSingleBeacon.start()
+  {
+    // Track a single beacon now
+    if (!m_tracking && !m_updatePending && !call Token.isOwner()) {
+      // find a single beacon now (treat this like a user request)
+      m_updateLogicalChannel = call MLME_GET.phyCurrentChannel();
+      m_updateTrackBeacon = FALSE;
+      m_stopTracking = TRUE;
+      m_updatePending = TRUE;
+      call Token.request();
+    }
+    return SUCCESS;
+  }
 
-  default event void MLME_SYNC_LOSS.indication (
-                          ieee154_status_t lossReason,
-                          uint16_t panID,
-                          uint8_t logicalChannel,
-                          uint8_t channelPage,
-                          ieee154_security_t *security){}
+  command error_t TrackSingleBeacon.stop()
+  {
+    // will stop automatically after beacon was tracked/not found
+    return FAIL;
+  }
   
-  event void DataRequest.pollDone(){}
-
-  async command uint8_t* GtsField.getNow() { return m_gtsField; }
-  async command uint32_t SfSlotDuration.getNow() { return m_sfSlotDuration; }
-  async command uint8_t FinalCapSlot.getNow() { return m_finalCapSlot; }
-  async command uint32_t CapStart.getNow() { return m_lastBeaconRxTime; }
-  async command ieee154_reftime_t* CapStartRefTime.getNow() { return &m_lastBeaconRxRefTime; }
-  async command uint32_t CapLen.getNow() { return call SfSlotDuration.getNow() * (call FinalCapSlot.getNow() + 1);}
-  async command uint32_t CapEnd.getNow() 
+  /* -----------------------  SF Structure, etc. ----------------------- */
+
+  async command uint32_t IncomingSF.sfStartTime()
+  { 
+    return m_lastBeaconRxTime; 
+  }
+
+  async command uint16_t IncomingSF.sfSlotDuration()
+  { 
+    return m_sfSlotDuration;
+  }
+
+  async command uint8_t IncomingSF.numCapSlots()
   {
-    return call CapStart.getNow() + call CapLen.getNow();
+    return m_numCapSlots;
   }
-  async command uint32_t CfpEnd.getNow() 
+
+  async command uint8_t IncomingSF.numGtsSlots()
   {
-    return call CapStart.getNow() + call SfSlotDuration.getNow() * IEEE154_aNumSuperframeSlots;
+    return m_numGtsSlots;
   }
-  async command uint32_t CfpLen.getNow()
+
+  async command uint16_t IncomingSF.battLifeExtDuration()
   {
-    return call SfSlotDuration.getNow() * (15 - call FinalCapSlot.getNow());
+    return m_battLifeExtDuration;
   }
-  async command uint32_t BeaconInterval.getNow()
+
+  async command const uint8_t* IncomingSF.gtsFields()
   {
-    return m_beaconInterval;
+    return m_gtsField;
   }
-  async command uint8_t NumGtsSlots.getNow() { return m_numGtsSlots; }
-  async command bool IsBLEActive.getNow(){ return m_BLELen>0;}
-  async command uint16_t BLELen.getNow(){ return m_BLELen;}
-  async command bool IsRxBroadcastPending.getNow() { return m_broadcastPending; }
+
+  async command uint16_t IncomingSF.guardTime()
+  {
+    return IEEE154_MAX_BEACON_JITTER(m_beaconOrder) + IEEE154_RADIO_RX_DELAY;
+  }
+
+  async command const ieee154_timestamp_t* IncomingSF.sfStartTimeRef()
+  {
+    return &m_lastBeaconRxRefTime;
+  }
+
+  async command bool IncomingSF.isBroadcastPending()
+  {
+    return m_framePendingBit;
+  }
+
+  async command bool IsTrackingBeacons.getNow()
+  { 
+    return m_tracking;
+  }
+
+  event void DataRequest.pollDone() {}
+
+  default event message_t* MLME_BEACON_NOTIFY.indication (message_t* frame) {return frame;}
+  default event void MLME_SYNC_LOSS.indication (
+                          ieee154_status_t lossReason,
+                          uint16_t panID,
+                          uint8_t logicalChannel,
+                          uint8_t channelPage,
+                          ieee154_security_t *security) {}
 
   event message_t* CoordRealignmentRx.received(message_t* frame)
   {
@@ -506,8 +531,7 @@ implementation
           panID,                 // PANId
           payload[5],            // LogicalChannel,
           call Frame.getPayloadLength(frame) == 9 ? payload[8] : call MLME_GET.phyCurrentPage(),
-          NULL
-          );
+          NULL);
     return frame;
   }
 }