
/******************************************************************************
*@file  : spl_comp.c
*@brief : COMP SPL module driver.
*@ver   : 1.0.0
*@date  : 2023.08.08
******************************************************************************/

#include "acm32g103_spl_conf.h"
/******************************************************************************
*@brief : de-Initialize the COMP. 
*@note  : If the selected comparator is locked, de-initialization can't be performed.
*         To unlock the configuration, perform a module reset.
*@param : COMP_Selection: COMP number
*@return: none
******************************************************************************/
void COMP_DeInit(uint32_t COMP_Selection)
{
    assert_param(IS_COMP_COMPx(COMP_Selection));
    /*!< Set COMP_CSR register to reset value */
    *(__IO uint32_t *) (COMP_BASE_ADDR + COMP_Selection) = ((uint32_t)0x00000000);
}
/******************************************************************************
*@brief : Initialize the COMP. 
*@note  : If the selected comparator is locked, initialization can't be performed.
*         To unlock the configuration, perform a module reset.
*@param : COMP_Selection: COMP number;COMP_InitStruct:COMP initialization parameter struct
*@return: none
******************************************************************************/
void COMP_Init(uint32_t COMP_Selection, COMP_InitTypeDef* COMP_InitStruct)
{
    uint32_t tempReg = 0;
    
    assert_param(IS_COMP_COMPx(COMP_Selection));

    assert_param(IS_COMP_WINOUT(COMP_InitStruct->WinOut));
    assert_param(IS_COMP_POLARITY(COMP_InitStruct->Polarity));      
    assert_param(IS_COMP_BLANKSEL(COMP_InitStruct->BlankSel));  
    assert_param(IS_COMP_HYS(COMP_InitStruct->HYS)); 
    tempReg |= ((COMP_InitStruct->WinOut & COMP_CR_WINOUT_Msk) | \
                (COMP_InitStruct->Polarity & COMP_CR_POLARITY_Msk) | \
                (COMP_InitStruct->BlankSel & COMP_CR_BLANKSEL_Msk) | \
                (COMP_InitStruct->HYS & COMP_CR_HYS_Msk));

    assert_param(IS_COMP_WINMODE(COMP_InitStruct->WinMode));
    tempReg |= COMP_InitStruct->WinMode & COMP_CR_WINMODE_Msk; 
    if(COMP_InitStruct->WinMode == COMP_WINMODE_SELF_INP)
    {
        assert_param(IS_COMP_INPSEL(COMP_InitStruct->InPSel));
        tempReg |= COMP_InitStruct->InPSel & COMP_CR_INPSEL_Msk;
    }    
    
    assert_param(IS_COMP_INMSEL(COMP_InitStruct->InMSel));
    tempReg |= COMP_InitStruct->InMSel & COMP_CR_INMSEL_Msk;
    if(COMP_InitStruct->InMSel == COMP_INMSEL_VREF_AVDD)
    {
        assert_param(IS_COMP_CRVSEL(COMP_InitStruct->CrvSel)); 
        assert_param(IS_COMP_CRVEN(COMP_InitStruct->CrvEn)); 
        tempReg |= ((COMP_InitStruct->CrvSel & COMP_CR_CRVSEL_Msk) | \
                    (COMP_InitStruct->CrvEn & COMP_CR_CRVEN_Msk));
        
        if(COMP_InitStruct->CrvEn == COMP_CRV_ENABLE)
        {
            assert_param(IS_COMP_CRVCFG(COMP_InitStruct->CrvCfg));
            tempReg |= COMP_InitStruct->CrvCfg << COMP_CR_CRVCFG_Pos;
        }
    }
    
    assert_param(IS_COMP_FLTEN(COMP_InitStruct->FltEn));
    tempReg |= COMP_InitStruct->FltEn & COMP_CR_FLTEN_Msk;
    if(COMP_InitStruct->FltEn == COMP_FLT_ENABLE)
    {
        assert_param(IS_COMP_FLTTIME(COMP_InitStruct->FltTime));
        tempReg |= COMP_InitStruct->FltTime & COMP_CR_FLTTIME_Msk;
    }
    
    CLEAR_BIT(*(__IO uint32_t *) (COMP_BASE_ADDR+COMP_Selection), COMP_CR_EN); //disable          

    //Write the COMP_CR register
    WRITE_REG(*(__IO uint32_t *) (COMP_BASE_ADDR+COMP_Selection),tempReg);
    
}

