/**
  ******************************************************************************
  * @file    ys32f030_comp.c
  * @author  YSPRING Application Team
  * @version V1.0.1
  * @date    2023.6.28
  * @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 "ys32f030_comp.h"

/** @addtogroup YS32F030_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 ~ 4 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 ~ 4  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));

  COMPx->CSR = COMP_InitStruct->COMP_PowerMode | COMP_InitStruct->COMP_Polarity;
  COMPx->FR = (COMP_InitStruct->COMP_FilterCount << COMP_FR_FLTCNT_Pos);
}

/**
 * @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;
}

/**
  * @brief  Enables or disables the specified COMP peripheral.
  * @param  COMPx: where x can be 1 ~ 4  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 |= COMP_CSR_EN;
  }
  else
  {
    COMPx->CSR &= ~COMP_CSR_EN;
  }
}

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

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

/**
  * @brief  Enables or disables the COMP3 and COMP4 hysteresis function.
  * @param  COMPx: COMP3 peripheral.
  * @param  NewState: new state of the COMP3 peripheral. 
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void COMP34_InputHysteresisCmd(COMP_TypeDef *COMPx, FunctionalState NewState)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    COMP3->CSR |= COMP_CSR_HYST;
  }
  else
  {
    COMP3->CSR &= ~COMP_CSR_HYST;
  }
}

/**
  * @brief  Enables or disables the Lock.
  * @param  COMPx: where x can be 1 ~ 4  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 |= COMP_CSR_LOCK;
  }
}

/**
 * @brief  Get the COMP Out Status.
 * @param  COMPx: where x can be 1 ~ 4  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 & COMP_CSR_COMP_OUT)
  {
    Status = SET;
  }

  return Status;
}

/**
  * @brief  Enables or disables the Filter.
  * @param  COMPx: where x can be 1 ~ 4  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 |= COMP_FR_FLTEN;
  }
  else
  {
    /* Disable the COMP Filter */
    COMPx->FR &= (uint16_t)(~((uint16_t)COMP_FR_FLTEN));
  }  
}

/**
 * @brief  config the Filter Count.
 * @param  COMPx: where x can be 1 ~ 4  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 &= ~COMP_FR_FLTCNT;
  COMPx->FR |= (Count<<COMP_FR_FLTCNT_Pos);
}

/**
 * @brief  config the COMP1 Window Mode Output selection.
 * @note   COMP1 and COMP2 The Window mode cannot be enabled at the same time.
 * @param  COMPx: COMP1 peripheral.
 * @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(COMP_TypeDef *COMPx, uint32_t Mode)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP1_WINDOW_MODE(Mode));

  COMPx->CSR &= ~COMP_CSR_WINMODE;
  COMPx->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  COMPx: COMP2 peripheral.
 * @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(COMP_TypeDef *COMPx, uint32_t Mode)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP2_WINDOW_MODE(Mode));

  COMPx->CSR &= ~COMP_CSR_WINMODE;
  COMPx->CSR |= Mode;
}

/**
 * @brief  config the COMP3 Window Mode Output selection.
 * @note   COMP3 and COMP4 The Window mode cannot be enabled at the same time.
 * @param  COMPx: COMP3 peripheral.
 * @param  Mode:  Mode selection.
 *          This parameter can be any combination of the following values:
 *            @arg COMP3_WindowMode_INPSEL   :  The signal is selected by INPSEL [1:0].
 *            @arg COMP3_WindowMode_COMP4_INP:  The signal is selected by COMP3_INP.
 * @retval None
 */
void COMP3_WindowModeConfig(COMP_TypeDef *COMPx, uint32_t Mode)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP3_WINDOW_MODE(Mode));

  COMPx->CSR &= ~COMP_CSR_WINMODE;
  COMPx->CSR |= Mode;
}

/**
 * @brief  config the COMP4 Window Mode Output selection.
 * @note   COMP3 and COMP4 The Window mode cannot be enabled at the same time.
 * @param  COMPx: COMP4 peripheral.
 * @param  Mode:  Mode selection.
 *          This parameter can be any combination of the following values:
 *            @arg COMP4_WindowMode_INPSEL   :  The signal is selected by INPSEL [1:0].
 *            @arg COMP4_WindowMode_COMP3_INP:  The signal is selected by COMP3_INP.
 * @retval None
 */
void COMP4_WindowModeConfig(COMP_TypeDef *COMPx, uint32_t Mode)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP4_WINDOW_MODE(Mode));

  COMPx->CSR &= ~COMP_CSR_WINMODE;
  COMPx->CSR |= Mode;
}

/**
 * @brief  config the COMP1 INP input signal.
 * @param  COMPx: COMP1 peripheral.
 * @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
 * @retval None
 */
void COMP1_InputPlusConfig(COMP_TypeDef *COMPx, uint32_t INPSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP1_INP_SIGNAL(INPSignal));

  COMPx->CSR &= ~COMP_CSR_INPSEL;
  COMPx->CSR |= INPSignal;
}

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

  COMPx->CSR &= ~COMP_CSR_INPSEL;
  COMPx->CSR |= INPSignal;
}

/**
 * @brief  config the COMP3 INP input signal.
 * @param  COMPx: COMP3 peripheral.
 * @param  INPSignal: INP input Signal.
 *          This parameter can be any combination of the following values:
 *            @arg COMP3_InputPlus_PA1 :  selection PA1 
 *            @arg COMP3_InputPlus_PB0 :  selection PB0
 *            @arg COMP3_InputPlus_PA5 :  selection PA5  
 * @retval None
 */
void COMP3_InputPlusConfig(COMP_TypeDef *COMPx, uint32_t INPSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP3_INP_SIGNAL(INPSignal));

  COMPx->CSR &= ~COMP_CSR_INPSEL;
  COMPx->CSR |= INPSignal;
}

/**
 * @brief  config the COMP4 INP input signal.
 * @param  COMPx: COMP4 peripheral.
 * @param  INPSignal: INP input Signal.
 *          This parameter can be any combination of the following values:
 *            @arg COMP4_InputPlus_PA0 :  selection PA0 
 *            @arg COMP4_InputPlus_PB3 :  selection PB3 
 *            @arg COMP4_InputPlus_PA5 :  selection PA5 
 * @retval None
 */
void COMP4_InputPlusConfig(COMP_TypeDef *COMPx, uint32_t INPSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP4_INP_SIGNAL(INPSignal));

  COMPx->CSR &= ~COMP_CSR_INPSEL;
  COMPx->CSR |= INPSignal;
}

/**
 * @brief  config the COMP1 INM input signal.
 * @param  COMPx: COMP1 peripheral.
 * @param  INMSignal: INM input Signal.
 *          This parameter can be any combination of the following values:
 *            @arg COMP1_InputMinus_1_4_VREF:  selection 1/4 VREFINT
 *            @arg COMP1_InputMinus_1_2_VREF:  selection 1/2 VREFINT
 *            @arg COMP1_InputMinus_3_4_VREF:  selection 3/4 VREFINT
 *            @arg COMP1_InputMinus_VREF    :  selection VREFINT
 *            @arg COMP1_InputMinus_PB7     :  selection PB7
 *            @arg COMP1_InputMinus_PA0     :  selection PA0
 *            @arg COMP1_InputMinus_PB3     :  selection PB3
 *            @arg COMP1_InputMinus_PB1     :  selection PB1
 * @retval None
 */
void COMP1_InputMinusConfig(COMP_TypeDef *COMPx, uint32_t INMSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP1_INM_SIGNAL(INMSignal));

  COMPx->CSR &= ~COMP_CSR_INMSEL;
  COMPx->CSR |= INMSignal;

  if(INMSignal <= COMP1_InputMinus_VREF)
  {
    COMPx->CSR |= COMP_CSR_SCALER_EN;
  }
  else
  {
    COMPx->CSR &= ~COMP_CSR_SCALER_EN;
  }
}

