⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 beacontransmitp.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 3 页
字号:
          // The realignment frame will be transmitted immediately after 
          // the next beacon - the result will be signalled in 
          // RealignmentBeaconEnabledTx.transmitDone(). Only then the superframe
          // structure is updated and MLME_START.confirm signalled.
          m_requestBitmap |= REQUEST_REALIGNMENT_DONE_PENDING; // lock
        }
      } else {
        // send realignment frame in unslotted csma-ca now
        if (call RealignmentNonBeaconEnabledTx.transmit(realignmentFrame) != IEEE154_SUCCESS) {
          m_requestBitmap = 0;
          call GetSetRealignmentFrame.set(realignmentFrame);
          signal MLME_START.confirm(IEEE154_TRANSACTION_OVERFLOW);
        } else {
          // A realignment frame will be transmitted now, the result will 
          // be signalled in RealignmentNonBeaconEnabledTx.transmitDone(). Only 
          // then the superframe structure is updated and MLME_START.confirm 
          // signalled.
          m_requestBitmap |= REQUEST_REALIGNMENT_DONE_PENDING; // lock
        }
      }
      return; 
    }

    // (2) update internal state
    m_startTime = m_updateStartTime;
    m_txOneBeaconImmediately = FALSE;
    m_previousBeaconInterval = 0;
    if (m_startTime) {
      memcpy(&m_lastBeaconTxRefTime, call IncomingSF.sfStartTimeRef(), sizeof(ieee154_timestamp_t));
      m_lastBeaconTxTime = call IncomingSF.sfStartTime();
    } else {
      // no StartTime defined by next higher layer - but
      // if a realignment frame was transmitted, the next
      // beacon tx time must take the old BI into consideration
      if (m_requestBitmap & REQUEST_REALIGNMENT_DONE_PENDING)
        m_previousBeaconInterval = m_beaconInterval;
      else
        m_txOneBeaconImmediately = TRUE;
    }
    m_beaconOrder = m_updateBeaconOrder; 
    m_superframeOrder = m_updateSuperframeOrder;
    if (m_beaconOrder < 15) {
      m_beaconInterval = ((uint32_t) 1 << m_updateBeaconOrder) * IEEE154_aBaseSuperframeDuration;
    } else {
      m_beaconInterval = 0;
    }
    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
    call MLME_SET.macBeaconOrder(m_beaconOrder);
    call SetMacSuperframeOrder.set(m_superframeOrder);
    call MLME_SET.macPANId(m_updatePANId);
    call MLME_SET.phyCurrentChannel(m_updateLogicalChannel);
    if (m_beaconOrder < 15)
      call MLME_SET.macBattLifeExt(m_updateBatteryLifeExtension);
    call SetMacPanCoordinator.set(m_updatePANCoordinator);

    // (4) assemble beacon header and payload
    shortAddress = call MLME_GET.macShortAddress();
    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;
    offset = MHR_INDEX_ADDRESS;
    *((nxle_uint16_t*) &m_beaconFrame.header->mhr[offset]) = m_updatePANId;
    offset += sizeof(ieee154_macPANId_t);
    if (isShortAddr) {
      *((nxle_uint16_t*) &m_beaconFrame.header->mhr[offset]) = shortAddress;
      offset += sizeof(ieee154_macShortAddress_t);
    } else {
      call FrameUtility.copyLocalExtendedAddressLE(&m_beaconFrame.header->mhr[offset]);
      offset += 8;
    }
    m_beaconFrame.headerLen = offset;
    m_payloadState |= MODIFIED_SPECS_MASK;    // update beacon payload
    signal BeaconPayloadUpdateTimer.fired();  // assemble initial beacon payload

    if (m_beaconOrder < 15) {
      // beacon-enabled PAN, signal confirm after next 
      // beacon has been transmitted (see MSC, Fig. 38)
      m_requestBitmap = REQUEST_CONFIRM_PENDING;
    } else {
      // beaconless PAN, we're done
      m_requestBitmap = 0;
      signal MLME_START.confirm(IEEE154_SUCCESS);
    }
  }

  task void signalGrantedTask()
  {
    signal RadioToken.granted();
  }

  event void RadioToken.granted()
  {
    dbg_serial("BeaconSynchronizeP","Token granted.\n");
    if (m_requestBitmap & REQUEST_REALIGNMENT_DONE_PENDING) {
      // 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 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())
      prepareBeaconTransmission();
    else
      ASSERT(call RadioOff.off() == SUCCESS); // will continue in prepareBeaconTransmission()
  }

  async event void RadioToken.transferredFrom(uint8_t fromClientID)
  {
    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()
  {
    prepareBeaconTransmission();
  }

  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 signalGrantedTask();
    } else if (m_beaconOrder == 15) {
      // we're not sending any beacons!?
      dbg_serial("BeaconTransmitP", "Stop sending beacons.\n");
      call RadioToken.release();
    } else {
      // get ready for next beacon transmission
      atomic {
        uint32_t delay = IEEE154_RADIO_TX_DELAY; 
        m_txState = S_TX_WAITING;
        if (m_txOneBeaconImmediately) {
          // transmit the beacon now
          dbg_serial("BeaconTransmitP", "Sending a beacon immediately.\n");
          signal BeaconSendAlarm.fired();
          return;
        } else if (m_startTime != 0) {
          // a new sf spec was put into operation, with a user-defined StartTime    
          // here m_lastBeaconTxTime is actually the last time a beacon was received

          dbg_serial("BeaconTransmitP", "First beacon to be sent at %lu.\n", m_startTime);
          m_dt = m_startTime;
          m_startTime = 0;
        } else if (m_previousBeaconInterval != 0) {
          // a new sf spec was put into operation, after a realignment frame 
          // broadcast; the next beacon time should still be calculated using the
          // old BI (one last time)

          dbg_serial("BeaconTransmitP", "Sending beacon after realignment dt=%lu.\n", m_previousBeaconInterval);
          m_dt = m_previousBeaconInterval;
          m_previousBeaconInterval = 0;
          if (m_requestBitmap & REQUEST_CONFIRM_PENDING) {
            // only now the next higher layer is to be informed 
            m_requestBitmap &= ~REQUEST_CONFIRM_PENDING;
            post signalStartConfirmSuccessTask();
          }
        }

        // The next beacon should be transmitted at time m_lastBeaconTxTime + m_dt, where m_dt
        // is typically the beacon interval. First we check if we're still in time.
        while (call TimeCalc.hasExpired(m_lastBeaconTxTime, m_dt)) { 
          // too late, we need to skip a beacon!
          dbg_serial("BeaconTransmitP", "Skipping a beacon: scheduled=%lu, now=%lu.\n", 
              (uint32_t) m_lastBeaconTxTime + m_dt, (uint32_t) call BeaconSendAlarm.getNow());
          m_dt += m_beaconInterval;
        }
        if (!call TimeCalc.hasExpired(m_lastBeaconTxTime - delay, m_dt)) {
          // don't load the beacon frame in the radio just yet - rather set a timer and
          // give the next higher layer the chance to modify the beacon payload 
          call BeaconSendAlarm.startAt(m_lastBeaconTxTime - delay, m_dt);
        } else
          signal BeaconSendAlarm.fired();
      }
    }
  }

  task void signalStartConfirmSuccessTask()
  {
    signal MLME_START.confirm(SUCCESS);
  }

  async event void BeaconSendAlarm.fired()
  {
    // start/schedule beacon transmission
    ieee154_timestamp_t *timestamp = &m_lastBeaconTxRefTime;
    m_txState = S_TX_LOCKED;

    if (call IsBroadcastReady.getNow())
      m_beaconFrame.header->mhr[MHR_INDEX_FC1] |= FC1_FRAME_PENDING;
    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;
    }
    call BeaconTx.transmit(&m_beaconFrame, timestamp, m_dt);
    dbg_serial("BeaconTransmitP","Beacon Tx scheduled for %lu.\n", (uint32_t) (*timestamp + m_dt));
  }

  async event void BeaconTx.transmitDone(ieee154_txframe_t *frame, const ieee154_timestamp_t *timestamp, error_t result)
  {
    // The beacon frame was transmitted, i.e. the CAP has just started
    // update the state then pass the token on to the next component 

    uint8_t gtsFieldLength;

    ASSERT(result == SUCCESS); // must succeed, we're sending without CCA or ACK request
    if (timestamp != NULL) {
      m_lastBeaconTxTime = frame->metadata->timestamp;
      memcpy(&m_lastBeaconTxRefTime, timestamp, sizeof(ieee154_timestamp_t));
      m_dt = m_beaconInterval; // transmit the next beacon at m_lastBeaconTxTime + m_dt 
      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 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 RadioToken.request();
      call RadioToken.release();      
      return;
    }

    // update superframe-related variables
    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[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[MHR_INDEX_FC1] & FC1_FRAME_PENDING)
      m_framePendingBit = TRUE;
    else
      m_framePendingBit = FALSE;
    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; 
      if (frame->headerLen + frame->payloadLen + 2 > IEEE154_aMaxSIFSFrameSize)
        m_battLifeExtDuration += IEEE154_MIN_LIFS_PERIOD;
      else
        m_battLifeExtDuration += IEEE154_MIN_SIFS_PERIOD;
      m_battLifeExtDuration = m_battLifeExtDuration + m_battLifeExtPeriods * 20;
    } else
      m_battLifeExtDuration = 0;

    // 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 SetMacBeaconTxTime.set(m_lastBeaconTxTime); // start of slot0, ie. first preamble byte of beacon
    call BeaconPayloadUpdateTimer.startOneShotAt(m_lastBeaconTxTime, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -