📄 zmac_receive.c
字号:
#if defined(I_AM_END_DEVICE)
void MACStartOrphanNotification(void)
{
// Once we start the orphan process, we assume that we are no
// longer associated with network - we are trying to find our
// previous network.
macState.bits.bIsAssociated = FALSE;
// This is how many times we should retry before giving out.
macFrameRetryCount = MAC_MAX_FRAME_RETRIES;
// Start with sending the notice.
smAssociation = SM_SEND_ORPHAN_NOTICE;
}
#endif
/*********************************************************************
* Function: BOOL MACIsOrphanNotificationComplete(void)
*
* PreCondition: MACStartOrphanNotification() is called.
*
* Input: None
*
* Output: TRUE if orphan notification process is complete
* FALSE otherwise.
*
* Side Effects: None
*
* Overview: Performs orphan notification steps as per
* IEEE spec.
*
* Note: Available to end devices only.
********************************************************************/
#if defined(I_AM_END_DEVICE)
BOOL MACIsOrphanNotificationComplete(void)
{
BOOL result;
// Begin with not ready return value.
result = FALSE;
switch(smAssociation)
{
case SM_SEND_ORPHAN_NOTICE:
DEBUG_OUT("MAC: MACIsOrphanNotificationComplete(): Sending an orphan request...\r\n");
// This is a retry
macFrameRetryCount--;
// macInfo is our address - source address in this case.
// As per spec, source address would be 64-bit address.
macInfo.addrMode = MAC_SRC_LONG_ADDR;
// And no PAN id.
macInfo.panID.Val = 0xffff;
// Destination will use not yet known short address with no PAN id.
macCoordInfo.addrMode = MAC_DST_SHORT_ADDR;
macCoordInfo.shortAddr.Val = 0xffff;
macCoordInfo.panID.Val = 0xffff;
// Prepare the header.
MACPutHeader(&macCoordInfo,
MAC_FRAME_CMD |
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_NO |
MAC_INTRA_PAN_NO);
// Copy orphan norification specific bytes in payload area.
PHYBeginTxFIFOAccess();
PHYPut(MAC_CMD_ORPHAN_NOTICE);
PHYEndTxFIFOAccess();
// Update transmit frame length to account for one byte
// that we added manually.
macPacketLen++;
// Mark this frame as ready to be transmitted.
MACFlush();
// Remember when we sent the frame.
macStartTick = TickGet();
// We will now wait for ACK from coordinator.
smAssociation = SM_WAIT_FOR_COORD_ALIGNMENT;
break;
case SM_WAIT_FOR_COORD_ALIGNMENT:
// See if we received any thing...
if( MACIsGetReady() )
{
// The coordinator alignment frame has 7 data bytes in addition to command identifier.
if ( macCurrentFrame.frameLength == 7 )
{
// Make sure that this is a coordinator realignment frame
if ( MACIsCommand() )
{
// Is this coordinator reliang command?
// Coordinator will respond with coordinator realignment frame
// to our orphan notice command.
if ( MACIsCoordRealign() )
{
// Now make sure that the frame header is correct according to realignment frame.
// TBD
// If we receive realignment frame, it means that we are in fact
// orphan to this coordinator. In that case, this response will
// contain our previously assigned short address.
// Fetch PAN id.
macInfo.panID.byte.LSB = MACGet();
macInfo.panID.byte.MSB = MACGet();
// Coordinator's PAN address is same as what is given to us
macCoordInfo.panID.Val = macInfo.panID.Val;
// Fetch coordinator short address.
macCoordInfo.shortAddr.byte.LSB = MACGet();
macCoordInfo.shortAddr.byte.MSB = MACGet();
// Remember the channel.
macCurrentChannel = MACGet();
// Now get our own short address.
macInfo.shortAddr.byte.LSB = MACGet();
macInfo.shortAddr.byte.MSB = MACGet();
// Now that we have our PAN id, update transciever buffer.
MACUpdateAddressInfo();
// Indicate that this process was successful.
SetZError(ZCODE_NO_ERROR);
// Remember that we are now associated.
macState.bits.bIsAssociated = TRUE;
// Return value.
result = TRUE;
}
}
}
// Discard now processed frame.
MACDiscardRx();
}
// Keep track of timeout so that we do not wait forever for the response.
else if ( TickGetDiff(TickGet(), macStartTick) >= MAC_RESPONSE_WAIT_TIME )
{
DEBUG_OUT("MAC: MACIsOrphanNotificationComplete(): ORPHAN Response timeout.\r\n");
// For every timeout, also make sure that we retry predefined number
// of times.
if ( macFrameRetryCount == 0 )
{
DEBUG_OUT("MAC: MACIsOrphanNotificationComplete(): ORPHAN Response retry timeout.\r\n");
// We exhausted retry count, set an error - NO_ACK
SetZError(ZCODE_NO_ACK);
// Done.
result = TRUE;
}
else
{
DEBUG_OUT("MAC: MACIsOrphanNotificationComplete(): Trying ORPHAN scan again...\r\n");
// We still have not exhausted retry count, try again...
smAssociation = SM_SEND_ORPHAN_NOTICE;
}
}
}
return result;
}
#endif
/*********************************************************************
* Function: BOOL MACProcessDisassociation(void)
*
* PreCondition: MACGetHeader() is already called and this frame
* is identified as Disassociate command frame.
*
* Input: None
*
* Output: TRUE if found valid association frame.
* FALSE othersie
*
* Side Effects: None
*
* Overview: Fetches rest of disassociation frame and validates
* as per IEEE spec.
*
* Note: Available to coordinator only.
********************************************************************/
#if defined(I_AM_COORDINATOR)
BOOL MACProcessDisassociation(void)
{
// There must be exactly two bytes of data in association request frame.
if( macCurrentFrame.frameLength == 1 )
{
// A disassociation request must have
// 1. Both source and destination addressing mode = 64-bit addresses.
// 2. Frame pending field set to 0.
// 3. Acknowledge field set to 1
//
// Make sure that current frame is indeed association request.
// LSB = Mask: 0b00100111 Value: 0b00100011,
// MSB = Mask: 0b11001100 Value: 0b11001100
if ( ((BYTE)(macCurrentFrame.frameCONLSB.Val & 0x27) == (BYTE)0x23) &&
((BYTE)(macCurrentFrame.frameCONMSB.Val & 0xCC) == (BYTE)0xCC) )
{
// Fetch and discard disassociation reason.
MACGet();
return TRUE;
}
}
return FALSE;
}
#endif
/*********************************************************************
* Function: void MACSendPANIDConflict(NODE_INFO *dest)
*
* PreCondition: TBD
*
* Input: TBD
*
* Output: TBD
*
* Side Effects: None
*
* Overview: TBD
*
* Note: Available to coordinator only.
********************************************************************/
#if 0
#if defined(I_AM_COORDINATOR)
void MACSendPANIDConflict(NODE_INFO *dest)
{
MACPutHeader(MAC_FRAME_CMD |
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_YES |
MAC_INTRA_PAN_YES,
MAC_SRC_LONG_ADDR |
MAC_DST_LONG_ADDR);
PHYBegin();
PHYPut(MAC_CMD_PAN_ID_CONFLICT);
PHYEnd();
MACFlush();
}
#endif
#endif
#define SUPERFRAME_SPEC_LSB (0x00)
#define SUPERFRAME_SPEC_MSB (0xC0)
#define GTS_FIELD_VAL (0x00)
/*********************************************************************
* Function: static void MACSendBeaconReq(void)
*
* PreCondition: MACIsPutready() = TRUE
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Sends out beacon request
*
* Note: None
********************************************************************/
static void MACSendBeaconReq(void)
{
// Now that we are trying to associate, forget previous PAN ID
macInfo.addrMode = MAC_SRC_NO_ADDR;
// Coordinator info will be same as what was received in beacon.
// But for time being use hardcoded value to test out...
macCoordInfo.addrMode = MAC_DST_SHORT_ADDR;
macCoordInfo.shortAddr.Val = 0xffff;
macCoordInfo.panID.Val = 0xffff;
MACPutHeader(&macCoordInfo, // Dest
MAC_FRAME_CMD | // Frame Control LSB
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_NO |
MAC_INTRA_PAN_NO);
// Load beacon req specific bytes in payload area.
PHYBeginTxFIFOAccess();
PHYPutTxData(MAC_CMD_BEACON_REQ);
PHYEndTxFIFOAccess();
// Manually update packet length here instead of calling MACPut() and adding more code
// and time.
macPacketLen++;
// Mark it as ready to transmit
MACFlush();
}
/*********************************************************************
* Function: static void MACSendBeacon(void)
*
* PreCondition: MACIsPutready() = TRUE
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Sends out beacon
*
* Note: Available to coordinator only
********************************************************************/
#if defined(I_AM_COORDINATOR)
static void MACSendBeacon(void)
{
// Coordinator uses extended address.
macInfo.addrMode = MAC_SRC_LONG_ADDR;
// In beacon, there is no destination address.
macCoordInfo.addrMode = MAC_DST_NO_ADDR;
MACPutHeader(&macCoordInfo, // Dest
MAC_FRAME_BEACON | // Frame Control LSB
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_NO |
MAC_INTRA_PAN_NO);
// Load beacon specific bytes into payload area.
PHYBeginTxFIFOAccess();
PHYPutTxData(SUPERFRAME_SPEC_LSB);
PHYPutTxData(SUPERFRAME_SPEC_MSB);
PHYPutTxData(GTS_FIELD_VAL);
// Pending address field - TBD
PHYPutTxData(0x00);
PHYEndTxFIFOAccess();
// Manually update packet length here instead of calling MACPut() and adding more code
// and time.
macPacketLen += 4;
MACFlush();
}
#endif
/*********************************************************************
* Function: void MACStartScan(BOOL bActiveScan)
*
* PreCondition: MACInit(), MACEnable() are called
* And MACIsPutReady() == TRUE
*
* Input: bActiveScan - flag to perform active/passive scan
*
* Output: None
*
* Side Effects: None
*
* Overview: If this is active scan, sends out beacon request
*
* Note: None
********************************************************************/
void MACStartScan(BOOL bActiveScan)
{
// Send beacon if this is active scan
if ( bActiveScan )
{
// First send out a beacon
MACSendBeaconReq();
}
// Earlier version of CC2420 (see zMAC.h for more info) has this
// bug where it would not receive beacon frame without disabling
// filter.
#if defined(CC2420_BUG1_WORKAROUND)
PHYEnableRxFilter(FALSE);
#endif
// Remember time so that we can know when to abort.
macStartTick = TickGet();
// Zero out number of discovered coordinators
PANDescCount = 0;
}
/*********************************************************************
* Function: BOOL MACIsScanComplete(void)
*
* PreCondition: MACStartScan() is called.
*
* Input: None
*
* Output: TRUE if scan is complete
* FALSE otherwise.
*
* Side Effects: None
*
* Overview: Checks to see a beacon was r
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -