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

📄 zmac.c

📁 zigbee精简协议栈代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#include "zMAC.h"


#if defined(I_AM_END_DEVICE)
	static SM_ASSOCIATION   smAssociation;

	// Running count of transmit retries used to association/disassociation
	BYTE                    macFrameRetryCount;
#endif

// MAC Module state info.
MAC_STATE               macState;

// Potential coordinator description - used when Associate process is started.
PAN_DESC                PANDesc;

// Number of coordinators found operating in radius.
BYTE                    PANDescCount;

// Current channel of operation.
BYTE                    macCurrentChannel;

// Running counter of MAC frame DSN.
BYTE                    macDSN;

BYTE                    lastMACDSN;

// Length of transmit packet that is being current loaded.
BYTE                    macPacketLen;

// MAC address info.
NODE_INFO               macInfo;

// Coordinator address info.
NODE_INFO               macCoordInfo;

// A temp NODE_INFO to store out going commands from the MAC layer
NODE_INFO               macDestInfo;

// RF channel energy as of last energy scan.
BYTE                    macCurrentEnergy;

// Current MAC frame header.
MAC_HEADER               macCurrentFrame;

// Array of recently transmitted frames that are yet to be acknowledged
// by remote nodes.
MAC_FRAME_STATUS        macFrameStatusQ[MAX_MAC_FRAME_STATUS];

BYTE                    macFrameStatusQLen;

// Tick value used to calculate timeout conditions.
TICK                    macStartTick;

// Handle to a frame - used by many command state machines
HFRAME                  hFrame;

#define PHYBeginTxFIFOAccess()      { PHYBegin(); PHYSelectTxFIFO(); }
#define PHYEndTxFIFOAccess()        PHYEnd()
#define PHYPutTxData(v)             PHYPut(v)

static HFRAME   AddDSNInQueue(BYTE dsn);

static void     UpdateQueue(BYTE dsn);

static void     TransmitIt(void);

static BOOL     MACGetHeader(void);

static void     MACSendBeaconReq(void);

static void     MACSendBeacon(void);

static BOOL     MACProcessBeacon(void);

static void     MACSendAck(ACK_TYPE ack);

// Only coordinator will process orphan notice.
// A orphan notice is said to be valid if there is no data bytes in addition to
// the command identifier itself.
#define MACProcessOrphanNotice()        (macCurrentFrame.frameLength == 0)

/*********************************************************************
 * Function:        void MACInit(void)
 *
 * PreCondition:    macInfo.longAddr must be initialized with
 *                  desired MAC address.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Initializes data variables used by MAC module.
 *
 * Note:            None
 ********************************************************************/
void MACInit(void)
{
    
    memset((void*)macFrameStatusQ, 0x00, sizeof(macFrameStatusQ));
    macFrameStatusQLen = 0;

    macCurrentFrame.Flags.Val = 0x00;
    macState.Val = 0x00;
	
	//du 读取地址	
	GetMACShortAddress(&macInfo.shortAddr);
	GetMACAddress(&macInfo.longAddr);

    //du 初始PAN ID = 0xffff
    MACSetPANIdLSB(0xff);
    MACSetPANIdMSB(0xff);

}

BOOL MACIsIdle()
{
	return (MACIsPutReady() && (macFrameStatusQLen == 0));
} 

/*********************************************************************
 * Function:        void MACEnable(void)
 *
 * PreCondition:    macInfo.longAddr must be initialized with
 *                  desired MAC address.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Enables PHY regulator and registers.
 *
 * Note:            None
 ********************************************************************/
void MACEnable(void)
{
    // Power up the PHY's internal regulator
    PHYEnable();

    // Initialize the PHY's registers/wait for it's oscillator to
    // become stable.  In the event the PHY malfunctions for too long
    // the watchdog timer will cause a reset to occur here.
    while( !PHYInit() );

    MACUpdateAddressInfo();

    PHYSetChannel(PHYGetChannel());

    macState.bits.bIsEnabled = TRUE;
}

/*********************************************************************
 * Function:        void MACISR(void)
 *
 * PreCondition:    MACInit() is previously called.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Determines if a frame has completed transmission
 *                  or not.
 *
 * Note:            None
 ********************************************************************/
void MACISR(void)
{  
	if ( macState.bits.bIsTxBusy )
         macState.bits.bIsTxBusy = FALSE;
 }   

/*********************************************************************
 * Function:        BYTE MACGet(void)
 *
 * PreCondition:    MACIsGetReady() == TRUE
 *
 * Input:           None
 *
 * Output:          Byte that was read
 *
 * Side Effects:    None
 *
 * Overview:        Retrives one bytes from RF RX buffer.
 *
 * Note:            Caller must make sure that RX buffer contains
 *                  at least one byte calling MACIsGetReady()
 ********************************************************************/
BYTE MACGet(void)
{
    BYTE v;

    // Start PHY RX buffer access.
    PHYBegin();
    PHYSelectRxFIFO();
    v = PHYGet();
    PHYEnd();

    // Update current frame length.
    macCurrentFrame.frameLength--;

    // Now return it.
    return v;
}

/*********************************************************************
 * Function:        void MACPutArray(BYTE *v, BYTE len)
 *
 * PreCondition:    MACIsPutReady() == TRUE
 *
 * Input:           b       - Buffer that is to be loaded.
 *                  len     - Number of bytes to get
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Loads given bytes into RF TX buffer.
 *
 * Note:            None
 ********************************************************************/
void MACPutArray(BYTE *v, BYTE len)
{
    // Start RX TX buffer access.
    PHYBeginTxFIFOAccess();

    // Copy all given bytes into TX buffer.
    while( len-- )
    {
        PHYPutTxData(*v);

        v++;

        // Keep count of current TX frame length.
        macPacketLen++;
    }

    // Conclude RX TX buffer access.
    PHYEndTxFIFOAccess();
}

