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

📄 mac_beacon_handler.c

📁 zigbee location examples
💻 C
📖 第 1 页 / 共 2 页
字号:
    *(pPayload++) = (BYTE) ((newPanId & 0xFF00) >> 8);
    *(pPayload++) = (BYTE) mpib.macShortAddress;
    *(pPayload++) = (BYTE) ((mpib.macShortAddress & 0xFF00) >> 8);
    *(pPayload++) = logicalChannel;
    *(pPayload++) = (BYTE) shortAddr;
    *(pPayload)   = (BYTE) ((shortAddr & 0xFF00) >> 8);

    // Calculate the packet duration (including ack. and IFS)
    pPacket->duration = msupCalcPacketDuration(pPacket->length, (BYTE)(txOptions & TX_OPT_ACK_REQ));

} // mbcnPrepareCoordinatorRealignment




//-------------------------------------------------------------------------------------------------------
//  void mbcnPrepareBeacon(void)
//
//  DESCRIPTION:
//      Prepares a valid beacon frame which can be transmitted using the TX engine.
//
//  ARGUMENTS:
//      MAC_TX_PACKET *pPacket
//          A pointer to the packet to be transmitted
//-------------------------------------------------------------------------------------------------------
void mbcnPrepareBeacon(MAC_TX_PACKET *pPacket) NEAR {
    BYTE srcAddrMode;
    WORD superframeSpec;
    BYTE   *pMacBeaconPayload;
    BYTE pendAddrSpec;
    MAC_TX_PACKET   *pIndirectPacket;
    UINT8 n, pendShortAddrCount, pendExtAddrCount;
    BYTE   *pPayload = pPacket->pPayload;

    // TX mode
    pPacket->txMode = 0;
    // pPacket->retriesLeft will be ignored (no ack)

    // Header
    srcAddrMode = (mpib.macShortAddress < 0xFFFE) ? SRC_ADDR_SHORT : SRC_ADDR_EXT;
    msupPrepareHeader(pPacket, FT_BEACON, srcAddrMode, mpib.macPANId, ((srcAddrMode == SRC_ADDR_SHORT) ? (ADDRESS  *)&mpib.macShortAddress : (ADDRESS  *) &aExtendedAddress), 0, NULL, (BYTE)(GET_MF(MF_BEACON_SECURITY)));

    // Superframe specification
    superframeSpec = (mpib.macBeaconOrder << SS_BEACON_ORDER_IDX) |
                     (mpib.macSuperframeOrder << SS_SUPERFRAME_ORDER_IDX) |
                     (15 << SS_FINAL_CAP_SLOT_IDX) |
                     (mpib.macBattLifeExt ? SS_BATT_LIFE_EXT_BM : 0) |
                     (GET_MF(MF_PAN_COORDINATOR) ? SS_PAN_COORDINATOR_BM : 0) |
                     (mpib.macAssociationPermit ? SS_ASSOCIATION_PERMIT_BM : 0);
    *((WORD   *) pPayload) = superframeSpec;
    pPayload += 2;

    // GTS list (not implemented)
    *(pPayload++) = 0x00;

    // Pending address list

    // Count the number of pending addresses to get the packet length
    n = miqInfo.firstIndirectPacket;
    pendShortAddrCount = 0;
    pendExtAddrCount = 0;
    while ((n != NO_PACKET) && ((pendShortAddrCount + pendExtAddrCount) < MAX_PENDING_LIST_SIZE)) {
        pIndirectPacket = &pMtxPacketPool[n];
        if (pIndirectPacket->timeToLive > 0) {
            if (pIndirectPacket->isFirstPacket) {
                if ((pIndirectPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_EXT) {
                    pendExtAddrCount++;
                } else {
                    pendShortAddrCount++;
                }
            }
        }
        n = pIndirectPacket->nextPacket;
    }

    // Pending address specification (indicates the number of short and extended addresses)
    pendAddrSpec = pendShortAddrCount + (pendExtAddrCount << 4);
    *(pPayload++) = pendAddrSpec;

    // Address list
    if (pendAddrSpec) {

        // Short addresses
        n = miqInfo.firstIndirectPacket;
        do {
            pIndirectPacket = &pMtxPacketPool[n];
            if (pIndirectPacket->isFirstPacket && (pIndirectPacket->timeToLive > 0) && ((pIndirectPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_SHORT)) {

                // Copy the packet destination address
                memcpy(pPayload, pIndirectPacket->pHeader + 5, 2);
                pendShortAddrCount--;
                pPayload += 2;
            }
            n = pIndirectPacket->nextPacket;
        } while (pendShortAddrCount);

        // Extended addresses
        n = miqInfo.firstIndirectPacket;
        do {
            pIndirectPacket = &pMtxPacketPool[n];
            if (pIndirectPacket->isFirstPacket && (pIndirectPacket->timeToLive > 0) && ((pIndirectPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_EXT)) {

                // Copy the packet destination address
                memcpy(pPayload, pIndirectPacket->pHeader + 5, 8);
                pendExtAddrCount--;
                pPayload += 8;
            }
            n = pIndirectPacket->nextPacket;
        } while (pendExtAddrCount);
    }

    // Beacon payload (safe access to mpib.pMacBeaconPayload)
    DISABLE_GLOBAL_INT();
    pMacBeaconPayload = mpib.pMacBeaconPayload;
    ENABLE_GLOBAL_INT();
    memcpy(pPayload, pMacBeaconPayload, mpib.macBeaconPayloadLength);
    pPayload += mpib.macBeaconPayloadLength;

    // Set the total packet length
    pPacket->length = pPacket->headerLength + (pPayload - pPacket->pPayload) + MAC_FCS_LENGTH;

    // Calculate the packet duration
    pPacket->duration = msupCalcPacketDuration(pPacket->length, pPacket->txOptions & TX_OPT_ACK_REQ);

} // mbcnPrepareBeacon

#endif  // MAC_OPT_FFD


/*******************************************************************************************************
 *******************************************************************************************************
 **************************                 UTILITY FUNCTIONS                 **************************
 *******************************************************************************************************
 *******************************************************************************************************/




//-------------------------------------------------------------------------------------------------------
//  void mbcnGetBeaconMargin(void)
//
//  DESCRIPTION:
//      Because of the crystal inaccuracy, a margin must be added before the beacon that will
//      be received. The result is that:
//          - RX must be turned on a short while before the beacon is expected to be received.
//          - TX must stop before this margin is reached
//
//      The Excel worksheet called "Beacon reception margin.xls" can be used to calculate these
//      constants.
//
//  RETURN VALUE:
//      UINT8
//          The margin as a number of backoff periods
//-------------------------------------------------------------------------------------------------------
UINT8 mbcnGetBeaconMargin(void) NEAR {
    switch (mpib.macBeaconOrder) {
        case 7:  return 2;
        case 8:  return 3;
        case 9:  return 5;
        case 10: return 10;
        case 11: return 20;
        case 12: return 40;
        case 13: return 79;
        case 14: return 158;
        default: return 1;
    }

} // mbcnGetBeaconMargin




//-------------------------------------------------------------------------------------------------------
//  void mbcnUpdateBufferedAttributes(void)
//
//  DESCRIPTION:
//      Updates category 4 attributes (see mlmeSetRequest()) before the beacon is received or
//      transmitted. Only attributes indicated in the update mask will be changed.
//-------------------------------------------------------------------------------------------------------
void mbcnUpdateBufferedPibAttributes(void) NEAR {
    DISABLE_GLOBAL_INT();

    if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_BATT_LIFE_EXT_BM)    mpib.macBattLifeExt = macInfo.pibTempBuffer.macBattLifeExt;
    if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_BEACON_ORDER_BM)     mpib.macBeaconOrder = macInfo.pibTempBuffer.macBeaconOrder;
    if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_RX_ON_WHEN_IDLE_BM)  mpib.macRxOnWhenIdle = macInfo.pibTempBuffer.macRxOnWhenIdle;
    if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_SUPERFRAME_ORDER_BM) mpib.macSuperframeOrder = macInfo.pibTempBuffer.macSuperframeOrder;

    macInfo.pibTempBuffer.updateMask = 0x00;
    ENABLE_GLOBAL_INT();
} // mbcnUpdateBufferedPibAttributes




//-------------------------------------------------------------------------------------------------------
//  void mbcnHandleBeaconModeChange(BOOL wasNonBeacon)
//
//  DESCRIPTION:
//      Handles the change from a beacon network to a non-beacon network and vice versa.
//
//  ARGUMENTS:
//      BOOL wasNonBeacon
//          Indicates the earlier state (BEFORE the mpib.macBeaconOrder variable was updated)
//-------------------------------------------------------------------------------------------------------
void mbcnHandleBeaconModeChange(BOOL wasNonBeacon) NEAR {

    // Handle non-beacon -> beacon network
    if (wasNonBeacon && (mpib.macBeaconOrder < 15)) {

        // Send backoff slot synchronous acknowledgments
        MDMCTRL1H |= 0x80;

        // "RX on when idle" should only be active in the superframe (set up by the beacon transmission task
        if (mpib.macRxOnWhenIdle) mrxDecrOnCounter();

#if MAC_OPT_FFD
        // The beacon transmission task will handle indirect packet expiration
        mtimCancelCallback(mbcnExpirePacketsNonBeacon);
#endif

    // Handle beacon -> non-beacon network
    } else if (!wasNonBeacon && (mpib.macBeaconOrder == 15)) {

        // Send acknowledgments ASAP
        MDMCTRL1H &= ~0x80;

        // Update buffered PIB attributes before the buffering mechanism is disabled
        macInfo.pibTempBuffer.updateMask &= MPIB_UPD_BATT_LIFE_EXT_BM | MPIB_UPD_RX_ON_WHEN_IDLE_BM;
        mbcnUpdateBufferedPibAttributes();

        // "RX on when idle" is always valid from now on
        if (mpib.macRxOnWhenIdle) mrxIncrOnCounter();

        // Cancel beacon transmission and reception, and turn on indirect packet expiration for non-beacon networks
#if MAC_OPT_FFD
        mtimCancelCallback(mbcnTxPeriodicalBeacon);
#endif
        mtimCancelCallback(mbcnRxPeriodicalBeacon);
#if MAC_OPT_FFD
        mtimSetCallback(mbcnExpirePacketsNonBeacon, (INT32)(aBaseSuperframeDuration / aUnitBackoffPeriod));
#endif
    }

} // mbcnHandleBeaconModeChange




