Beispiel #1
0
/**************************************************************************************************
 * @fn          MRFI_WakeUp
 *
 * @brief       Wake up radio from sleep state.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void MRFI_WakeUp(void)
{
  /* if radio is already awake, just ignore wakeup request */
  if (!mrfiRadioIsSleeping)
  {
    return;
  }

  /* drive CSn low to initiate wakeup */
  MRFI_SPI_DRIVE_CSN_LOW();
  
  /* wait for MISO to go high indicating the oscillator is stable */
  while (MRFI_SPI_SO_IS_HIGH());
  
  /* wakeup is complete, drive CSn high and continue */
  MRFI_SPI_DRIVE_CSN_HIGH();

/*
 *  The test registers must be restored after sleep for the CC1100 and CC2500 radios.
 *  This is not required for the CC1101 radio.
 */
#ifndef MRFI_CC1101
  mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_TEST2, SMARTRF_SETTING_TEST2 );
  mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_TEST1, SMARTRF_SETTING_TEST1 );
  mrfiSpiWriteReg( MRFI_CC2500_SPI_REG_TEST0, SMARTRF_SETTING_TEST0 );
#endif

  /* clear any residual SYNC pin interrupt and then re-enable SYNC pin interrupts */
  MRFI_CLEAR_SYNC_PIN_INT_FLAG();
  MRFI_ENABLE_SYNC_PIN_INT();

  /* clear sleep flag and enter receive mode */
  mrfiRadioIsSleeping = 0;
  mrfiSpiCmdStrobe(MRFI_CC2500_SPI_STROBE_SRX);
}
Beispiel #2
0
void radioISR(void)
{
  unsigned int coreIntSource = RF1AIV;            // Radio Core      interrupt register

  // Radio Core interrupt
  if(coreIntSource)
  {
    // Check for SYNC interrupt
    if(coreIntSource == RF1AIV_RFIFG9)
    {
      if(MRFI_SYNC_PIN_INT_IS_ENABLED())
      {
        static CCPACKET ccPacket;

        /*  clear the sync pin interrupt, run sync pin ISR */
        /*
         *  NOTE!  The following macro clears the interrupt flag but it also *must*
         *  reset the interrupt capture.  In other words, if a second interrupt
         *  occurs after the flag is cleared it must be processed, i.e. this interrupt
         *  exits then immediately starts again.  Most microcontrollers handle this
         *  naturally but it must be verified for every target.
         */

        MRFI_CLEAR_SYNC_PIN_INT_FLAG();
        MRFI_DISABLE_SYNC_PIN_INT();

        // Any packet waiting to be read?
        if (panstamp.radio.receiveData(&ccPacket) > 0)
        {
          // Is CRC OK?
          if (ccPacket.crc_ok)
          {            
            if (panstamp.ccPacketReceived != NULL)
              panstamp.ccPacketReceived(&ccPacket);
          }
          MRFI_ENABLE_SYNC_PIN_INT();
        }
      }
    }
    // Check for RF_RDY (Event1 WOR) interrupt
    else if(coreIntSource == RF1AIV_RFIFG14)
    {
      RF1AIE |= BIT9 + BIT1;
      RF1AIFG &= ~(BIT9 + BIT1);
      RF1AIES |= BIT9; // Falling edge of RFIFG9
      panstamp.radio.setRxState();
      __bic_SR_register_on_exit(LPM3_bits);
    }
  }
}
Beispiel #3
0
/**************************************************************************************************
 * @fn          MRFI_GpioIsr
 *
 * @brief       Interrupt Service Routine for handling GPIO interrupts.  The sync pin interrupt
 *              comes in through GPIO.  This function is designed to be compatible with "ganged"
 *              interrupts.  If the GPIO interrupt services more than just a single pin (very
 *              common), this function just needs to be called from the higher level interrupt
 *              service routine.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void MRFI_GpioIsr(void)
{
  /* see if sync pin interrupt is enabled and has fired */
  if (MRFI_SYNC_PIN_INT_IS_ENABLED() && MRFI_SYNC_PIN_INT_FLAG_IS_SET())
  {
    /*  clear the sync pin interrupt, run sync pin ISR */

    /*
     *  NOTE!  The following macro clears the interrupt flag but it also *must*
     *  reset the interrupt capture.  In other words, if a second interrupt
     *  occurs after the flag is cleared it must be processed, i.e. this interrupt
     *  exits then immediately starts again.  Most microcontrollers handle this
     *  naturally but it must be verified for every target.
     */
    MRFI_CLEAR_SYNC_PIN_INT_FLAG();
    MRFI_SyncPinRxIsr();
  }
}
Beispiel #4
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 );
}
Beispiel #5
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();
}