
/******************************************************************************
* @file      : spl_pmu.c
* @version   : 1.0
* @date      : 2023.2.7
* @brief     : PMU SPL module driver
*   
* @history   :	
*   2023.2.7    lwq    create                     
******************************************************************************/
#include "acm32g103_spl_conf.h" 


//#ifdef SPL_PMU_MODULE_ENABLED


/******************************************************************************
* @brief:  Deinitializes the PMU peripheral registers to their default reset values.     
* @param:  None
* @return: None
******************************************************************************/
void PMU_DeInit(void)
{
    /* Release PMU from reset state */
    __RCC_PMU_RESET();
    
    /* Clear PMU status */
    PMU_ClearFlag(PMU_FLAG_ALL);
}

/******************************************************************************
* @brief:  Initialize the PMU peripheral.     
* @param:  None
* @return: None
******************************************************************************/
void PMU_Init(void)
{
    /* Enable PMU CLK */
    __RCC_PMU_CLK_ENABLE();	 
}

/******************************************************************************
* @brief:  Enables or disables access to the RTC domain (RTC registers, RTC 
*          backup data registers).
* @param:  NewState: new state of the access to the backup domain.
*          This parameter can be: ENABLE or DISABLE.
* @return: None
******************************************************************************/
void PMU_BackupAccessCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    /* RTC module write enable */
    if (NewState != DISABLE)
    {
        PMU->CTRL0 |= PMU_CTL0_RTC_WE;   
    }
    else
    { 
        /* RTC module write disable */
        PMU->CTRL0 &= (~PMU_CTL0_RTC_WE);
    }
}

/******************************************************************************
* @brief:  Configures the voltage threshold detected by the Low Voltage Detector(LVD).
* @param:  PMU_LVDVoltage: specifies the LVD detection voltage
* @return: None
******************************************************************************/
void PMU_LVDVoltageConfig(uint32_t PMU_LVDVoltage)
{
    /* Check the parameters */
    assert_param(IS_PMU_LVD_VOLTAGE(PMU_LVDVoltage));

    /* Clear CTRL1[3:1] bits */
    PMU->CTRL1 &= (~PMU_CTL1_LVD_SEL_Msk);

    /* Set CTRL1[3:1] bits according to PMU_LVDVoltage value */
    PMU->CTRL1 |= PMU_LVDVoltage;
}

/******************************************************************************
* @brief:  Enables or disables the Low Voltage Detector(LVD).
* @param:  NewState: new state of the LVD.
* @return: None
******************************************************************************/
void PMU_LVDCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* enable LVD */
    if (NewState != DISABLE)
    {
        PMU->CTRL1 |= PMU_CTL1_LVDEN;   
    }
    else
    { 
        /* disable LVD */
        PMU->CTRL1 &= (~PMU_CTL1_LVDEN);
    }
}

/******************************************************************************
* @brief:  Configures the LVD Filter.
* @param:  PMU_LVDFilter: Specifies the LVD filter.
* @return: None
******************************************************************************/
void PMU_LVDFilterConfig(uint32_t PMU_LVDFilter)
{
    /* Check the parameters */
    assert_param(IS_PMU_LVD_FILTER(PMU_LVDFilter));
    
    /* Clear CTRL1[11:9] bits */
    PMU->CTRL1 &= (~PMU_CTL1_FLT_TIME_Msk);	
    
    /* Set CTRL1[11:9] bits according to PMU_LVDFilter value */
    PMU->CTRL1 |= PMU_LVDFilter;        
}

/******************************************************************************
* @brief:  Enables or disables the LVD Filter.
* @param:  NewState: new state of the LVD Filter.
* @return: None
******************************************************************************/
void PMU_LVDFilterCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* enable LVD Filter */
    if (NewState != DISABLE)
    {
        PMU->CTRL1 |= PMU_CTL1_LVD_FLTEN;   
    }
    else
    { 
        /* disable LVD Filter */
        PMU->CTRL1 &= (~PMU_CTL1_LVD_FLTEN);
    }
}

/******************************************************************************
* @brief:  Enables or disables the LVD Filter.
* @param:  None
* @return: LVD original state and state after LVD Filter
******************************************************************************/
uint32_t PMU_GetLVDFilterStatus(void)
{
    return (PMU->CTRL1 & 0x0000C000);
}

