/**
  **************************************************************************
  * @file     at32f435_437_spi.c
  * @brief    contains all the functions for the spi firmware library
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "at32f435_437_conf.h"

/** @addtogroup AT32F435_437_periph_driver
  * @{
  */

/** @defgroup SPI
  * @brief SPI driver modules
  * @{
  */

#ifdef SPI_MODULE_ENABLED

/** @defgroup SPI_private_functions
  * @{
  */

/**
  * @brief  spi reset by crm reset register
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @retval none
  */
void spi_i2s_reset(spi_type *spi_x)
{
  if(spi_x == SPI1)
  {
    crm_periph_reset(CRM_SPI1_PERIPH_RESET, TRUE);
    crm_periph_reset(CRM_SPI1_PERIPH_RESET, FALSE);
  }
  else if(spi_x == SPI2)
  {
    crm_periph_reset(CRM_SPI2_PERIPH_RESET, TRUE);
    crm_periph_reset(CRM_SPI2_PERIPH_RESET, FALSE);
  }
  else if(spi_x == SPI3)
  {
    crm_periph_reset(CRM_SPI3_PERIPH_RESET, TRUE);
    crm_periph_reset(CRM_SPI3_PERIPH_RESET, FALSE);
  }
  else if(spi_x == SPI4)
  {
    crm_periph_reset(CRM_SPI4_PERIPH_RESET, TRUE);
    crm_periph_reset(CRM_SPI4_PERIPH_RESET, FALSE);
  }
}

/**
  * @brief  spi init config with its default value.
  * @param  spi_init_struct : pointer to a spi_init_type structure which will
  *         be initialized.
  * @retval none
  */
void spi_default_para_init(spi_init_type* spi_init_struct)
{
  spi_init_struct->transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
  spi_init_struct->master_slave_mode = SPI_MODE_SLAVE;
  spi_init_struct->mclk_freq_division = SPI_MCLK_DIV_2;
  spi_init_struct->first_bit_transmission = SPI_FIRST_BIT_MSB;
  spi_init_struct->frame_bit_num = SPI_FRAME_8BIT;
  spi_init_struct->clock_polarity = SPI_CLOCK_POLARITY_LOW;
  spi_init_struct->clock_phase = SPI_CLOCK_PHASE_1EDGE;
  spi_init_struct->cs_mode_selection = SPI_CS_SOFTWARE_MODE;
}

/**
  * @brief  spi init config with its setting value.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  spi_init_struct : pointer to a spi_init_type structure which will be initialized.
  * @retval none
  */
void spi_init(spi_type* spi_x, spi_init_type* spi_init_struct)
{
  spi_x->i2sctrl_bit.i2smsel = FALSE;
  if(spi_init_struct->transmission_mode == SPI_TRANSMIT_FULL_DUPLEX)
  {
    spi_x->ctrl1_bit.slben = FALSE;
    spi_x->ctrl1_bit.slbtd = FALSE;
    spi_x->ctrl1_bit.ora = FALSE;
  }
  else if(spi_init_struct->transmission_mode == SPI_TRANSMIT_SIMPLEX_RX)
  {
    spi_x->ctrl1_bit.slben = FALSE;
    spi_x->ctrl1_bit.slbtd = FALSE;
    spi_x->ctrl1_bit.ora = TRUE;
  }
  else if(spi_init_struct->transmission_mode == SPI_TRANSMIT_HALF_DUPLEX_RX)
  {
    spi_x->ctrl1_bit.slben = TRUE;
    spi_x->ctrl1_bit.slbtd = FALSE;
    spi_x->ctrl1_bit.ora = FALSE;
  }
  else if(spi_init_struct->transmission_mode == SPI_TRANSMIT_HALF_DUPLEX_TX)
  {
    spi_x->ctrl1_bit.slben = TRUE;
    spi_x->ctrl1_bit.slbtd = TRUE;
    spi_x->ctrl1_bit.ora = FALSE;
  }

  spi_x->ctrl1_bit.swcsen = spi_init_struct->cs_mode_selection;
  if((spi_init_struct->master_slave_mode == SPI_MODE_MASTER) && (spi_init_struct->cs_mode_selection == SPI_CS_SOFTWARE_MODE))
  {
    spi_x->ctrl1_bit.swcsil = TRUE;
  }
  else
  {
    spi_x->ctrl1_bit.swcsil = FALSE;
  }
  spi_x->ctrl1_bit.msten = spi_init_struct->master_slave_mode;

  if(spi_init_struct->mclk_freq_division <= SPI_MCLK_DIV_256)
  {
    spi_x->ctrl2_bit.mdiv3en = FALSE;
    spi_x->ctrl2_bit.mdiv_h = FALSE;
    spi_x->ctrl1_bit.mdiv_l = spi_init_struct->mclk_freq_division;
  }
  else if(spi_init_struct->mclk_freq_division == SPI_MCLK_DIV_3)
  {
    spi_x->ctrl2_bit.mdiv3en = TRUE;
    spi_x->ctrl2_bit.mdiv_h = FALSE;
    spi_x->ctrl1_bit.mdiv_l = 0;
  }
  else
  {
    spi_x->ctrl2_bit.mdiv3en = FALSE;
    spi_x->ctrl2_bit.mdiv_h = TRUE;
    spi_x->ctrl1_bit.mdiv_l = spi_init_struct->mclk_freq_division & 0x7;
  }

  spi_x->ctrl1_bit.ltf = spi_init_struct->first_bit_transmission;
  spi_x->ctrl1_bit.fbn = spi_init_struct->frame_bit_num;
  spi_x->ctrl1_bit.clkpol = spi_init_struct->clock_polarity;
  spi_x->ctrl1_bit.clkpha = spi_init_struct->clock_phase;
}

