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

📄 zmac_receive.c

📁 通过cc2420+pic实现无线通信
💻 C
📖 第 1 页 / 共 5 页
字号:
        if ( currentQueueItem == MAX_MAC_FRAME_STATUS )
            currentQueueItem = 0;

        // If an entry is in use, see if it is ack'ed.
        if ( pCurrentFrame->Flags.bits.bIsInUse )
        {
            // If not ack'ed and timeout has occurred,
            if ( !pCurrentFrame->Flags.bits.bIsConfirmed )
            {
                // Mark it as as timed out.
                if ( TickGetDiff(TickGet(), pCurrentFrame->lastTick) >= MAC_ACK_WAIT_DURATION )
                {
                    pCurrentFrame->Flags.bits.bIsTimedOut = TRUE;

                    // Notify of a timeout condition.
                    AppMACFrameTimeOutOccurred();

                }
            }
        }

#if defined(MAC_USE_TX_INDIRECT_BUFFER)
        // Do same for tx stagged frames.
        ProcessTxIndirectBuffer();
#endif
        return TRUE;
    }

    // See if it has a valid header.
    if ( !MACGetHeader() )
        return TRUE;

    // Notify application of arrival of a new frame.
    AppMACFrameReceived();

    // Mark that we have a valid frame.
    macCurrentFrame.Flags.bits.bIsGetReady = TRUE;

    // Send ack back if requested.
    if ( macCurrentFrame.frameCONLSB.bits.AckRequest )
    {
        MACSendAck();
    }

    // If this is ACK, update our queue status.
    if ( MACIsAck() )
    {
        UpdateQueue(macCurrentFrame.macDSN);

        // Once registered, discard ACK frame.
        MACDiscardRx();
    }

#if defined(I_AM_COORDINATOR)
    else if ( MACIsCommand() )
    {
        // If this is coordinator, respond to beacon requests.
        // A coordinator will respond to following requests only
        // after it has established its own network.

        if ( MACIsBeaconRequest() )
        {
            MACDiscardRx();

            if ( MACIsNetworkEstablished() )
            {
                DEBUG_OUT("MAC: MACTask(): Sending Beacon...\r\n");
                MACSendBeacon();
            }
        }

        // New associations are allowed only if it is permitted by application.
        else if ( MACIsAssocRequest() )
        {
            if ( MACIsJoinPermitted() )
            {
                if ( !MACProcessAssociation() )
                    MACDiscardRx();
            }
            else
                MACDiscardRx();
        }

        // Same with disassociation.
        else if ( MACIsDisassocNotice() )
        {
            if ( !MACProcessDisassociation() )
                MACDiscardRx();

        }

        // Orphan can be rejoined only after we have established new network.
        else if ( MACIsOrphanNotice() )
        {
            if ( MACIsNetworkEstablished() )
            {
                if ( !MACProcessOrphanNotice() )
                    MACDiscardRx();
            }
            else
                MACDiscardRx();
        }

        // Same with data request.
        else if ( MACIsDataReq() )
        {
            if ( MACIsNetworkEstablished() )
            {
                // This function always discards packet.
                MACProcessDataReq();
            }
            else
                MACDiscardRx();

        }

    }
#endif

    return TRUE;
}


/*********************************************************************
 * Function:        static BOOL MACGetHeader(void)
 *
 * PreCondition:    _MACIsGetReady() == TRUE
 *
 * Input:           None
 *
 * Output:          TRUE        - if current frame has valid header
 *                  FALSE       - if current frame does not have
 *                                valid header
 *
 * Side Effects:    None
 *
 * Overview:        Fetches rx frame one byte at a time and validates
 *                  as per 802.15.4 spec.
 *
 * Note:            This is private function, called MAC module only.
 ********************************************************************/
