/**
  ******************************************************************************
  * @file    lcm32f06x_spi.c
  * @author  System R&D Team
  * @version V2.0.2
  * @date    10-April-2025
  * @brief   This file provides all the spi firmware functions.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) Hangzhou Lingxin Microelectronics Co.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "lcm32f06x_spi.h"

/**
  * @name   SPI_DeInit
  * @brief  EN: Deinitializes SPI peripheral registers to their default reset values.
  *         CN: 将 SPI 外设寄存器初始化为其默认重置值。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @retval None
  */
void SPI_DeInit(SPI_TypeDef *SPIx)
{
  RCC_APB0PeriphResetCmd(RCC_APB0Periph_SPI0, ENABLE);

  RCC_APB0PeriphResetCmd(RCC_APB0Periph_SPI0, DISABLE);
}

/**
  * @name   SPI_StructInit
  * @brief  EN: Fills each SPI_InitStruct member with its default value.
  *         CN: 用默认值填充每个 SPI_InitStruct 成员。
  * @param  SPI_InitStruct:
  *         EN: pointer to a SPI_InitTypeDef structure that contains the 
  *             configuration information for the specified SPI peripheral.
  *         CN: 指向 SPI_InitTypeDef 结构的指针，该结构包含指定 SPI 外设的配置信息。
  * @retval None
  */
void SPI_StructInit(SPI_InitTypeDef *SPI_InitStruct)
{
  SPI_InitStruct->SPI_Mode = SPI_Mode_Master;
  SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
  SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStruct->SPI_SlaveTx = SPI_SlaveTx_Enable;
  SPI_InitStruct->SPI_SpeedMode = SPI_Speed_High;
}

/**
  * @name SPI_Init
  * @brief  EN: Initializes the SPI according to the specified
  *             parameters in the SPI_InitTypeDef.
  *         CN: 根据SPI_InitTypeDef中指定的参数初始化SPI。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_InitStruct: 
  *         EN: pointer to a SPI_InitTypeDef structure that contains the
  *             configuration information for the specified SPI peripheral.
  *         CN: 指向SPI_InitTypeDef结构的指针，该结构包含指定SPI外围设备的配置信息。
  * @retval None
  */
void SPI_Init(SPI_TypeDef *SPIx, SPI_InitTypeDef *SPI_InitStruct)
{
  uint16_t tmpreg = 0x00, tmp = 0x00 , tmp1 = 0X00;
  assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode));
  assert_param(IS_SPI_DATA_SIZE(SPI_InitStruct->SPI_DataSize));
  assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL));
  assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA));
  assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_InitStruct->SPI_BaudRatePrescaler));
  assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->SPI_FirstBit));
  assert_param(IS_SPI_SLAVE_TX(SPI_InitStruct->SPI_SlaveTx));

  tmpreg = SPIx->SPICR0;
  tmpreg &= 0XFFFF0000;
  tmpreg = (tmpreg | (SPI_InitStruct->SPI_BaudRatePrescaler) |
            (SPI_InitStruct->SPI_CPOL) |
            (SPI_InitStruct->SPI_CPHA) |
            (SPI_InitStruct->SPI_DataSize));
  SPIx->SPICR0 = tmpreg;

  tmp = SPIx->SPICR1;
  tmp &= 0XFFFFFFF0;
  tmp = ((SPI_InitStruct->SPI_SlaveTx) | (SPI_InitStruct->SPI_Mode));
  SPIx->SPICR1 = tmp;

  tmp1 = SPIx->SPICR2;
  tmp1 &= 0XFFFFFF7C;
  tmp1 = (tmp1|SPI_InitStruct->SPI_SpeedMode | SPI_InitStruct->SPI_FirstBit);
  SPIx->SPICR2 = tmp1;
  SPIx->SPICPSR = 0x02;
}

/**
  * @name   SPI_Cmd
  * @brief  EN: Enables or disables the specified SPIx peripheral.
  *         CN: 启用或禁用指定的 SPIx 外设。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  NewState: 
  *         EN: New state of the USARTx peripheral.
  *         CN: SPIx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void SPI_Cmd(SPI_TypeDef *SPIx, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    SPIx->SPICR1 |= SPI_SSPCR1_SSE_Msk;
  }
  else
  {
    SPIx->SPICR1 &= ~SPI_SSPCR1_SSE_Msk;
  }
}

/**
  * @name   SPI_DataSizeConfig
  * @brief  EN: Frame data length selection.
  *         CN: 帧数据长度选择。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_DataSize: 
  *         EN: Data frame length selection.
  *         CN: 数据帧长度选择。
  * @retval None
  */
void SPI_DataSizeConfig(SPI_TypeDef *SPIx, uint16_t SPI_DataSize)
{
  assert_param(IS_SPI_DATA_SIZE(SPI_DataSize));
  SPIx->SPICR0 &= ((uint16_t)0xFFF0);
  SPIx->SPICR0 |= SPI_DataSize;
}

/**
  * @name   SPI_SendData8
  * @brief  EN: Send 8-bit data.
  *         CN: 发送8位数据。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  Data: 
  *         EN: 8-bit data.
  *         CN: 8位数据。
  * @retval None
  */
void SPI_SendData8(SPI_TypeDef *SPIx, uint8_t Data)
{
  SPIx->SPIDR = Data;
}

/**
  * @name   SPI_SendData16
  * @brief  EN: Send 16-bit data.
  *         CN: 发送16位数据。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  Data: 
  *         EN: 16-bit data.
  *         CN: 16位数据。
  * @retval None
  */
void SPI_SendData16(SPI_TypeDef *SPIx, uint16_t Data)
{
  SPIx->SPIDR = Data;
}

/**
  * @name   SPI_ReceiveData8
  * @brief  EN: Receive 8-bit data.
  *         CN: 接收8位数据。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @retval uint8_t: 
  *         EN: 8-bit data.
  *         CN: 8位数据。
  */
uint8_t SPI_ReceiveData8(SPI_TypeDef *SPIx)
{
  uint8_t temp = 0x00;
  temp = SPIx->SPIDR;
  return temp;
}

/**
  * @name   SPI_ReceiveData16
  * @brief  EN: Receive 16-bit data.
  *         CN: 接收16位数据。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @retval uint16_t: 
  *         EN: 16-bit data.
  *         CN: 16位数据。
  */
uint16_t SPI_ReceiveData16(SPI_TypeDef *SPIx)
{
  uint16_t temp = 0x00;
  temp = SPIx->SPIDR;
  return temp;
}

/**
  * @name   SPI_DMACmd
  * @brief  EN: Enable SPI DMA data transmission corresponding.
  *         CN: 启用相应的SPI DMA数据传输。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_DMAReq ：
  *         EN: Select SPI transmission that requires DMA to be enabled.
  *         CN: 选择需要开启DMA的SPI传输。
  *             @arg SPI_DMAReq_Tx
  *             @arg SPI_DMAReq_Rx
  * @param  NewState: 
  *         EN: New state of SPI DMA transmission.
  *         CN: SPI DMA 传输的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void SPI_DMACmd(SPI_TypeDef *SPIx, uint16_t SPI_DMAReq, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    SPIx->SPIDMACR |= SPI_DMAReq;
  }
  else
  {
    SPIx->SPIDMACR |= ~SPI_DMAReq;
  }
}

/**
  * @name   SPI_ITConfig
  * @brief  EN: Enables or disables the specified SPI interrupts.
  *         CN: 启用或禁用指定的SPI中断。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_IT: 
  *         EN: Specifies the SPI interrupt sources to be enabled or disabled.
  *         CN: 指定要启用或禁用的SPI中断源。
  *             @arg SPI_IT_Tx
  *             @arg SPI_IT_Rx
  *             @arg SPI_IT_RT
  *             @arg SPI_IT_ROR
  *             @arg SPI_IT_ALL
  * @param  NewState: 
  *         EN: new state of the specified SPI interrupts.
  *         CN: 指定SPI中断的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void SPI_ITConfig(SPI_TypeDef *SPIx, uint8_t SPI_IT, FunctionalState NewState)
{
  assert_param(IS_SPI_CONFIG_IT(IT));
  if (NewState == DISABLE)
  {
    SPIx->SPIIMSC &= ~SPI_IT;
  }
  else
  {
    SPIx->SPIIMSC |= SPI_IT;
  }
}

/**
  * @name   SPI_GetFlagStatus
  * @brief  EN: Get SPI status flags.
  *         CN: 获取SPI状态标志。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_FLAG: 
  *         EN: Specify the SPI flag to be obtained.
  *         CN: 指定要获取的SPI标志。
  *             @arg SPI_FLAG_BSY
  *             @arg SPI_FLAG_RFF
  *             @arg SPI_FLAG_RNE
  *             @arg SPI_FLAG_TNF
  *             @arg SPI_FLAG_TFE
  * @retval None
  */
