Example #1
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);
}
Example #2
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);
}
Example #3
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);
}
Example #4
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);
}
Example #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;
}