static BOOL MACGetHeader(void)
{
    BYTE_VAL temp;
    BYTE frameType;
    BYTE_VAL length;

    PHYBegin();

    // Start reading RX FIFO.
    PHYSelectRxFIFO();

    // First byte is length
    length.Val = PHYGetMac();

    // Make sure that this is a valid length
    if ( length.Val == 0 || length.bits.b7 == 1 )
        goto DiscardAndReturn;

    // Save received packet length minus 2 bytes of CRC/(RSSI + CORRELATION for CC2420)
    macCurrentFrame.frameLength = length.Val - 2;

    // Get frame control field - LSB.
    temp.Val = PHYGetMac();
    // One less byte from packet count.
    macCurrentFrame.frameLength--;

    // save frame LSB
    macCurrentFrame.frameCONLSB.Val = temp.Val;

    // Extract and save frame type
    macCurrentFrame.type = temp.Val & 0x07;

    // Reject "Reserved" frame type.
    frameType = macCurrentFrame.type;
    if ( frameType > 0x03 )
        goto DiscardAndReturn;

    // Other bits will be processed later...

    // Now get MSB
    temp.Val = PHYGetMac();
    // One less byte from packet count.
    macCurrentFrame.frameLength--;

    // Save MSB
    macCurrentFrame.frameCONMSB.Val = temp.Val;

    // Save frame MSB.
    macCurrentFrame.dst.addrMode = temp.Val & 0x0c;
    macCurrentFrame.src.addrMode = temp.Val & 0xc0;

    // Get Sequence number
    macCurrentFrame.macDSN = PHYGetMac();
    macCurrentFrame.frameLength--;

    // Mode value of non-zero means that destination PAN identifier is present.
    if ( macCurrentFrame.dst.addrMode == MAC_DST_ADDR_RESERVED )
        goto DiscardAndReturn;

    // If the destination addressing mode field is non-zero, there is a dst PAN ID.
    if ( macCurrentFrame.dst.addrMode )
    {
        macCurrentFrame.dst.panID.byte.LSB = PHYGetMac();
        macCurrentFrame.dst.panID.byte.MSB = PHYGetMac();

        macCurrentFrame.frameLength -= 2;
    }

    // Fetch destination address according to its type
    if ( macCurrentFrame.dst.addrMode == MAC_DST_SHORT_ADDR )
    {
        macCurrentFrame.dst.shortAddr.byte.LSB = PHYGetMac();
        macCurrentFrame.dst.shortAddr.byte.MSB = PHYGetMac();

        macCurrentFrame.frameLength -= 2;
    }
    else if ( macCurrentFrame.dst.addrMode == MAC_DST_LONG_ADDR )
    {
        macCurrentFrame.dst.longAddr.v[0] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[1] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[2] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[3] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[4] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[5] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[6] = PHYGetMac();
        macCurrentFrame.dst.longAddr.v[7] = PHYGetMac();

        macCurrentFrame.frameLength -= 8;
    }

    // Mode value of non-zero means that source PAN identifier is present.
    if ( macCurrentFrame.src.addrMode == MAC_SRC_ADDR_RESERVED )
        goto DiscardAndReturn;

    // If the source addressing mode field is non-zero and the IntraPAN flag is clear,
    // the IEEE spec says there will be a src PAN ID.
    if ( macCurrentFrame.src.addrMode &&
         macCurrentFrame.frameCONLSB.bits.IntraPAN == 0 )
    {
        macCurrentFrame.src.panID.byte.LSB = PHYGetMac();
        macCurrentFrame.src.panID.byte.MSB = PHYGetMac();

        macCurrentFrame.frameLength -= 2;
    }


    // Fetch source address according to its type
    if ( macCurrentFrame.src.addrMode == MAC_SRC_SHORT_ADDR )
    {
        macCurrentFrame.src.shortAddr.byte.LSB = PHYGetMac();
        macCurrentFrame.src.shortAddr.byte.MSB = PHYGetMac();

        macCurrentFrame.frameLength -= 2;
    }
    else if ( macCurrentFrame.src.addrMode == MAC_SRC_LONG_ADDR )
    {
        macCurrentFrame.src.longAddr.v[0] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[1] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[2] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[3] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[4] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[5] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[6] = PHYGetMac();
        macCurrentFrame.src.longAddr.v[7] = PHYGetMac();

        macCurrentFrame.frameLength -= 8;
    }

    // If this is a command frame, extract and save command id.
    if ( macCurrentFrame.type == MAC_FRAME_CMD )
    {
        macCurrentFrame.frameLength--;
        macCurrentFrame.cmd = PHYGetMac();
    }
#if defined(I_AM_END_DEVICE)
    else if ( macCurrentFrame.type == MAC_FRAME_DATA )
        macState.bits.bIsPollDone = TRUE;
#endif

    PHYEnd();

    return TRUE;


DiscardAndReturn:
    PHYEnd();

    PHYBegin();
    PHYFlushRx();
    PHYEnd();
    return FALSE;
}