/*********************************************************************
 * Function:        BOOL MACIsPutReady(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Determines if it is okay to load new tx frame
 *                  into RF TX buffer.
 *
 * Note:            None
 ********************************************************************/
BOOL MACIsPutReady(void)
{
    // The transmitter is said to be ready when
    // 1. It has finished previous transmission,
    // 2. We are part of a network
    // 3. Enabled.
    // 4. Ack queue is not full.
    return (macState.bits.bIsTxBusy == FALSE    &&
            macState.bits.bIsAssociated == TRUE &&
            macState.bits.bIsEnabled == TRUE &&
            macFrameStatusQLen < MAX_MAC_FRAME_STATUS);
}

/*********************************************************************
 * Function:        void MACPut(BYTE v)
 *
 * PreCondition:    MACIsPutReady() == TRUE
 *
 * Input:           v       - A byte to put
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Copies given byte into RF TX buffer and increments
 *                  write pointer.
 *
 * Note:            None
 ********************************************************************/
void MACPut(BYTE v)
{
    // Put given byte into TXFIFO
    PHYBeginTxFIFOAccess();
    PHYPutTxData(v);
    PHYEndTxFIFOAccess();

    // Maintain length so that we update header.
    macPacketLen++;
}

/*********************************************************************
 * Function:        HFRAME MACFlush(void)
 *
 * PreCondition:    MACIsPutReady() == TRUE and
 *                  a valid TX frame is constructured using
 *                  MACPutHeader() and MACPut()
 *
 * Input:           None
 *
 * Output:          HFRAME_INVALID if an Ack wasn't requested or the
 *                  DSN queue was full. Otherwise, the handle to the
 *                  DSN queue entry is returned which can later be
 *                  used when the Ack frame arrives.
 *
 * Side Effects:    None
 *
 * Overview:        Sets the tx frame length, marks the tx frame
 *                  as ready to be transmitted.
 *                  If this frame requires ack from remote node,
 *                  an entry is made into DSN queue so that
 *                  we can match future ACK with this frame.
 *
 * Note:            None
 ********************************************************************/
HFRAME MACFlush(void)
{
    hFrame = HFRAME_INVALID;

    // Remember that current message is in transmit buffer.
    macState.bits.bIsTxBusy = TRUE;

    if ( macCurrentFrame.Flags.bits.bToBeQueued )
        hFrame = AddDSNInQueue(macDSN);

    macCurrentFrame.Flags.bits.bToBeQueued = FALSE;

    // First, update the packet length.
    PHYBegin();

    PHYSelectTxRAM();

    PHYPut(macPacketLen);

    // Terminate RAM access
    PHYEnd();

    // Now transmit it.
    TransmitIt();

    // Forget packet length.
    macPacketLen = 0;

    return hFrame;
}

static void TransmitIt(void)
{
    BYTE v;
    BYTE backOffCycles;

    // Wait until transceiver is idle
    //while( !PHYIsIdle() );

    // To creat randomness in initial backoff, we will use
    // LSB of current tick counter.
    backOffCycles = (BYTE)TickGet();

    // Remember that a message is being transmitted.
    macState.bits.bIsTxBusy = TRUE;

    // Turn on RX
    PHYSetTRXState(PHY_TRX_RX_ON);
	
    // Wait for RSSI to become valid
    PHYBegin();
    do
    {
        PHYPut(STROBE_SNOP);
        v = PHYGet();
        if ( v & 0x02 )
            break;
    } while(1);
    PHYEnd();

    PHYBegin();
    do
    {
        PHYTx();
        v = PHYGet();


        PHYPut(STROBE_SNOP);
        v = PHYGet();


        // If transmission was started, break out of this loop.
        if ( v & 0x08 )
            break;


        //TODO(DF9): CSMA-CA back-off needed
        // Else, need to back-off - not quite IEEE compliant.
        backOffCycles <<= 1;

        // Reinitialize backoff time if we reach 0 or 0xff value.
        if ( backOffCycles == 0x00 || backOffCycles == 0xff )
            backOffCycles = (BYTE)TickGet();

        // Now wait until backoff cycles expire.
        v = backOffCycles;
        while( v-- );

    } while( 1 );
    PHYEnd();


    // Tell application that we have just transmitted a frame.
    AppMACFrameTransmitted();
}

/*********************************************************************
 * Function:        void MACUpdateTimeoutFlags( void )
 *
 * PreCondition:    MACInit() is called
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    Frame timeout flags are updated
 *
 * Overview:        This function goes through the frame queue and
 *                  checks each frame that is currently waiting for
 *                  an acknowledge to see if it has timed out.  It
 *                  then calls the application call-back.
 *
 * Note:            None
 ********************************************************************/
void MACUpdateTimeoutFlags( void )
{
    BYTE i;
    MAC_FRAME_STATUS *pMACFrameStatus;

    pMACFrameStatus = macFrameStatusQ;
    for ( i = 0; i < sizeof(macFrameStatusQ)/sizeof(macFrameStatusQ[0]); i++, pMACFrameStatus++ )
    {
        if ( pMACFrameStatus->Flags.bits.bIsInUse )
        {
            if ( !pMACFrameStatus->Flags.bits.bIsConfirmed )
            {
                if ( TickGetDiff(TickGet(), pMACFrameStatus->lastTick) >= MAC_ACK_WAIT_DURATION )
                {
                    pMACFrameStatus->Flags.bits.bIsTimedOut = TRUE;

⌨️ 快捷键说明

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