/**
 * @file xmc_spi.h
 * @date 2020-12-05
 *
 * @cond
 *****************************************************************************
 * XMClib v2.2.0 - XMC Peripheral Driver Library
 *
 * Copyright (c) 2015-2020, Infineon Technologies AG
 * All rights reserved.
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * To improve the quality of the software, users are encouraged to share
 * modifications, enhancements or bug fixes with Infineon Technologies AG
 * at XMCSupport@infineon.com.
 *****************************************************************************
 *
 * Change History
 * --------------
 *
 * 2015-02-20:
 *     - Initial
 *
 * 2015-05-20:
 *     - Documentation improved <br>
 *     - Added XMC_SPI_CH_SetSlaveSelectDelay(), XMC_SPI_CH_TriggerServiceRequest() and
 *       XMC_SPI_CH_SelectInterruptNodePointer() <br>
 *     - Added XMC_SPI_CH_SetInterwordDelaySCLK() <br>
 *
 * 2015-06-20:
 *     - Removed version macros and declaration of GetDriverVersion API <br>
 *
 * 2015-08-24:
 *     - Added APIs for enabling/disabling delay compensation XMC_SPI_CH_DisableDelayCompensation() and
 *       XMC_SPI_CH_EnableDelayCompensation() <br>
 *
 * 2015-08-27:
 *     - Added APIs for external input for BRG configuration:XMC_SPI_CH_ConfigExternalInputSignalToBRG() <br>
 *
 * 2015-09-01:
 *     - Modified XMC_SPI_CH_SetInputSource() for avoiding complete DXCR register overwriting. <br>
 *     - Modified XMC_SPI_CH_EVENT_t enum for supporting XMC_SPI_CH_EnableEvent() and XMC_SPI_CH_DisableEvent()
 *       for supporting multiple events configuration <br>
 *
 * 2015-09-08:
 *     - Adding API for configuring the receiving clock phase in the slave:XMC_SPI_CH_DataLatchedInTrailingEdge() and XMC_SPI_CH_DataLatchedInLeadingEdge() <br>
 *
 * 2016-04-10:
 *     - Added an API for configuring the transmit mode:XMC_SPI_CH_SetTransmitMode() <br>
 *
 * 2016-05-20:
 *     - Added XMC_SPI_CH_EnableDataTransmission() and XMC_SPI_CH_DisableDataTransmission()
 *
 * 2019-03-30:
 *     - Fix XMC_SPI_CH_MODE_STANDARD_HALFDUPLEX macro value
 *
 * 2019-05-07:
 *     - Added normal_divider_mode to XMC_SPI_CH_CONFIG_t configuration structure.
 *       It selects normal divider mode for baudrate generator instead of default fractional divider decreasing jitter at cost of frequency selection
 *     - Added XMC_SPI_CH_SetBaudrateEx()
 *
 * 2019-09-04:
 *    - Added XMC_SPI_CLOCK_MODE_t enum
 *
 * 2020-12-05:
 *    - Added XMC_SPI_CH_InitEx() that allows user select if automatic baudrate configuration should be done or not
 * 
 * @endcond
 *
 */

#ifndef XMC_SPI_H
#define XMC_SPI_H

/**********************************************************************************************************************
 * HEADER FILES
 *********************************************************************************************************************/
#include "xmc_usic.h"

/**
 * @addtogroup XMClib XMC Peripheral Library
 * @{
 */

/**
 * @addtogroup SPI
 * @brief Synchronous serial channel driver for SPI-like communication.
 *
 * The SPI driver uses Universal Serial Interface Channel(USIC) module.
 * The USIC module supports multiple data lines for SPI communication. \n
 * -# Full duplex communication with 2 separate lines for transmission and reception.
 * -# Half duplex communication with 1 common line shared for transmission and reception.
 * -# Dual mode communication with 2 common lines shared for transmission and reception.
 * -# Quad mode communication with 4 common lines shared for transmission and reception.<br><br>
 *
 * SPI driver provides structures, enumerations and APIs for configuring the USIC channel for SPI communication
 * and also for data transaction.<br>
 * SPI driver features:
 * -# Configuration structure XMC_SPI_CH_CONFIG_t and SPI initialization function XMC_SPI_CH_Init()
 * -# Allows configuration of protocol word and frame length using XMC_SPI_CH_SetWordLength(), XMC_SPI_CH_SetFrameLength()
 * -# Allows manipulation of data frame at runtime using XMC_SPI_CH_EnableSOF(), XMC_SPI_CH_EnableEOF(),
 XMC_SPI_CH_EnableSlaveSelect(), XMC_SPI_CH_DisableSlaveSelect()
 * -# Provides APIs for transmitting data and receiving data using XMC_SPI_CH_Transmit(), XMC_SPI_CH_Receive(), XMC_SPI_CH_GetReceivedData()
 * -# Allows configuration of shift clock using XMC_SPI_CH_ConfigureShiftClockOutput()
 * -# Provides enumeration of SPI protocol events using @ref XMC_SPI_CH_STATUS_FLAG_t
 * @{
 */

/***********************************************************************************************************************
 * MACROS
 **********************************************************************************************************************/

#if defined(USIC0)
#define XMC_SPI0_CH0 XMC_USIC0_CH0 /**< SPI0 channel 0 base address */
#define XMC_SPI0_CH1 XMC_USIC0_CH1 /**< SPI0 channel 1 base address */
#endif

#if defined(USIC1)
#define XMC_SPI1_CH0 XMC_USIC1_CH0 /**< SPI1 channel 0 base address */
#define XMC_SPI1_CH1 XMC_USIC1_CH1 /**< SPI1 channel 1 base address */
#endif

#if defined(USIC2)
#define XMC_SPI2_CH0 XMC_USIC2_CH0 /**< SPI2 channel 0 base address */
#define XMC_SPI2_CH1 XMC_USIC2_CH1 /**< SPI2 channel 1 base address */
#endif

/***********************************************************************************************************************
 * ENUMS
 ***********************************************************************************************************************/

/**
 * Defines return status of SPI driver APIs
 */
typedef enum XMC_SPI_CH_STATUS
{
  XMC_SPI_CH_STATUS_OK,    /**< Status of the Module: OK */
  XMC_SPI_CH_STATUS_ERROR, /**< Status of the Module: ERROR */
  XMC_SPI_CH_STATUS_BUSY   /**< The Module is busy */
} XMC_SPI_CH_STATUS_t;
/**
 * Defines the SPI bus mode
 */
typedef enum XMC_SPI_CH_BUS_MODE
{
  XMC_SPI_CH_BUS_MODE_MASTER, /**< SPI Master */
  XMC_SPI_CH_BUS_MODE_SLAVE   /**< SPI Slave */
} XMC_SPI_CH_BUS_MODE_t;

/**
 * Defines the Polarity of the slave select signals SELO[7:0] in relation to the master slave select signal MSLS.
 */
typedef enum XMC_SPI_CH_SLAVE_SEL_MSLS_INV
{
  XMC_SPI_CH_SLAVE_SEL_SAME_AS_MSLS = 0x0UL, /**< The SELO outputs have the same polarity as the MSLS signal
                                                  (active high) */
  XMC_SPI_CH_SLAVE_SEL_INV_TO_MSLS = 0x1UL << USIC_CH_PCR_SSCMode_SELINV_Pos /**< The SELO outputs have the inverted
                                                                                  polarity to the MSLS signal
                                                                                  (active low)*/
} XMC_SPI_CH_SLAVE_SEL_MSLS_INV_t;

/**
 * Defines the Polarity of the data inputs.
 */
typedef enum XMC_SPI_CH_DATA_POLARITY
{
  XMC_SPI_CH_DATA_POLARITY_DIRECT = 0x0UL, /**< The polarity of the data line is not inverted */
  XMC_SPI_CH_DATA_POLARITY_INVERT = 0x1UL << USIC_CH_DX2CR_DPOL_Pos /**< The polarity of the data line is inverted */
} XMC_SPI_CH_DATA_POLARITY_t;

/**
 * Defines Slave Select lines
 */
typedef enum XMC_SPI_CH_SLAVE_SELECT
{
  XMC_SPI_CH_SLAVE_SELECT_0 = 1UL << USIC_CH_PCR_SSCMode_SELO_Pos,  /**< Slave Select line 0 */
  XMC_SPI_CH_SLAVE_SELECT_1 = 2UL << USIC_CH_PCR_SSCMode_SELO_Pos,  /**< Slave Select line 1 */
  XMC_SPI_CH_SLAVE_SELECT_2 = 4UL << USIC_CH_PCR_SSCMode_SELO_Pos,  /**< Slave Select line 2 */
  XMC_SPI_CH_SLAVE_SELECT_3 = 8UL << USIC_CH_PCR_SSCMode_SELO_Pos,  /**< Slave Select line 3 */
  XMC_SPI_CH_SLAVE_SELECT_4 = 16UL << USIC_CH_PCR_SSCMode_SELO_Pos, /**< Slave Select line 4 */
  XMC_SPI_CH_SLAVE_SELECT_5 = 32UL << USIC_CH_PCR_SSCMode_SELO_Pos, /**< Slave Select line 5 */
  XMC_SPI_CH_SLAVE_SELECT_6 = 64UL << USIC_CH_PCR_SSCMode_SELO_Pos, /**< Slave Select line 6 */
  XMC_SPI_CH_SLAVE_SELECT_7 = 128UL << USIC_CH_PCR_SSCMode_SELO_Pos /**< Slave Select line 7 */
} XMC_SPI_CH_SLAVE_SELECT_t;

/**
 * Defines SPI specific events
 */
typedef enum XMC_SPI_CH_EVENT
{
  XMC_SPI_CH_EVENT_RECEIVE_START       = USIC_CH_CCR_RSIEN_Msk, /**< Receive start event */
  XMC_SPI_CH_EVENT_DATA_LOST           = USIC_CH_CCR_DLIEN_Msk, /**< Data lost event */
  XMC_SPI_CH_EVENT_TRANSMIT_SHIFT      = USIC_CH_CCR_TSIEN_Msk, /**< Transmit shift event */
  XMC_SPI_CH_EVENT_TRANSMIT_BUFFER     = USIC_CH_CCR_TBIEN_Msk, /**< Transmit buffer event */
  XMC_SPI_CH_EVENT_STANDARD_RECEIVE    = USIC_CH_CCR_RIEN_Msk,  /**< Receive event */
  XMC_SPI_CH_EVENT_ALTERNATIVE_RECEIVE = USIC_CH_CCR_AIEN_Msk,  /**< Alternate receive event */
  XMC_SPI_CH_EVENT_BAUD_RATE_GENERATOR = USIC_CH_CCR_BRGIEN_Msk, /**< Baudrate generator event */

  XMC_SPI_CH_EVENT_PARITY_ERROR = USIC_CH_PCR_SSCMode_PARIEN_Msk >> 13U,       /**< Parity error event */
  XMC_SPI_CH_EVENT_MSLS_CHANGE =  USIC_CH_PCR_SSCMode_MSLSIEN_Msk >> 13U,      /**< Master slave select(MSLS) output transition event*/
  XMC_SPI_CH_EVENT_DX2TIEN_ACTIVATED = USIC_CH_PCR_SSCMode_DX2TIEN_Msk >> 13U  /**< Slave select input signal transition event*/
} XMC_SPI_CH_EVENT_t;

/**
 * Defines SPI event status
 */
typedef enum XMC_SPI_CH_STATUS_FLAG
{
  XMC_SPI_CH_STATUS_FLAG_MSLS = USIC_CH_PSR_SSCMode_MSLS_Msk,                          /**< Status of Master slave
                                                                                            select(MSLS) signal */
  XMC_SPI_CH_STATUS_FLAG_DX2S = USIC_CH_PSR_SSCMode_DX2S_Msk,                          /**< Status of slave select
                                                                                            input(DX2) signal*/
  XMC_SPI_CH_STATUS_FLAG_MSLS_EVENT_DETECTED = USIC_CH_PSR_SSCMode_MSLSEV_Msk,         /**< Status for master slave select
                                                                                            output signal transition*/
  XMC_SPI_CH_STATUS_FLAG_DX2T_EVENT_DETECTED = USIC_CH_PSR_SSCMode_DX2TEV_Msk,         /**< Status for slave select
                                                                                            input signal transition */
  XMC_SPI_CH_STATUS_FLAG_PARITY_ERROR_EVENT_DETECTED = USIC_CH_PSR_SSCMode_PARERR_Msk, /**< Indicates status of the
                                                                                            parity error */
  XMC_SPI_CH_STATUS_FLAG_RECEIVER_START_INDICATION = USIC_CH_PSR_SSCMode_RSIF_Msk,     /**< Status for receive start
                                                                                            event */
  XMC_SPI_CH_STATUS_FLAG_DATA_LOST_INDICATION = USIC_CH_PSR_SSCMode_DLIF_Msk,          /**< Status for data lost event*/
  XMC_SPI_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION = USIC_CH_PSR_SSCMode_TSIF_Msk,      /**< Status for transmit shift
                                                                                            event */
  XMC_SPI_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION = USIC_CH_PSR_SSCMode_TBIF_Msk,    /**< Status for transmit buffer
                                                                                            event */
  XMC_SPI_CH_STATUS_FLAG_RECEIVE_INDICATION = USIC_CH_PSR_SSCMode_RIF_Msk,             /**< Status for receive event */
  XMC_SPI_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION = USIC_CH_PSR_SSCMode_AIF_Msk, /**< Status for alternative
                                                                                            receive event */
  XMC_SPI_CH_STATUS_FLAG_BAUD_RATE_GENERATOR_INDICATION = USIC_CH_PSR_SSCMode_BRGIF_Msk/**< Status for baud rate
                                                                                            generation error event */
} XMC_SPI_CH_STATUS_FLAG_t;

/**
 * Defines input frequency sources for slave select signal delay configuration.
 */
typedef enum XMC_SPI_CH_INPUT_FREQ_SLAVE_SELECT_DELAY
{
  XMC_SPI_CH_INPUT_FREQ_SLAVE_SELECT_DELAY_FPDIV = 0x0UL, /**< Output of PDIV divider: FPDIV */
  XMC_SPI_CH_INPUT_FREQ_SLAVE_SELECT_DELAY_FPPP  = 0x1UL << USIC_CH_PCR_SSCMode_CTQSEL1_Pos, /**< Peripheral clock: FPPP */
  XMC_SPI_CH_INPUT_FREQ_SLAVE_SELECT_DELAY_FSCLK = 0x2UL << USIC_CH_PCR_SSCMode_CTQSEL1_Pos, /**< Shift clock: FSCLK */
  XMC_SPI_CH_INPUT_FREQ_SLAVE_SELECT_DELAY_FMCLK = 0x3UL << USIC_CH_PCR_SSCMode_CTQSEL1_Pos  /**< Master clock: FMCLK */
} XMC_SPI_CH_INPUT_FREQ_SLAVE_SELECT_DELAY_t;

/**
 * Define data and clock input stages
 */
typedef enum XMC_SPI_CH_INPUT
{
  XMC_SPI_CH_INPUT_DIN0 = 0UL,         /**< Data input stage 0 */
  XMC_SPI_CH_INPUT_SLAVE_SCLKIN = 1UL, /**< Clock input stage */
  XMC_SPI_CH_INPUT_SLAVE_SELIN = 2UL,  /**< Slave select input stage */
  XMC_SPI_CH_INPUT_DIN1 = 3UL,         /**< Data input stage 1 */
  XMC_SPI_CH_INPUT_DIN2 = 4UL,         /**< Data input stage 2 */
  XMC_SPI_CH_INPUT_DIN3 = 5UL          /**< Data input stage 3 */
} XMC_SPI_CH_INPUT_t;

/**
 * Define SPI data transfer mode
 */
typedef enum XMC_SPI_CH_MODE
{
  XMC_SPI_CH_MODE_STANDARD = 0UL,            /**< SPI standard full duplex mode */
  XMC_SPI_CH_MODE_STANDARD_HALFDUPLEX = 5UL, /**< SPI standard half duplex mode */
  XMC_SPI_CH_MODE_DUAL = 6UL,                /**< SPI half duplex mode with dual data lines */
  XMC_SPI_CH_MODE_QUAD = 7UL                 /**< SPI half duplex mode with quad data lines */
} XMC_SPI_CH_MODE_t;


/**
 * SPI Baudrate Generator shift clock passive level
 */
typedef enum XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL
{
  /**< Passive clock level 0, delay disabled */
  XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_DISABLED = XMC_USIC_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_DISABLED,
  /**< Passive clock level 1, delay disabled */
  XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_DISABLED = XMC_USIC_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_DISABLED,
  /**< Passive clock level 0, delay enabled */
  XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_ENABLED  = XMC_USIC_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_ENABLED,
  /**< Passive clock level 1, delay enabled */
  XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_ENABLED  = XMC_USIC_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_ENABLED
} XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_t;

/**
 * SPI clock modes
 */

/* CPOL=0 is a clock which idles at 0, and each cycle consists of a pulse of 1. That is, the leading edge is a rising edge, and the trailing edge is a falling edge */
/* CPOL=1 is a clock which idles at 1, and each cycle consists of a pulse of 0. That is, the leading edge is a falling edge, and the trailing edge is a rising edge */
/* CPHA=0, the "out" side changes the data on the trailing edge of the preceding clock cycle, while the "in" side captures the data on (or shortly after) the leading edge of the clock cycle.
   The out side holds the data valid until the trailing edge of the current clock cycle. For the first cycle, the first bit must be on the MOSI line before the leading clock edge.*/
/* For CPHA=1, the "out" side changes the data on the leading edge of the current clock cycle, while the "in" side captures the data on (or shortly after) the trailing edge of the clock cycle.
  The out side holds the data valid until the leading edge of the following clock cycle. For the last cycle, the slave holds the MISO line valid until slave select is deasserted. */
typedef enum XMC_SPI_CLOCK_MODE
{
  XMC_SPI_CPOL_0_CPHA_0 = XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_ENABLED,
  XMC_SPI_CPOL_0_CPHA_1 = XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_0_DELAY_DISABLED,
  XMC_SPI_CPOL_1_CPHA_0 = XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_DISABLED,
  XMC_SPI_CPOL_1_CPHA_1 = XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_1_DELAY_ENABLED
} XMC_SPI_CLOCK_MODE_t;

/**
 * SPI Baudrate Generator shift clock output
*/
typedef enum XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT
{
  XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_SCLK = XMC_USIC_CH_BRG_SHIFT_CLOCK_OUTPUT_SCLK,  /**< Baudrate Generator shift clock output: SCLK*/
  XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_DX1  = XMC_USIC_CH_BRG_SHIFT_CLOCK_OUTPUT_DX1   /**< Clock obtained as input from master: DX1*/
} XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_t;

/**
 * SPI channel interrupt node pointers
 */
typedef enum XMC_SPI_CH_INTERRUPT_NODE_POINTER
{
  XMC_SPI_CH_INTERRUPT_NODE_POINTER_TRANSMIT_SHIFT      = XMC_USIC_CH_INTERRUPT_NODE_POINTER_TRANSMIT_SHIFT, /**< Node pointer for transmit shift interrupt */
  XMC_SPI_CH_INTERRUPT_NODE_POINTER_TRANSMIT_BUFFER     = XMC_USIC_CH_INTERRUPT_NODE_POINTER_TRANSMIT_BUFFER, /**< Node pointer for transmit buffer interrupt */
  XMC_SPI_CH_INTERRUPT_NODE_POINTER_RECEIVE             = XMC_USIC_CH_INTERRUPT_NODE_POINTER_RECEIVE,  /**< Node pointer for receive interrupt */
  XMC_SPI_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE   = XMC_USIC_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE,  /**< Node pointer for alternate receive interrupt */
  XMC_SPI_CH_INTERRUPT_NODE_POINTER_PROTOCOL            = XMC_USIC_CH_INTERRUPT_NODE_POINTER_PROTOCOL   /**< Node pointer for protocol related interrupts */
} XMC_SPI_CH_INTERRUPT_NODE_POINTER_t;

/**********************************************************************************************************************
 * DATA STRUCTURES
**********************************************************************************************************************/

/**
 * Structure for initializing SPI channel.
 */
typedef struct XMC_SPI_CH_CONFIG
{
  uint32_t baudrate;							                /**< Module baud rate for communication */
  bool normal_divider_mode;                       /**< Selects normal divider mode for baudrate generator instead of default fractional divider decreasing jitter at cost of frequency selection */
  XMC_SPI_CH_BUS_MODE_t bus_mode;                 /**< Bus mode: Master/Slave */
  XMC_SPI_CH_SLAVE_SEL_MSLS_INV_t selo_inversion; /**< Enable inversion of Slave select signal relative to the internal
                                                       MSLS signal  */
  XMC_USIC_CH_PARITY_MODE_t parity_mode;          /**< Enable parity check for transmit and received data */
} XMC_SPI_CH_CONFIG_t;

/**********************************************************************************************************************
 * API PROTOTYPES
 *********************************************************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param config pointer to constant SPI channel configuration data structure.\n
 *               Refer data structure @ref XMC_SPI_CH_CONFIG_t for detail.
 * @param init_brg Selects if the baudrate generator should be configured automatically.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Initializes the selected SPI \a channel with the \a config structure.\n\n
 * Enable SPI channel by calling XMC_USIC_CH_Enable() and then configures
 * <ul>
 * <li>Baudrate,</li>
 * <li>Passive data level as active high,</li>
 * <li>Shift control signal as active high,</li>
 * <li>Frame length as 64U,</li>
 * <li>Word length as 8U,</li>
 * <li>Enable Hardware port control mode,</li>
 * <li>Enable transmission of data TDV(Transmit data valid) bit is set to 1,</li>
 * <li>Enable invalidation of data in TBUF once loaded into shift register,</li>
 * <li>Parity mode settings</li>
 * </ul>
 * And if master mode is selected,
 * <ul>
 * <li>Enables MSLS signal generation,</li>
 * <li>configures slave selection as normal mode,</li>
 * <li>Set polarity for the Slave signal,</li>
 * <li>Enable Frame end mode(MSLS signal is kept active after transmission of a frame)</li>
 * </ul>
 */
void XMC_SPI_CH_InitEx(XMC_USIC_CH_t *const channel, const XMC_SPI_CH_CONFIG_t *const config, bool init_brg);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param config pointer to constant SPI channel configuration data structure.\n
 *               Refer data structure @ref XMC_SPI_CH_CONFIG_t for detail.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Initializes the selected SPI \a channel with the \a config structure.\n\n
 * Enable SPI channel by calling XMC_USIC_CH_Enable() and then configures
 * <ul>
 * <li>Baudrate,</li>
 * <li>Passive data level as active high,</li>
 * <li>Shift control signal as active high,</li>
 * <li>Frame length as 64U,</li>
 * <li>Word length as 8U,</li>
 * <li>Enable Hardware port control mode,</li>
 * <li>Enable transmission of data TDV(Transmit data valid) bit is set to 1,</li>
 * <li>Enable invalidation of data in TBUF once loaded into shift register,</li>
 * <li>Parity mode settings</li>
 * </ul>
 * And if master mode is selected,
 * <ul>
 * <li>Enables MSLS signal generation,</li>
 * <li>configures slave selection as normal mode,</li>
 * <li>Set polarity for the Slave signal,</li>
 * <li>Enable Frame end mode(MSLS signal is kept active after transmission of a frame)</li>
 * </ul>
 */
__STATIC_INLINE void XMC_SPI_CH_Init(XMC_USIC_CH_t *const channel, const XMC_SPI_CH_CONFIG_t *const config)
{
  XMC_SPI_CH_InitEx(channel, config, true);
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Set the selected USIC channel to operate in SPI mode, by setting CCR.MODE bits.\n\n
 * It should be executed after XMC_SPI_CH_Init() during initialization. By invoking XMC_SPI_CH_Stop(), the MODE is set
 * to IDLE state. Call XMC_SPI_CH_Start() to set the SPI mode again, as needed later in the program.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Init(), XMC_SPI_CH_Stop()
 */
__STATIC_INLINE void XMC_SPI_CH_Start(XMC_USIC_CH_t *const channel)
{
  /* USIC channel in SPI mode */
  XMC_USIC_CH_SetMode(channel, XMC_USIC_CH_OPERATING_MODE_SPI);
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return XMC_SPI_CH_STATUS_t Status of the SPI driver after the request for stopping is processed. \n
 *        XMC_SPI_CH_STATUS_OK- If the USIC channel is successfully put to IDLE mode. \n
 *        XMC_SPI_CH_STATUS_BUSY- If the USIC channel is busy transmitting data.
 *
 * \par<b>Description:</b><br>
 * Set the selected SPI channel to IDLE mode, by clearing CCR.MODE bits.\n\n
 * After calling XMC_SPI_CH_Stop, channel is IDLE mode. So no communication is supported. XMC_SPI_CH_Start() has to be
 * invoked to start the communication again.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Start()
 */
XMC_SPI_CH_STATUS_t XMC_SPI_CH_Stop(XMC_USIC_CH_t *const channel);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param rate Bus speed in bits per second
 *
 * @return XMC_SPI_CH_STATUS_t Status of the SPI driver after the request for setting baudrate is processed. \n
 *        XMC_SPI_CH_STATUS_OK- If the baudrate is successfully changed. \n
 *        XMC_SPI_CH_STATUS_ERROR- If the new baudrate value is out of range.
 *
 * \par<b>Description:</b><br>
 * Sets the bus speed in bits per second
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Init(), XMC_SPI_CH_Stop(), XMC_USIC_CH_GetSCLKFrequency()
 */
XMC_SPI_CH_STATUS_t XMC_SPI_CH_SetBaudrate(XMC_USIC_CH_t *const channel, const uint32_t rate);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param rate Bus speed in bits per second
 * @param normal_divider_mode Selects normal divider mode for baudrate generator instead of default fractional divider decreasing jitter of signal at the cost of frequency selection
 *
 * @return XMC_SPI_CH_STATUS_t Status of the SPI driver after the request for setting baudrate is processed. \n
 *        XMC_SPI_CH_STATUS_OK- If the baudrate is successfully changed. \n
 *        XMC_SPI_CH_STATUS_ERROR- If the new baudrate value is out of range.
 *
 * \par<b>Description:</b><br>
 * Sets the bus speed in bits per second
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Init(), XMC_SPI_CH_Stop(), XMC_USIC_CH_GetSCLKFrequency()
 */
XMC_SPI_CH_STATUS_t XMC_SPI_CH_SetBaudrateEx(XMC_USIC_CH_t *const channel, const uint32_t rate, bool normal_divider_mode);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param slave Slave select signal.\n
 *              Refer @ref XMC_SPI_CH_SLAVE_SELECT_t for valid values.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enable the selected slave signal by setting PCR.SELO bits.\n\n
 * Each slave is connected with one slave select signal. This is not configured in XMC_SPI_CH_Init(). Invoke
 * XMC_SPI_CH_EnableSlaveSelect() with required \a slave to to start the communication. After finishing the
 * communication XMC_SPI_CH_DisableSlaveSelect() can be invoked to disable the slaves.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableSlaveSelect()
 */
void XMC_SPI_CH_EnableSlaveSelect(XMC_USIC_CH_t *const channel, const XMC_SPI_CH_SLAVE_SELECT_t slave);

/**
 * @param channel A constant ponter to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disable all the slave signals by clearing PCR.SELO bits.\n\n
 * XMC_SPI_CH_EnableSlaveSelect() has to be invoked to start the communication with the desired slave again.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableSlaveSelect()
 */
void XMC_SPI_CH_DisableSlaveSelect(XMC_USIC_CH_t *const channel);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param mode Communication mode of the SPI, based on this mode TCI(Transmit control information)is updated.\n
 *             Refer @ref XMC_SPI_CH_MODE_t for valid values.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * In Dual and Quad modes,  hardware port control(CCR.HPCEN) mode is enabled. \n\n
 * By enabling this the direction of the data pin is updated by hardware itself. Before transmitting the data set the
 * mode to ensure the proper communication.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Transmit()
 */
__STATIC_INLINE void XMC_SPI_CH_SetTransmitMode(XMC_USIC_CH_t *const channel, const XMC_SPI_CH_MODE_t mode)
{
  channel->CCR = (channel->CCR & (uint32_t)(~USIC_CH_CCR_HPCEN_Msk)) |
                 (((uint32_t) mode << USIC_CH_CCR_HPCEN_Pos) & (uint32_t)USIC_CH_CCR_HPCEN_Msk);
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param data Data to be transmitted
 * @param mode Communication mode of the SPI, based on this mode TCI(Transmit control information)is updated.\n
 *             Refer @ref XMC_SPI_CH_MODE_t for valid values.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Puts the data into FIFO, if FIFO mode is enabled or else into standard buffer, by setting the proper mode.\n\n
 * In Dual and Quad modes,  hardware port control(CCR.HPCEN) mode is enabled. By enabling this the direction of the data
 * pin is updated by hardware itself. TCI(Transmit Control Information) allows dynamic control of both the data shift mode
 * and pin direction during data transfers by writing to SCTR.DSM and SCTR.HPCDIR bit fields. To support this auto
 * update, TCSR.HPCMD(Hardware Port control) will be enabled during the initialization using XMC_SPI_CH_Init() for all modes.
 *
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Receive()
 */
void XMC_SPI_CH_Transmit(XMC_USIC_CH_t *const channel, const uint16_t data, const XMC_SPI_CH_MODE_t mode);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param mode Communication mode of the SPI, based on this mode TCI(Transmit control information)is updated.\n
 *             Refer @ref XMC_SPI_CH_MODE_t for valid values.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Transmits a dummy data(FFFFH) to provide clock for slave and receives the data from the slave.\n\n
 * XMC_SPI_CH_Receive() receives the data and places it into buffer based on the FIFO selection. After reception of data
 * XMC_SPI_CH_GetReceivedData() can be invoked to read the data from the buffers.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_GetReceivedDaa()
 */
__STATIC_INLINE void XMC_SPI_CH_Receive(XMC_USIC_CH_t *const channel, const XMC_SPI_CH_MODE_t mode)
{
  /* Transmit dummy data */
  XMC_SPI_CH_Transmit(channel, (uint16_t)0xffffU, (XMC_SPI_CH_MODE_t)((uint16_t)mode & 0xfffbU));
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return uint16_t Data read from the receive buffer.
 *
 * \par<b>Description:</b><br>
 * Reads data from the receive buffer based on the FIFO selection.\n\n
 * Invocation of XMC_SPI_CH_Receive() receives the data and place it into receive buffer. After receiving the data
 * XMC_SPI_CH_GetReceivedData() can be used to read the data from the buffer.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_Receive()
 */
uint16_t XMC_SPI_CH_GetReceivedData(XMC_USIC_CH_t *const channel);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Set the order of data transfer from LSB to MSB, by clearing SCTR.SDIR bit.\n\n
 * This is typically based on the slave settings. Invoke XMC_SPI_CH_SetBitOrderLsbFirst() to set direction as needed in
 * the program.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_SetBitOrderMsbFirst()
 */
__STATIC_INLINE void XMC_SPI_CH_SetBitOrderLsbFirst(XMC_USIC_CH_t *const channel)
{
  channel->SCTR &= (uint32_t)~USIC_CH_SCTR_SDIR_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Set the order of data transfer from MSB to LSB, by setting SCTR.SDIR bit.\n\n
 * This is typically based on the slave settings. This is not set during XMC_SPI_CH_Init().
 * Invoke XMC_SPI_CH_SetBitOrderMsbFirst() to set direction as needed in the program.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_SetBitOrderLsbFirst()
 */
__STATIC_INLINE void XMC_SPI_CH_SetBitOrderMsbFirst(XMC_USIC_CH_t *const channel)
{
  channel->SCTR |= (uint32_t)USIC_CH_SCTR_SDIR_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param event Protocol events which have to be enabled.
 *              Refer @ XMC_SPI_CH_EVENT_t for valid values. <b>OR</b> combinations of these enum items can be used
 *              as input.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enables the SPI protocol specific events, by configuring PCR register.\n\n
 * Events can be enabled as needed using XMC_SPI_CH_EnableEvent().
 * XMC_SPI_CH_DisableEvent() can be used to disable the events.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableEvent()
 */
void XMC_SPI_CH_EnableEvent(XMC_USIC_CH_t *const channel, const uint32_t event);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param event Protocol events which have to be disabled.
 *              Refer @ XMC_SPI_CH_EVENT_t for valid values. <b>OR</b> combinations of these enum item can be used
 *              as input.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disables the SPI protocol specific events, by configuring PCR register.\n\n
 * After disabling the events, XMC_SPI_CH_EnableEvent() has to be invoked to re-enable the events.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableEvent()
 */
void XMC_SPI_CH_DisableEvent(XMC_USIC_CH_t *const channel, const uint32_t event);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return uint32_t Status of SPI protocol events.
 *
 * \par<b>Description:</b><br>
 * Returns the status of the events, by reading PSR register.\n\n
 * This indicates the status of the all the events, for SPI communication.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_ClearStatusFlag()
 */
__STATIC_INLINE uint32_t XMC_SPI_CH_GetStatusFlag(XMC_USIC_CH_t *const channel)
{
  return channel->PSR_SSCMode;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param flag Protocol event status to be cleared for detection of next occurence.
 *              Refer @ XMC_SPI_CH_STATUS_FLAG_t for valid values. <b>OR</b> combinations of these enum item can be used
 *              as input.
 * @return None
 *
 * \par<b>Description:</b><br>
 * Clears the events specified, by setting PSCR register.\n\n
 * During communication the events occurred have to be cleared to detect their next occurence.\n
 * e.g: During transmission Transmit buffer event occurs to indicating data word transfer has started. This
 *       event has to be cleared after transmission of each data word. Otherwise next event cannot be recognized.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_GetStatusFlag()
 */
__STATIC_INLINE void XMC_SPI_CH_ClearStatusFlag(XMC_USIC_CH_t *const channel, const uint32_t flag)
{
  channel->PSCR |= flag;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enables the generation of Master clock by setting PCR.MCLK bit.\n\n
 * This clock can be used as a clock reference for external devices. This is not enabled during initialization in
 * XMC_SPI_CH_Init(). Invoke XMC_SPI_CH_EnableMasterClock() to enable as needed in the program, or if it is disabled by
 * XMC_SPI_CH_DisableMasterClock().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableMasterClock()
 */
__STATIC_INLINE void XMC_SPI_CH_EnableMasterClock(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode |= (uint32_t)USIC_CH_PCR_SSCMode_MCLK_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disables the generation of Master clock by clearing PCR.MCLK bit.\n\n
 * This clock can be enabled by invoking XMC_SPI_CH_EnableMasterClock() as needed in the program.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableMasterClock()
 */
__STATIC_INLINE void XMC_SPI_CH_DisableMasterClock(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode &= (uint32_t)~USIC_CH_PCR_SSCMode_MCLK_Msk;
}
#ifdef USIC_CH_PCR_SSCMode_SLPHSEL_Msk
/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Data bits are shifted out with the leading edge of the shift clock signal and latched in with the trailing edge.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DataLatchedInLeadingEdge()
 */
__STATIC_INLINE void XMC_SPI_CH_DataLatchedInTrailingEdge(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode &= (uint32_t)~USIC_CH_PCR_SSCMode_SLPHSEL_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * The first data bit is shifted out when the data shift unit receives a low to high transition from the DX2
 * stage. Subsequent bits are shifted out with the trailing edge of the shift clock signal. Data bits are
 * always latched in with the leading edge.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DataLatchedInTrailingEdge()
 */
__STATIC_INLINE void XMC_SPI_CH_DataLatchedInLeadingEdge(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode |= USIC_CH_PCR_SSCMode_SLPHSEL_Msk;
}
#endif
/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Enables the delay after each word, by setting PCR.TIWEN bit.\n\n
 * The inter word delay starts at the end of last SCLK cycle of data word. During this time no clock pulses are
 * generated and MSLS signal stays active. If inter word delay is not enabled, last data bit of a data word is directly
 * followed by the first data bit of the next data word. This is not enabled in XMC_SPI_CH_Init(). To enable
 * XMC_SPI_CH_EnableInterwordDelay() has to be invoked as needed in the program. And can be disabled by invoking
 * XMC_SPI_CH_DisableInterwordDelay().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableInterwordDelay()
 */
__STATIC_INLINE void XMC_SPI_CH_EnableInterwordDelay(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode |= (uint32_t)USIC_CH_PCR_SSCMode_TIWEN_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Disables the delay after after each word, by clearing PCR.TIWEN bit.\n\n
 * So the last data bit of a data word is directly followed by the first data bit of the next data word. If needed can
 * be enabled by invoking XMC_SPI_CH_EnableInterwordDelay().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableInterwordDelay()
 */
__STATIC_INLINE void XMC_SPI_CH_DisableInterwordDelay(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode &= (uint32_t)~USIC_CH_PCR_SSCMode_TIWEN_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param tinterword_delay_ns delay in terms of nano seconds.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Configures the inter word delay by setting PCR.PCTQ1, PCR.DCTQ1 bit fields.\n\n
 * The inter word delay is dependent on the peripheral clock. The maximum possible value is calculated by using the
 * below formula\n
 *            Maximum inter word delay = ((1 + PCTQ1_max)(1 + DCTQ1_max)) / peripheral clock\n
 *                                       where PCTQ1_max = 3 and DCTQ1_max = 31\n
 * After configuring the inter word delay, this has to be enabled by invoking XMC_SPI_CH_EnableInterwordDelay().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableInterwordDelay(),XMC_SPI_CH_SetInterwordDelaySCLK()
 */
void XMC_SPI_CH_SetInterwordDelay(XMC_USIC_CH_t *const channel, uint32_t tinterword_delay_ns);

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param sclk_period  in terms of clk cycles.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Configures the inter word delay by setting PCR.DCTQ1 bit fields.\n\n
 * This delay is dependent on the peripheral clock. The maximum possible value supported by this API
 * is 32 clock cycles.
 * After configuring the inter word delay, this has to be enabled by invoking XMC_SPI_CH_EnableInterwordDelay().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableInterwordDelay(),XMC_SPI_CH_EnableInterwordDelay()
 */
__STATIC_INLINE void XMC_SPI_CH_SetInterwordDelaySCLK(XMC_USIC_CH_t *const channel, uint32_t sclk_period)
{
  channel->PCR_SSCMode = (uint32_t)((channel->PCR_SSCMode) & (~(USIC_CH_PCR_SSCMode_DCTQ1_Msk |
                                    USIC_CH_PCR_SSCMode_PCTQ1_Msk |
                                    USIC_CH_PCR_SSCMode_CTQSEL1_Msk))) |
                         (((sclk_period - 1U) <<  USIC_CH_PCR_SSCMode_DCTQ1_Pos) |
                          (0x02U <<  USIC_CH_PCR_SSCMode_CTQSEL1_Pos));
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param sclk_period delay in terms of sclk clock cycles.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Configures the leading/trailing delay by setting BRG.DCTQ bit field.\n\n
 * This delay is dependent on the peripheral clock. The maximum possible value supported by this API
 * is 30 clock cycles.
 *
 */
__STATIC_INLINE void XMC_SPI_CH_SetSlaveSelectDelay(XMC_USIC_CH_t *const channel, uint32_t sclk_period)
{

  channel->BRG = (channel->BRG & ~(USIC_CH_BRG_DCTQ_Msk |
                                   USIC_CH_BRG_PCTQ_Msk)) |
                 (((sclk_period - 1U) << USIC_CH_BRG_DCTQ_Pos) | (0x01U << USIC_CH_BRG_PCTQ_Pos));
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 *
 * Configure to keep MSLS(Slave select signal) active even after finishing the current data frame,
 * by setting PCR.FEM bit.\n\n
 * This is typically used during the transmission of multi-data word frames, where there is possibility of delay in
 * delivering the data. Frame end mode is enabled in XMC_SPI_CH_Init() during initialization. To disable
 * XMC_SPI_CH_DisableFEM() can be invoked as needed in the program.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableFEM()
 */
__STATIC_INLINE void XMC_SPI_CH_EnableFEM(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode |= (uint32_t)USIC_CH_PCR_SSCMode_FEM_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Configure to disable the MSLS(Slave select signal) if the current data frame is considered as finished,
 * by setting PCR.FEM bit.\n\n
 *
 * When the last bit of a data word has been sent out and the transmit buffer TBUF does not contain new data, is
 * considered as frame is ended and MSLS(Slave select signal) is disabled.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableFEM()
 */
__STATIC_INLINE void XMC_SPI_CH_DisableFEM(XMC_USIC_CH_t *const channel)
{
  channel->PCR_SSCMode &= (uint32_t)~USIC_CH_PCR_SSCMode_FEM_Msk;
}

/**
 * @param channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param passive_level polarity and delay of the selected shift clock.\n
 *                      Refer @ref XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_t for valid inputs.
 * @param clock_output shift clock source.\n
 *                     Refer @ref XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_t for valid inputs.
 *
 * @return None
 *
 * \par<b>Description:</b><br>
 * Configures the shift clock source with the selected polarity and delay by setting BRG.SCLKOSEL and BRG.SCLKCFG.\n\n
 * In Master mode operation, shift clock is generated by the internal baud rate generator. This SCLK is made available
 * for external slave devices by SCLKOUT signal.\n
 * In Slave mode, the signal is received from the external master. So the DX1(input) stage has to be connected to input.\n
 * The shift clock output(SCLKOUT) signal polarity can be set relative to SCLK, with the delay of half the shift clock
 * period. These settings are applicable only in master mode.
 */
__STATIC_INLINE void XMC_SPI_CH_ConfigureShiftClockOutput(XMC_USIC_CH_t *const channel,
    const XMC_SPI_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_t passive_level,
    const XMC_SPI_CH_BRG_SHIFT_CLOCK_OUTPUT_t clock_output)
{
  XMC_USIC_CH_ConfigureShiftClockOutput(channel, (XMC_USIC_CH_BRG_SHIFT_CLOCK_PASSIVE_LEVEL_t)passive_level,
                                        (XMC_USIC_CH_BRG_SHIFT_CLOCK_OUTPUT_t)clock_output);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param  word_length Number of bits to be configured for a data word. \n
 *         \b Range: 1 to 16.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Defines the data word length.\n\n
 * Sets the number of bits to represent a data word. Frame length should be a multiple of word length.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_SetFrameLength()
 */
__STATIC_INLINE void XMC_SPI_CH_SetWordLength(XMC_USIC_CH_t *const channel, const uint8_t word_length)
{
  XMC_USIC_CH_SetWordLength(channel, word_length);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param  frame_length Number of bits in a frame. \n
 *                \b Range: 1 to 64. If the value 64 is configured, then the frame does not
 *                automatically end. User should explicitly end the frame.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Define the data frame length.\n\n
 * Set the number of bits to be serially transmitted in a frame.
 * The frame length should be multiples of word length. If the value is set to 64, the frame does not
 * automatically end. Use XMC_SPI_CH_DisableSlaveSelect() to end the frame after all the data
 * is transmitted.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_USIC_CH_SetWordLength(), XMC_USIC_CH_EnableFrameLengthControl(), XMC_SPI_CH_DisableSlaveSelect()
 */
__STATIC_INLINE void XMC_SPI_CH_SetFrameLength(XMC_USIC_CH_t *const channel, const uint8_t frame_length)
{
  XMC_USIC_CH_SetFrameLength(channel, frame_length);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Configure the handling of start of frame through software, by setting TCSR.SOF bit.\n\n
 * This can be used if the software handles the TBUF data without FIFO. If SOF is set, a valid content of the TBUF is
 * considered as first word of a new frame by finishing the currently running frame. For software handling of SOF bit,
 * it is recommended to configure TCSR.WLEMD as 0. This is not configured during initialization. XMC_SPI_CH_EnableSOF()
 * can be called as needed in the program and can be disabled by XMC_SPI_CH_DisableSOF().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableSOF()
 */
__STATIC_INLINE void XMC_SPI_CH_EnableSOF(XMC_USIC_CH_t *const channel)
{
  channel->TCSR |= (uint32_t)USIC_CH_TCSR_SOF_Msk;
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Set the control of the handling start of frame through hardware, by clearing TCSR.SOF bit.\n\n
 * Typically this can be disabled, where the transmission control is done by the hardware.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableSOF()
 */
__STATIC_INLINE void XMC_SPI_CH_DisableSOF(XMC_USIC_CH_t *const channel)
{
  channel->TCSR &= (uint32_t)~USIC_CH_TCSR_SOF_Msk;
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Configure the handling of end of frame through software, by setting TCSR.EOF bit.\n\n
 * This can be used if the software handles the TBUF data without FIFO. If EOF is set, a valid content of the TBUF is
 * considered as last word of a frame. After transfer of the last word, MSLS signal becomes inactive. For software
 * handling of EOF bit, it is recommended to configure TCSR.WLEMD as 0. \n
 * \b Note: The API should be called before putting the last data word of the frame to TBUF.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableEOF()
 */
__STATIC_INLINE void XMC_SPI_CH_EnableEOF(XMC_USIC_CH_t *const channel)
{
  channel->TCSR |= (uint32_t)USIC_CH_TCSR_EOF_Msk;
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Configure the handling of end of frame through hardware, by clearing TCSR.EOF bit.\n\n
 * Typically this can be disabled, where the transmission control is done by the hardware.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableEOF()
 */
__STATIC_INLINE void XMC_SPI_CH_DisableEOF(XMC_USIC_CH_t *const channel)
{
  channel->TCSR &= (uint32_t)~USIC_CH_TCSR_EOF_Msk;
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param  input SPI channel input stage.\n
 *               Refer @ref XMC_SPI_CH_INPUT_t for valid values
 * @param  source Input source select for the input stage.
 *                Range : [0 to 7]
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Selects the data source for SPI input stage, by configuring DXCR.DSEL bits.\n\n
 * Selects the input data signal source among DXnA, DXnB.. DXnG for the input stage. The API can be used for all the
 * input stages like DX0CR, DX1CR etc. This is not done during initialization. This has to be configured before starting
 * the SPI communication.
 */
__STATIC_INLINE void XMC_SPI_CH_SetInputSource(XMC_USIC_CH_t *const channel,
    const XMC_SPI_CH_INPUT_t input,
    const uint8_t source)
{
  channel->DXCR[input] = (uint32_t)(channel->DXCR[input] & (~USIC_CH_DX0CR_DSEN_Msk)) | USIC_CH_DX0CR_INSW_Msk;
  XMC_USIC_CH_SetInputSource(channel, (XMC_USIC_CH_INPUT_t)input, source);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param  selo_inversion Polarity of the slave select signal relative to the MSLS signal.\n
 *               Refer @ref XMC_SPI_CH_SLAVE_SEL_MSLS_INV_t for valid values
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Set the polarity of the slave select signal, by configuring PCR.SELINV bit.\n\n
 * Normally MSLS signal is active low level signal. SO based on the slave inversion has to be applied. This is configured
 * in XMC_SPI_CH_Init() during initialization. Invoke XMC_SPI_CH_SetSlaveSelectPolarity() with desired settings as
 * needed later in the program.
 */
__STATIC_INLINE void XMC_SPI_CH_SetSlaveSelectPolarity(XMC_USIC_CH_t *const channel,
    const XMC_SPI_CH_SLAVE_SEL_MSLS_INV_t selo_inversion)
{
  /* Configuration of Protocol Control Register */
  channel->PCR_SSCMode = (uint32_t)((channel->PCR_SSCMode & (~USIC_CH_PCR_SSCMode_SELINV_Msk)) | (uint32_t)selo_inversion);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param  input SPI channel input stage.\n
 *               Refer @ref XMC_SPI_CH_INPUT_t for valid inputs.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Enables the polarity inversion of input data signal, by setting DXyCR.DPOL(where y = \a input).\n\n
 * This is not set in XMC_SPI_CH_Init(). Invoke XMC_SPI_CH_EnableInputInversion() as needed later in the program. To
 * disable the inversion XMC_SPI_CH_DisableInputInversion() can be invoked.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableInputInversion()
 */
__STATIC_INLINE void XMC_SPI_CH_EnableInputInversion(XMC_USIC_CH_t *const channel,
    const XMC_SPI_CH_INPUT_t input)
{
  XMC_USIC_CH_EnableInputInversion(channel, (XMC_USIC_CH_INPUT_t)input);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param  input SPI channel input stage.\n
 *               Refer @ref XMC_SPI_CH_INPUT_t for valid inputs.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Disables the polarity inversion of input data signal, by clearing DXyCR.DPOL(where y = \a input).\n\n
 * Resets the input data polarity. Invoke XMC_SPI_CH_EnableInputInversion() to apply inversion.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableInputInversion()
 */
__STATIC_INLINE void XMC_SPI_CH_DisableInputInversion(XMC_USIC_CH_t *const channel,
    const XMC_SPI_CH_INPUT_t input)
{
  XMC_USIC_CH_DisableInputInversion(channel, (XMC_USIC_CH_INPUT_t)input);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 * @param service_request Service request number.
                          Range: [0 to 5]
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Sets the interrupt node for SPI channel events.\n\n
 * For an event to generate interrupt, node pointer should be configured with service request(SR0, SR1..SR5).
 * The NVIC node gets linked to the interrupt event by doing so. This is not configured in XMC_SPI_CH_Init() during
 * initialization.
 *
 * \par<b>Note::</b><BR>
 * 1. NVIC node should be separately enabled to generate the interrupt.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_USIC_CH_EnableEvent()
 */
__STATIC_INLINE void XMC_SPI_CH_SetInterruptNodePointer(XMC_USIC_CH_t *const channel,
    const uint8_t service_request)
{
  XMC_USIC_CH_SetInterruptNodePointer(channel, XMC_USIC_CH_INTERRUPT_NODE_POINTER_PROTOCOL, (uint32_t)service_request);
}


/**
 * @param channel Pointer to USIC channel handler of type @ref XMC_USIC_CH_t \n
 * 				  \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @param  interrupt_node Interrupt node pointer to be configured. \n
 * 						  \b Range: @ref XMC_SPI_CH_INTERRUPT_NODE_POINTER_TRANSMIT_SHIFT,
 * 						  			@ref XMC_SPI_CH_INTERRUPT_NODE_POINTER_TRANSMIT_BUFFER etc.
 * @param service_request Service request number.\n
 * 						  \b Range: 0 to 5.
 * @return None
 *
 * \par<b>Description</b><br>
 * Sets the interrupt node for USIC channel events. \n\n
 * For an event to generate interrupt, node pointer should be configured with service request(SR0, SR1..SR5).
 * The NVIC node gets linked to the interrupt event by doing so.<br>
 * Note: NVIC node should be separately enabled to generate the interrupt.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableEvent() \n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_SelectInterruptNodePointer(XMC_USIC_CH_t *const channel,
    const XMC_SPI_CH_INTERRUPT_NODE_POINTER_t interrupt_node,
    const uint32_t service_request)
{
  XMC_USIC_CH_SetInterruptNodePointer(channel, (XMC_USIC_CH_INTERRUPT_NODE_POINTER_t)interrupt_node,
                                      (uint32_t)service_request);
}

/**
 * @param  channel Pointer to USIC channel handler of type @ref XMC_USIC_CH_t \n
 * 				   \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @param  service_request_line service request number of the event to be triggered. \n
 * 			\b Range: 0 to 5.
 * @return None
 *
 * \par<b>Description</b><br>
 * Trigger a SPI interrupt service request.\n\n
 * When the SPI service request is triggered, the NVIC interrupt associated with it will be
 * generated if enabled.
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_SelectInterruptNodePointer() \n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_TriggerServiceRequest(XMC_USIC_CH_t *const channel, const uint32_t service_request_line)
{
  XMC_USIC_CH_TriggerServiceRequest(channel, (uint32_t)service_request_line);
}

/**
 * @param  channel Pointer to USIC channel handler of type @ref XMC_USIC_CH_t \n
 * 				   \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @return None
 *
 * \par<b>Description</b><br>
 * Enables delay compensation. \n\n
 *
 * Delay compensation can be applied to the receive path.
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableDelayCompensation()\n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_EnableDelayCompensation(XMC_USIC_CH_t *const channel)
{
  XMC_USIC_CH_EnableDelayCompensation(channel);
}

/**
 * @param  channel Pointer to USIC channel handler of type @ref XMC_USIC_CH_t \n
 * 				   \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @return None
 *
 * \par<b>Description</b><br>
 * Disables delay compensation.. \n\n
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableDelayCompensation()\n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_DisableDelayCompensation(XMC_USIC_CH_t *const channel)
{
  XMC_USIC_CH_DisableDelayCompensation(channel);
}

/**
 * @param  channel Pointer to USIC channel handler of type @ref XMC_USIC_CH_t \n
 * 				   \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @param  pdiv Desired divider for the external frequency input. \b Range: minimum value = 1, maximum value = 1024 \n
 * @param  combination_mode  USIC channel input combination mode \n
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Enables the external frequency input for the Baudrate Generator and configures the divider, oversampling and
 * the combination mode of the USIC channel. \n\n
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_USIC_CH_SetBRGInputClockSource(), XMC_USIC_CH_SetInputTriggerCombinationMode() \n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_ConfigExternalInputSignalToBRG(XMC_USIC_CH_t *const channel,
    const uint16_t pdiv,
    const XMC_USIC_CH_INPUT_COMBINATION_MODE_t combination_mode)
{
  XMC_USIC_CH_ConfigExternalInputSignalToBRG(channel, pdiv, 2U, combination_mode);
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * The SELOx lines (with x = 1-7) can be used as addresses for an external address
 * decoder to increase the number of external slave devices.
 */
__STATIC_INLINE void XMC_SPI_CH_EnableSlaveSelectCodedMode(XMC_USIC_CH_t *const channel)
{
  /* Configuration of Protocol Control Register */
  channel->PCR_SSCMode = (uint32_t)(channel->PCR_SSCMode & (~USIC_CH_PCR_SSCMode_SELCTR_Msk));
}

/**
 * @param  channel A constant pointer to XMC_USIC_CH_t, pointing to the USIC channel base address.
 *
 * @return None
 *
 * \par<b>Description</b><br>
 * Each SELOx line (with x = 0-7) can be directly connected to an external slave device.
 */
__STATIC_INLINE void XMC_SPI_CH_DisableSlaveSelectCodedMode(XMC_USIC_CH_t *const channel)
{
  /* Configuration of Protocol Control Register */
  channel->PCR_SSCMode |= (uint32_t)USIC_CH_PCR_SSCMode_SELCTR_Msk;
}

/**
 * @param channel Constant pointer to USIC channel handle of type @ref XMC_USIC_CH_t \n
 *          \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @return None
 *
 * \par<b>Description</b><br>
 * Enable data transmission.\n\n
 * Use this function in combination with XMC_SPI_CH_DisableDataTransmission() to fill the FIFO and send the FIFO content without gaps in the transmission.
 * FIFO is filled using XMC_USIC_CH_TXFIFO_PutData().
 * @note If you need more control over the start of transmission use XMC_USIC_CH_SetStartTransmisionMode()
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_DisableDataTransmission()\n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_EnableDataTransmission(XMC_USIC_CH_t *const channel)
{
  XMC_USIC_CH_SetStartTransmisionMode(channel, XMC_USIC_CH_START_TRANSMISION_ON_TDV);
}

/**
 * @param channel Constant pointer to USIC channel handle of type @ref XMC_USIC_CH_t \n
 *          \b Range: @ref XMC_SPI0_CH0, @ref XMC_SPI0_CH1,@ref XMC_SPI1_CH0,@ref XMC_SPI1_CH1,@ref XMC_SPI2_CH0,@ref XMC_SPI2_CH1 @note Availability of SPI1 and SPI2 depends on device selection
 * @return None
 *
 * \par<b>Description</b><br>
 * Disable data transmission.\n\n
 * Use this function in combination with XMC_SPI_CH_EnableDataTransmission() to fill the FIFO and send the FIFO content without gaps in the transmission.
 * FIFO is filled using XMC_USIC_CH_TXFIFO_PutData().
 *
 * \par<b>Related APIs:</b><BR>
 * XMC_SPI_CH_EnableDataTransmission()\n\n\n
 */
__STATIC_INLINE void XMC_SPI_CH_DisableDataTransmission(XMC_USIC_CH_t *const channel)
{
  XMC_USIC_CH_SetStartTransmisionMode(channel, XMC_USIC_CH_START_TRANSMISION_DISABLED);
}

#ifdef __cplusplus
}
#endif

/**
 * @}
 */

/**
 * @}
 */

#endif
