/**
 * @file xmc_usic.c
 * @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 draft <br>
 *     - Documentation improved <br>
 *
 * 2015-05-08:
 *     - Clearing bit fields PDIV, PCTQ, PPPEN in XMC_USIC_CH_SetBaudrate() API <br>
 *
 * 2015-06-20:
 *     - Removed version macros and declaration of GetDriverVersion API <br>
 *
 * 2015-08-27:
 *     - Added APIs for external input for BRG configuration:XMC_USIC_CH_ConfigExternalInputSignalToBRG() <br>
 *
 * 2015-08-28:
 *     - Added asserts to XMC_USIC_CH_ConfigExternalInputSignalToBRG() <br>
 *
 * 2015-09-01:
 *     - Fixed warning in the asserts <br>
 *
 * 2018-09-29:
 *     - Added XMC_USIC_CH_SetBaudrateEx which uses the integer divider instead of the fractional divider <br>
 *
 * 2019-03-30:
 *     - Changed XMC_USIC_Enable() adding polling to check clock ungate
 *
 * 2019-05-07:
 *     - Added XMC_USIC_CH_GetBaudrate(), XMC_USIC_CH_GetSCLKFrequency() and XMC_USIC_CH_GetMCLKFrequency()
 *
 * 2019-07-01:
 *     - XMC_USIC_CH_SetBaudrateEx() change type of input parameters
 *
 * 2019-09-25:
 *     - Fixed XMC_USIC_CH_SetBaudrate() which under certain circumtances, i.e. if fPERI == baudrate * oversampling, delivers wrong calculations
 *
 * 2020-04-30:
 *     - Fixed XMC_USIC_CH_TXFIFO_SetSizeTriggerLimit() and  XMC_USIC_CH_RXFIFO_SetSizeTriggerLimit(), avoid disabling the FIFO while the channel is active.
 *       For new projects please use XMC_USIC_CH_TXFIFO_SetTriggerLimit() and XMC_USIC_CH_RXFIFO_SetTriggerLimit()
 *
 * 2020-12-05:
 *     - Added XMC_USIC_CH_SetBaudrateDivider()
 * 
 * @endcond
 *
 */

/*******************************************************************************
 * HEADER FILES
 *******************************************************************************/

#include "xmc_usic.h"
#include "xmc_scu.h"

#include <stdlib.h>     /* abs */

/*******************************************************************************
 * MACROS
 *******************************************************************************/

#define USIC_CH_INPR_Msk       (0x7UL)

/*******************************************************************************
 * API IMPLEMENTATION
 *******************************************************************************/

void XMC_USIC_CH_Enable(XMC_USIC_CH_t *const channel)
{
  XMC_ASSERT("XMC_USIC_CH_Enable: channel not valid", XMC_USIC_IsChannelValid(channel));

  if ((channel == XMC_USIC0_CH0) || (channel == XMC_USIC0_CH1))
  {
    XMC_USIC_Enable(XMC_USIC0);
  }
#if defined(USIC1)
  else if ((channel == XMC_USIC1_CH0) || (channel == XMC_USIC1_CH1))
  {
    XMC_USIC_Enable(XMC_USIC1);
  }
#endif
#if defined(USIC2)
  else if ((channel == XMC_USIC2_CH0) || (channel == XMC_USIC2_CH1))
  {
    XMC_USIC_Enable(XMC_USIC2);
  }
#endif
  else
  {
    XMC_ASSERT("USIC module not available", 0U/*Always*/);
  }

  /* USIC channel switched on*/
  channel->KSCFG = (USIC_CH_KSCFG_MODEN_Msk | USIC_CH_KSCFG_BPMODEN_Msk);
  while ((channel->KSCFG & USIC_CH_KSCFG_MODEN_Msk) == 0U)
  {
    /* Wait till the channel is enabled */
  }

  /* Set USIC channel in IDLE mode */
  channel->CCR &= (uint32_t)~USIC_CH_CCR_MODE_Msk;
}

void XMC_USIC_CH_Disable(XMC_USIC_CH_t *const channel)
{
  channel->KSCFG = (uint32_t)((channel->KSCFG & (~USIC_CH_KSCFG_MODEN_Msk)) | USIC_CH_KSCFG_BPMODEN_Msk);
}

XMC_USIC_CH_STATUS_t XMC_USIC_CH_SetBaudrate(XMC_USIC_CH_t *const channel, uint32_t rate, uint32_t oversampling)
{
  XMC_USIC_CH_STATUS_t status;

  uint32_t peripheral_clock;

  uint32_t clock_divider;
  uint32_t clock_divider_min;

  uint32_t pdiv;
  uint32_t pdiv_int;
  uint32_t pdiv_int_min;

  uint32_t pdiv_frac;
  uint32_t pdiv_frac_min;

  /* The rate and peripheral clock are divided by 100 to be able to use only 32bit arithmetic */
  if ((rate >= 100U) && (oversampling != 0U))
  {
    peripheral_clock = XMC_SCU_CLOCK_GetPeripheralClockFrequency() / 100U;
    rate = rate / 100U;

    clock_divider_min = 1024U;
    pdiv_int_min = 1U;
    pdiv_frac_min = 0x3ffU;

    for (clock_divider = 1024U; clock_divider > 0U; --clock_divider)
    {
      pdiv = ((peripheral_clock * clock_divider) / (rate * oversampling));
      pdiv_int = pdiv >> 10U;
      pdiv_frac = pdiv & 0x3ffU;

      if ((pdiv_int <= 1024U) && (pdiv_frac < pdiv_frac_min))
      {
        pdiv_frac_min = pdiv_frac;
        pdiv_int_min = pdiv_int;
        clock_divider_min = clock_divider;
      }
    }

    channel->FDR = XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL |
                   ((clock_divider_min - 1) << USIC_CH_FDR_STEP_Pos);

    channel->BRG = (channel->BRG & ~(USIC_CH_BRG_DCTQ_Msk |
                                     USIC_CH_BRG_PDIV_Msk |
                                     USIC_CH_BRG_PCTQ_Msk |
                                     USIC_CH_BRG_PPPEN_Msk)) |
                   ((oversampling - 1U) << USIC_CH_BRG_DCTQ_Pos) |
                   ((pdiv_int_min - 1U) << USIC_CH_BRG_PDIV_Pos);

    status = XMC_USIC_CH_STATUS_OK;
  }
  else
  {
    status = XMC_USIC_CH_STATUS_ERROR;
  }

  return status;
}

XMC_USIC_CH_STATUS_t XMC_USIC_CH_SetBaudrateEx(XMC_USIC_CH_t *const channel, int32_t rate, int32_t oversampling)
{
  int32_t peripheral_clock = XMC_SCU_CLOCK_GetPeripheralClockFrequency();
  int32_t brg_clock = rate * oversampling;
  int32_t actual_rate_upper;
  int32_t actual_rate_lower;
  uint32_t pdiv = 1;
  uint32_t divider_step;
  XMC_USIC_CH_STATUS_t status;

  if (peripheral_clock > brg_clock)
  {
    divider_step = peripheral_clock / brg_clock; // integer division gets truncated
    while (divider_step >= 1023)
    {
      pdiv++;
      brg_clock = rate * oversampling * pdiv;
      divider_step = peripheral_clock / brg_clock; // integer division gets truncated
    }
    actual_rate_upper = peripheral_clock / (divider_step * oversampling * pdiv);
    actual_rate_lower = peripheral_clock / ((divider_step + 1) * oversampling * pdiv);

    // choose better approximation if the peripheral frequency is not a multiple of the baudrate
    if (abs(rate - actual_rate_lower) < abs(rate - actual_rate_upper))
    {
      divider_step += 1;
    }

    divider_step = 1024 - divider_step;


    channel->FDR = XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_NORMAL |
                   (divider_step << USIC_CH_FDR_STEP_Pos);

    channel->BRG = (channel->BRG & ~(USIC_CH_BRG_DCTQ_Msk |
                                     USIC_CH_BRG_PDIV_Msk |
                                     USIC_CH_BRG_PCTQ_Msk |
                                     USIC_CH_BRG_PPPEN_Msk)) |
                   ((oversampling - 1U) << USIC_CH_BRG_DCTQ_Pos) |
                   ((pdiv - 1) << USIC_CH_BRG_PDIV_Pos);

    status = XMC_USIC_CH_STATUS_OK;
  }
  else
  {
    status = XMC_USIC_CH_STATUS_ERROR;
  }

  return status;
}

void XMC_USIC_CH_SetBaudrateDivider(XMC_USIC_CH_t *const channel, 
                                    XMC_USIC_CH_BRG_CLOCK_SOURCE_t clksel,
                                    bool pppen,
                                    uint32_t pdiv,
                                    XMC_USIC_CH_BRG_CTQSEL_t ctqsel,
                                    uint32_t pctq,
                                    uint32_t dctq)
{
    uint32_t regval = channel->BRG;
    regval &= (uint32_t)~(USIC_CH_BRG_CLKSEL_Msk | USIC_CH_BRG_PPPEN_Msk | USIC_CH_BRG_PDIV_Msk | USIC_CH_BRG_CTQSEL_Msk | USIC_CH_BRG_PCTQ_Msk | USIC_CH_BRG_DCTQ_Msk);
    regval |= clksel | (pppen ? USIC_CH_BRG_PPPEN_Msk : 0) | (pdiv << USIC_CH_BRG_PDIV_Pos) | ctqsel | (pctq << USIC_CH_BRG_PCTQ_Pos) | (dctq << USIC_CH_BRG_DCTQ_Pos);
    channel->BRG = regval;
}

uint32_t XMC_USIC_CH_GetBaudrate(XMC_USIC_CH_t *const channel)
{
  uint32_t divider;
  if ((channel->BRG & USIC_CH_BRG_CTQSEL_Msk) == USIC_CH_BRG_CTQSEL_Msk)
  {
    // CTQSEL = 3
    divider = 2;
  }
  else
  {
    // CTQSEL = 0, 1, or 2
    divider = (channel->BRG & USIC_CH_BRG_PPPEN_Msk) ? 2 : 1;

    if ((((channel->BRG & USIC_CH_BRG_CTQSEL_Msk) >> USIC_CH_BRG_CTQSEL_Pos) & 0x1) == 0)
    {
      // CTQSEL = 0 or 2
      divider *= ((channel->BRG & USIC_CH_BRG_PDIV_Msk) >> USIC_CH_BRG_PDIV_Pos) + 1;
      if ((((channel->BRG & USIC_CH_BRG_CTQSEL_Msk) >> USIC_CH_BRG_CTQSEL_Pos) & 0x2) != 0)
      {
        // CTQSEL = 2
        divider *= 2;
      }
    }
  }

  divider *= ((channel->BRG & USIC_CH_BRG_PCTQ_Msk) >> USIC_CH_BRG_PCTQ_Pos) + 1;
  divider *= ((channel->BRG & USIC_CH_BRG_DCTQ_Msk) >> USIC_CH_BRG_DCTQ_Pos) + 1;

  uint32_t fperi = XMC_SCU_CLOCK_GetPeripheralClockFrequency();
  float baudrate;
  if ((channel->FDR & USIC_CH_FDR_DM_Msk) == XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL)
  {
    baudrate = fperi * (((channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos) / 1024.0F);
  }
  else
  {
    /* Normal divider mode */
    baudrate = fperi * (1.0F / (1024 - ((channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos)));
  }

  baudrate /= divider;

  return (uint32_t)baudrate;
}

uint32_t XMC_USIC_CH_GetSCLKFrequency(XMC_USIC_CH_t *const channel)
{
  uint32_t divider;
  divider = (channel->BRG & USIC_CH_BRG_PPPEN_Msk) ? 2 : 1;
  divider *= ((channel->BRG & USIC_CH_BRG_PDIV_Msk) >> USIC_CH_BRG_PDIV_Pos) + 1;
  divider *= 2;

  uint32_t fperi = XMC_SCU_CLOCK_GetPeripheralClockFrequency();
  float baudrate;
  if ((channel->FDR & USIC_CH_FDR_DM_Msk) == XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL)
  {
    /* Fractional divider mode */
    baudrate = fperi * (((channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos) / 1024.0F);
  }
  else
  {
    /* Normal divider mode */
    baudrate = fperi * (1.0F / (1024 - ((channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos)));
  }

  baudrate /= divider;

  return (uint32_t)baudrate;
}

uint32_t XMC_USIC_CH_GetMCLKFrequency(XMC_USIC_CH_t *const channel)
{
  uint32_t fperi = XMC_SCU_CLOCK_GetPeripheralClockFrequency();

  float baudrate;
  if ((channel->FDR & USIC_CH_FDR_DM_Msk) == XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL)
  {
    /* Fractional divider mode */
    baudrate = fperi * (1.0F / (1024 - ((channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos)));
  }
  else
  {
    /* Normal divider mode */
    baudrate = fperi / (((channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos) / 1024.0F);
  }

  baudrate /= 2;

  return (uint32_t)baudrate;
}


void XMC_USIC_CH_ConfigExternalInputSignalToBRG(XMC_USIC_CH_t *const channel,
    const uint16_t pdiv,
    const uint32_t oversampling,
    const XMC_USIC_CH_INPUT_COMBINATION_MODE_t combination_mode)
{
  XMC_ASSERT("XMC_USIC_CH_ConfigExternalInputSignalToBRG: Divider out of range", ((1U < pdiv) || (pdiv < 1024U)));
  XMC_ASSERT("XMC_USIC_CH_ConfigExternalInputSignalToBRG: Oversampling out of range", ((1U < oversampling) || (oversampling < 32U)));

  /* Setting the external input frequency source through DX1 */
  XMC_USIC_CH_SetBRGInputClockSource(channel, XMC_USIC_CH_BRG_CLOCK_SOURCE_DX1T);

  /* Setting the trigger combination mode */
  XMC_USIC_CH_SetInputTriggerCombinationMode(channel, XMC_USIC_CH_INPUT_DX1, combination_mode);

  /* Configuring the dividers and oversampling */
  channel->BRG = (channel->BRG & ~(USIC_CH_BRG_DCTQ_Msk |
                                   USIC_CH_BRG_PDIV_Msk |
                                   USIC_CH_BRG_PCTQ_Msk |
                                   USIC_CH_BRG_PPPEN_Msk)) |
                 (((oversampling) - 1U) << USIC_CH_BRG_DCTQ_Pos) |
                 (((pdiv) - 1U) << USIC_CH_BRG_PDIV_Pos);
}

void XMC_USIC_CH_TXFIFO_Configure(XMC_USIC_CH_t *const channel,
                                  const uint32_t data_pointer,
                                  const XMC_USIC_CH_FIFO_SIZE_t size,
                                  const uint32_t limit)
{
  /* Disable FIFO */
  channel->TBCTR &= (uint32_t)~USIC_CH_TBCTR_SIZE_Msk;

  /* LOF = 0, A standard transmit buffer event occurs when the filling level equals the limit value and gets
   * lower due to transmission of a data word
   * STBTEN = 0, the trigger of the standard transmit buffer event is based on the transition of the fill level
   *  from equal to below the limit, not the fact being below
   */
  channel->TBCTR = (uint32_t)(channel->TBCTR & (uint32_t)~(USIC_CH_TBCTR_LIMIT_Msk |
                              USIC_CH_TBCTR_DPTR_Msk |
                              USIC_CH_TBCTR_SIZE_Msk)) |
                   (uint32_t)((limit << USIC_CH_TBCTR_LIMIT_Pos) |
                              (data_pointer << USIC_CH_TBCTR_DPTR_Pos) |
                              ((uint32_t)size << USIC_CH_TBCTR_SIZE_Pos));
}


void XMC_USIC_CH_RXFIFO_Configure(XMC_USIC_CH_t *const channel,
                                  const uint32_t data_pointer,
                                  const XMC_USIC_CH_FIFO_SIZE_t size,
                                  const uint32_t limit)
{
  /* Disable FIFO */
  channel->RBCTR &= (uint32_t)~USIC_CH_RBCTR_SIZE_Msk;

  /* LOF = 1, A standard receive buffer event occurs when the filling level equals the limit value and gets bigger
   *  due to the reception of a new data word
   */
  channel->RBCTR = (uint32_t)((channel->RBCTR & (uint32_t)~(USIC_CH_RBCTR_LIMIT_Msk |
                               USIC_CH_RBCTR_DPTR_Msk |
                               USIC_CH_RBCTR_LOF_Msk)) |
                              ((limit << USIC_CH_RBCTR_LIMIT_Pos) |
                               (data_pointer << USIC_CH_RBCTR_DPTR_Pos) |
                               ((uint32_t)size << USIC_CH_RBCTR_SIZE_Pos) |
                               (uint32_t)USIC_CH_RBCTR_LOF_Msk));
}

void XMC_USIC_CH_TXFIFO_SetSizeTriggerLimit(XMC_USIC_CH_t *const channel,
    const XMC_USIC_CH_FIFO_SIZE_t size,
    const uint32_t limit)
{
  XMC_UNUSED_ARG(size);

  /* STBTEN = 0, the trigger of the standard transmit buffer event is based on the transition of the fill level
   *  from equal to below the limit, not the fact being below
   */
  channel->TBCTR = (uint32_t)((uint32_t)(channel->TBCTR & (uint32_t)~USIC_CH_TBCTR_LIMIT_Msk) |
                              (limit << USIC_CH_TBCTR_LIMIT_Pos));
}

void XMC_USIC_CH_RXFIFO_SetSizeTriggerLimit(XMC_USIC_CH_t *const channel,
    const XMC_USIC_CH_FIFO_SIZE_t size,
    const uint32_t limit)
{
  XMC_UNUSED_ARG(size);

  channel->RBCTR = (uint32_t)((uint32_t)(channel->RBCTR & (uint32_t)~USIC_CH_RBCTR_LIMIT_Msk) |
                              (limit << USIC_CH_RBCTR_LIMIT_Pos));
}

void XMC_USIC_CH_SetInterruptNodePointer(XMC_USIC_CH_t *const channel,
    const XMC_USIC_CH_INTERRUPT_NODE_POINTER_t interrupt_node,
    const uint32_t service_request)
{
  channel->INPR = (uint32_t)((channel->INPR & (~(uint32_t)(USIC_CH_INPR_Msk << (uint32_t)interrupt_node))) |
                             (service_request << (uint32_t)interrupt_node));
}

void XMC_USIC_CH_TXFIFO_SetInterruptNodePointer(XMC_USIC_CH_t *const channel,
    const XMC_USIC_CH_TXFIFO_INTERRUPT_NODE_POINTER_t interrupt_node,
    const uint32_t service_request)
{
  channel->TBCTR = (uint32_t)((channel->TBCTR & (~(uint32_t)(USIC_CH_INPR_Msk << (uint32_t)interrupt_node))) |
                              (service_request << (uint32_t)interrupt_node));
}

void XMC_USIC_CH_RXFIFO_SetInterruptNodePointer(XMC_USIC_CH_t *const channel,
    const XMC_USIC_CH_RXFIFO_INTERRUPT_NODE_POINTER_t interrupt_node,
    const uint32_t service_request)
{
  channel->RBCTR = (uint32_t)((channel->RBCTR & (~(uint32_t)(USIC_CH_INPR_Msk << (uint32_t)interrupt_node))) |
                              (service_request << (uint32_t)interrupt_node));
}

void XMC_USIC_Enable(XMC_USIC_t *const usic)
{
  if (usic == USIC0)
  {
#if defined(CLOCK_GATING_SUPPORTED)
    XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USIC0);
    while (XMC_SCU_CLOCK_IsPeripheralClockGated(XMC_SCU_PERIPHERAL_CLOCK_USIC0));
#endif
#if defined(PERIPHERAL_RESET_SUPPORTED)
    XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USIC0);
    while (XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_USIC0));
#endif
  }
#if defined(USIC1)
  else if (usic == USIC1)
  {
#if defined(CLOCK_GATING_SUPPORTED)
    XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USIC1);
    while (XMC_SCU_CLOCK_IsPeripheralClockGated(XMC_SCU_PERIPHERAL_CLOCK_USIC1));
#endif
#if defined(PERIPHERAL_RESET_SUPPORTED)
    XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USIC1);
    while (XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_USIC1));
#endif
  }
#endif
#if defined(USIC2)
  else if (usic == USIC2)
  {
#if defined(CLOCK_GATING_SUPPORTED)
    XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USIC2);
    while (XMC_SCU_CLOCK_IsPeripheralClockGated(XMC_SCU_PERIPHERAL_CLOCK_USIC2));
#endif
#if defined(PERIPHERAL_RESET_SUPPORTED)
    XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USIC2);
    while (XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_USIC2));
#endif
  }
#endif
  else
  {
    XMC_ASSERT("USIC module not available", 0/*Always*/);
  }
}

void XMC_USIC_Disable(XMC_USIC_t *const usic)
{
  if (usic == (XMC_USIC_t *)USIC0)
  {
#if defined(PERIPHERAL_RESET_SUPPORTED)
    XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USIC0);
#endif
#if defined(CLOCK_GATING_SUPPORTED)
    XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USIC0);
#endif
  }
#if defined(USIC1)
  else if (usic == (XMC_USIC_t *)USIC1)
  {
#if defined(PERIPHERAL_RESET_SUPPORTED)
    XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USIC1);
#endif
#if defined(CLOCK_GATING_SUPPORTED)
    XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USIC1);
#endif
  }
#endif
#if defined(USIC2)
  else if (usic == (XMC_USIC_t *)USIC2)
  {
#if defined(PERIPHERAL_RESET_SUPPORTED)
    XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_USIC2);
#endif
#if defined(CLOCK_GATING_SUPPORTED)
    XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_USIC2);
#endif
  }
#endif
  else
  {
    XMC_ASSERT("USIC module not available", 0/*Always*/);
  }

}
