Example #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 );
}
Example #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_TRANSMIT_SUCCESS - transmit succeeded
 *                  MRFI_TRANSMIT_CCA_FAILED - transmit failed because of CCA check(s)
 *                  MRFI_TRANSMIT_RADIO_ASLEEP - transmit failed because radio was asleep
 **************************************************************************************************
 */
uint8_t MRFI_Transmit(mrfiPacket_t * pPacket)
{
  uint8_t ccaRetries;
  uint8_t txBufLen;
  uint8_t savedSyncIntState;
  uint8_t returnValue;

  /* abort transmit if radio is asleep */
  {
    bspIState_t s;

    /* critical section necessary for watertight testing and setting of state variables */
    BSP_ENTER_CRITICAL_SECTION(s);

    /* if radio is asleep, abort transmit and return reason for failure */
    if (mrfiRadioIsSleeping)
    {
      BSP_EXIT_CRITICAL_SECTION(s);
      return( MRFI_TRANSMIT_RADIO_ASLEEP );
    }
    
    /* radio is not asleep, set flag that indicates transmit is active */
    mrfiTxActive = 1;
    BSP_EXIT_CRITICAL_SECTION(s);
  }
  
  /* set number of CCA retries */
  ccaRetries = MRFI_CCA_RETRIES;
  
  /* compute number of bytes to write to transmit FIFO */
  txBufLen = pPacket->frame[MRFI_LENGTH_FIELD_OFS] + MRFI_LENGTH_FIELD_SIZE;
  
  /* write packet to transmit FIFO */
  mrfiSpiWriteTxFifo(&(pPacket->frame[0]), txBufLen);
  
  /* ===============================================================================
   *    Main Loop 
   *  =============
   */
  for (;;)
  {
    /* CCA delay */
    MRFI_DELAY(2000);

    /* disable sync pin interrupts, necessary because both transmit and receive affect sync signal */
    MRFI_DISABLE_SYNC_PIN_INT();

    /* store the sync pin interrupt flag, important so original state can be restored */
    savedSyncIntState = MRFI_SYNC_PIN_INT_FLAG_IS_SET();
      
    /*
     *  Clear the PA_PD pin interrupt flag.  This flag, not the interrupt itself,
     *  is used to capture the transition that indicates a transmit was started.
     *  The pin level cannot be used to indicate transmit success as timing may
     *  prevent the transition from being detected.  The interrupt latch captures
     *  the event regardless of timing.
     */
    MRFI_CLEAR_PAPD_PIN_INT_FLAG();
    
    /* send strobe to initiate transmit */
    mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_STX);
    
    /*  delay long enough for the PA_PD signal to indicate a successful transmit */
    MRFI_DELAY(250);

    /* if the interrupt flag of the PA_PD pin is set, CCA passed and the transmit has started */
    if (MRFI_PAPD_INT_FLAG_IS_SET())
    {
      /* ------------------------------------------------------------------
       *    Clear Channel Assessment passed.
       *   ----------------------------------
       */

      /* wait for transmit to complete */
      while (!MRFI_PAPD_PIN_IS_HIGH());

      /*
       *  Restore the original sync interrupt state.  The successful transmit just
       *  caused a transition on the sync signal that set the flag (if not already
       *  set).  To restore the original state, the flag is simply cleared if it
       *  was clear earlier.
       */
      if (!savedSyncIntState)
      {
        MRFI_CLEAR_SYNC_PIN_INT_FLAG();
      }
      
      /* transmit complete, enable sync pin interrupts */
      MRFI_ENABLE_SYNC_PIN_INT();

      /* set return value for successful transmit and break */      
      returnValue = MRFI_TRANSMIT_SUCCESS;
      break;
    }

    /* ------------------------------------------------------------------
     *    Clear Channel Assessment failed.
     *   ----------------------------------
     */
    
    /* CCA failed, safe to enable sync pin interrupts */
    MRFI_ENABLE_SYNC_PIN_INT();

    /* if no CCA retries are left, transmit failed so abort */    
    if (ccaRetries == 0)
    {
      bspIState_t s;

      /*
       *  Flush the transmit FIFO.  It must be flushed so that
       *  the next transmit can start with a clean slate.
       *  Critical section prevents receive interrupt from
       *  occurring in the middle of clean-up.
       */
      BSP_ENTER_CRITICAL_SECTION(s);
      mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SIDLE);
      mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SFTX);
      mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX);
      BSP_EXIT_CRITICAL_SECTION(s);

      /* set return value for failed transmit and break */      
      returnValue = MRFI_TRANSMIT_CCA_FAILED;
      break;
    }

    /* decrement CCA retries before loop continues */
    ccaRetries--;
  }
  /*
   * =============================================================================== */

  mrfiTxActive = 0;
  return( returnValue );
}