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

📄 zmac_receive.c

📁 通过cc2420+pic实现无线通信
💻 C
📖 第 1 页 / 共 5 页
字号:
BYTE MACGet(void)
{
    BYTE v;

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

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

    // Now return it.
    return v;
}

/*********************************************************************
 * Function:        void MACCopyRxPacketToRx(void)
 *
 * PreCondition:    MACIsGetReady() == TRUE &&
 *                  MACIsPutReady() == TRUE
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Copies remaining RX data bytes into current
 *                  TX buffer.
 *
 * Note:            None
 ********************************************************************/
void MACCopyRxPacketToTx(void)
{
    // Copy reminaing RX to TX buffer.
    while( macCurrentFrame.frameLength )
        MACPut(MACGet());
}

/*********************************************************************
 * 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:        void MACTxFrameEnqeue(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Enqueues current tx frame to tx indirect buffer.
 *
 * Note:            This function is available when MAC_USE_TX_INDIRECT_BUFFER
 *                  is defined (i.e. Coordinator mode)
 ********************************************************************/
#if defined(MAC_USE_TX_INDIRECT_BUFFER)
void MACTxFrameEnqueue(void)
{
    // Set frame length into current tx state buffer.
    *(txIndirectBuffer[currentTxIndirectBuffer].pBuffer) = macPacketLen;

    // Remember when we enqueue this frame so that we can discard it if it
    // were to stay for long time.
    txIndirectBuffer[currentTxIndirectBuffer].lastTick = TickGet();

    // Remember current macDSN for this queued frame so that we can match its ACK
    txIndirectBuffer[currentTxIndirectBuffer].frameDSN = macDSN;

    // Once we finish loading tx indirect buffer,
    // reset the setting so that next tx operation
    // will be on RF chip buffer unless explictly changed by caller.
    macState.bits.bUseTxRAM = FALSE;

}
#endif


/*********************************************************************
 * 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();

#if defined(WIN32)
        break;
#else
        PHYPut(STROBE_SNOP);
        v = PHYGet();


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

        // 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:        static void _MACIndirectTransmit(
 *                          TX_INDIRECT_BUFFER *pIndirectTxBuffer)
 *
 * PreCondition:    None
 *
 * Input:           pIndirectTxBuffer - pointer to the frame in
 *                                      txIndirectBuffer to transmit
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Transmits current indirect tx buffer
 *
 * Note:            None
 ********************************************************************/
#if defined(MAC_USE_TX_INDIRECT_BUFFER)
static void _MACIndirectTransmit(TX_INDIRECT_BUFFER *pIndirectTxBuffer)
{
    // Get the frame length from the buffer.
    pCurrentTxIndirectData = pIndirectTxBuffer->pBuffer;
    macPacketLen = *pCurrentTxIndirectData++;

    // Clear TXFIFO
    PHYBegin();
    PHYFlushTx();
    PHYEnd();

    // Load the entire frame starting from the frame length byte.
    PHYBegin();
    PHYSelectTxFIFO();

    PHYPut(macPacketLen);

    // macPacketLen includes the two checksum bytes. Since checksum bytes
    // are automatically generated by the RF chip, we will reduce macPacketLen
    // by two and let RF chip stuff checksum byte at the end.
    macPacketLen -= 2;

    // Load entire frame into RF chip buffer.
    while( macPacketLen-- )
    {
        PHYPut(*pCurrentTxIndirectData++);
    };

    PHYEnd();

    // A indirect frame may be transmitted multiple times.
    // If this is the first time, add that in DSN queue and remember
    // the queue handle so that we can check for ack status for this frame.
    if ( !pIndirectTxBuffer->Flags.bIsSent )
    {
        pIndirectTxBuffer->Flags.hFrame =
            AddDSNInQueue(pIndirectTxBuffer->frameDSN);

        // Remember that this frame is transmitted at least once.
        pIndirectTxBuffer->Flags.bIsSent = TRUE;
    }

    // Remember when we transmitted this so that we can determine when to
    // discard it if we do not receive any ack.
//TODO: HS - I think this is redundant information.  A tick count is stored in macFrameStatusQ[pIndirectTxBuffer->Flags.hFrame] as well.
    pIndirectTxBuffer->lastTick = TickGet();

    // Decrement the transmit attempt counter so that we can determine
    // when to discard it if we never receive an ack.
    macFrameStatusQ[pIndirectTxBuffer->Flags.hFrame].retryCount--;

    // Now transmit it.
    TransmitIt();

    // Forget packet length.
    macPacketLen = 0;
}
#endif



/*********************************************************************
 * Function:        BOOL MACTask(void)
 *
 * PreCondition:    MACInit() is called
 *
 * Input:           None
 *
 * Output:          TRUE        - If Processing is complete
 *                  FALSE       - If further processing is required
 *
 * Side Effects:    None
 *
 * Overview:        If previous frame is processed, it checks
 *                  for new RX frame.
 *                  Fetches the header and determiens if it is valid
 *                  Automatically sends ACK if remote node has
 *                  requested it.
 *                  Also performs some other automatic processing
 *                  based on the frame type.
 *                  If there is no frame in buffer, it goes through
 *                  DSN queue and calculates timeout for unack'ed
 *                  TX frames.
 *
 * Note:            This function must be called as many times as
 *                  possible to keep handling MAC frames.
 ********************************************************************/
BOOL MACTask(void)
{
    MAC_FRAME_STATUS *pCurrentFrame;

    // If there was an overflow, handle it.
    // Since this is a half-duplex and the way CC2420 indicates RX FIFO OVERFLOW,
    // check for overflow condition only when RF is not actively transmitting a packet.
    if ( macState.bits.bIsTxBusy == FALSE )
    {
        if ( PHYProcessRxOverflow() )
        {
            DEBUG_OUT("MAC: A receive overflow was detected and removed.\r\n");
        }
    }


    // Do not process any new frame until current one is all processed.
    if ( MACIsGetReady() )
        return TRUE;

    // Continue only if there is a new frame in buffer.
    if ( !_MACIsGetReady() )
    {

        // Get pointer to current frame that we want to operate on.
        pCurrentFrame = &macFrameStatusQ[currentQueueItem];

        // Now prepare for next item.
        currentQueueItem++;

        // Wrap the number if we reached the end of queue.

⌨️ 快捷键说明

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