FlagStatus SPI_GetFlagStatus(SPI_TypeDef *SPIx, uint16_t SPI_FLAG)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  assert_param(IS_SPI_GET_FLAG(SPI_FLAG));

  /* Check the status of the specified SPI flag */
  if ((SPIx->SPISR & SPI_FLAG) != (uint16_t)RESET)
  {
    /* SPI_I2S_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* SPI_I2S_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the SPI_I2S_FLAG status */
  return bitstatus;
}

/**
  * @name   SPI_ClearFlag
  * @brief  EN: Clear SPI status flag.
  *         CN: 清除SPI状态标志。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_ERROR_FLAG: 
  *         EN:Specify the SPI flag to be clear.
  *         CN:指定要清除的SPI标志。
  *             @arg SPI_ERROR_FLAG_RT
  *             @arg SPI_ERROR_FLAF_ROR
  * @retval None
  */
void SPI_ClearFlag(SPI_TypeDef *SPIx, uint16_t SPI_ERROR_FLAG)
{
  assert_param(IS_SPI_CLEAR_FLAG(SPI_ERROR_FLAG));
  SPIx->SPIICR |= SPI_ERROR_FLAG;
}

/**
  * @name   SPI_GetITStatus
  * @brief  EN: Read the specified SPI interrupt status.
  *         CN: 读取指定的SPI中断状态。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_IT: 
  *         EN: Specifies the SPI interrupt sources to be enabled or disabled.
  *         CN: 指定要启用或禁用的SPI中断源。
  *             @arg SPI_IT_Tx
  *             @arg SPI_IT_Rx
  *             @arg SPI_IT_RT
  *             @arg SPI_IT_ROR
  *             @arg SPI_IT_ALL
  * @retval ITStatus
  */
ITStatus SPI_GetITStatus(SPI_TypeDef *SPIx, uint8_t SPI_IT)
{
  assert_param(IS_SPI_CONFIG_IT(IT));
  if (SPIx->SPIMIS & SPI_IT)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   SPI_GetITRawStatus
  * @brief  EN: Read the specified SPI raw interrupt status.
  *         CN: 读取指定的SPI原始中断状态。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_IT: 
  *         EN: Specifies the SPI interrupt sources to be enabled or disabled.
  *         CN: 指定要启用或禁用的SPI中断源。
  *             @arg SPI_IT_Tx
  *             @arg SPI_IT_Rx
  *             @arg SPI_IT_RT
  *             @arg SPI_IT_ROR
  *             @arg SPI_IT_ALL
  * @retval ITStatus
  */
ITStatus SPI_GetITRawStatus(SPI_TypeDef *SPIx, uint8_t SPI_IT)
{
  assert_param(IS_SPI_CONFIG_IT(IT));
  if (SPIx->SPIRIS & SPI_IT)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
  * @name   SPI_MasterModeDelaySelect
  * @brief  EN: Host mode sampling delay time selection, only related to host mode (MS=0), only effective in high-speed mode.
  *         CN: 主机模式采样延迟时间选择，只与主机模式有关（MS=0），只在高速模式下生效。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  SPI_DataSize: 
  *         EN: Delay time selection.
  *         CN: 延迟时间选择。
  *         @arg SPI_DELAY_TIME_00NS
  *         @arg SPI_DELAY_TIME_10NS
  *         @arg SPI_DELAY_TIME_20NS
  *         @arg SPI_DELAY_TIME_30NS
  * @retval None
  */
void SPI_MasterModeDelaySelect(SPI_TypeDef *SPIx, uint16_t SPI_DelayTime)
{
  assert_param(IS_SPI_DELAY_TIME(SPI_DelayTime));
  SPIx->SPICR2 &= ~SPI_SSPCR2_MRXDDS_Msk;
  SPIx->SPICR2 |= SPI_DelayTime;
}

/**
  * @name   SPI_SlaveModeDelayRxDataCmd
  * @brief  EN: Enable delayed data reception in slave mode, only related to slave mode (MS=1), only effective in high-speed mode.
  *         CN: 从机模式延迟接收数据使能，只与从机模式有关（MS=1），只在高速模式下生效。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  NewState: 
  *         EN: Enable delay of 5ns/disable delay.
  *         CN: 启用延迟5ns/禁止延迟。
  * @retval None
  */
void SPI_SlaveModeDelayRxDataCmd(SPI_TypeDef *SPIx, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    SPIx->SPICR2 |= SPI_SSPCR2_SPXDD_Msk;
  }
  else
  {
    SPIx->SPICR2 &= ~SPI_SSPCR2_SPXDD_Msk;
  }
}

/**
  * @name   SPI_SlaveModeDelayRxFilmSelectCmd
  * @brief  EN: Slave mode delay reception Film selection enable, only related to slave mode (MS=1), only effective in high-speed mode.
  *         CN: 从机模式延迟接收片选使能，只与从机模式有关（MS=1），只在高速模式下生效。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  NewState: 
  *         EN: Enable delay of 5ns/disable delay.
  *         CN: 启用延迟5ns/禁止延迟。
  * @retval None
  */
void SPI_SlaveModeDelayRxFilmSelectCmd(SPI_TypeDef *SPIx, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    SPIx->SPICR2 |= SPI_SSPCR2_SFSSD_Msk;
  }
  else
  {
    SPIx->SPICR2 &= ~SPI_SSPCR2_SFSSD_Msk;
  }
}

/**
  * @name   SPI_SlaveModeDelayRxClockCmd
  * @brief  EN: Slave mode delay reception clock enable, only related to slave mode (MS=1), only effective in high-speed mode.
  *         CN: 从机模式延迟接收时钟使能，只与从机模式有关（MS=1），只在高速模式下生效。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  NewState: 
  *         EN: Enable delay of 5ns/disable delay.
  *         CN: 启用延迟5ns/禁止延迟。
  * @retval None
  */
void SPI_SlaveModeDelayRxClockCmd(SPI_TypeDef *SPIx, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    SPIx->SPICR2 |= SPI_SSPCR2_SCLKD_Msk;
  }
  else
  {
    SPIx->SPICR2 &= ~SPI_SSPCR2_SCLKD_Msk;
  }
}

/**
  * @name   SPI_SlaveModeFilmSelectCmd
  * @brief  EN: Film selection signal software enable, only related to slave mode (MS=1).
  *         CN: 片选信号软件使能，只与从机模式有关（MS=1）。
  * @param  SPIx: 
  *         EN: where x can be from 0 select the SPI peripheral.
  *         CN: 其中x可以是0以选择 SPI 外设。
  * @param  NewState: 
  *         EN: FSS signal working normally/ignoring FSS signal.
  *         CN: FSS信号正常工作/无视FSS信号。
  * @retval None
  */
void SPI_SlaveModeFilmSelectCmd(SPI_TypeDef *SPIx, FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    SPIx->SPICR2 |= SPI_SSPCR2_FSSE_Msk;
  }
  else
  {
    SPIx->SPICR2 &= ~SPI_SSPCR2_FSSE_Msk;
  }
}
