Exemplo n.º 1
0
/**************************************************************************************************
 * @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;
}
Exemplo n.º 2
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 3
0
/**************************************************************************************************
 * @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;
}
Exemplo n.º 4
0
/**************************************************************************************************
 * @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 );
}
Exemplo n.º 5
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 6
0
/**************************************************************************************************
 * @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;
  }
}
Exemplo n.º 7
0
/**************************************************************************************************
 * @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);
  }
}
Exemplo n.º 8
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)) );
}
Exemplo n.º 9
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 10
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 11
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 12
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 13
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 14
0
/**************************************************************************************************
 * @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 );
}
Exemplo n.º 15
0
/**************************************************************************************************
 * @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 );
}
Exemplo n.º 16
0
/**************************************************************************************************
 * @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;
}
Exemplo n.º 17
0
/**************************************************************************************************
 * @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 );
}
Exemplo n.º 18
0
/**************************************************************************************************
 * @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();
}
Exemplo n.º 19
0
/**************************************************************************************************
 * @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();
  }
}
Exemplo n.º 20
0
/**************************************************************************************************
 * @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();
}
Exemplo n.º 21
0
/**************************************************************************************************
 * @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();
}
Exemplo n.º 22
0
/**************************************************************************************************
 * @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. */
}
Exemplo n.º 23
0
/**************************************************************************************************
 * @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();
}