/**
  ******************************************************************************
  * @file    ys32md211_comp.c
  * @author  YSPRING Application Team
  * @version V1.0.1
  * @date    2025.02.15
  * @brief   This file provides firmware functions to manage the following 
  *          functionalities of the Power Controller COMP peripheral:
  *           + Initialization and Configuration functions
  *           + COMP input and output pins configuration
  *           + COMP hysteresis, Filter, lock function configuration
  *           + COMP output status
  *
  *  @verbatim
 ===============================================================================
                      ##### How to use this driver #####
 ===============================================================================
    [..]
    (#) Enable the COMP interface clock using 
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_COMPx, ENABLE); 
    (#) COMP pins configuration
       (++) Enable the clock for the COMP GPIOs using the following function:
            RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOx, ENABLE);   
       (++) Configure these COMP pins in analog mode using GPIO_Init();  
       (++) Select the COMP input pin, using COMPx_INPSignalConfig() and 
            COMPx_INMSignalConfig() function.
    (#) Configure the COMP, using the COMP_Init() function.
        Select the COMP output,using COMPx_WindowModeConfig() function.
    (#) Activate the COMP peripheral using COMP_Cmd() function.

  @endverbatim
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "ys32md211_comp.h"

/** @addtogroup YS32MD211_StdPeriph_Driver
 * @{
 */

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

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup COMP_Private_Functions
 * @{
 */

/**
 * @brief  Deinitializes COMP peripheral registers to their default reset values.
 * @param  COMPx: where x can be 1 ~ 2 to select the COMP peripheral.
 * @retval None
 */
void COMP_DeInit(COMP_TypeDef *COMPx)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));

  COMPx->CSR = 0x00;
  COMPx->FR = 0x00;
}

/**
  * @brief  Initializes the COMPx peripheral according to the specified
  *         parameters in the COMP_InitStruct.
  * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
  * @param  COMP_InitStruct: pointer to a COMP_InitTypeDef structure that
  *         contains the configuration information for the specified COMP peripheral.
  * @retval None
  */
void COMP_Init(COMP_TypeDef *COMPx, COMP_InitTypeDef * COMP_InitStruct)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP_POWER_MODE(COMP_InitStruct->COMP_PowerMode));
  assert_param(IS_COMP_POLARITY(COMP_InitStruct->COMP_Polarity));
  assert_param(IS_COMP_FILTER_COUNT(COMP_InitStruct->COMP_FilterCount));
  assert_param(IS_COMP_AnologFilter(COMP_InitStruct->COMP_DegCtrl));

  COMPx->CSR = COMP_InitStruct->COMP_PowerMode | COMP_InitStruct->COMP_Polarity;
  if((COMP_InitStruct->COMP_FilterCount) != 0x0)
  {
     COMPx->FR |= (uint32_t)COMP1_FR_FLTEN; 
  }
  COMPx->FR = ((COMP_InitStruct->COMP_FilterCount << COMP1_FR_FLTCNT_Pos) | (COMP_InitStruct->COMP_DegCtrl));
}

/**
 * @brief  Fills each COMP_InitStruct member with its reset value.
 * @param  COMP_InitStruct: pointer to a COMP_InitTypeDef structure which will
 *         be initialized.
 * @retval None
 */
void COMP_StructInit(COMP_InitTypeDef *COMP_InitStruct)
{
  COMP_InitStruct->COMP_PowerMode   = COMP_PowerMode_High;
  COMP_InitStruct->COMP_Polarity    = COMP_Polarity_NotReversed;
  COMP_InitStruct->COMP_FilterCount = 0;
  COMP_InitStruct->COMP_DegCtrl     = COMP_AnologFilter_Disable;
}

/**
  * @brief  Enables or disables the specified COMP peripheral.
  * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
  * @param  NewState: new state of the COMPx peripheral. 
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void COMP_Cmd(COMP_TypeDef *COMPx, FunctionalState NewState)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    COMPx->CSR |= (uint32_t)COMP1_CSR_EN;
  }
  else
  {
    COMPx->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_EN));
  }
}

/**
  * @brief  Enables or disables the COMP1 and COMP2 hysteresis function.
  * @param  NewState: new state of the COMP1 peripheral. 
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void COMP12_InputHysteresisCmd(FunctionalState NewState)
{
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    COMP1->CSR |= (uint32_t)COMP1_CSR_HYST;
  }
  else
  {
    COMP1->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_HYST));
  }
}

/**
  * @brief  Enables or disables the Lock.
  * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
  * @param  NewState: new state of the COMPx peripheral. 
  *         This parameter can be: ENABLE.
  * @note   System reset to clear lock.
  * @retval None
  */
void COMP_LockCmd(COMP_TypeDef *COMPx, FunctionalState NewState)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    COMPx->CSR |= COMP1_CSR_LOCK;
  }
  else
  {
    COMP1->CSR &= ~COMP1_CSR_LOCK;
  }
}

/**
 * @brief  Get the COMP Out Status.
 * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
 * @retval COMP Out Status: SET or RESET
 */
FlagStatus COMP_GetOutStatus(COMP_TypeDef *COMPx)
{
  FlagStatus Status = RESET;
 // assert_param(IS_COMP_ALL_PERIPH(COMPx));

  if (COMPx->CSR & COMP1_CSR_COMP_OUT)
  {
    Status = SET;
  }

  return Status;
}

/**
  * @brief  Enables or disables the Filter.
  * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
  * @param  NewState: new state of the COMPx peripheral. 
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void COMP_DigitalFilterCmd(COMP_TypeDef *COMPx, FunctionalState NewState)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if ((NewState != DISABLE))
  {
    COMPx->FR |= (uint32_t)COMP1_FR_FLTEN;
  }
  else
  {
    /* Disable the COMP Filter */
    COMPx->FR &= (uint32_t)(~((uint32_t)COMP1_FR_FLTEN));
  }  
}

/**
 * @brief  config the Filter Count.
 * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
 * @param  Count: Filter Count value.
 *         This parameter can be 0x00 ~ 0xFFFF
 * @retval None
 */
void COMP_DigitalFilterCountConfig(COMP_TypeDef *COMPx, uint32_t Count)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP_FILTER_COUNT(Count));

  COMPx->FR &= ~COMP1_FR_FLTCNT;
  COMPx->FR |= (Count<<COMP1_FR_FLTCNT_Pos);
}

/**
 * @brief  Comp anolog filtering intensity selection.
 * @param  COMPx: where x can be 1 ~ 2  to select the COMP peripheral.
 * @param  Intensity:  Intensity selection.
 *         This parameter can be any combination of the following values:
 *            @arg COMP_AnologFilter_Disable  :  Disable analog filtering.
 *            @arg COMP_AnologFilter_Low      :  Low intensity, can filter 120ns width burrs.
 *            @arg COMP_AnologFilter_Medium   :  Medium intensity, can filter 220ns width burrs.
 *            @arg COMP_AnologFilter_High     :  High intensity, can filter 330ns width burrs.
 *
 * @retval None
 */
void COMP_AnologFilterSelect(COMP_TypeDef *COMPx, uint32_t intensity)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP_FILTER_COUNT(Count));

  COMPx->FR &= ~COMP1_FR_DEG_CTRL1;
  COMPx->FR |= (intensity);//<<COMP1_FR_DEG_CTRL1_Pos);

}
/**
 * @brief  config the COMP1 Window Mode Output selection.
 * @note   COMP1 and COMP2 The Window mode cannot be enabled at the same time.
 * @param  Mode:  Mode selection.
 *         This parameter can be any combination of the following values:
 *            @arg COMP1_WindowMode_INPSEL   :  The signal is selected by INPSEL [1:0].
 *            @arg COMP1_WindowMode_COMP2_INP:  The signal is selected by COMP2_INP.
 * @retval None
 */
void COMP1_WindowModeConfig(uint32_t Mode)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP1_WINDOW_MODE(Mode));

  COMP1->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_WINMODE));
  COMP1->CSR |= Mode;
}

/**
 * @brief  config the COMP2 Window Mode Output selection.
 * @note   COMP1 and COMP2 The Window mode cannot be enabled at the same time.
 * @param  Mode:  Mode selection.
 *         This parameter can be any combination of the following values:
 *            @arg COMP2_WindowMode_INPSEL   :  The signal is selected by INPSEL [1:0].
 *            @arg COMP2_WindowMode_COMP1_INP:  The signal is selected by COMP1_INP.
 * @retval None
 */
void COMP2_WindowModeConfig(uint32_t Mode)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP2_WINDOW_MODE(Mode));

  COMP2->CSR &= (uint32_t)(~((uint32_t)COMP2_CSR_WINMODE));
  COMP2->CSR |= Mode;
}

/**
 * @brief  config the COMP1 INP input signal.
 * @param  INPSignal: INP input Signal.
 *         This parameter can be any combination of the following values:
 *            @arg COMP1_InputPlus_PF4:  selection PF4
 *            @arg COMP1_InputPlus_PB2:  selection PB2
 *            @arg COMP1_InputPlus_PA3:  selection PA3
 *            @arg COMP1_InputPlus_OPA1: selection OPA1_OUT
 * @retval None
 */