/******************************************************************************
* @brief:  Configures the voltage threshold detected by the LBOR.
* @param:  PMU_BORVoltage: specifies the BOR detection voltage
* @return: None
******************************************************************************/
void PMU_BORVoltageConfig(uint32_t PMU_BORVoltage)
{
    /* Check the parameters */
    assert_param(IS_PMU_BOR_VOLTAGE(PMU_BORVoltage));

    /* Clear CTRL2[27:26] bits */
    PMU->CTRL2 &= (~PMU_CTL2_BOR_CFG_Msk);

    /* Set CTRL2[27:26] bits according to PMU_BORVoltage value */
    PMU->CTRL2 |= PMU_BORVoltage;
}

/******************************************************************************
* @brief:  Enables or disables the BOR.
* @param:  NewState: new state of the BOR.
* @return: None
******************************************************************************/
void PMU_BORCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* enable BOR */
    if (NewState != DISABLE)
    {
        PMU->CTRL2 |= PMU_CTL2_BOR_EN;   
    }
    else
    { 
        /* disable BOR */
        PMU->CTRL1 &= (~PMU_CTL2_BOR_EN);
    }
}

/******************************************************************************
* @brief:  Enables or disables the BOR Reset function.
* @param:  NewState: new state of the BOR.
* @return: None
******************************************************************************/
void PMU_BORResetCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* enable BOR */
    if (NewState != DISABLE)
    {
        PMU->CTRL2 |= PMU_CTL2_BORRST_EN;   
    }
    else
    { 
        /* disable BOR */
        PMU->CTRL1 &= (~PMU_CTL2_BORRST_EN);
    }
}

/******************************************************************************
* @brief:  Enables or disables the WakeUp Pin functionality.
* @param:  PMU_WakeUpPinx: specifies the WakeUp Pin.
* @param:  NewState: new state of the WakeUp Pin functionality.
* @return: None
******************************************************************************/
void PMU_WakeUpPinCmd(uint32_t PMU_WakeUpPinx, FunctionalState NewState)
{
    /* Check the parameters */  
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    assert_param(IS_PMU_WAKEUP_PIN(PMU_WakeUpPinx));
    
    /* WKUPx (x=5~1) pin wake-up function enable */
    if (NewState != DISABLE)
    {
        PMU->CTRL2 |= PMU_WakeUpPinx;   
    }
    else
    { 
        /* WKUPx (x=5~1) pin wake-up function disable */
        PMU->CTRL2 &= (~PMU_WakeUpPinx);
    }
}

/******************************************************************************
* @brief:  Enables or disables the WKUPx (x=5~1) pin filter.
* @param:  PMU_WakeUpPinx: specifies the WakeUp Pin.
* @param:  NewState: new state of the LVD Filter.
* @return: None
******************************************************************************/
void PMU_WakeUpPinFilterCmd(uint32_t PMU_WakeUpPinx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    assert_param(IS_PMU_WAKEUP_PIN(PMU_WakeUpPinx));
    
    /* enable wakeup pin Filter */
    if (NewState != DISABLE)
    {
        PMU->CTRL2 |= (PMU_WakeUpPinx << PMU_CTL2_WUXFILEN_Pos);   
    }
    else
    { 
        /* disable wakeup pin Filter */
        PMU->CTRL2 &= (~(PMU_WakeUpPinx << PMU_CTL2_WUXFILEN_Pos));
    }
}

/******************************************************************************
* @brief:  Configure WKUPx (x=5~1) pin wake-up polarity.
* @param:  PMU_WakeUpPinx: specifies the WakeUp Pin.
* @param:  NewState: new state of the LVD Filter.
* @return: None
******************************************************************************/
void PMU_WakeUpPinPolarityConfig(uint32_t PMU_WakeUpPinx, uint32_t PMU_WakeUpPinPolarity)
{
    /* Check the parameters */
    assert_param(IS_PMU_WAKEUP_PIN_POLARITY(PMU_WakeUpPinPolarity));
    assert_param(IS_PMU_WAKEUP_PIN(PMU_WakeUpPinx));
    
    /* WKUPx pin low level wake-up */
    if (PMU_WakeUpPinPolarity == PMU_WAKEUPPIN_POLARITY_LOW)
    {
        PMU->CTRL3 |= PMU_WakeUpPinx;   
    }
    else
    { 
        /* WKUPx pin high level wake-up */
        PMU->CTRL2 &= ~(PMU_WakeUpPinx);
    }
}

/******************************************************************************
* @brief : Enters SLEEP mode.
* @param : PMU_SLEEPEntry: specifies if SLEEP mode in entered with WFI 
           or WFE instruction
* @return: None
******************************************************************************/
void PMU_EnterSLEEPMode(uint8_t PMU_SLEEPEntry)
{
    /* Check the parameters */
    assert_param(IS_PMU_LOWPOWR_ENTRY(PMU_SLEEPEntry));
    
    /* Reset SLEEPDEEP bit of Cortex System Control Register */
    SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);     

    /* Select STOP mode entry */
    if(PMU_SLEEPEntry == PMU_LOWPOWRENTRY_WFI)       
    {
        /* Request Wait For Interrupt */
        __WFI();
    }
    else
    {
        /* Request Wait For Event */
        __SEV();      
        __WFE();
        __WFE();   
    }  
}