/**
 * @brief  config the COMP2 INM input signal.
 * @param  COMPx: COMP2 peripheral.
 * @param  INMSignal: INM input Signal.
 *          This parameter can be any combination of the following values:
 *            @arg COMP2_InputMinus_1_4_VREF:  selection 1/4 VREFINT
 *            @arg COMP2_InputMinus_3_4_VREF:  selection 3/4 VREFINT
 *            @arg COMP2_InputMinus_1_2_VREF:  selection 1/2 VREFINT
 *            @arg COMP2_InputMinus_VREF    :  selection VREFINT
 *            @arg COMP2_InputMinus_PA4     :  selection PA4 
 *            @arg COMP2_InputMinus_PA2     :  selection PA2
 *            @arg COMP2_InputMinus_PB7     :  selection PB7
 *            @arg COMP2_InputMinus_PA5     :  selection PA5 
 * @retval None
 */
void COMP2_InputMinusConfig(COMP_TypeDef *COMPx, uint32_t INMSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP2_INM_SIGNAL(INMSignal));

  COMPx->CSR &= ~COMP_CSR_INMSEL;
  COMPx->CSR |= INMSignal;
  
  if(INMSignal <= COMP1_InputMinus_VREF)
  {
    COMP1->CSR |= COMP_CSR_SCALER_EN;
  }
  else
  {
    COMP1->CSR &= ~COMP_CSR_SCALER_EN;
  }

}

/**
 * @brief  config the COMP3 INM input signal.
 * @param  COMPx: COMP3 peripheral.
 * @param  INMSignal: INM input Signal.
 *          This parameter can be any combination of the following values:
 *            @arg COMP3_InputMinus_1_4_VREF:  selection 1/4 VREFINT
 *            @arg COMP3_InputMinus_3_4_VREF:  selection 3/4 VREFINT
 *            @arg COMP3_InputMinus_1_2_VREF:  selection 1/2 VREFINT
 *            @arg COMP3_InputMinus_VREF    :  selection VREFINT
 *            @arg COMP3_InputMinus_PB2     :  selection PB2 
 *            @arg COMP3_InputMinus_PA2     :  selection PA2
 *            @arg COMP3_InputMinus_PB13    :  selection PB13 
 *            @arg COMP3_InputMinus_PB5     :  selection PB5
 * @retval None
 */
void COMP3_InputMinusConfig(COMP_TypeDef *COMPx, uint32_t INMSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP3_INM_SIGNAL(INMSignal));

  COMPx->CSR &= ~COMP_CSR_INMSEL;
  COMPx->CSR |= INMSignal;

  if(INMSignal <= COMP3_InputMinus_VREF)
  {
    COMPx->CSR |= COMP_CSR_SCALER_EN;
  }
  else
  {
    COMPx->CSR &= ~COMP_CSR_SCALER_EN;
  }
}

/**
 * @brief  config the COMP4 INM input signal.
 * @param  COMPx: COMP4 peripheral.
 * @param  INMSignal: INM input Signal.
 *          This parameter can be any combination of the following values:
 *            @arg COMP4_InputMinus_1_4_VREF:  selection 1/4 VREFINT
 *            @arg COMP4_InputMinus_3_4_VREF:  selection 3/4 VREFINT
 *            @arg COMP4_InputMinus_1_2_VREF:  selection 1/2 VREFINT
 *            @arg COMP4_InputMinus_VREF    :  selection VREFINT
 *            @arg COMP4_InputMinus_PA4     :  selection PA4 
 *            @arg COMP4_InputMinus_PA1     :  selection PA1
 *            @arg COMP4_InputMinus_PB13    :  selection PB13 
 *            @arg COMP4_InputMinus_PB1     :  selection PB1
 * @retval None
 */
void COMP4_InputMinusConfig(COMP_TypeDef *COMPx, uint32_t INMSignal)
{
  assert_param(IS_COMP_ALL_PERIPH(COMPx));
  assert_param(IS_COMP4_INM_SIGNAL(INMSignal));

  COMPx->CSR &= ~COMP_CSR_INMSEL;
  COMPx->CSR |= INMSignal;
  
  if(INMSignal <= COMP1_InputMinus_VREF)
  {
    COMP3->CSR |= COMP_CSR_SCALER_EN;
  }
  else
  {
    COMP3->CSR &= ~COMP_CSR_SCALER_EN;
  }

}
/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
