/************************************************************************************************** * @fn MRFI_EnableRxAddrFilter * * @brief Enable received packet filtering. * * @param none * * @return none ************************************************************************************************** */ void MRFI_EnableRxAddrFilter(void) { MRFI_ASSERT( (PAN_ID0 != 0xFF) && (PAN_ID1 != 0xFF) ); /* filter address not set */ /* enable hardware filtering on the radio */ FRMFILT0 |= FRAME_FILTER_EN; }
/************************************************************************************************** * @fn MRFI_SetLogicalChannel * * @brief Set logical channel. * * @param chan - logical channel number * * @return none ************************************************************************************************** */ void MRFI_SetLogicalChannel(uint8_t chan) { uint8_t phyChannel; /* logical channel is not valid */ MRFI_ASSERT( chan < MRFI_NUM_LOGICAL_CHANS ); /* make sure radio is off before changing channels */ Mrfi_RxModeOff(); /* convert logical channel number into physical channel number */ phyChannel = mrfiLogicalChanTable[chan]; /* write frequency value of new channel */ mrfiSpiWriteReg(FREQCTRL, (FREQCTRL_BASE_VALUE + (FREQCTRL_FREQ_2405MHZ + 5 * ((phyChannel) - 11)))); /* remember this. need it when waking up. */ mrfiCurrentLogicalChannel = chan; /* Put the radio back in RX state, if it was in RX before channel change */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_EnableRxAddrFilter * * @brief Enable received packet filtering. * * @param none * * @return none ************************************************************************************************** */ void MRFI_EnableRxAddrFilter(void) { MRFI_ASSERT( (PANIDL != 0xFF) && (PANIDH != 0xFF) ); /* filter address not set */ /* enable hardware filtering on the radio */ MDMCTRL0H |= ADDR_DECODE; }
/************************************************************************************************** * @fn MRFI_EnableRxAddrFilter * * @brief Enable received packet filtering. * * @param none * * @return none ************************************************************************************************** */ void MRFI_EnableRxAddrFilter(void) { MRFI_ASSERT(mrfiRxFilterAddr[0] != mrfiBroadcastAddr[0]); /* filter address must be set before enabling filter */ /* set flag to indicate filtering is enabled */ mrfiRxFilterEnabled = 1; /* enable hardware filtering on the radio */ MRFI_WRITE_REGISTER( PKTCTRL1, PKTCTRL1_ADDR_FILTER_ON ); }
/************************************************************************************************** * @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) { /* radio must be powered ON before we can move it to RX state */ MRFI_ASSERT( mrfiRadioState != MRFI_RADIO_STATE_OFF ); /* Put the radio in RX state, if not already */ if(mrfiRadioState != MRFI_RADIO_STATE_RX) { mrfiRadioState = MRFI_RADIO_STATE_RX; Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_RxIdle * * @brief Put radio in idle mode (receiver is off). No harm is done if * this function is called when radio is already idle. * * @param none * * @return none ************************************************************************************************** */ void MRFI_RxIdle(void) { /* radio must be powered ON to move it to idle mode */ MRFI_ASSERT( mrfiRadioState != MRFI_RADIO_STATE_OFF ); /* if radio is on, turn it off */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOff(); mrfiRadioState = MRFI_RADIO_STATE_IDLE; } }
/************************************************************************************************** * @fn MRFI_EnableRxAddrFilter * * @brief Enable received packet filtering. * * @param none * * @return none ************************************************************************************************** */ void MRFI_EnableRxAddrFilter(void) { MRFI_ASSERT( mrfiAddrFilterStatus & MRFI_FILTER_ADDRESS_SET ); /* filter address not set */ mrfiAddrFilterStatus |= MRFI_FILTER_ADDRESS_ENABLED; /* Can access radio only if it is not OFF */ if(mrfiRadioState != MRFI_RADIO_STATE_OFF) { /* enable hardware filtering on the radio */ mrfiSpiBitSet(FRMFILT0, 0); } }
/************************************************************************************************** * @fn MRFI_Rssi * * @brief Returns "live" RSSI value * * @param none * * @return RSSI value in units of dBm. ************************************************************************************************** */ int8_t MRFI_Rssi(void) { /* Radio must be in RX state to measure rssi. */ MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX ); /* Wait for the RSSI to be valid: * Just having the Radio ON is not enough to read * the correct RSSI value. The Radio must in RX mode for * a certain duration. */ MRFI_RSSI_VALID_WAIT(); /* Read and convert RSSI to decimal and do offset compensation. */ return( Mrfi_CalculateRssi(mrfiSpiReadReg(RSSI)) ); }
/************************************************************************************************** * @fn MRFI_SetRFPwr * * @brief Set RF Output power level. * * @param idx - index into power table. * * @return none ************************************************************************************************** */ void MRFI_SetRFPwr(uint8_t idx) { /* is power level specified valid? */ MRFI_ASSERT( idx < MRFI_NUM_POWER_SETTINGS ); /* make sure radio is off before changing power levels */ Mrfi_RxModeOff(); MRFI_WRITE_REGISTER( PA_TABLE0, mrfiRFPowerTable[idx] ); /* turn radio back on if it was on before power level change */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_SetLogicalChannel * * @brief Set logical channel. * * @param chan - logical channel number * * @return none ************************************************************************************************** */ void MRFI_SetLogicalChannel(uint8_t chan) { /* logical channel is not valid? */ MRFI_ASSERT( chan < MRFI_NUM_LOGICAL_CHANS ); /* make sure radio is off before changing channels */ Mrfi_RxModeOff(); MRFI_WRITE_REGISTER( CHANNR, mrfiLogicalChanTable[chan] ); /* turn radio back on if it was on before channel change */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_SetRFPwr * * @brief Set RF pwoer level. * * @param idx - index into power level table * * @return none ************************************************************************************************** */ void MRFI_SetRFPwr(uint8_t idx) { /* is power level specified valid? */ MRFI_ASSERT( idx < MRFI_NUM_POWER_SETTINGS ); /* make sure radio is off before changing power levels */ Mrfi_RxModeOff(); /* write value of new power level */ TXCTRLL = mrfiRFPowerTable[idx]; /* Put the radio back in RX state, if it was in RX before change */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_SetRFPwr * * @brief Set RF power level. * * @param idx - index into power level table * * @return none ************************************************************************************************** */ void MRFI_SetRFPwr(uint8_t idx) { /* is power level specified valid? */ MRFI_ASSERT( idx < MRFI_NUM_POWER_SETTINGS ); /* make sure radio is off before changing power level */ Mrfi_RxModeOff(); /* write value of new power level */ mrfiSpiWriteReg(TXPOWER, mrfiRFPowerTable[idx]); /* remember this. need it when waking up. */ mrfiCurrentPowerLevel = idx; /* Put the radio back in RX state, if it was in RX before change */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_SetLogicalChannel * * @brief Set logical channel. * * @param chan - logical channel number * * @return none ************************************************************************************************** */ void MRFI_SetLogicalChannel(uint8_t chan) { uint8_t phyChannel; /* logical channel is not valid */ MRFI_ASSERT( chan < MRFI_NUM_LOGICAL_CHANS ); /* make sure radio is off before changing channels */ Mrfi_RxModeOff(); /* convert logical channel number into physical channel number */ phyChannel = mrfiLogicalChanTable[chan]; /* write frequency value of new channel */ FREQCTRL = FREQ_2405MHZ + (5 * (phyChannel - 11)); /* Put the radio back in RX state, if it was in RX before channel change */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } }
/************************************************************************************************** * @fn MRFI_Rssi * * @brief Returns "live" RSSI value * * @param none * * @return RSSI value in units of dBm. ************************************************************************************************** */ int8_t MRFI_Rssi(void) { int8_t rssi; /* Radio must be in RX state to measure rssi. */ MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX ); /* * Assuming that the Radio was just turned on, we must wait for * RSSI to be valid. */ MRFI_RSSI_VALID_WAIT(); /* read RSSI value from hardware */ rssi = RSSI; /* apply offset given in datasheet */ rssi = rssi + MRFI_RSSI_OFFSET; /* return RSSI value */ return( rssi ); }
/************************************************************************************************** * @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_TX_RESULT_SUCCESS - transmit succeeded * MRFI_TX_RESULT_FAILED - transmit failed because CCA failed ************************************************************************************************** */ uint8_t MRFI_Transmit(mrfiPacket_t * pPacket, uint8_t txType) { static uint8_t dsn = 0; uint8_t txResult = MRFI_TX_RESULT_SUCCESS; /* radio must be awake to transmit */ MRFI_ASSERT( mrfiRadioState != MRFI_RADIO_STATE_OFF ); /* ------------------------------------------------------------------ * Initialize hardware for transmit * ----------------------------------- */ /* turn off reciever */ Mrfi_RxModeOff(); /* clear 'transmit done' interrupt flag, this bit is tested to see when transmit completes */ RFIRQF1 &= ~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 (!(RFIRQF1 & IRQ_TXDONE)); /* transmit is done */ } 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 the receiver to perform CCA. Can not call Mrfi_RxModeOn(), * since that will enable the rx interrupt, which we do not want. */ RFST = ISRXON; /* * Wait for CCA to be valid. */ MRFI_RSSI_VALID_WAIT(); /* * 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 = FSMSTAT1 & SAMPLED_CCA; BSP_EXIT_CRITICAL_SECTION(s); /* see transmit went out */ if (txActive) { /* ----------| CCA Passed |---------- */ /* wait for transmit to complete */ while (!(RFIRQF1 & IRQ_TXDONE)); /* transmit is done. 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 the radio was in RX state when transmit was attempted, * put it back in RX state. */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } /* return the result of the transmit */ return( txResult ); }
/************************************************************************************************** * @fn MRFI_RxIsr * * @brief Receive interrupt. Reads incoming packet from radio FIFO. If CRC passes the * external function MRFI_RxCompleteISR() is called. * * @param none * * @return none ************************************************************************************************** */ BSP_ISR_FUNCTION( MRFI_RxIsr, RF_VECTOR ) { uint8_t numBytes; uint8_t i, crcOK; /* Clear the MCU interrupt. */ S1CON = 0x00; /* Process FIFOP interrupt */ if(RFIF & IRQ_FIFOP) { /* We should receive this interrupt only in RX state * Should never receive it if RX was turned On only for * some internal mrfi processing like - during CCA. * Otherwise something is terribly wrong. */ MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX ); /* While there is at least one frame in the Rx FIFO */ 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) */ MRFI_RADIO_FLUSH_RX_BUFFER(); break; } /* ------------------------------------------------------------------ * 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 */ /* Add the RSSI offset to get the proper RSSI value. */ mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] = RFD + MRFI_RSSI_OFFSET; /* The second byte has 7 bits of Correlation value and 1 bit of * CRC pass/fail info. Remove the CRC pass/fail bit info. * Also note that for CC2430 radio this is the correlation value and not * the LQI value. Some convertion is needed to extract the LQI value. * This convertion is left to the application at this time. */ crcOK = RFD; /* get CRC/LQI byte */ if (crcOK & MRFI_RX_METRICS_CRC_OK_MASK) { /* CRC OK. Save LQI info */ mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] = (crcOK & MRFI_RX_METRICS_LQI_MASK); /* Eliminate frames that are the correct size but we can tell are bogus * by their frame control fields. */ if ((p1[MRFI_FCF_OFFSET] == MRFI_FCF_0_7) && (p1[MRFI_FCF_OFFSET+1] == MRFI_FCF_8_15)) { /* call external, higher level "receive complete" */ MRFI_RxCompleteISR(); } } } /* Frame fits in the buffer. */ /* Clear the interrupt source flag. This must be done after reading * the frame from the buffer. Otherwise the flag remains set. If another * frame is sitting in the buffer, the IRQ_FIFOP will be immediately set * again. */ RFIF &= ~IRQ_FIFOP; } /* While there is at least one frame in the Rx FIFO */ } /* Process FIFOP interrupt */ else { /* Don't assert here. It is possible that the MCU interrupt was set by * FIFOP but we processed it in the while() loop of the FIFOP handler in * the previous run of this ISR. */ /* If any other RF interrupt is enabled, add that handler here. */ } /* Bugzilla Chip Bug#297: Don't delete */ RFIF = 0xFF; }
/************************************************************************************************** * @fn MRFI_Transmit * * @brief Transmit a packet. * * @param pPacket - pointer to packet to transmit * txType - FORCED or CCA * * @return Return code indicates success or failure of transmit: * MRFI_TX_RESULT_SUCCESS - transmit succeeded * MRFI_TX_RESULT_FAILED - transmit failed because CCA failed ************************************************************************************************** */ uint8_t MRFI_Transmit(mrfiPacket_t * pPacket, uint8_t txType) { uint8_t txResult = MRFI_TX_RESULT_SUCCESS; static uint8_t dsn = 0; /* radio must be awake to transmit */ MRFI_ASSERT( mrfiRadioState != MRFI_RADIO_STATE_OFF ); /* TX_DONE line status must be low. If high, some state logic problem. */ MRFI_ASSERT(!MRFI_TX_DONE_STATUS()); /* Turn off reciever. We ignore/drop incoming packets during transmit. */ Mrfi_RxModeOff(); /* -------------------------------------- * Populate the IEEE fields in frame * ------------------------------------ */ /* set the sequence number, also known as DSN (Data Sequence Number) */ pPacket->frame[MRFI_DSN_OFFSET] = dsn++; 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 frameLen; uint8_t *p; /* flush FIFO of any previous transmit that did not go out */ MRFI_RADIO_FLUSH_TX_BUFFER(); /* 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. */ frameLen = txBufLen + MRFI_RX_METRICS_SIZE; mrfiSpiWriteTxFifo(&frameLen, 1); /* skip the length field which we already sent to FIFO. */ p++; /* write packet bytes to FIFO */ mrfiSpiWriteTxFifo(p, txBufLen); } /* Forced transmit */ if(txType == MRFI_TX_TYPE_FORCED) { /* NOTE: Bug (#1) described in the errata swrz024.pdf for CC2520: * We never strobe TXON when the radio is in receive state. * If this is changed, must implement the bug workaround as described in the * errata (flush the Rx FIFO). */ /* strobe transmit */ mrfiSpiCmdStrobe(STXON); /* wait for transmit to complete */ while (!MRFI_TX_DONE_STATUS()); /* Clear the TX_FRM_DONE exception flag register in the radio. */ mrfiSpiBitClear(EXCFLAG0, 1); } else /* CCA Transmit */ { /* set number of CCA retries */ uint8_t ccaRetries = MRFI_CCA_RETRIES; MRFI_ASSERT( txType == MRFI_TX_TYPE_CCA ); /* ====================================================================== * CCA Algorithm Loop * ====================================================================== */ while(1) { /* Turn ON the receiver to perform CCA. Can not call Mrfi_RxModeOn(), * since that will enable the rx interrupt, which we do not want. */ mrfiSpiCmdStrobe(SRXON); /* Wait for RSSI to be valid. */ MRFI_RSSI_VALID_WAIT(); /* Request transmit on cca */ mrfiSpiCmdStrobe(STXONCCA); /* If sampled CCA is set, transmit has begun. */ if(MRFI_SAMPLED_CCA()) { /* wait for transmit to complete */ while( !MRFI_TX_DONE_STATUS() ); /* Clear the TX_FRM_DONE exception flag register in the radio. */ mrfiSpiBitClear(EXCFLAG0, 1); /* transmit is done. break out of CCA algorithm loop */ break; } else { /* ------------------------------------------------------------------ * Clear Channel Assessment failed. * ------------------------------------------------------------------ */ /* Retry ? */ if(ccaRetries != 0) { /* turn off reciever to conserve power during backoff */ Mrfi_RxModeOff(); /* delay for a random number of backoffs */ Mrfi_RandomBackoffDelay(); /* decrement CCA retries before loop continues */ ccaRetries--; } else /* No CCA retries left, abort */ { /* set return value for failed transmit and break */ txResult = MRFI_TX_RESULT_FAILED; break; } } } /* End CCA Algorithm Loop */ } /* turn radio back off to put it in a known state */ Mrfi_RxModeOff(); /* If the radio was in RX state when transmit was attempted, * put it back in RX state. */ if(mrfiRadioState == MRFI_RADIO_STATE_RX) { Mrfi_RxModeOn(); } /* return the result of the transmit */ return( txResult ); }
/************************************************************************************************** * @fn MRFI_Init * * @brief Initialize MRFI. * * @param none * * @return none ************************************************************************************************** */ void MRFI_Init(void) { /* Configure Output lines */ MRFI_CONFIG_RESETN_PIN_AS_OUTPUT(); MRFI_CONFIG_VREG_EN_PIN_AS_OUTPUT(); /* Configure Input lines */ MRFI_CONFIG_TX_FRAME_DONE_AS_INPUT(); MRFI_CONFIG_FIFO_AS_INPUT(); MRFI_CONFIG_FIFOP_AS_INPUT(); /* Initialize SPI */ mrfiSpiInit(); /* Power up the radio chip */ Mrfi_TurnOnRadioPower(); /* Confirm that we are talking to the right hardware */ MRFI_ASSERT(mrfiSpiReadReg(CHIPID) == MRFI_RADIO_PARTNUM); /* Random Number Generator: * The seed value for the randon number generator logic * is derived from the radio. */ /* Set radio in rx mode, but with symbol search disabled. Used for RSSI * measurments or when we don't care about the received frames. */ mrfiSpiWriteReg(FRMCTRL0, FRMCTRL0_RESET_VALUE | RX_MODE_RSSI_ONLY); /* Turn on the receiver */ mrfiSpiCmdStrobe(SRXON); /* * Wait for RSSI to be valid. RANDOM command strobe can be used * to generate random number only after this. */ MRFI_RSSI_VALID_WAIT(); /* Get random byte from the radio */ mrfiRndSeed = mrfiSpiRandomByte(); /* * The seed value must not be zero. If it is, the pseudo random sequence * will be always be zero. There is an extremely small chance this seed could * randomly be zero (more likely some type of hardware problem would cause * this). If it is zero, initialize it to something. */ if(mrfiRndSeed == 0) { mrfiRndSeed = 0x80; } /* Random number initialization is done. Turn the radio off */ Mrfi_TurnOffRadioPower(); /* Initial radio state is - OFF state */ mrfiRadioState = MRFI_RADIO_STATE_OFF; /********************************************************************************** * Compute reply delay scalar * * The IEEE radio has a fixed data rate of 250 Kbps. Data rate inference * from radio regsiters is not necessary for this radio. * * The maximum delay needed depends on the MAX_APP_PAYLOAD parameter. Figure * out how many bits that will be when overhead is included. Bits/bits-per-second * is seconds to transmit (or receive) the maximum frame. We multiply this number * by 1000 to find the time in milliseconds. We then additionally multiply by * 10 so we can add 5 and divide by 10 later, thus rounding up to the number of * milliseconds. This last won't matter for slow transmissions but for faster ones * we want to err on the side of being conservative and making sure the radio is on * to receive the reply. The semaphore monitor will shut it down. The delay adds in * a fudge factor that includes processing time on peer plus lags in Rx and processing * time on receiver's side. * * ********************************************************************************** */ #define PLATFORM_FACTOR_CONSTANT 2 #define PHY_PREAMBLE_SYNC_BYTES 8 { uint32_t bits, dataRate = 250000; bits = ((uint32_t)((PHY_PREAMBLE_SYNC_BYTES + MRFI_MAX_FRAME_SIZE)*8))*10000; /* processing on the peer + the Tx/Rx time plus more */ sReplyDelayScalar = PLATFORM_FACTOR_CONSTANT + (((bits/dataRate)+5)/10); } /* Random delay: This prevents devices on the same power source from repeated * transmit collisions on power up. */ Mrfi_RandomBackoffDelay(); BSP_ENABLE_INTERRUPTS(); }
/************************************************************************************************** * @fn Mrfi_FiFoPIsr * * @brief Interrupt Service Routine for handling FIFO_P event. * * @param none * * @return none ************************************************************************************************** */ void Mrfi_FiFoPIsr(void) { uint8_t numBytes; uint8_t i; /* NOTE: Bug #2 described in the errata swrz024.pdf for CC2520: * There is a possiblity of small glitch in the fifo_p signal * (2 cycle of 32 MHz). Workaround is to make sure that fifo_p signal stays * high for longer than that. Else, it is a false alarm. */ if(!MRFI_FIFOP_STATUS()) return; if(!MRFI_FIFOP_STATUS()) return; /* Ah... it is for real... Continue processing. */ /* We should receive this interrupt only in RX state * Should never receive it if RX was turned ON only for * some internal mrfi processing like - during CCA. * Otherwise something is terribly wrong. */ MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX ); do { /* * Pend on frame rx completion. First time 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( !MRFI_FIFOP_STATUS() ); /* Check for Rx overflow. Checking here means we may flush a valid frame */ if( MRFI_FIFOP_STATUS() && !MRFI_FIFO_STATUS() ) { /* Flush receive FIFO to recover from overflow */ MRFI_RADIO_FLUSH_RX_BUFFER(); break; } /* clear interrupt flag so we can detect another frame later. */ MRFI_CLEAR_RX_INTERRUPT_FLAG(); /* * 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). */ mrfiSpiReadRxFifo(&numBytes, 1); numBytes &= 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)) { uint8_t dummy; /* packet is too big or too small. remove it from FIFO */ for (i=0; i<numBytes; i++) { /* read and discard bytes from FIFO */ mrfiSpiReadRxFifo(&dummy, 1); } } else { uint8_t *p, nextByte; /* Clear out my buffer to remove leftovers in case a bogus packet gets through */ for(i=0; i < MRFI_MAX_FRAME_SIZE; i++) { mrfiIncomingPacket.frame[i] = 0; } /* set pointer at first byte of frame storage */ p = &mrfiIncomingPacket.frame[MRFI_LENGTH_FIELD_OFFSET]; /* * 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 rx FIFO and store into incoming packet memory */ p++; mrfiSpiReadRxFifo(p, numBytes-MRFI_RX_METRICS_SIZE); /* The next two bytes in the rx fifo are: * - RSSI of the received frams * - CRC OK bit and the 7 bit wide correlation value. * Read this rx metrics and store to incoming packet. */ /* Add the RSSI offset to get the proper RSSI value. */ mrfiSpiReadRxFifo(&nextByte, 1); mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] = Mrfi_CalculateRssi(nextByte); /* The second byte has 7 bits of Correlation value and 1 bit of * CRC pass/fail info. Remove the CRC pass/fail bit info. * Also note that for CC2520 radio this is the correlation value and not * the LQI value. Some convertion is needed to extract the LQI value. * This convertion is left to the application at this time. */ mrfiSpiReadRxFifo(&nextByte, 1); mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] = nextByte & MRFI_RX_METRICS_LQI_MASK; /* Eliminate frames that are the correct size but we can tell are bogus * by their frame control fields OR if CRC failed. */ if( (nextByte & MRFI_RX_METRICS_CRC_OK_MASK) && (mrfiIncomingPacket.frame[MRFI_FCF_OFFSET] == MRFI_FCF_0_7) && (mrfiIncomingPacket.frame[MRFI_FCF_OFFSET+1] == MRFI_FCF_8_15)) { /* call external, higher level "receive complete" (CRC checking is done by hardware) */ MRFI_RxCompleteISR(); } } /* If the client code takes long time to process the frame, * rx fifo could overflow during this time. As soon as this condition is * reached, the radio fsm stops all activities till the rx fifo is flushed. * It also puts the fifo signal low. When we come out of this while loop, * we really don't know if it is because of overflow condition or * there is no data in the fifo. So we must check for overflow condition * before exiting the ISR otherwise it could get stuck in this "overflow" * state forever. */ } while( MRFI_FIFO_STATUS() ); /* Continue as long as there is some data in FIFO */ /* Check if we exited the loop due to fifo overflow. * and not due to no data in fifo. */ if( MRFI_FIFOP_STATUS() && !MRFI_FIFO_STATUS() ) { /* Flush receive FIFO to recover from overflow */ MRFI_RADIO_FLUSH_RX_BUFFER(); } }
/************************************************************************************************** * @fn MRFI_Init * * @brief Initialize MRFI. * * @param none * * @return none ************************************************************************************************** */ void MRFI_Init(void) { /* ------------------------------------------------------------------ * Run-time integrity checks * --------------------------- */ /* verify the correct radio is installed */ MRFI_ASSERT( CHIPID == MRFI_RADIO_PARTNUM ); /* wrong radio */ MRFI_ASSERT( CHVER >= MRFI_RADIO_MIN_VERSION ); /* obsolete radio version */ /* ------------------------------------------------------------------ * Configure IO ports * --------------------------- */ #if defined(MRFI_PA_LNA_ENABLED) && defined(BSP_BOARD_SRF04EB) MRFI_BOARD_PA_LNA_CONFIG_PORTS(); MRFI_BOARD_PA_LNA_HGM(); #endif /* ------------------------------------------------------------------ * Configure clock to use XOSC * ----------------------------- */ SLEEP &= ~OSC_PD; /* turn on 16MHz RC and 32MHz XOSC */ while (!(SLEEP & XOSC_STB)); /* wait for 32MHz XOSC stable */ asm("NOP"); /* chip bug workaround */ { uint16_t i; /* Require 63us delay for all revs */ for (i=0; i<504; i++) { asm("NOP"); } } CLKCON = (0x00 | OSC_32KHZ); /* 32MHz XOSC */ while (CLKCON != (0x00 | OSC_32KHZ)); SLEEP |= OSC_PD; /* turn off 16MHz RC */ /* ------------------------------------------------------------------ * Variable Initialization * ------------------------- */ #ifdef MRFI_ASSERTS_ARE_ON PANIDL = 0xFF; PANIDH = 0xFF; #endif /* ------------------------------------------------------------------ * Initialize Random Seed Value * ------------------------------- */ /* turn on radio power, pend for the power-up delay */ RFPWR &= ~RREG_RADIO_PD; while((RFPWR & ADI_RADIO_PD)); /* * Set radio for infinite reception. Once radio reaches this state, * it will stay in receive mode regardless RF activity. */ MDMCTRL1L = MDMCTRL1L_RESET_VALUE | RX_MODE_INFINITE_RECEPTION; /* turn on the receiver */ RFST = ISRXON; /* * Wait for radio to reach infinite reception state. Once it does, * The least significant bit of ADTSTH should be pretty random. */ while (FSMSTATE != FSM_FFCTRL_STATE_RX_INF) /* put 16 random bits into the seed value */ { uint16_t rndSeed; uint8_t i; rndSeed = 0; for(i=0; i<16; i++) { /* use most random bit of analog to digital receive conversion to populate the random seed */ rndSeed = (rndSeed << 1) | (ADCTSTH & 0x01); } /* * The seed value must not be zero. If it is, the pseudo random sequence will be always be zero. * There is an extremely small chance this seed could randomly be zero (more likely some type of * hardware problem would cause this). To solve this, a single bit is forced to be one. This * slightly reduces the randomness but guarantees a good seed value. */ rndSeed |= 0x0080; /* * Two writes to RNDL will set the random seed. A write to RNDL copies current contents * of RNDL to RNDH before writing new the value to RNDL. */ RNDL = rndSeed & 0xFF; RNDL = rndSeed >> 8; } /* turn off the receiver, flush RX FIFO just in case something got in there */ RFST = ISRFOFF; /* flush the rx buffer */ MRFI_RADIO_FLUSH_RX_BUFFER(); /* take receiver out of infinite reception mode; set back to normal operation */ MDMCTRL1L = MDMCTRL1L_RESET_VALUE | RX_MODE_NORMAL_OPERATION; /* turn radio back off */ RFPWR |= RREG_RADIO_PD; /* Initial radio state is OFF state */ mrfiRadioState = MRFI_RADIO_STATE_OFF; /* ------------------------------------------------------------------ * Configure Radio Registers * --------------------------- */ /* tuning adjustments for optimal radio performance; details available in datasheet */ RXCTRL0H = 0x32; RXCTRL0L = 0xF5; /* disable address filtering */ MDMCTRL0H &= ~ADDR_DECODE; /* set FIFOP threshold to maximum */ IOCFG0 = 127; /* set default channel */ MRFI_SetLogicalChannel( 0 ); /* enable general RF interrupts */ IEN2 |= RFIE; /* ------------------------------------------------------------------ * Final Initialization * ----------------------- */ /********************************************************************************** * Compute reply delay scalar * * The IEEE radio has a fixed data rate of 250 Kbps. Data rate inference * from radio regsiters is not necessary for this radio. * * The maximum delay needed depends on the MAX_APP_PAYLOAD parameter. Figure * out how many bits that will be when overhead is included. Bits/bits-per-second * is seconds to transmit (or receive) the maximum frame. We multiply this number * by 1000 to find the time in milliseconds. We then additionally multiply by * 10 so we can add 5 and divide by 10 later, thus rounding up to the number of * milliseconds. This last won't matter for slow transmissions but for faster ones * we want to err on the side of being conservative and making sure the radio is on * to receive the reply. The semaphore monitor will shut it down. The delay adds in * a fudge factor that includes processing time on peer plus lags in Rx and processing * time on receiver's side. * * ********************************************************************************** */ #define PLATFORM_FACTOR_CONSTANT 2 #define PHY_PREAMBLE_SYNC_BYTES 8 { uint32_t bits, dataRate = 250000; bits = ((uint32_t)((PHY_PREAMBLE_SYNC_BYTES + MRFI_MAX_FRAME_SIZE)*8))*10000; /* processing on the peer + the Tx/Rx time plus more */ sReplyDelayScalar = PLATFORM_FACTOR_CONSTANT + (((bits/dataRate)+5)/10); } /* * 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_Init * * @brief Initialize MRFI. * * @param none * * @return none ************************************************************************************************** */ void MRFI_Init(void) { /* ------------------------------------------------------------------ * Run-time integrity checks * --------------------------- */ memset(&mrfiIncomingPacket, 0x0, sizeof(mrfiIncomingPacket)); /* verify the correct radio is installed */ MRFI_ASSERT( CHIPID == MRFI_RADIO_PARTNUM ); /* wrong radio */ MRFI_ASSERT( CHVER >= MRFI_RADIO_MIN_VERSION ); /* obsolete radio version */ /* ------------------------------------------------------------------ * Configure IO ports * --------------------------- */ #if defined(MRFI_PA_LNA_ENABLED) && defined(BSP_BOARD_SRF04EB) MRFI_BOARD_PA_LNA_CONFIG_PORTS(); MRFI_BOARD_PA_LNA_HGM(); #endif /* ------------------------------------------------------------------ * Configure clock to use XOSC * ----------------------------- */ SLEEPCMD &= ~OSC_PD; /* turn on 16MHz RC and 32MHz XOSC */ while (!(SLEEPSTA & XOSC_STB)); /* wait for 32MHz XOSC stable */ asm("NOP"); /* chip bug workaround */ { uint16_t i; /* Require 63us delay for all revs */ for (i=0; i<504; i++) { asm("NOP"); } } CLKCONCMD = (0x00 | OSC_32KHZ); /* 32MHz XOSC */ while (CLKCONSTA != (0x00 | OSC_32KHZ)); SLEEPCMD |= OSC_PD; /* turn off 16MHz RC */ /* Configure radio registers that should be different from reset values. */ Mrfi_RadioRegConfig(); /* ------------------------------------------------------------------ * Variable Initialization * ------------------------- */ #ifdef MRFI_ASSERTS_ARE_ON PAN_ID0 = 0xFF; PAN_ID1 = 0xFF; #endif /* ------------------------------------------------------------------ * Initialize Random Seed Value * ------------------------------- */ /* * Set radio for infinite reception. Once radio reaches this state, * it will stay in receive mode regardless RF activity. */ FRMCTRL0 = (FRMCTRL0 & ~RX_MODE_MASK) | RX_MODE_INFINITE_RX; /* turn on the receiver */ RFST = ISRXON; /* Wait for RSSI to be valid. Once valid, radio is stable and random bits * can be read. */ MRFI_RSSI_VALID_WAIT(); /* put 16 random bits into the seed value */ { uint16_t rndSeed; uint8_t i; rndSeed = 0; for(i=0; i<16; i++) { /* read random bit to populate the random seed */ rndSeed = (rndSeed << 1) | (RFRND & 0x01); } /* * The seed value must not be zero. If it is, the pseudo random sequence will be always be zero. * There is an extremely small chance this seed could randomly be zero (more likely some type of * hardware problem would cause this). To solve this, a single bit is forced to be one. This * slightly reduces the randomness but guarantees a good seed value. */ rndSeed |= 0x0080; /* * Two writes to RNDL will set the random seed. A write to RNDL copies current contents * of RNDL to RNDH before writing new the value to RNDL. */ RNDL = rndSeed & 0xFF; RNDL = rndSeed >> 8; } /* turn off the receiver, flush RX FIFO just in case something got in there */ RFST = ISRFOFF; /* flush the rx buffer */ MRFI_RADIO_FLUSH_RX_BUFFER(); /* take receiver out of infinite reception mode; set back to normal operation */ FRMCTRL0 = (FRMCTRL0 & ~RX_MODE_MASK) | RX_MODE_NORMAL; /* Initial radio state is OFF state */ mrfiRadioState = MRFI_RADIO_STATE_OFF; /* ------------------------------------------------------------------ * Configure Radio Registers * --------------------------- */ /* disable address filtering */ FRMFILT0 &= ~FRAME_FILTER_EN; /* reject beacon/ack/cmd frames and accept only data frames, * when filtering is enabled. */ FRMFILT1 &= ~(ACCEPT_BEACON | ACCEPT_ACK | ACCEPT_CMD); /* don't enable rx after tx is done. */ FRMCTRL1 &= ~RX_ENABLE_ON_TX; /* set FIFOP threshold to maximum */ FIFOPCTRL = 127; /* set default channel */ MRFI_SetLogicalChannel( 0 ); /* set default output power level */ MRFI_SetRFPwr(MRFI_NUM_POWER_SETTINGS - 1); /* enable general RF interrupts */ IEN2 |= RFIE; /* ------------------------------------------------------------------ * Final Initialization * ----------------------- */ /********************************************************************************** * Compute reply delay scalar * * The IEEE radio has a fixed data rate of 250 Kbps. Data rate inference * from radio regsiters is not necessary for this radio. * * The maximum delay needed depends on the MAX_APP_PAYLOAD parameter. Figure * out how many bits that will be when overhead is included. Bits/bits-per-second * is seconds to transmit (or receive) the maximum frame. We multiply this number * by 1000 to find the time in milliseconds. We then additionally multiply by * 10 so we can add 5 and divide by 10 later, thus rounding up to the number of * milliseconds. This last won't matter for slow transmissions but for faster ones * we want to err on the side of being conservative and making sure the radio is on * to receive the reply. The semaphore monitor will shut it down. The delay adds in * a platform fudge factor that includes processing time on peer plus lags in Rx and * processing time on receiver's side. Also includes round trip delays from CCA * retries. This portion is included in PLATFORM_FACTOR_CONSTANT defined in mrfi.h. * * ********************************************************************************** */ #define PHY_PREAMBLE_SYNC_BYTES 8 { uint32_t bits, dataRate = 250000; bits = ((uint32_t)((PHY_PREAMBLE_SYNC_BYTES + MRFI_MAX_FRAME_SIZE)*8))*10000; /* processing on the peer + the Tx/Rx time plus more */ sReplyDelayScalar = PLATFORM_FACTOR_CONSTANT + (((bits/dataRate)+5)/10); } /* * 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_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, crcOK; /* We should receive this interrupt only in RX state * Should never receive it if RX was turned On only for * some internal mrfi processing like - during CCA. * Otherwise something is terribly wrong. */ MRFI_ASSERT( mrfiRadioState == MRFI_RADIO_STATE_RX ); /* 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 (!(RFIRQF0 & IRQ_FIFOP)) ; /* Check for Rx overflow. Checking here means we may flush a valid frame */ if ((FSMSTAT1 & FIFOP) && (!(FSMSTAT1 & FIFO))) { /* flush receive FIFO to recover from overflow (per datasheet, flush must be done twice) */ MRFI_RADIO_FLUSH_RX_BUFFER(); break; } /* clear interrupt flag so we can detect another frame later. */ RFIRQF0 &= ~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 */ /* Add the RSSI offset to get the proper RSSI value. */ mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_RSSI_OFS] = RFD + MRFI_RSSI_OFFSET; /* The second byte has 7 bits of Correlation value and 1 bit of * CRC pass/fail info. Remove the CRC pass/fail bit info. * Also note that for CC2430 radio this is the correlation value and not * the LQI value. Some convertion is needed to extract the LQI value. * This convertion is left to the application at this time. */ crcOK = RFD; /* get CRC/LQI byte */ if (!(crcOK & (~MRFI_RX_METRICS_LQI_MASK))) { /* bad CRC. Move on... */ continue; } /* CRC OK. Save LQI info */ mrfiIncomingPacket.rxMetrics[MRFI_RX_METRICS_CRC_LQI_OFS] = (crcOK & MRFI_RX_METRICS_LQI_MASK); /* Eliminate frames that are the correct size but we can tell are bogus * by their frame control fields. */ if ((p1[MRFI_FCF_OFFSET] == MRFI_FCF_0_7) && (p1[MRFI_FCF_OFFSET+1] == MRFI_FCF_8_15)) { /* call external, higher level "receive complete" */ MRFI_RxCompleteISR(); } } } while (RXFIFOCNT); /* ------------------------------------------------------------------ * Clean up on exit * -------------------- */ /* Clear FIFOP interrupt: * This is an edge triggered interrupt. The interrupt must be first cleared * at the MCU before re-enabling the interrupt at the source. */ S1CON = 0x00; /* Clear the interrupt at MCU. */ RFIRQF0 &= ~IRQ_FIFOP; /* Clear the interrupt source flag. */ }
/************************************************************************************************** * @fn MRFI_Init * * @brief Initialize MRFI. * * @param none * * @return none ************************************************************************************************** */ void MRFI_Init(void) { /* ------------------------------------------------------------------ * Initialization * ----------------- */ /* initialize radio state variables */ mrfiRxFilterEnabled = 0; mrfiRadioIsSleeping = 0; mrfiTxActive = 0; mrfiRxActive = 0; /* initialize GPIO pins */ MRFI_CONFIG_GDO0_PIN_AS_INPUT(); MRFI_CONFIG_GDO2_PIN_AS_INPUT(); /* initialize SPI */ mrfiSpiInit(); /* ------------------------------------------------------------------ * Radio power-up reset * ---------------------- */ MRFI_ASSERT(MRFI_SPI_CSN_IS_HIGH()); /* pulse CSn low then high */ MRFI_SPI_DRIVE_CSN_LOW(); MRFI_DELAY(10); MRFI_SPI_DRIVE_CSN_HIGH(); /* hold CSn high for at least 40 microseconds */ MRFI_DELAY(100); /* pull CSn low and wait for SO to go low */ MRFI_SPI_DRIVE_CSN_LOW(); while (MRFI_SPI_SO_IS_HIGH()); /* directly send strobe command - cannot use function as it affects CSn pin */ MRFI_SPI_WRITE_BYTE(MRFI_CC2500_SPI_STROBE_SRES); MRFI_SPI_WAIT_DONE(); /* wait for SO to go low again, reset is complete at that point */ while (MRFI_SPI_SO_IS_HIGH()); /* return CSn pin to its default high level */ MRFI_SPI_DRIVE_CSN_HIGH(); /* ------------------------------------------------------------------ * Run-time integrity checks * --------------------------- */ /* verify that SPI is working */ #ifdef MRFI_ASSERTS_ARE_ON #define TEST_VALUE 0xA5 mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_PKTLEN, TEST_VALUE ); MRFI_ASSERT( mrfiSpiReadReg( MRFI_CC2500_SPI_REG_PKTLEN ) == TEST_VALUE ); /* SPI is not responding */ #endif /* verify the correct radio is installed */ MRFI_ASSERT( mrfiSpiReadReg( MRFI_CC2500_SPI_REG_PARTNUM ) == MRFI_RADIO_PARTNUM); /* incorrect radio specified */ MRFI_ASSERT( mrfiSpiReadReg( MRFI_CC2500_SPI_REG_VERSION ) >= MRFI_RADIO_MIN_VERSION); /* obsolete radio specified */ /* ------------------------------------------------------------------ * Configure radio * ----------------- */ /* initialize radio registers */ { uint8_t i; for (i=0; i<(sizeof(mrfiRadioCfg)/sizeof(mrfiRadioCfg[0])); i++) { mrfiSpiWriteReg(mrfiRadioCfg[i][0], mrfiRadioCfg[i][1]); } } /* send strobe to turn on receiver */ mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX); /* ------------------------------------------------------------------ * Configure interrupts * ---------------------- */ /* * Configure and enable the SYNC signal interrupt. * * This interrupt is used to indicate receive. The SYNC signal goes * high when a receive OR a transmit begins. It goes high once the * sync word is received or transmitted and then goes low again once * the packet completes. */ MRFI_CONFIG_SYNC_PIN_FALLING_EDGE_INT(); MRFI_CLEAR_SYNC_PIN_INT_FLAG(); MRFI_ENABLE_SYNC_PIN_INT(); /* configure PA_PD signal interrupt */ MRFI_CONFIG_PAPD_FALLING_EDGE_INT(); /* enable global interrupts */ BSP_ENABLE_INTERRUPTS(); }