📄 mrfi_radio.c
字号:
IOCFG0 = 127;
/* set default channel */
MRFI_SetLogicalChannel( 0 );
/* enable general RF interrupts */
IEN2 |= RFIE;
/* ------------------------------------------------------------------
* Final Initialization
* -----------------------
*/
/*
* Random delay - This prevents devices on the same power source from repeated
* transmit collisions on power up.
*/
Mrfi_RandomBackoffDelay();
/* enable global interrupts */
BSP_ENABLE_INTERRUPTS();
}
/**************************************************************************************************
* @fn MRFI_Transmit
*
* @brief Transmit a packet using CCA algorithm.
*
* @param pPacket - pointer to packet to transmit
*
* @return Return code indicates success or failure of transmit:
* MRFI_TRANSMIT_SUCCESS - transmit succeeded
* MRFI_TRANSMIT_CCA_FAILED - transmit failed because of CCA check(s)
**************************************************************************************************
*/
uint8_t MRFI_Transmit(mrfiPacket_t * pPacket, uint8_t txType)
{
static uint8_t dsn = 0;
uint8_t txResult;
MRFI_ASSERT( mrfiRadioIsAwake ); /* radio must be awake to transmit */
/* ------------------------------------------------------------------
* Initialize hardware for transmit
* -----------------------------------
*/
/* turn off reciever */
Mrfi_RxModeOff();
/* clear 'transmit done' interrupt flag, this bit is tested to see when transmit completes */
RFIF &= ~IRQ_TXDONE;
/* ------------------------------------------------------------------
* Populate the IEEE fields in frame
* ------------------------------------
*/
/* set the sequence number, also known as DSN (Data Sequence Number) */
pPacket->frame[MRFI_DSN_OFFSET] = dsn;
/* increment the sequence number, value is retained (static variable) for use in next transmit */
dsn++;
/*
* Populate the FCF (Frame Control Field) with the following settings.
*
* bits description setting
* --------------------------------------------------------------------------------------
* 0-2 Frame Type 001 - data frame
* 3 Security Enabled 0 - security disabled
* 4 Frame Pending 0 - no pending data
* 5 Ack Request 0 - no Ack request
* 6 PAN ID Compression 0 - no PAN ID compression
* 7 Reserved 0 - reserved
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* 8-9 Reserved 00 - reserved
* 10-11 Destination Addressing Mode 10 - PAN ID + 16-bit short address
* 12-13 Frame Version 00 - IEEE Std 802.15.4-2003
* 14-15 Source Addressing Mode 10 - PAN ID + 16-bit short address
*
*/
pPacket->frame[MRFI_FCF_OFFSET] = MRFI_FCF_0_7;
pPacket->frame[MRFI_FCF_OFFSET+1] = MRFI_FCF_8_15;
/* ------------------------------------------------------------------
* Write packet to transmit FIFO
* --------------------------------
*/
{
uint8_t txBufLen;
uint8_t * p;
uint8_t i;
/* flush FIFO of any previous transmit that did not go out */
RFST = ISFLUSHTX;
/* set point at beginning of outgoing frame */
p = &pPacket->frame[MRFI_LENGTH_FIELD_OFFSET];
/* get number of bytes in the packet (does not include the length byte) */
txBufLen = *p;
/*
* Write the length byte to the FIFO. This length does *not* include the length field
* itself but does include the size of the FCS (generically known as RX metrics) which
* is generated automatically by the radio.
*/
RFD = txBufLen + MRFI_RX_METRICS_SIZE;
/* write packet bytes to FIFO */
for (i=0; i<txBufLen; i++)
{
p++;
RFD = *p;
}
}
/* ------------------------------------------------------------------
* Immediate transmit
* ---------------------
*/
if (txType == MRFI_TX_TYPE_FORCED)
{
/* strobe transmit */
RFST = ISTXON;
/* wait for transmit to complete */
while (!(RFIF & IRQ_TXDONE));
/* transmit is guaranteed so is always successful */
txResult = MRFI_TX_RESULT_SUCCESS;
}
else
{
/* ------------------------------------------------------------------
* CCA transmit
* ---------------
*/
MRFI_ASSERT( txType == MRFI_TX_TYPE_CCA );
{
bspIState_t s;
uint8_t txActive;
uint8_t ccaRetries;
/* set number of CCA retries */
ccaRetries = MRFI_CCA_RETRIES;
/* ===============================================================================
* CCA Algorithm Loop
* ====================
*/
for (;;)
{
/* turn on receiver */
Mrfi_RxModeOn();
/*
* Wait for CCA to be valid.
* We need to wait for 20 symbol periods for this to happen:
* - 12 symbols to go from idle to rx state
* - 8 symbols to calculate the RSSI value
*/
Mrfi_DelayUsec( 20 * IEEE_USECS_PER_SYMBOL );
/*
* Initiate transmit with CCA. Command is strobed and then status is
* immediately checked. If status shows transmit is active, this means
* that CCA passed and the transmit has gone out. A critical section
* guarantees timing status check happens immediately after strobe.
*/
BSP_ENTER_CRITICAL_SECTION(s);
RFST = ISTXONCCA;
txActive = RFSTATUS & TX_ACTIVE;
BSP_EXIT_CRITICAL_SECTION(s);
/* see transmit went out */
if (txActive)
{
/* ----------| CCA Passed |---------- */
/* wait for transmit to complete */
while (!(RFIF & IRQ_TXDONE));
/* set return value for successful transmit */
txResult = MRFI_TX_RESULT_SUCCESS;
/* break out of CCA algorithm loop */
break;
}
else
{
/* ----------| CCA Failed |---------- */
/* if no CCA retries are left, transmit failed so abort */
if (ccaRetries == 0)
{
/* set return value for failed transmit */
txResult = MRFI_TX_RESULT_FAILED;
/* break out of CCA algorithm loop */
break;
}
/* decrement CCA retries before loop continues */
ccaRetries--;
/* turn off reciever to conserve power during backoff */
Mrfi_RxModeOff();
/* delay for a random number of backoffs */
Mrfi_RandomBackoffDelay();
}
}
/*
* --- end CCA Algorithm Loop ---
* =============================================================================== */
}
}
/* turn radio back off to put it in a known state */
Mrfi_RxModeOff();
/* if radio was previously on, turn it back on now */
if (mrfiRxOn)
{
Mrfi_RxModeOn();
}
/* return the result of the transmit */
return( txResult );
}
/**************************************************************************************************
* @fn MRFI_Receive
*
* @brief Copies last packet received to the location specified.
* This function is meant to be called after the ISR informs
* higher level code that there is a newly received packet.
*
* @param pPacket - pointer to location of where to copy received packet
*
* @return none
**************************************************************************************************
*/
void MRFI_Receive(mrfiPacket_t * pPacket)
{
/* copy last received packed into indicated memory */
*pPacket = mrfiIncomingPacket;
}
/**************************************************************************************************
* @fn MRFI_RxOn
*
* @brief Turn on the receiver. No harm is done if this function is called when
* receiver is already on.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void MRFI_RxOn(void)
{
MRFI_ASSERT( mrfiRadioIsAwake ); /* radio must be awake to turn on receiver */
/* if radio is off, turn it on */
if (!mrfiRxOn)
{
mrfiRxOn = 1;
Mrfi_RxModeOn();
}
}
/**************************************************************************************************
* @fn MRFI_RxIdle
*
* @brief Put radio in idle mode (receiver if off). No harm is done this function is
* called when radio is already idle.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void MRFI_RxIdle(void)
{
MRFI_ASSERT( mrfiRadioIsAwake ); /* radio must be awake for idle mode */
/* if radio is on, turn it off */
if (mrfiRxOn)
{
mrfiRxOn = 0;
Mrfi_RxModeOff();
}
}
/**************************************************************************************************
* @fn MRFI_RxIsr
*
* @brief Receive interrupt. Reads incoming packet from radio FIFO. If CRC passes the
* external function MRFI_RxCompleteISR() is called.
*
* Note : All RF interrupts use this same interrupt vector. Normally, the interrupt
* enable bits and interrupt flag bits are examined to see which interrupts need to
* be serviced. In this implementation, only the FIFOP interrupt is used. This
8 function is optimized to take advantage of that fact.
*
* @param none
*
* @return none
**************************************************************************************************
*/
BSP_ISR_FUNCTION( MRFI_RxIsr, RF_VECTOR )
{
uint8_t numBytes;
uint8_t i;
/* While there is stuff in the Rx FIFO... */
do {
/*
* Pend on frame completion. First timne through this always passes.
* Later, though, it is possible that the Rx FIFO has bytes but we
* havn't received a complete frame yet.
*/
while (!(RFIF & IRQ_FIFOP)) ;
/* Check for Rx overflow. Checking here means we may flush a valid frame */
if ((RFSTATUS & FIFOP) && (!(RFSTATUS & FIFO)))
{
/* flush receive FIFO to recover from overflow (per datasheet, flush must be done twice) */
RFST = ISFLUSHRX;
RFST = ISFLUSHRX;
break;
}
/* clear interrupt flag so we can detect another frame later. */
RFIF &= ~IRQ_FIFOP;
/* ------------------------------------------------------------------
* Read packet from FIFO
* -----------------------
*/
/*
* Determine number of bytes to be read from receive FIFO. The first byte
* has the number of bytes in the packet. A mask must be applied though
* to strip off unused bits. The number of bytes in the packet does not
* include the length byte itself but does include the FCS (generically known
* as RX metrics).
*/
numBytes = RFD & IEEE_PHY_PACKET_SIZE_MASK;
/* see if frame will fit in maximum available buffer or is too small */
if (((numBytes + MRFI_LENGTH_FIELD_SIZE - MRFI_RX_METRICS_SIZE) > MRFI_MAX_FRAME_SIZE) ||
(numBytes < MRFI_MIN_SMPL_FRAME_SIZE))
{
/* packet is too big or too small. remove it from FIFO */
for (i=0; i<numBytes; i++)
{
/* read and discard bytes from FIFO */
RFD;
}
}
else
{
uint8_t *p, *p1;
/* set pointer at first byte of frame storage */
p = &mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFFSET];
p1 = mrfiIncomingPacket.frame;
/* Clear out my buffer to remove leftovers in case a bogus packet gets through */
memset(p1, 0x0, sizeof(mrfiIncomingPacket.frame));
/*
* Store frame length into the incoming packet memory. Size of rx metrics
* is subtracted to get the MRFI frame length which separates rx metrics from
* the frame length.
*/
*p = numBytes - MRFI_RX_METRICS_SIZE;
/* read frame bytes from receive FIFO and store into incoming packet memory */
for (i=0; i<numBytes-MRFI_RX_METRICS_SIZE; i++)
{
p++;
*p = RFD;
}
/* read rx metrics and store to incoming packet */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -