/**
  ******************************************************************************
  * @file    lcm32f06x_dac.c
  * @author  System R&D Team
  * @version V2.0.2
  * @date    10-April-2025
  * @brief   This file provides all the DAC 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_dac.h"

/**
  * @name   DAC_DeInit
  * @brief  EN: Deinitializes DAC peripheral registers to their default reset values.
  *         CN: 将 DAC 外设寄存器初始化为其默认重置值。
  * @param  None
  * @retval None
  * @note   EN: DAC ACMP and OPA share the same clock enable which can be used once.
  *         CN: DAC ACMP OPA 共用一个时钟使能，使用一次即可。
  */
void DAC_DeInit(void)
{
  RCC_APB0PeriphResetCmd(RCC_APB0Periph_ANACTRL, ENABLE);
  RCC_APB0PeriphResetCmd(RCC_APB0Periph_ANACTRL, DISABLE);
}

/**
  * @name   DAC_Init
  * @brief  EN: Initializes the DAC peripheral according to the specified 
  *             parameters in the DAC.
  *         CN: 根据 DAC_InitStruct 中指定的参数初始化 DAC。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_InitStruct: 
  *         EN: pointer to a DAC_InitTypeDef structure that contains the 
  *             configuration information for the specified DAC peripheral.
  *         CN: 指向 DAC_InitTypeDef 结构的指针，该结构包含指定 DAC 外设的配置信息。
  * @retval None
  */
void DAC_Init(DAC_TypeDef *DACx, DAC_InitTypeDef *DAC_InitStruct)
{
  DACx->DAC_CR = ( DAC_InitStruct->DAC_WaveGeneration |
                   DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | DAC_InitStruct->DAC_Vref_Select |
                   ((DAC_InitStruct->DAC_DmaMode) << 12) | ((DAC_InitStruct->DAC_DMAUDR_IE) << 13));
  ANACTRL->ANA_CTRL |= DAC_InitStruct->DAC_OutputBuffer;
}

/**
  * @name   DAC_StructInit
  * @brief  EN: Fills each DAC_InitStruct member with its default value.
  *         CN: 用默认值填充每个 DAC_InitStruct 成员。
  * @param  DAC_InitStruct: 
  *         EN: pointer to a DAC_InitTypeDef structure that contains the 
  *             configuration information for the specified DAC peripheral.
  *         CN: 指向 DAC_InitTypeDef 结构的指针，该结构包含指定 DAC 外设的配置信息。
  * @retval None
  */
void DAC_StructInit(DAC_InitTypeDef *DAC_InitStruct)
{
  /*--------------- Reset DAC init structure parameters values -----------------*/

  DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None;

  DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;

  DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Disable;

  DAC_InitStruct->DAC_Vref_Select = DAC_Vref_ADCref;

  DAC_InitStruct->DAC_DmaMode = DISABLE;

  DAC_InitStruct->DAC_DMAUDR_IE = DISABLE;
}

/**
  * @name   DAC_Cmd
  * @brief  EN: Enables or disables the specified DAC peripheral.
  *         CN: 启用或禁用指定的 DAC 外设。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  NewState: 
  *         EN: New state of the DACx peripheral.
  *         CN: DACx 外设的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void DAC_Cmd(DAC_TypeDef *DACx, FunctionalState NewState)
{

  if (NewState != DISABLE)
  {
    /* Enable the selected DAC channel */

    DACx->DAC_CR |= ANACTRL_DACX_CR_EN_Msk;
  }
  else
  {
    /* Disable the selected DAC channel */

    DACx->DAC_CR &= ~(ANACTRL_DACX_CR_EN_Msk);
  }
}

/**
  * @name   DAC_SoftwareTriggerCmd
  * @brief  EN: DAC Software triggered command.
  *         CN: DAC软件触发命令。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  NewState: 
  *         EN: New state of the DAC Software Trigger.
  *         CN: DACx 软件触发的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void DAC_SoftwareTriggerCmd(DAC_TypeDef *DACx, FunctionalState NewState)
{

  if (NewState != DISABLE)
  {
    /* Enable software trigger for the selected DAC channel */

    DACx->DAC_SR |= (ANACTRL_DACX_SR_SWTRIG_Msk);
  }
  else
  {
    /* Disable software trigger for the selected DAC channel */

    DACx->DAC_SR &= ~(ANACTRL_DACX_SR_SWTRIG_Msk);
  }
}

/**
  * @name   DAC_WaveGenerationCmd
  * @brief  EN: DAC waveform setting: noise triangle.
  *         CN: DAC波形设置：噪声 三角。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_Wave: 
  *         EN: waveform selection.
  *         CN: 波形选择。
  *             @arg DAC_WaveGeneration_None
  *             @arg DAC_WaveGeneration_Noise
  *             @arg DAC_WaveGeneration_Triangle
  * @param  NewState: 
  *         EN: New state of the DAC wave.
  *         CN: DACx 波形的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void DAC_WaveGenerationCmd(DAC_TypeDef *DACx, uint32_t DAC_Wave, FunctionalState NewState)
{
  uint32_t temp;
  assert_param(IS_DAC_WaveGeneration(DAC_Wave));
  
  temp = DACx->DAC_CR & (~ANACTRL_DACX_CR_WAVE_Msk);

  if (NewState != DISABLE)
  {
    /* Enable the selected DAC Wave */
    temp |= DAC_Wave;
  }
  else
  {
    /* Disable the selected DAC Wave */
    temp &= (uint32_t)(~ANACTRL_DACX_CR_WAVE_Msk);
  }
  DACx->DAC_CR = temp;
}

/**
  * @name   DAC_SetDac_10B_Data
  * @brief  EN: Set the DAC data conversion.
  *         CN: 设置dac数据转换。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设.
  * @param  DAC_Align: 
  *         EN: Data alignment mode left and right
  *         CN: 数据对齐模式。
  *             @arg DAC_Align_10B_R
  *             @arg DAC_Align_10B_L
  * @param  Data: 
  *         EN: DAC Data.
  *         CN: DAC 数据。
  * @retval None
  */
void DAC_SetDac_10B_Data(DAC_TypeDef *DACx, uint32_t DAC_Align, uint16_t Data)
{
  uint32_t Rdata = 0;

  assert_param(IS_DAC_Align(DAC_Align));

  DACx->DAC_CR &= ~(ANACTRL_DACX_CR_ALIGN_Msk);
  DACx->DAC_CR |= DAC_Align;
  Rdata = ((DACx->DAC_CR) >> 15) & 0x01;
  if (Rdata == 1)
  {
    DACx->DAC_DHR = (Data << 6);
  }
  else
  {
    DACx->DAC_DHR = Data;
  }
}

/**
  * @name   DAC_WaveGenerationCmd
  * @brief  EN: Get data register.
  *         CN: 获取数据寄存器。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @retval uint16_t
  *         EN: DAC Data.
  *         CN: DAC 数据。
  */
uint16_t DAC_GetDataOutputValue_10bit(DAC_TypeDef *DACx)
{
  uint32_t data = 0;
  uint32_t tmp = 0;
  data = ((DACx->DAC_CR) >> 15) & 0x01;

  if (data == 1)
  {
    tmp = ((DACx->DAC_DOR) >> 6) & 0xfff;
  }
  else
  {
    tmp = (DACx->DAC_DOR) & 0xfff;
  }
  return tmp;
}

/**
  * @name   DAC_ITConfig
  * @brief  EN: Enables or disables the specified DAC interrupts.
  *         CN: 启用或禁用指定的DAC中断。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_IT: 
  *         EN: Specifies the DAC rupt sources to be enabled or disabled.
  *         CN: 指定要启用或禁用的 DAC 中断源。
  *             @arg DAC_IT_DMAUDR
  * @param  NewState: 
  *         EN: new state of the specified DAC interrupts.
  *         CN: 指定DAC中断的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void DAC_ITConfig(DAC_TypeDef *DACx, uint32_t DAC_IT, FunctionalState NewState)
{
  assert_param(IS_DAC_IT_CONFIG(DAC_IT));

  if (NewState != DISABLE)
  {
    /* Enable the selected DAC interrupts */

    DACx->DAC_CR |= DAC_IT;
  }
  else
  {
    /* Disable the selected DAC interrupts */

    DACx->DAC_CR &= (~(uint32_t)DAC_IT);
  }
}

/**
  * @name   DAC_GetFlagStatus
  * @brief  EN: Read DAC status flags.
  *         CN: 读取 DAC 状态标志。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_FLAG: 
  *         EN: Specify the DAC flag to be read.
  *         CN: 指定DAC要读取的标志。
  *             @arg DAC_FLAG_DMAUDR
  *             @arg DAC_FLAG_DACSOFT
  * @retval FlagStatus
  */
FlagStatus DAC_GetFlagStatus(DAC_TypeDef *DACx, uint32_t DAC_FLAG)
{
  FlagStatus bitstatus = RESET;
  uint32_t tmpreg = 0;

  /* Check the parameters */
  assert_param(IS_DAC_FLAG_CONFIG(DAC_FLAG));

  tmpreg = DACx->DAC_SR;

  /* Check the status of the specified ADC flag */
  if ((tmpreg & DAC_FLAG) != (uint32_t)RESET)
  {
    /* ADC_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* ADC_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the ADC_FLAG status */
  return bitstatus;
}

/**
  * @name   DAC_ClearFlag
  * @brief  EN: The DAC clears the flags.
  *         CN: DAC清除标志位。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_FLAG: 
  *         EN: Specifies the DAC flag to be enabled or disabled.
  *         CN: 指定要启用或禁用的DAC 标志。
  *             @arg DAC_FLAG_DMAUDR
  *             @arg DAC_FLAG_DACSOFT
  * @retval None
  */
void DAC_ClearFlag(DAC_TypeDef *DACx, uint32_t DAC_FLAG)
{
  assert_param(IS_DAC_FLAG_CONFIG(DAC_FLAG));

  /* Clear the selected DAC flags */

  DACx->DAC_SR = DAC_FLAG;
}

/**
  * @name   DAC_ClearITPendingBit
  * @brief  EN: The DAC clears the interrupt flags.
  *         CN: DAC清中断标志位。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_IT: 
  *         EN:Specifies the DAC interrupt sources to be enabled or disabled.
  *         CN:指定要启用或禁用的DAC中断源。
  *             @arg DAC_IT_DMAUDR
  * @retval None
  */
void DAC_ClearITPendingBit(DAC_TypeDef *DACx, uint32_t DAC_IT)
{
  assert_param(IS_DAC_GET_IT_CONFIG(DAC_IT));
  /* Clear the selected DAC interrupt pending bits */

  DACx->DAC_SR = DAC_IT;
}

/**
  * @name   DAC_TriggerSourceConfig
  * @brief  EN: DAC triggered Souce config.
  *         CN: DAC触发源选择配置。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  DAC_TriggerSource: 
  *         EN: DAC trigger source selection.
  *         CN: DAC 触发源选择。
  *             @arg DAC_TiggerSource_EXTI9
  *             @arg DAC_TiggerSource_EXTI1
  *             @arg DAC_TiggerSource_TIM14_TRIG_OC1
  *             @arg DAC_TiggerSource_TIM16_TRIG_OC1
  *             @arg DAC_TiggerSource_TIM15_TRGO
  *             @arg DAC_TiggerSource_TIM3_TRGO
  *             @arg DAC_TiggerSource_TIM1_TRGO
  *             @arg DAC_TiggerSource_SOFTWARE
  * @param  DAC_TriggerMode: 
  *         EN: DAC trigger source mode selection.
  *         CN: DAC触发源模式选择。
  *             @arg DAC_TiggerMode_Externnal_RiseEdge
  *             @arg DAC_TiggerMode_Externnal_FallEdge
  *             @arg DAC_TiggerMode_Externnal_DoubleEdge
  *             @arg DAC_TiggerMode_NoExternalTrigger
  * @retval None
  */
void DAC_TriggerSourceConfig(DAC_TypeDef *DACx, uint32_t DAC_TriggerSource, uint32_t DAC_TriggerMode)
{
  uint32_t temp = 0;
  if( DACx == DAC)
  {
        temp = SYSCTRL->EDU_CFG17 & 0xFFFFFF8C;
        sysctrl_access();
        SYSCTRL->EDU_CFG17 = temp | (DAC_TriggerSource | DAC_TriggerMode);
        __dekey();
  }
}

/**
  * @name   DAC_OutputBuff
  * @brief  EN: DAC Outpt Buff Enable.
  *         CN: DAC 输出Buff使能。
  * @param  DACx: 
  *         EN: where x can be 0 to select the DAC peripheral.
  *         CN: x 可以是 0 以选择 DAC 外设。
  * @param  NewState: 
  *         EN: new state of the specified DAC Output Buff.
  *         CN: 指定DAC 输出BUFF的新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void DAC_OutputBuff(DAC_TypeDef *DACx, FunctionalState NewState)
{
    if( DACx == DAC)
    {
        if (NewState != DISABLE)
        {
            ANACTRL->ANA_CTRL |= ANACTRL_ANA_CTRL_DAC_BUFEN_Msk;
        }
        else
        {
            ANACTRL->ANA_CTRL &= (~ANACTRL_ANA_CTRL_DAC_BUFEN_Msk);
        }
    }
}