/******************************************************************************
* @brief:  Enters STOP mode.
* @param:  PMU_STOPMode: Specify stop mode.
* @param:  PMU_STOPEntry: specifies if STOP mode in entered with WFI 
           or WFE instruction.
* @return: None
******************************************************************************/
void PMU_EnterSTOPMode(uint32_t PMU_STOPMode, uint8_t PMU_STOPEntry)
{
    /* Check the parameters */
    assert_param(IS_PMU_STOP(PMU_STOPMode));
    assert_param(IS_PMU_LOWPOWR_ENTRY(PMU_STOPEntry));
    
    /* Clear all wake-up flags */ 
    PMU_ClearFlag(PMU_FLAG_ALL);

    /* Clear LPMS bits */
    PMU->CTRL0 &= (~PMU_CTL0_LPMS_Msk);

    /* Set LPMS bits according to PMU_STOPMode value */
    PMU->CTRL0 |= PMU_STOPMode;
  
    /* Set SLEEPDEEP bit of Cortex System Control Register */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    /* Select STOP mode entry */
    if(PMU_STOPEntry == PMU_LOWPOWRENTRY_WFI)
    {   
        /* Request Wait For Interrupt */
        __WFI();
    }
    else
    {
        /* Request Wait For Event */
        __SEV();   
        __WFE();
        __WFE(); 
    }
    /* Reset SLEEPDEEP bit of Cortex System Control Register */
    SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);  
}

/******************************************************************************
* @brief:  Whether the RC64M is automatically closed in STOP0/STOP1 mode.
* @param:  NewState: New state of RC64M automatic shutdown.
* @return: None
******************************************************************************/
void PMU_STOPRC64MAutoCloseCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* Enable RC64M automatic shutdown */
    if (NewState != DISABLE)
    {
        PMU->CTRL0 |= PMU_CTL0_RC64MPDEN;   
    }
    else
    { 
        /* Disable RC64M automatic shutdown */
        PMU->CTRL0 &= (~PMU_CTL0_RC64MPDEN);
    } 
}

/******************************************************************************
* @brief:  In STOP0/STOP1/STOP2 mode, RC64M selects 16 frequency division output.
* @param:  NewState: New state of 16 frequency division output.
* @return: None
******************************************************************************/
void PMU_STOPRC64MDivisionCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* Enable 16 frequency division output */
    if (NewState != DISABLE)
    {
        PMU->CTRL0 |= PMU_CTL0_RC64M_DIV_EN;   
    }
    else
    { 
        /* Disable 16 frequency division output */
        PMU->CTRL0 &= (~PMU_CTL0_RC64M_DIV_EN);
    } 
}

/******************************************************************************
* @brief:  Set the wake-up waiting time of STOP mode.
* @param:  PMU_STOPWaitTime: sSpecified STOP mode wake-up waiting time.
* @return: None
******************************************************************************/
void PMU_SetSTOPWakeWaitTime(uint32_t PMU_STOPWaitTime)
{
    /* Check the parameters */
    assert_param(IS_PMU_STOP_WAKE_WAIT(PMU_STOPWaitTime));

    /* Clear STOP_WPT bits */
    PMU->CTRL0 &= (~PMU_CTL0_STOP_WPT_Msk);

    /* Set STOP_WPT bits */
    PMU->CTRL0 |= (PMU_CTL0_STOP_WPT_Msk << PMU_CTL0_STOP_WPT_Pos);
}

/******************************************************************************
* @brief:  Whether MLDO enters low power consumption mode in STOP0 mode.
* @param:  NewState: New state of MLDO low-power mode.
* @return: None
******************************************************************************/
void PMU_MLDOLowpowerCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    /* Enable MLDO low-power mode */
    if (NewState != DISABLE)
    {
        PMU->CTRL0 |= PMU_CTL0_MLDO12_LOWP;   
    }
    else
    { 
        /* Disable MLDO low-power mode */
        PMU->CTRL0 &= (~PMU_CTL0_MLDO12_LOWP);
    } 
}