/*******************************************************************************************************
 *******************************************************************************************************
 **************************                  BEACON TRACKING                  **************************
 *******************************************************************************************************
 *******************************************************************************************************/




//-------------------------------------------------------------------------------------------------------
//  void mbcnSyncToBeacons(MAC_TASK_INFO *pTask)
//
//  DESCRIPTION:
//      This task starts synchronization to beacons
//
//  TASK DATA:
//      0
//-------------------------------------------------------------------------------------------------------
void mbcnSyncToBeacons(MAC_TASK_INFO *pTask) NEAR {

    // Reserve the beacon tracking task if necessary
    if (mbcnInfo.rxTaskNumber == NO_TASK) mbcnInfo.rxTaskNumber = mschReserveTask();

    // Set track status variables
    mbcnInfo.findBeacon = TRUE;
    mbcnInfo.noBcnCountdown = aMaxLostBeacons;
    mbcnInfo.trackBeacon = (BOOL) LOBYTE(pTask->taskData);

    // Switch radio channel if necessary
    msupSetChannel(HIBYTE(pTask->taskData), TRUE);
    mrxIncrOnCounter();

    // Start receiving beacons
    mbcnRxPeriodicalBeacon();

    // Remove this task
    mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);

} // mbcnSyncToBeacons




/*******************************************************************************************************
 *******************************************************************************************************
 **************************          NON-BEACON INDIRECT EXPIRATION           **************************
 *******************************************************************************************************
 *******************************************************************************************************/



#if MAC_OPT_FFD

//-------------------------------------------------------------------------------------------------------
//  void mbcnExpirePacketsNonBeacon(void)
//
//  DESCRIPTION:
//      Schedules the next expiration "tick", and starts the expiration task
//-------------------------------------------------------------------------------------------------------
void mbcnExpirePacketsNonBeacon(void) NEAR {

    // Schedule the next round (48 backoff periods from now)
    mtimSetCallback(mbcnExpirePacketsNonBeacon, (INT32)(aBaseSuperframeDuration / aUnitBackoffPeriod));

    // Create the task that will expire old packets
    mschAddTask(mschReserveTask(), MAC_TASK_PRI_MEDIUM, mbcnExpirePacketsNonBeaconTask, 0);

} // mbcnExpirePacketsNonBeacon




//-------------------------------------------------------------------------------------------------------
//  void mbcnExpirePacketsNonBeaconTask(MAC_TASK_INFO *pTask)
//
//  DESCRIPTION:
//      Expires indirect packets in a non-beacon network by decrementing the "time to live" counter, and
//      then transforming the task into an miqExpireIndirectPacketsTask().
//
//  TASK DATA:
//      0
//-------------------------------------------------------------------------------------------------------
void mbcnExpirePacketsNonBeaconTask(MAC_TASK_INFO *pTask) NEAR {

    // Decrement "time to live"
    miqDecrTimeToLive();

    // Continue in the miqExpireIndirectPacketsTask() function
    pTask->pTaskFunc = miqExpireIndirectPacketsTask;

} // mbcnExpirePacketsNonBeaconTask


#endif // MAC_OPT_FFD

⌨️ 快捷键说明

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