/*********************************************************************
 * Function:        void MACStartAssociation(void)
 *
 * PreCondition:    MACAcceptCurrentPAN() is already called.
 *                  A network scan was performed and appropriate
 *                  coordinator was selected.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Prepares MAC state machine to begin association
 *                  sequence.
 *
 * Note:            This is available for end device only.
 ********************************************************************/
#if defined(I_AM_END_DEVICE)
void MACStartAssociation(void)
{
    // Forget about previous association.
    macState.bits.bIsAssociated = FALSE;

    macFrameRetryCount = MAC_MAX_FRAME_RETRIES;

    // Reset the state machine.
    smAssociation = SM_SEND_ASSOCIATE_REQ;

}
#endif


/*********************************************************************
 * Function:        BOOL MACIsAssociationComplete(void)
 *
 * PreCondition:    MACStartAssociation() is called.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        performs association sequence as per 802.15.4
 *                  spec.
 *
 * Note:            This is available for end device only.
 ********************************************************************/
#if defined(I_AM_END_DEVICE)
BOOL MACIsAssociationComplete(void)
{
    BOOL result;
    MAC_ASSOCIATE_STATUS    macAssociationStatus;

    result = FALSE;
    switch(smAssociation)
    {
    case SM_SEND_ASSOCIATE_REQ:
        macFrameRetryCount--;

        // When associating, provide long address and no pan id.
        macInfo.addrMode    = MAC_SRC_LONG_ADDR;
        macInfo.panID.Val   = 0xffff;

        MACPutHeader(&macCoordInfo,            // Dest
                    MAC_FRAME_CMD |           // Frame Control LSB
                    MAC_SECURITY |
                    MAC_FRAME_PENDING_NO |
                    MAC_ACK_YES|
                    MAC_INTRA_PAN_NO);



        PHYBeginTxFIFOAccess();
        PHYPutTxData(MAC_CMD_ASSOCIATE_REQ);
        PHYPutTxData(MAC_CAP_INFO);
        PHYEndTxFIFOAccess();

        // Manually update packet length here instead of calling MACPut() and adding more code
        // and time.
        macPacketLen += 2;

        hFrame = MACFlush();

        DEBUG_OUT("MAC: MACSendAssociateRequest(): Sent association request...\r\n");

        macStartTick = TickGet();
        smAssociation = SM_WAIT_FOR_ACK;
        break;


    case SM_WAIT_FOR_ACK:
        if ( MACFrameIsAcked(hFrame) )
        {
            MACFrameRemove(hFrame);

            DEBUG_OUT("MAC: MACIsAssociated(): Valid ACK received, asking for response...\r\n");
            smAssociation = SM_SEND_DATA_REQ;
        }
        else if ( TickGetDiff(TickGet(), macStartTick) >= MAC_ACK_WAIT_DURATION )
        {
            // Remove current frame and try again, if needed.
            MACFrameRemove(hFrame);

            if ( macFrameRetryCount == 0 )
            {
                DEBUG_OUT("MAC: MACIsAssociated(): No ACK.\r\n");
                SetZError(ZCODE_NO_ACK);
                result = TRUE;
            }
            else
            {
                DEBUG_OUT("MAC: MACIsAssociated(): ACK Timeout, retrying...\r\n");
                smAssociation = SM_SEND_ASSOCIATE_REQ;
            }
        }

        break;

    case SM_SEND_DATA_REQ:
        DEBUG_OUT("MAC: MACIsAssociated(); Sending Data Request...\r\n");

        hFrame = MACPoll();

        macStartTick = TickGet();

        smAssociation = SM_WAIT_FOR_ASSOC_RESP;
        break;

    case SM_DATA_REQ_ACK_WAIT:
        if ( MACFrameIsAcked(hFrame) )
        {
            MACFrameRemove(hFrame);


⌨️ 快捷键说明

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