Exemplo n.º 1
0
/*=================================================================================================
 * @fn          spiRegAccess
 *
 * @brief       This function performs a read or write.  The
 *              calling code must configure the read/write bit of the register's address byte.
 *              This bit is set or cleared based on the type of access.
 *
 * @param       regAddrByte - address byte of register; the read/write bit already configured
 *
 * @return      register value
 *=================================================================================================
 */
static uint8_t spiRegAccess(uint8_t addrByte, uint8_t writeValue)
{
  uint8_t readValue;
  mrfiSpiIState_t s;

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
  bool comm_state = sActiveSPI; // save comm state
#endif

  MRFI_SPI_ASSERT( MRFI_SPI_IS_INITIALIZED() );   /* SPI is not initialized */

  /* disable interrupts that use SPI */
  MRFI_SPI_ENTER_CRITICAL_SECTION(s);

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
  sActiveSPI = true;            // indicate active comm state
#endif

  /* turn chip select "off" and then "on" to clear any current SPI access */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_TURN_CHIP_SELECT_ON();

  /* send register address byte, the read/write bit is already configured */
  MRFI_SPI_WRITE_BYTE(addrByte);
  MRFI_SPI_WAIT_DONE();

  /*
   *  Send the byte value to write.  If this operation is a read, this value
   *  is not used and is just dummy data.  Wait for SPI access to complete.
   */
  MRFI_SPI_WRITE_BYTE(writeValue);
  MRFI_SPI_WAIT_DONE();

  /*
   *  If this is a read operation, SPI data register now contains the register
   *  value which will be returned.  For a read operation, it contains junk info
   *  that is not used.
   */
  readValue = MRFI_SPI_READ_BYTE();

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
  sActiveSPI = comm_state; // restore comm state
#endif

  /* turn off chip select; enable interrupts that call SPI functions */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_EXIT_CRITICAL_SECTION(s);

  /* return the register value */
  return(readValue);
}
Exemplo n.º 2
0
/**************************************************************************************************
 * @fn          mrfiSpiCmdStrobe
 *
 * @brief       Send command strobe to the radio.  Returns status byte read during transfer
 *              of strobe command.
 *
 * @param       addr - address of register to strobe
 *
 * @return      status byte of radio
 **************************************************************************************************
 */
uint8_t mrfiSpiCmdStrobe(uint8_t addr)
{
  uint8_t statusByte;
  mrfiSpiIState_t s;

  MRFI_SPI_ASSERT( MRFI_SPI_IS_INITIALIZED() );       /* SPI is not initialized */
  MRFI_SPI_ASSERT((addr >= 0x30) && (addr <= 0x3D));  /* invalid address */

  /* disable interrupts that use SPI */
  MRFI_SPI_ENTER_CRITICAL_SECTION(s);

  /* turn chip select "off" and then "on" to clear any current SPI access */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_TURN_CHIP_SELECT_ON();

  /* send the command strobe, wait for SPI access to complete */
  MRFI_SPI_WRITE_BYTE(addr);
  MRFI_SPI_WAIT_DONE();

  /* read the readio status byte returned by the command strobe */
  statusByte = MRFI_SPI_READ_BYTE();

  /* turn off chip select; enable interrupts that call SPI functions */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_EXIT_CRITICAL_SECTION(s);

  /* return the status byte */
  return(statusByte);
}
Exemplo n.º 3
0
/*=================================================================================================
 * @fn          spiRegAccess
 *
 * @brief       This function performs a read or write.  The
 *              calling code must configure the read/write bit of the register's address byte.
 *              This bit is set or cleared based on the type of access.
 *
 * @param       regAddrByte - address byte of register; the read/write bit already configured
 *
 * @return      register value
 *=================================================================================================
 */
static uint8_t spiRegAccess(uint8_t addrByte, uint8_t writeValue)
{
  uint8_t readValue;
  mrfiSpiIState_t s;

  MRFI_SPI_ASSERT( MRFI_SPI_IS_INITIALIZED() );   /* SPI is not initialized */

  /* disable interrupts that use SPI */
  MRFI_SPI_ENTER_CRITICAL_SECTION(s);

  /* make sure clock phase and polarity are correct for radio */
  MRFI_SPI_CLK_CONFIG();

  /* turn chip select "off" and then "on" to clear any current SPI access */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_TURN_CHIP_SELECT_ON();

  /* send register address byte, the read/write bit is already configured */
  MRFI_SPI_WRITE_BYTE(addrByte);
  MRFI_SPI_WAIT_DONE();

  /*
   *  Send the byte value to write.  If this operation is a read, this value
   *  is not used and is just dummy data.  Wait for SPI access to complete.
   */
  MRFI_SPI_WRITE_BYTE(writeValue);
  MRFI_SPI_WAIT_DONE();

  /*
   *  If this is a read operation, SPI data register now contains the register
   *  value which will be returned.  For a write operation, it contains junk info
   *  that is not used.
   */
  readValue = MRFI_SPI_READ_BYTE();

  /* turn off chip select; enable interrupts that call SPI functions */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_EXIT_CRITICAL_SECTION(s);

  /* return the register value */
  return(readValue);
}
Exemplo n.º 4
0
/**************************************************************************************************
 * @fn          mrfiSpiCmdStrobe
 *
 * @brief       Send command strobe to the radio.  Returns status byte read during transfer
 *              of strobe command.
 *
 * @param       addr - address of register to strobe
 *
 * @return      status byte of radio
 **************************************************************************************************
 */