/******************************************************************************
* @brief:  Whether MLDO12 voltage is automatically adjusted in STOP/STANDBY mode.
* @param:  PMU_BORVoltage: specifies the MLDO voltage.
* @return: None
******************************************************************************/
void PMU_MLDOVoltageConfig(uint32_t PMU_MLDOVoltage)
{
    /* Check the parameters */
    assert_param(IS_PMU_MLDO_VOLTAGE(PMU_MLDOVoltage)); 
    
    /* Clear MLDO12_LV bits */
    PMU->CTRL0 &= (~PMU_CTL0_MLDO12_LV_Msk);

    /* Set MLDO12_LV bits according to PMU_MLDOVoltage value */
    PMU->CTRL0 |= PMU_MLDOVoltage;
}

/******************************************************************************
* @brief:  Whether LPLDO12 voltage is automatically adjusted in STOP1/STOP2 mode.
* @param:  PMU_BORVoltage: specifies the LPLDO voltage.
* @return: None
******************************************************************************/
void PMU_LPLDOVoltageConfig(uint32_t PMU_LPLDOVoltage)
{
    /* Check the parameters */
    assert_param(IS_PMU_LPLDO_VOLTAGE(PMU_LPLDOVoltage)); 
    
    /* Clear LPLDO12_LV bits */
    PMU->CTRL0 &= (~PMU_CTL0_MLDO12_LOWP_Msk);

    /* Set LPLDO12_LV bits according to PMU_LPLDOVoltage value */
    PMU->CTRL0 |= PMU_LPLDOVoltage;
}

/******************************************************************************
* @brief:  Enters STANDBY mode.
* @param:  PMU_STANDBYEntry: specifies if STANDBY mode in entered with WFI 
           or WFE instruction.
* @return: None
******************************************************************************/
void PMU_EnterSTANDBYMode(uint8_t PMU_STANDBYEntry)
{
    /* Check the parameters */
    assert_param(IS_PMU_LOWPOWR_ENTRY(PMU_STANDBYEntry));
    
    /* Clear all wake-up flags */ 
    PMU_ClearFlag(PMU_FLAG_ALL);

    /* Clear LPMS bits */
    PMU->CTRL0 &= (~PMU_CTL0_LPMS_Msk);

    /* Set LPMS bits */
    PMU->CTRL0 |= PMU_CTL0_LPMS_2;
  
    /* Set SLEEPDEEP bit of Cortex System Control Register */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    /* Select STOP mode entry */
    if(PMU_STANDBYEntry == PMU_LOWPOWRENTRY_WFI)
    {   
        /* Request Wait For Interrupt */
        __WFI();
    }
    else
    {
        /* Request Wait For Event */
        __SEV();   
        __WFE();
        __WFE(); 
    }
    /* Reset SLEEPDEEP bit of Cortex System Control Register */
    SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);  
}

/******************************************************************************
* @brief:  Set the wake-up waiting time of STANDBY mode.
* @param:  PMU_STANDBYWaitTime: sSpecified standby mode wake-up waiting time.
* @return: None
******************************************************************************/
void PMU_SetSTANDBYWakeWaitTime(uint32_t PMU_STANDBYWaitTime)
{
    /* Check the parameters */
    assert_param(IS_PMU_STANDBY_WAKE_WAIT(PMU_STANDBYWaitTime));

    /* Clear STDBY_WPT bits */
    PMU->CTRL2 &= (~PMU_CTL2_STDBY_WPT_Msk);

    /* Set STDBY_WPT bits */
    PMU->CTRL2 |= (PMU_STANDBYWaitTime << PMU_CTL2_STDBY_WPT_Pos);
}