void COMP1_InputPlusConfig(uint32_t INPSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP1_INP_SIGNAL(INPSignal));

  COMP1->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_INPSEL));
  COMP1->CSR |= INPSignal;
}

/**
 * @brief  config the COMP2 INP input signal.
 * @param  INPSignal: INP input Signal.
 *         This parameter can be any combination of the following values:
 *            @arg COMP2_InputPlus_PF4:  selection PF4
 *            @arg COMP2_InputPlus_PA1:  selection PA3
 *            @arg COMP2_InputPlus_PA3:  selection PA1
 *            @arg COMP2_InputPlus_OPA2: selection OPA2_OUT
 * @retval None
 */
void COMP2_InputPlusConfig(uint32_t INPSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP2_INP_SIGNAL(INPSignal));

  COMP2->CSR &= (uint32_t)(~((uint32_t)COMP2_CSR_INPSEL));
  COMP2->CSR |= INPSignal;
}

/**
 * @brief  config the COMP1 INM input signal.
 * @param  INMSignal: INM input Signal.
 *         This parameter can be any combination of the following values:
 *            @arg COMP1_InputMinus_PA0         :  selection PA0
 *            @arg COMP1_InputMinus_PB1         :  selection PB1
 *            @arg COMP1_InputMinus_PB3         :  selection PB3
 *            @arg COMP1_InputMinus_PB7         :  selection PB7
 *            @arg COMP1_InputMinus_1_8_VBG1P2  :  selection 1/8 VBG1P2
 *            @arg COMP1_InputMinus_2_8_VBG1P2  :  selection 2/8 VBG1P2
 *            @arg COMP1_InputMinus_3_8_VBG1P2  :  selection 3/8 VBG1P2
 *            @arg COMP1_InputMinus_4_8_VBG1P2  :  selection 4/8 VBG1P2
 *            @arg COMP1_InputMinus_5_8_VBG1P2  :  selection 5/8 VBG1P2
 *            @arg COMP1_InputMinus_6_8_VBG1P2  :  selection 6/8 VBG1P2
 *            @arg COMP1_InputMinus_7_8_VBG1P2  :  selection 7/8 VBG1P2
 *            @arg COMP1_InputMinus_VBG1P2      :  selection VBG1P2
 * @retval None
 */
void COMP1_InputMinusConfig(uint32_t INMSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP1_INM_SIGNAL(INMSignal));

  COMP1->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_INMSEL));
  COMP1->CSR |= INMSignal;

  if(INMSignal >= COMP1_InputMinus_1_8_VBG1P2)
  {
    COMP1->CSR |= (uint32_t)COMP1_CSR_SCALER_EN;
  }
  else
  {
    COMP1->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_SCALER_EN));
  }
}

/**
 * @brief  config the COMP2 INM input signal.
 * @param  INMSignal: INM input Signal.
 *         This parameter can be any combination of the following values:
 *            @arg COMP2_InputMinus_PA2         :  selection PA2
 *            @arg COMP2_InputMinus_PA4         :  selection PA4
 *            @arg COMP2_InputMinus_PA5         :  selection PA5
 *            @arg COMP2_InputMinus_PB7         :  selection PB7
 *            @arg COMP2_InputMinus_1_8_VBG1P2  :  selection 1/8 VBG1P2
 *            @arg COMP2_InputMinus_2_8_VBG1P2  :  selection 2/8 VBG1P2
 *            @arg COMP2_InputMinus_3_8_VBG1P2  :  selection 3/8 VBG1P2
 *            @arg COMP2_InputMinus_4_8_VBG1P2  :  selection 4/8 VBG1P2
 *            @arg COMP2_InputMinus_5_8_VBG1P2  :  selection 5/8 VBG1P2
 *            @arg COMP2_InputMinus_6_8_VBG1P2  :  selection 6/8 VBG1P2
 *            @arg COMP2_InputMinus_7_8_VBG1P2  :  selection 7/8 VBG1P2
 *            @arg COMP2_InputMinus_VBG1P2      :  selection VBG1P2
 * @retval None
 */
void COMP2_InputMinusConfig(uint32_t INMSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP2_INM_SIGNAL(INMSignal));

  COMP2->CSR &= (uint32_t)(~((uint32_t)COMP2_CSR_INMSEL));
  COMP2->CSR |= INMSignal;
  
  if(INMSignal >= COMP1_InputMinus_1_8_VBG1P2)
  {
    COMP1->CSR |= (uint32_t)COMP1_CSR_SCALER_EN;
  }
  else
  {
    COMP1->CSR &= (uint32_t)(~((uint32_t)COMP1_CSR_SCALER_EN));
  }

}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
