Пример #1
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 );
}
Пример #2
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 );
}