]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/mac/tkn154/BeaconTransmitP.nc
- fixed an issue with the beacon sequence number being set incorrectly
[tinyos-2.x.git] / tos / lib / mac / tkn154 / BeaconTransmitP.nc
index 8d977ae71d4d44be05d5f060b3d2347b64a4b098..7ddc5a284746da7e24372e5a2d1378fa4d4e43f4 100644 (file)
@@ -59,10 +59,7 @@ module BeaconTransmitP
     interface RadioTx as BeaconTx;
     interface MLME_GET;
     interface MLME_SET;
-    interface Resource as Token;
-    interface ResourceTransferred as TokenTransferred;
-    interface ResourceTransfer as TokenToBroadcast;
-    interface GetNow<bool> as IsTokenRequested;
+    interface TransferableResource as RadioToken;
     interface FrameTx as RealignmentBeaconEnabledTx;
     interface FrameTx as RealignmentNonBeaconEnabledTx;
     interface FrameRx as BeaconRequestRx;
@@ -77,6 +74,7 @@ module BeaconTransmitP
     interface GetSet<ieee154_txframe_t*> as GetSetRealignmentFrame;
     interface GetNow<bool> as IsBroadcastReady; 
     interface TimeCalc;
+    interface Random;
     interface Leds;
   }
 }
@@ -95,7 +93,6 @@ implementation
   norace uint32_t m_beaconInterval;
   norace uint32_t m_previousBeaconInterval;
   norace uint32_t m_dt;
-  norace uint8_t m_bsn;
   norace uint32_t m_lastBeaconTxTime;
   norace ieee154_timestamp_t m_lastBeaconTxRefTime;
   norace ieee154_macBattLifeExtPeriods_t m_battLifeExtPeriods;
@@ -154,7 +151,8 @@ implementation
   /* function/task prototypes */
   task void txDoneTask();
   task void signalStartConfirmSuccessTask();
-  void prepareNextBeaconTransmission();
+  void nextRound();
+  void prepareBeaconTransmission();
   void continueStartRequest();
   void finishRealignment(ieee154_txframe_t *frame, ieee154_status_t status);
 
@@ -162,6 +160,8 @@ implementation
   {
     // reset this component, will only be called while we're not owning the token
     // TODO: check to signal MLME_START.confirm ?
+
+    call MLME_SET.macBSN(call Random.rand16());
     m_beaconFrame.header = &m_header;
     m_beaconFrame.headerLen = 0;
     m_beaconFrame.payload = m_payload;
@@ -216,7 +216,7 @@ implementation
       status =  IEEE154_INVALID_PARAMETER;
     else if (startTime && !call IsTrackingBeacons.getNow())
       status = IEEE154_TRACKING_OFF;
-    else if (startTime && 0xFF000000)
+    else if (startTime & 0xFF000000)
       status = IEEE154_INVALID_PARAMETER;
     else if (m_requestBitmap & (REQUEST_CONFIRM_PENDING | REQUEST_UPDATE_SF))
       status = IEEE154_TRANSACTION_OVERFLOW;
@@ -242,7 +242,7 @@ implementation
       if (m_beaconOrder == 15) {
         // We're not already transmitting beacons, i.e. we have to request the token
         // (otherwise we'd get the token "automatically" for the next scheduled beacon).
-        call Token.request();
+        call RadioToken.request();
       }
       // We'll continue the MLME_START operation in continueStartRequest() once we have the token
     }
@@ -331,7 +331,6 @@ implementation
     }
     m_dt = m_beaconInterval;
     m_txState = S_TX_IDLE;
-    m_bsn = call MLME_GET.macBSN()+1;
     m_battLifeExtPeriods = call MLME_GET.macBattLifeExtPeriods();
 
     // (3) update PIB
@@ -348,6 +347,7 @@ implementation
     isShortAddr = (shortAddress != 0xFFFE);
     m_beaconFrame.header->mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_BEACON;
     m_beaconFrame.header->mhr[MHR_INDEX_FC2] = isShortAddr ? FC2_SRC_MODE_SHORT : FC2_SRC_MODE_EXTENDED;
+    m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = call MLME_GET.macBSN() + 1;
     offset = MHR_INDEX_ADDRESS;
     *((nxle_uint16_t*) &m_beaconFrame.header->mhr[offset]) = m_updatePANId;
     offset += sizeof(ieee154_macPANId_t);
@@ -373,59 +373,61 @@ implementation
     }
   }
 
-  task void grantedTask()
+  task void signalGrantedTask()
   {
-    signal Token.granted();
+    signal RadioToken.granted();
   }
 
-  event void Token.granted()
+  event void RadioToken.granted()
   {
-    dbg_serial("BeaconSynchronizeP","Got token, will Tx beacon in %lu\n",
-        (uint32_t) ((m_lastBeaconTxTime + m_dt) - call BeaconSendAlarm.getNow())); 
+    dbg_serial("BeaconSynchronizeP","Token granted.\n");
     if (m_requestBitmap & REQUEST_REALIGNMENT_DONE_PENDING) {
-      // unlikely to occur: we have not yet received a done()
+      // very unlikely: we have not yet received a done()
       // event after sending out a realignment frame 
       dbg_serial("BeaconTransmitP", "Realignment pending (request: %lu) !\n", (uint32_t) m_requestBitmap);
-      post grantedTask(); // spin
+      post signalGrantedTask(); // spin
       return;
     } else if (m_requestBitmap & REQUEST_UPDATE_SF) {
       dbg_serial("BeaconTransmitP","Putting new superframe spec into operation\n"); 
       m_requestBitmap &= ~REQUEST_UPDATE_SF;
       continueStartRequest();
     }
+    nextRound();
+  }
+
+  void nextRound()
+  {
     if (call RadioOff.isOff())
-      prepareNextBeaconTransmission();
+      prepareBeaconTransmission();
     else
-      ASSERT(call RadioOff.off() == SUCCESS); // will continue in prepareNextBeaconTransmission()
+      ASSERT(call RadioOff.off() == SUCCESS); // will continue in prepareBeaconTransmission()
   }
 
-  async event void TokenTransferred.transferred()
+  async event void RadioToken.transferredFrom(uint8_t fromClientID)
   {
-    if (call IsTokenRequested.getNow()) {
-      // some other component needs the token - we give it up for now, 
-      // but before make another request to get it back afterwards     
-      dbg_serial("BeaconTransmitP", "Token is requested, releasing it now.\n");
-      call Token.request();
-      call Token.release();
-    } else
-      post grantedTask();
+    dbg_serial("BeaconSynchronizeP","Token transferred, will Tx beacon in %lu\n",
+        (uint32_t) ((m_lastBeaconTxTime + m_dt) - call BeaconSendAlarm.getNow())); 
+    if (m_requestBitmap & (REQUEST_REALIGNMENT_DONE_PENDING | REQUEST_UPDATE_SF))
+      post signalGrantedTask(); // need to be in sync context
+    else
+      nextRound();
   }  
 
   async event void RadioOff.offDone()
   {
-    prepareNextBeaconTransmission();
+    prepareBeaconTransmission();
   }
 
-  void prepareNextBeaconTransmission()
+  void prepareBeaconTransmission()
   {
     if (m_txState == S_TX_LOCKED) {
       // have not had time to finish processing the last sent beacon
       dbg_serial("BeaconTransmitP", "Token was returned too fast!\n");
-      post grantedTask();
+      post signalGrantedTask();
     } else if (m_beaconOrder == 15) {
       // we're not sending any beacons!?
       dbg_serial("BeaconTransmitP", "Stop sending beacons.\n");
-      call Token.release();
+      call RadioToken.release();
     } else {
       // get ready for next beacon transmission
       atomic {
@@ -492,7 +494,6 @@ implementation
     else
       m_beaconFrame.header->mhr[MHR_INDEX_FC1] &= ~FC1_FRAME_PENDING;
 
-    m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = m_bsn; // update beacon seqno
     if (m_txOneBeaconImmediately) {
       m_txOneBeaconImmediately = FALSE;
       timestamp = NULL;
@@ -516,27 +517,31 @@ implementation
       dbg_serial("BeaconTransmitP", "Beacon Tx success at %lu\n", (uint32_t) m_lastBeaconTxTime);
     } else {
       // Timestamp is invalid; this is bad. We need the beacon timestamp for the 
-      // slotted CSMA-CA, because it defines slot reference time. We can't use this superframe
+      // slotted CSMA-CA, because it defines the slot reference time. We can't use this superframe
       // TODO: check if this was the initial beacon (then m_lastBeaconTxRefTime is invalid)
       dbg_serial("BeaconTransmitP", "Invalid timestamp!\n");
       m_dt += m_beaconInterval;
-      call Token.request();
-      call Token.release();      
+      call RadioToken.request();
+      call RadioToken.release();      
       return;
     }
 
     // update superframe-related variables
-    m_numGtsSlots = (frame->payload[2] & 0x07);
+    m_numGtsSlots = 
+      (frame->payload[BEACON_INDEX_GTS_SPEC] & GTS_DESCRIPTOR_COUNT_MASK) >> GTS_DESCRIPTOR_COUNT_OFFSET;
     gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
-    m_numCapSlots = (frame->payload[1] & 0x0F) + 1;
-    m_sfSlotDuration = (((uint32_t) 1) << ((frame->payload[0] & 0xF0) >> 4)) * IEEE154_aBaseSlotDuration;
+    m_numCapSlots = 
+      ((frame->payload[BEACON_INDEX_SF_SPEC2] & SF_SPEC2_FINAL_CAPSLOT_MASK) >> SF_SPEC2_FINAL_CAPSLOT_OFFSET) + 1;
+    m_sfSlotDuration = 
+      (((uint32_t) 1) << ((frame->payload[BEACON_INDEX_SF_SPEC1] & SF_SPEC1_SO_MASK) >> SF_SPEC1_SO_OFFSET)) * 
+      IEEE154_aBaseSlotDuration;
 
-    if (frame->header->mhr[0] & FC1_FRAME_PENDING)
+    if (frame->header->mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING)
       m_framePendingBit = TRUE;
     else
       m_framePendingBit = FALSE;
-    memcpy(m_gtsField, &frame->payload[2], gtsFieldLength);
-    if (frame->payload[1] & 0x10) {
+    memcpy(m_gtsField, &frame->payload[BEACON_INDEX_GTS_SPEC], gtsFieldLength);
+    if (frame->payload[BEACON_INDEX_SF_SPEC2] & SF_SPEC2_BATT_LIFE_EXT) {
       // BLE is active; calculate the time offset from slot 0
       m_battLifeExtDuration = IEEE154_SHR_DURATION + 
         (frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET; 
@@ -547,13 +552,18 @@ implementation
       m_battLifeExtDuration = m_battLifeExtDuration + m_battLifeExtPeriods * 20;
     } else
       m_battLifeExtDuration = 0;
-    call TokenToBroadcast.transfer(); 
+
+    // we pass on the token now, but make a reservation to get it back 
+    // to transmit the next beacon (at the start of the next superframe)
+    call RadioToken.request();  
+    call RadioToken.transferTo(RADIO_CLIENT_COORDBROADCAST); 
     post txDoneTask();
   }
 
   task void txDoneTask()
   {
-    call MLME_SET.macBSN(m_bsn++);
+    call MLME_SET.macBSN(m_beaconFrame.header->mhr[MHR_INDEX_SEQNO]);
+    m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] += 1; // may be overwritten by the next higher layer
     call SetMacBeaconTxTime.set(m_lastBeaconTxTime); // start of slot0, ie. first preamble byte of beacon
     call BeaconPayloadUpdateTimer.startOneShotAt(m_lastBeaconTxTime, 
         (m_beaconInterval>BEACON_PAYLOAD_UPDATE_INTERVAL) ? (m_beaconInterval - BEACON_PAYLOAD_UPDATE_INTERVAL): 0);
@@ -645,7 +655,7 @@ implementation
   uint8_t getNumGtsSlots(uint8_t *gtsInfoField)
   {
     uint8_t i, num=0;
-    for (i=0; i<(gtsInfoField[0] & GTS_DESCRIPTOR_COUNT_MASK); i++)
+    for (i=0; i<((gtsInfoField[0] & GTS_DESCRIPTOR_COUNT_MASK) >> GTS_DESCRIPTOR_COUNT_OFFSET); i++)
       num += ((gtsInfoField[4+i*3] & GTS_LENGTH_MASK) >> GTS_LENGTH_OFFSET);
     return num;
   }
@@ -695,13 +705,15 @@ implementation
       // (3) update SF spec
       beaconSpecs -= 2; // sizeof SF Spec
       if (m_payloadState & MODIFIED_SF_SPEC) {
-        beaconSpecs[0] = m_beaconOrder | (m_superframeOrder << 4);
-        beaconSpecs[1] = 0;
+        beaconSpecs[BEACON_INDEX_SF_SPEC1] = 
+          (m_beaconOrder << SF_SPEC1_BO_OFFSET) | (m_superframeOrder << SF_SPEC1_SO_OFFSET);
+        beaconSpecs[BEACON_INDEX_SF_SPEC2] = 0;
         if (call MLME_GET.macAssociationPermit())
-          beaconSpecs[1] |= SF_SPEC2_ASSOCIATION_PERMIT;        
+          beaconSpecs[BEACON_INDEX_SF_SPEC2] |= SF_SPEC2_ASSOCIATION_PERMIT;        
         if (call MLME_GET.macPanCoordinator())
-          beaconSpecs[1] |= SF_SPEC2_PAN_COORD;
-        beaconSpecs[1] |= ((15-numGtsSlots) & 0x0F); // update FinalCAPSlot field
+          beaconSpecs[BEACON_INDEX_SF_SPEC2] |= SF_SPEC2_PAN_COORD;
+        beaconSpecs[BEACON_INDEX_SF_SPEC2] |= 
+          ((15-numGtsSlots) & SF_SPEC2_FINAL_CAPSLOT_MASK);
       }
       m_beaconFrame.payloadLen = (m_pendingAddrLen + m_pendingGtsLen + 2) + m_beaconPayloadLen;
       m_beaconFrame.payload = beaconSpecs;
@@ -709,6 +721,7 @@ implementation
     } // end atomic (give BeaconSendAlarm.fired() the chance to execute)
 
     signal IEEE154TxBeaconPayload.aboutToTransmit();
+    m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = call MLME_GET.macBSN() + 1;
 
     atomic {
       // (4) try to update beacon payload