uint8_t mrfiSpiCmdStrobe(uint8_t addr)
{
	uint8_t statusByte;
	mrfiSpiIState_t s;

#ifdef DEBUG_SPI
	DEBUG("SPI!C# ");
	DEBUG_LN(cmdRegs[addr-SRES]);
#endif

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
	bool comm_state = sActiveSPI; // save comm state
#endif

	MRFI_SPI_ASSERT( MRFI_SPI_IS_INITIALIZED() );       /* SPI is not initialized */
	MRFI_SPI_ASSERT((addr >= 0x30) && (addr <= 0x3D));  /* invalid address */

	/* disable interrupts that use SPI */
	MRFI_SPI_ENTER_CRITICAL_SECTION(s);

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
	sActiveSPI = true;            // indicate active comm state
#endif

	/* turn chip select "off" and then "on" to clear any current SPI access */
	MRFI_SPI_TURN_CHIP_SELECT_OFF();
	MRFI_SPI_TURN_CHIP_SELECT_ON();

	/* send the command strobe, wait for SPI access to complete */
	MRFI_SPI_WRITE_BYTE(addr);
	MRFI_SPI_WAIT_DONE();

	/* read the readio status byte returned by the command strobe */
	statusByte = MRFI_SPI_READ_BYTE();

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
	sActiveSPI = comm_state; // restore comm state
#endif

	/* turn off chip select; enable interrupts that call SPI functions */
	MRFI_SPI_TURN_CHIP_SELECT_OFF();
	MRFI_SPI_EXIT_CRITICAL_SECTION(s);

	/* return the status byte */
	return(statusByte);
}
Exemplo n.º 5
0
/*=================================================================================================
 * @fn          spiBurstFifoAccess
 *
 * @brief       Burst mode access used for reading or writing to radio FIFOs.
 *
 *              For more efficient interrupt latency, this function does not keep interrupts
 *              disabled for its entire execution.  It is designed to recover if an interrupt
 *              occurs that accesses SPI.  See comments in code for further details.
 *
 * @param       addrByte - first byte written to SPI, contains address and mode bits
 * @param       pData    - pointer to data to read or write
 * @param       len      - length of data in bytes
 *
 * @return      true if an interrupt was detected during the transfer, false otherwise
 *=================================================================================================
 */
static bool spiBurstFifoAccess(uint8_t addrByte, uint8_t * pData, uint8_t len)
{
  bool result = false; // initialize to successful status
  mrfiSpiIState_t s;

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
  bool comm_state = sActiveSPI; // save comm state
#endif

  MRFI_SPI_ASSERT( MRFI_SPI_IS_INITIALIZED() );   /* SPI is not initialized */
  MRFI_SPI_ASSERT(len != 0);                      /* zero length is not allowed */
  MRFI_SPI_ASSERT(addrByte & BURST_BIT);          /* only burst mode supported */

  /* disable interrupts that use SPI */
  MRFI_SPI_ENTER_CRITICAL_SECTION(s);

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
  sActiveSPI = true;            // indicate active comm state
#endif

  /* turn chip select "off" and then "on" to clear any current SPI access */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_TURN_CHIP_SELECT_ON();

  /*-------------------------------------------------------------------------------
   *  Main loop.  If the SPI access is interrupted, execution comes back to
   *  the start of this loop.  Loop exits when nothing left to transfer.
   */
  do
  {
    /* send FIFO access command byte, wait for SPI access to complete */
    MRFI_SPI_WRITE_BYTE(addrByte);
    MRFI_SPI_WAIT_DONE();

    /*-------------------------------------------------------------------------------
     *  Inner loop.  This loop executes as long as the SPI access is not interrupted.
     *  Loop completes when nothing left to transfer.
     */
    do
    {
      MRFI_SPI_WRITE_BYTE(*pData);
        
      /*-------------------------------------------------------------------------------
       *  Use idle time.  Perform increment/decrement operations before pending on
       *  completion of SPI access.
       *
       *  Decrement the length counter.  Wait for SPI access to complete.
       */
      len--;
      MRFI_SPI_WAIT_DONE();

      /*-------------------------------------------------------------------------------
       *  SPI data register holds data just read.  If this is a read operation,
       *  store the value into memory.
       */
      if (addrByte & READ_BIT)
      {
        *pData = MRFI_SPI_READ_BYTE();
      }

      /*-------------------------------------------------------------------------------
       *  At least one byte of data has transferred.  Briefly enable (and then disable)
       *  interrupts that can call SPI functions.  This provides a window for any timing
       *  critical interrupts that might be pending.
       *
       *  To improve latency, take care of pointer increment within the interrupt
       *  enabled window.
       */
      MRFI_SPI_EXIT_CRITICAL_SECTION(s);
      pData++;
      MRFI_SPI_ENTER_CRITICAL_SECTION(s);

      /*-------------------------------------------------------------------------------
       *  If chip select is "off" the SPI access was interrupted (all SPI access
       *  functions leave chip select in the "off" state).  In this case, turn
       *  back on chip select and break to the main loop.  The main loop will
       *  pick up where the access was interrupted.
       */
      if (MRFI_SPI_CHIP_SELECT_IS_OFF())
      {
        MRFI_SPI_TURN_CHIP_SELECT_ON();
        result = true;   // indicate interruption detected
        break;
      }

    /*-------------------------------------------------------------------------------
     */
    } while (len); /* inner loop */
  } while (len);   /* main loop */

#ifdef MRFI_TIMER_ALWAYS_ACTIVE
  sActiveSPI = comm_state; // restore comm state
#endif

  /* turn off chip select; enable interrupts that call SPI functions */
  MRFI_SPI_TURN_CHIP_SELECT_OFF();
  MRFI_SPI_EXIT_CRITICAL_SECTION(s);
  
  return result;
}
Exemplo n.º 6
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();
}