/******************************************************************************
* @brief:  Checks whether the specified PMU flag is set or not.
* @param:  PMU_FLAG: specifies the flag to check.
* @return: The new state of PMU_FLAG (SET or RESET).
******************************************************************************/
FlagStatus PMU_GetFlagStatus(uint32_t PMU_FLAG)
{
    FlagStatus bitstatus = RESET;

    /* Check the parameters */
    assert_param(IS_PMU_FLAG(PMU_FLAG));

    if ((PMU->SR & PMU_FLAG) != (uint32_t)RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    /* Return the flag status */
    return bitstatus;
}

/******************************************************************************
* @brief:  Clears the PMU's pending flags.
* @param:  PMU_FLAG: specifies the flag to clear.
* @return: None
******************************************************************************/
void PMU_ClearFlag(uint32_t PMU_FLAG)
{
    /* Check the parameters */
    assert_param(IS_PMU_FLAG(PMU_FLAG));
    
    PMU->STCLR |= PMU_FLAG;
}

/******************************************************************************
* @brief:  STANDBY domain IO function selection.
* @param:  PMU_Pin: specifies the STANDBY domain IO Pin.
* @param:  PMU_Func: Specify the IO pin function of STANDBY domain.
* @return: None
******************************************************************************/
void PMU_STANDBYDomainPinConfig(uint32_t PMU_Pin, uint32_t PMU_Func)
{
    /* Check the parameters */
    assert_param(IS_PMU_PIN(PMU_Pin));
    assert_param(IS_PMU_PIN_FUNCTION(PMU_Func));
    
    /* PC13 pin function selection */
    if(PMU_Pin == PMU_PIN_PC13)
    {
        /* Clear PC13_SEL bits */
        PMU->IOSEL &= (~PMU_IOSEL_PC13_SEL_Msk);
        
        /* Set PC13_SEL bits according to PMU_Func value */
        PMU->IOSEL |= (PMU_Func << PMU_IOSEL_PC13_SEL_Pos);
    }
    /* PC14 pin function selection */
    else if(PMU_Pin == PMU_PIN_PC14)
    {
        /* Clear PC14_SEL bits */
        PMU->IOSEL &= (~PMU_IOSEL_PC14_SEL_Msk);
        
        /* Set PC14_SEL bits according to PMU_Func value */
        PMU->IOSEL |= (PMU_Func << PMU_IOSEL_PC14_SEL_Pos);
    }
    /* PC15 pin function selection */
    else
    {
        /* Clear PC15_SEL bits */
        PMU->IOSEL &= (~PMU_IOSEL_PC15_SEL_Msk);
        
        /* Set PC15_SEL bits according to PMU_Func value */
        PMU->IOSEL |= (PMU_Func << PMU_IOSEL_PC15_SEL_Pos);
    }
}

/******************************************************************************
* @brief:  Set STANDBY domain IO value.
* @param:  PMU_Pin: specifies the STANDBY domain IO Pin.
* @param:  PMU_PinValue: specifies the STANDBY domain Pin Value.
* @return: None
******************************************************************************/
void PMU_SetSTANDBYDomainPinValue(uint32_t PMU_Pin, uint32_t PMU_PinValue)
{
    /* Check the parameters */
    assert_param(IS_PMU_PIN(PMU_Pin));
    assert_param(IS_PMU_PIN_VALUE(PMU_PinValue));
    
    /* PC13 pin function selection */
    if(PMU_Pin == PMU_PIN_PC13)
    {
        /* Clear PC13_Value bits */
        PMU->IOSEL &= (~PMU_IOSEL_PC13_VALUE_Msk);
        
        /* Set PC13_Value bits according to PMU_Func value */
        PMU->IOSEL |= (PMU_PinValue << PMU_IOSEL_PC13_VALUE_Pos);
    }
    /* PC14 pin function selection */
    else if(PMU_Pin == PMU_PIN_PC14)
    {
        /* Clear PC14_Value bits */
        PMU->IOSEL &= (~PMU_IOSEL_PC14_VALUE_Msk);
        
        /* Set PC14_Value bits according to PMU_Func value */
        PMU->IOSEL |= (PMU_PinValue << PMU_IOSEL_PC14_VALUE_Pos);
    }
    /* PC15 pin function selection */
    else
    {
        /* Clear PC15_Value bits */
        PMU->IOSEL &= (~PMU_IOSEL_PC15_VALUE_Msk);
        
        /* Set PC15_Value bits according to PMU_Func value */
        PMU->IOSEL |= (PMU_PinValue << PMU_IOSEL_PC15_VALUE_Pos);
    }
}

/******************************************************************************
* @brief:  Get STANDBY domain IO value.
* @param:  PMU_Pin: specifies the STANDBY domain IO Pin.
* @return: Pin Value
******************************************************************************/
uint32_t PMU_GetSTANDBYDomainPinValue(uint32_t PMU_Pin)
{
    uint32_t tmp_value = 0;
    /* Check the parameters */
    assert_param(IS_PMU_PIN(PMU_Pin));
    
    /* get PC13 pin value */
    if(PMU_Pin == PMU_PIN_PC13)
    {
        tmp_value = ((PMU->IOSEL & 0x001C0000) >> PMU_IOSEL_PC13_VALUE_Pos);
    }
    /* get PC14 pin value */
    else if(PMU_Pin == PMU_PIN_PC14)
    {
        tmp_value = ((PMU->IOSEL & 0x001C0000) >> PMU_IOSEL_PC14_VALUE_Pos);
    }
    /* get PC15 pin value */
    else
    {
        tmp_value = ((PMU->IOSEL & 0x001C0000) >> PMU_IOSEL_PC15_VALUE_Pos);
    }
    return tmp_value;
}



//#endif    /* SPL_PMU_MODULE_ENABLED */


/************************ (C) COPYRIGHT AISINOCHIP *****END OF FILE****/