/******************************************************************************
*@brief : Enable or Disable comparator.
*@param : COMP_Selection: COMP number;NewState: ENABLE or DISABLE
*@return: none
******************************************************************************/
void COMP_Cmd(uint32_t COMP_Selection, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_COMP_COMPx(COMP_Selection));
//    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected COMPx peripheral */
        *(__IO uint32_t *) (COMP_BASE_ADDR + COMP_Selection) |= (uint32_t) (COMP_CR_EN);
    }
    else
    {
        /* Disable the selected COMP peripheral    */
        *(__IO uint32_t *) (COMP_BASE_ADDR + COMP_Selection) &= (uint32_t)(~COMP_CR_EN);
    }
}
/******************************************************************************
*@brief : lock comparator.
*@param : COMP_Selection: COMP number
*@return: none
******************************************************************************/
void COMP_LockConfig(uint32_t COMP_Selection)
{
    /* Check the parameter */
    assert_param(IS_COMP_COMPx(COMP_Selection));

    /* Set the lock bit corresponding to selected comparator */
    *(__IO uint32_t *) (COMP_BASE_ADDR + COMP_Selection) |= (uint32_t) (COMP_CR_LOCK);
}

/******************************************************************************
*@brief : Initialize the COMP initialization parameter struct. 
*@note  :
*@param : COMP_InitStruct:COMP initialization parameter struct
*@return: none
******************************************************************************/
void COMP_StructInit(COMP_InitTypeDef* COMP_InitStruct)
{
    COMP_InitStruct->InMSel = COMP_INMSEL_P0;
    COMP_InitStruct->InPSel = COMP_INPSEL_P0;
    COMP_InitStruct->BlankSel = COMP_BLANKSEL_NONE;
    COMP_InitStruct->Polarity = COMP_POLARITY_NOINVERT;
    COMP_InitStruct->HYS = COMP_HYS_NONE;
    COMP_InitStruct->FltEn = COMP_FLT_DISABLE;
    COMP_InitStruct->FltTime = COMP_FLTTIME_1CLK;
    COMP_InitStruct->CrvEn = COMP_CRV_DISABLE;
    COMP_InitStruct->CrvSel = COMP_CRVSEL_AVDD;
    COMP_InitStruct->CrvCfg = 9;
    COMP_InitStruct->WinMode = COMP_WINMODE_SELF_INP;
    COMP_InitStruct->WinOut = COMP_WINOUT_DIRECT;
}
/******************************************************************************
*@brief : Get the output level of the comparator. the value is returned.
*@param : COMP_Selection: COMP number
*@return: output value
******************************************************************************/
uint32_t COMP_GetOutputLevel(uint32_t COMP_Selection)
{
    uint32_t compout = 0x0;

    /* Check the parameters */
    assert_param(IS_COMP_COMPx(COMP_Selection));

    if(COMP_Selection == COMP1)
    {
        compout    = (COMP->SR & COMP_SR_VCOUT1) ? COMP_OutputLevel_High : COMP_OutputLevel_Low;
    }
    else if(COMP_Selection == COMP2)
    {
        compout   = (COMP->SR & COMP_SR_VCOUT2) ? COMP_OutputLevel_High : COMP_OutputLevel_Low;
    }    
    else if(COMP_Selection == COMP3)
    {
        compout    = (COMP->SR & COMP_SR_VCOUT3) ? COMP_OutputLevel_High : COMP_OutputLevel_Low;
    }    
    else if(COMP_Selection == COMP4)
    {
        compout    = (COMP->SR & COMP_SR_VCOUT4) ? COMP_OutputLevel_High : COMP_OutputLevel_Low;
    }

    /* Return the comparator output level */
    return (uint32_t)(compout);
}