/**
  * @brief  enable or disable the ti mode for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  new_state: new state of ti mode.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void spi_ti_mode_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->ctrl2_bit.tien = new_state;
}

/**
  * @brief  spi next transmit crc for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @retval none
  */
void spi_crc_next_transmit(spi_type* spi_x)
{
  spi_x->ctrl1_bit.ntc = TRUE;
}

/**
  * @brief  set the crc polynomial value for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  crc_poly: crc polynomial value.
  * @retval none
  */
void spi_crc_polynomial_set(spi_type* spi_x, uint16_t crc_poly)
{
  spi_x->cpoly_bit.cpoly = crc_poly;
}

/**
  * @brief  return the crc polynomial register value for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @retval the select crc polynomial register value
  */
uint16_t spi_crc_polynomial_get(spi_type* spi_x)
{
  return spi_x->cpoly_bit.cpoly;
}

/**
  * @brief  enable or disable the hardware crc calculation for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  new_state: new state of crc calculation.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void spi_crc_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->ctrl1_bit.ccen = new_state;
}

/**
  * @brief  return the transmit or the receive crc value for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  crc_direction: select transmit or receive crc value to be read
  *         - SPI_CRC_RX
  *         - SPI_CRC_TX
  * @retval the select crc register value
  */
uint16_t spi_crc_value_get(spi_type* spi_x, spi_crc_direction_type crc_direction)
{
  if(crc_direction == SPI_CRC_RX)
    return  spi_x->rcrc_bit.rcrc;
  else
    return  spi_x->tcrc_bit.tcrc;
}

/**
  * @brief  enable or disable the hardware cs output for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  new_state: new state of spi master cs output.
  *         this parameter can be: TRUE or FALSE.
  *         note:the bit only use in spi master mode
  * @retval none
  */
void spi_hardware_cs_output_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->ctrl2_bit.hwcsoe = new_state;
}

/**
  * @brief  set the software cs internal level for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  level: set the state of spi cs level.
  *         this parameter can be one of the following values:
  *         - SPI_SWCS_INTERNAL_LEVEL_LOW
  *         - SPI_SWCS_INTERNAL_LEVEL_HIGHT
  *         note:the bit only use when swcsen bit is set.
  *         note:when use this bit,io operation on the cs pin are invalid.
  * @retval none
  */
void spi_software_cs_internal_level_set(spi_type* spi_x, spi_software_cs_level_type level)
{
  spi_x->ctrl1_bit.swcsil = level;
}

/**
  * @brief  set the data frame bit num for the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  bit_num: set the data frame size
  *         - SPI_FRAME_8BIT
  *         - SPI_FRAME_16BIT
  * @retval none
  */
void spi_frame_bit_num_set(spi_type* spi_x, spi_frame_bit_num_type bit_num)
{
  spi_x->ctrl1_bit.fbn = bit_num;
}

/**
  * @brief  set the data transmission direction in single line bidirectiona half duplex mode of the spi peripheral.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  direction: data transfer direction
  *         this parameter can be one of the following values:
  *         - SPI_HALF_DUPLEX_DIRECTION_RX
  *         - SPI_HALF_DUPLEX_DIRECTION_TX
  * @retval none
  */
void spi_half_duplex_direction_set(spi_type* spi_x, spi_half_duplex_direction_type direction)
{
    spi_x->ctrl1_bit.slbtd = direction;
}

/**
  * @brief  enable or disable spi.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4
  * @param  new_state: new state of spi.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void spi_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->ctrl1_bit.spien = new_state;
}

/**
  * @brief  i2s init config with its default value.
  * @param  i2s_init_struct : pointer to a i2s_init_type structure which will
  *         be initialized.
  * @retval none
  */
void i2s_default_para_init(i2s_init_type* i2s_init_struct)
{
  i2s_init_struct->operation_mode = I2S_MODE_SLAVE_TX;
  i2s_init_struct->audio_protocol = I2S_AUDIO_PROTOCOL_PHILLIPS;
  i2s_init_struct->audio_sampling_freq = I2S_AUDIO_FREQUENCY_DEFAULT;
  i2s_init_struct->data_channel_format = I2S_DATA_16BIT_CHANNEL_16BIT;
  i2s_init_struct->clock_polarity = I2S_CLOCK_POLARITY_LOW;
  i2s_init_struct->mclk_output_enable = FALSE;
}

/**
  * @brief  i2s init config with its setting value.
  * @param  spi_x: select the spi peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  i2s_init_struct : pointer to a i2s_init_type structure which will be initialized.
  * @retval none
  */
void i2s_init(spi_type* spi_x, i2s_init_type* i2s_init_struct)
{
  crm_clocks_freq_type clocks_freq;
  uint32_t i2s_sclk_index = 0;
  uint32_t i2sdiv_index = 2, i2sodd_index = 0, frequency_index = 0;

  /* i2s audio frequency config */
  if(i2s_init_struct->audio_sampling_freq == I2S_AUDIO_FREQUENCY_DEFAULT)
  {
    i2sodd_index = 0;
    i2sdiv_index = 2;
  }
  else
  {
    crm_clocks_freq_get(&clocks_freq);
    i2s_sclk_index = clocks_freq.sclk_freq;
    if((i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_PCM_SHORT) || (i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_PCM_LONG))
    {
      if(i2s_init_struct->mclk_output_enable == TRUE)
      {
        frequency_index = (((i2s_sclk_index / 128) * 10) / i2s_init_struct->audio_sampling_freq) + 5;
      }
      else
      {
        if(i2s_init_struct->data_channel_format == I2S_DATA_16BIT_CHANNEL_16BIT)
          frequency_index = (((i2s_sclk_index / 16) * 10) / i2s_init_struct->audio_sampling_freq) + 5;
        else
          frequency_index = (((i2s_sclk_index / 32) * 10) / i2s_init_struct->audio_sampling_freq) + 5;
      }
    }
    else
    {
      if(i2s_init_struct->mclk_output_enable == TRUE)
      {
        frequency_index = (((i2s_sclk_index / 256) * 10) / i2s_init_struct->audio_sampling_freq) + 5;
      }
      else
      {
        if(i2s_init_struct->data_channel_format == I2S_DATA_16BIT_CHANNEL_16BIT)
          frequency_index = (((i2s_sclk_index / 32) * 10) / i2s_init_struct->audio_sampling_freq) + 5;
        else
          frequency_index = (((i2s_sclk_index / 64) * 10) / i2s_init_struct->audio_sampling_freq) + 5;
      }
    }
  }
  frequency_index = frequency_index / 10;
  i2sodd_index = frequency_index & (uint16_t)0x0001;
  i2sdiv_index = (frequency_index - i2sodd_index) / 2;
  if((i2sdiv_index < 2) || (i2sdiv_index > 0x03FF))
  {
    i2sodd_index = 0;
    i2sdiv_index = 2;
  }
  spi_x->i2sclk_bit.i2sodd = i2sodd_index;
  if(i2sdiv_index > 0x00FF)
  {
    spi_x->i2sclk_bit.i2sdiv_h = (i2sdiv_index >> 8) & 0x0003;
    spi_x->i2sclk_bit.i2sdiv_l = i2sdiv_index & 0x00FF;
  }
  else
  {
    spi_x->i2sclk_bit.i2sdiv_h = 0;
    spi_x->i2sclk_bit.i2sdiv_l = i2sdiv_index;
  }

  /* i2s audio_protocol set*/
  if(i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_PCM_LONG)
  {
    spi_x->i2sctrl_bit.pcmfssel = 1;
    spi_x->i2sctrl_bit.stdsel = 3;
  }
  else if(i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_PCM_SHORT)
  {
    spi_x->i2sctrl_bit.pcmfssel = 0;
    spi_x->i2sctrl_bit.stdsel = 3;
  }
  else if(i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_LSB)
  {
    spi_x->i2sctrl_bit.pcmfssel = 0;
    spi_x->i2sctrl_bit.stdsel = 2;
  }
  else if(i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_MSB)
  {
    spi_x->i2sctrl_bit.pcmfssel = 0;
    spi_x->i2sctrl_bit.stdsel = 1;
  }
  else if(i2s_init_struct->audio_protocol == I2S_AUDIO_PROTOCOL_PHILLIPS)
  {
    spi_x->i2sctrl_bit.pcmfssel = 0;
    spi_x->i2sctrl_bit.stdsel = 0;
  }

  /* i2s data_channel_format set*/
  if(i2s_init_struct->data_channel_format == I2S_DATA_16BIT_CHANNEL_16BIT)
  {
    spi_x->i2sctrl_bit.i2scbn = 0;
    spi_x->i2sctrl_bit.i2sdbn = 0;
  }
  else if(i2s_init_struct->data_channel_format == I2S_DATA_16BIT_CHANNEL_32BIT)
  {
    spi_x->i2sctrl_bit.i2scbn = 1;
    spi_x->i2sctrl_bit.i2sdbn = 0;
  }
  else if(i2s_init_struct->data_channel_format == I2S_DATA_24BIT_CHANNEL_32BIT)
  {
    spi_x->i2sctrl_bit.i2scbn = 1;
    spi_x->i2sctrl_bit.i2sdbn = 1;
  }
  else if(i2s_init_struct->data_channel_format == I2S_DATA_32BIT_CHANNEL_32BIT)
  {
    spi_x->i2sctrl_bit.i2scbn = 1;
    spi_x->i2sctrl_bit.i2sdbn = 2;
  }

  spi_x->i2sctrl_bit.i2sclkpol = i2s_init_struct->clock_polarity;
  spi_x->i2sclk_bit.i2smclkoe = i2s_init_struct->mclk_output_enable;
  spi_x->i2sctrl_bit.opersel = i2s_init_struct->operation_mode;
  spi_x->i2sctrl_bit.i2smsel = TRUE;
}

/**
  * @brief  enable or disable i2s.
  * @param  spi_x: select the i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  new_state: new state of i2s.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void i2s_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->i2sctrl_bit.i2sen = new_state;
}

/**
  * @brief  enable or disable the specified spi/i2s interrupts.
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  spi_i2s_int: specifies the spi/i2s interrupt sources to be enabled or disabled.
  *         this parameter can be one of the following values:
  *         - SPI_I2S_ERROR_INT
  *         - SPI_I2S_RDBF_INT
  *         - SPI_I2S_TDBE_INT
  * @param  new_state: new state of the specified spi/i2s interrupts.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void spi_i2s_interrupt_enable(spi_type* spi_x, uint32_t spi_i2s_int, confirm_state new_state)
{
  if(new_state != FALSE)
  {
    spi_x->ctrl2 |= spi_i2s_int;
  }
  else
  {
    spi_x->ctrl2 &= ~spi_i2s_int;
  }
}

/**
  * @brief  enable or disable the spi/i2s dma transmitter mode.
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  new_state: new state of the dma request.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void spi_i2s_dma_transmitter_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->ctrl2_bit.dmaten = new_state;
}

/**
  * @brief  enable or disable the spi/i2s dma receiver mode.
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  new_state: new state of the dma request.
  *         this parameter can be: TRUE or FALSE.
  * @retval none
  */
void spi_i2s_dma_receiver_enable(spi_type* spi_x, confirm_state new_state)
{
  spi_x->ctrl2_bit.dmaren = new_state;
}

/**
  * @brief  spi/i2s data transmit
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  tx_data: the data to be transmit.
  *         this parameter can be:
  *         - (0x0000~0xFFFF)
  * @retval none
  */
void spi_i2s_data_transmit(spi_type* spi_x, uint16_t tx_data)
{
  spi_x->dt = tx_data;
}

/**
  * @brief  spi/i2s data receive
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @retval the received data value
  */
uint16_t spi_i2s_data_receive(spi_type* spi_x)
{
  return (uint16_t)spi_x->dt;
}

/**
  * @brief  get flag of the specified spi/i2s peripheral.
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  spi_i2s_flag: select the spi/i2s flag
  *         this parameter can be one of the following values:
  *         - SPI_I2S_RDBF_FLAG
  *         - SPI_I2S_TDBE_FLAG
  *         - I2S_ACS_FLAG    (this flag only use in i2s mode)
  *         - I2S_TUERR_FLAG  (this flag only use in i2s mode)
  *         - SPI_CCERR_FLAG  (this flag only use in spi mode)
  *         - SPI_MMERR_FLAG  (this flag only use in spi mode)
  *         - SPI_I2S_ROERR_FLAG
  *         - SPI_I2S_BF_FLAG
  *         - SPI_CSPAS_FLAG
  * @retval the new state of spi/i2s flag
  */
flag_status spi_i2s_flag_get(spi_type* spi_x, uint32_t spi_i2s_flag)
{
  flag_status status = RESET;
  if ((spi_x->sts & spi_i2s_flag) == RESET)
  {
    status = RESET;
  }
  else
  {
    status = SET;
  }
  return status;
}

/**
  * @brief  clear flag of the specified spi/i2s peripheral.
  * @param  spi_x: select the spi/i2s peripheral.
  *         this parameter can be one of the following values:
  *         SPI1, SPI2, SPI3 ,SPI4 , I2S2EXT, I2S3EXT
  * @param  spi_i2s_flag: select the spi/i2s flag
  *         this parameter can be one of the following values:
  *         - SPI_CCERR_FLAG
  *         - SPI_I2S_RDBF_FLAG
  *         - I2S_TUERR_FLAG
  *         - SPI_MMERR_FLAG
  *         - SPI_I2S_ROERR_FLAG
  *         - SPI_CSPAS_FLAG
  * @note
  *         SPI_I2S_TDBE_FLAG  this flag is cleared when the tx buffer already contain data to be transmit.
  *         I2S_ACS_FLAG       this flag cann't cleared by software,the flag indicate the channel side(not use in pcm standard mode).
  *         SPI_I2S_BF_FLAG    this flag cann't cleared by software, it's set and cleared by hardware.
  * @retval none
  */
void spi_i2s_flag_clear(spi_type* spi_x, uint32_t spi_i2s_flag)
{
  if(spi_i2s_flag == SPI_CCERR_FLAG)
    spi_x->sts = ~SPI_CCERR_FLAG;
  else if(spi_i2s_flag == SPI_I2S_RDBF_FLAG)
    UNUSED(spi_x->dt);
  else if(spi_i2s_flag == I2S_TUERR_FLAG)
    UNUSED(spi_x->sts);
  else if(spi_i2s_flag == SPI_CSPAS_FLAG)
    UNUSED(spi_x->sts);
  else if(spi_i2s_flag == SPI_MMERR_FLAG)
  {
    UNUSED(spi_x->sts);
    spi_x->ctrl1 = spi_x->ctrl1;
  }
  else if(spi_i2s_flag == SPI_I2S_ROERR_FLAG)
  {
    UNUSED(spi_x->dt);
    UNUSED(spi_x->sts);
  }
}

/**
  * @}
  */

#endif

/**
  * @}
  */

/**
  * @}
  */
