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

/*--------------------------------------------------------------------------------------------
sleepmode cmd :  mcu Working current about 400ua
  --------------------------------------------------------------------------------------------*/
/**
  * @name   PWR_LDODriverLevel
  * @brief  EN: Enters Sleep mode.
  *         CN: 进入睡眠模式。
  * @param  PWR_SLEEPEntry: 
  *         EN: specifies if SLEEP mode in entered with WFI or WFE instruction.
  *         CN: 指定是否使用WFI或WFE指令进入睡眠模式。
  *             @arg PWR_SLEEPEntry_WFI
  *             @arg PWR_SLEEPEntry_WFE
  * @retval None
  */
void PWR_EnterSleepMode(uint32_t PWR_SLEEPEntry)
{
  assert_param(IS_PWR_SLEEP_ENTRY(PWR_SLEEPEntry));

  /* Clear SLEEPDEEP bit of Cortex-M0 System Control Register */
  SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);

  /* Select SLEEP mode entry -------------------------------------------------*/
  if (PWR_SLEEPEntry == PWR_SLEEPEntry_WFI)
  {
    __WFI();
  }
  else
  {
    __WFE();
  }
}
/**
  * @name   PWR_EnterUR_STOPMode
  * @brief  EN: Enters Ultra low power stop mode.
  *         CN: 进入超低功耗停机模式。
  * @param  PWR_STOPEntry: 
  *         EN: specifies if Ultra low power stop mode in entered with WFI or WFE instruction.
  *         CN: 指定是否使用WFI或WFE指令进入超低功耗停机模式。
  *             @arg PWR_STOPEntry_WFI
  *             @arg PWR_STOPEntry_WFE
  * @retval None
  */
void PWR_EnterUR_STOPMode(uint32_t PWR_STOPEntry)
{
  /* Check the parameters */
  assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));

  // deep-sleep
  PWR_LowPowerCmd(ENABLE);              // PUMEN
  PWR_FlashPowerDownDeepSleep(ENABLE);  // FPDS
  PWR_LowPowerDeepSleep(ENABLE);        // LPDS  内核LDO  /kernel LDO
  PWR_UltraLowPowerDeepSleep(ENABLE);   // ULPDS  使能超低功耗 /Enable ultra-low power consumption
  /* Select STOP mode entry --------------------------------------------------*/

  SCB->SCR |= ((uint32_t)SCB_SCR_SLEEPDEEP_Msk);

  if (PWR_STOPEntry == PWR_STOPEntry_WFI)
  {
    /* Request Wait For Interrupt */
    __WFI();
    SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
  }
  else
  {
    /* Request Wait For Event */
    __WFE();
    SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
  }

  /* Reset SLEEPDEEP bit of Cortex System Control Register */
}

/**
  * @name   PWR_EnterSTOPMode
  * @brief  EN: Enters stop mode.
  *         CN: 进入停机模式。
  * @param  PWR_STOPEntry: 
  *         EN: specifies if stop mode in entered with WFI or WFE instruction.
  *         CN: 指定是否使用WFI或WFE指令进入停机模式。
  *             @arg PWR_STOPEntry_WFI
  *             @arg PWR_STOPEntry_WFE
  * @retval None
  */
void PWR_EnterSTOPMode(uint32_t PWR_STOPEntry)
{

  PWR_LowPowerCmd(ENABLE);
  PWR_FlashPowerDownDeepSleep(ENABLE);
  //	PWR_PowerDownDeepSleep(DISABLE);
  PWR_LowPowerDeepSleep(DISABLE);
  PWR_UltraLowPowerDeepSleep(DISABLE);

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

/**
  * @name   PWR_EnterLowPowerSTOPMode
  * @brief  EN: Enters low power stop mode.
  *         CN: 进入低功耗停机模式。
  * @param  PWR_STOPEntry: 
  *         EN: specifies if low power stop mode in entered with WFI or WFE instruction.
  *         CN: 指定是否使用WFI或WFE指令进入低功耗停机模式。
  *             @arg PWR_STOPEntry_WFI
  *             @arg PWR_STOPEntry_WFE
  * @retval None
  */
void PWR_EnterLowPowerSTOPMode(uint32_t PWR_STOPEntry)
{
  PWR_LowPowerCmd(ENABLE);
  PWR_FlashPowerDownDeepSleep(ENABLE);
//  PWR_PowerDownDeepSleep(DISABLE);
  PWR_LowPowerDeepSleep(ENABLE);
  PWR_UltraLowPowerDeepSleep(DISABLE);

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

/**
  * @name   PWR_EnterSTANDBYMode
  * @brief  EN: Enters standyby mode.
  *         CN: 进入待机模式。
  * @retval None
  */
void PWR_EnterSTANDBYMode(void)
{ /* Check the parameters */

  // deep-sleep

  PWR_LowPowerCmd(ENABLE);              //CHIPCTRL->CR_b.PMUEN=1;
  PWR_FlashPowerDownDeepSleep(ENABLE);  //CHIPCTRL->CR_b.FPDS=1;
  PWR_LowPowerDeepSleep(ENABLE);        //CHIPCTRL->CR_b.LPDS=1;
  PWR_UltraLowPowerDeepSleep(ENABLE);   //CHIPCTRL->CR_b.ULPDS=1;
  SCB->SCR |= ((uint32_t)SCB_SCR_SLEEPDEEP_Msk);

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

/**
  * @name   PWR_AOUTConfig
  * @brief  EN: Chip power observation output selection.
  *         CN: 芯片电源观测输出选择。
  * @param  PWR_AOUT: 
  *         EN: specifies if Chip power observation output .
  *         CN: 指定芯片功率观测输出。
  *             @arg PWR_AOUT_SEL_VBG
  *             @arg PWR_AOUT_SEL_FLASH
  *             @arg PWR_AOUT_SEL_LOWPOWER
  *             @arg PWR_AOUT_SEL_ACMPCVREF
  *             @arg PWR_AOUT_SEL_HALL_MID
  *             @arg PWR_AOUT_SEL_VDDA_2
  * @retval None
  */
void PWR_AOUTConfig(uint8_t PWR_AOUT)
{
  assert_param(IS_PWR_AOUT_SEL_MODE(PWR_AOUT));
  chipctrl_access();
  CHIPCTRL->PWR_CFG_b.AOUT_SEL = PWR_AOUT;
  __dekey();
}

/**
  * @name   PWR_AOUTcmd
  * @brief  EN: Chip power observation output enable.
  *         CN: 芯片电源观测输出使能。
  * @param  NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_AOUTcmd(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.AOUT_EN = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.AOUT_EN = 0;
  }
  __dekey();
}

/**
  * @name   PWR_LVDConfig
  * @brief  EN: LVD low-voltage detection level selection.
  *         CN: LVD 低压检测电平选择。
  * @param  IE: 
  *         EN: PWR_LVDLevel.
  *         CN: 检测源。
  * @param  PWR_LVDLevel: 
  *         EN: Detecting voltage levels.
  *         CN: 检测电压水平。
  * @retval None
  */
void PWR_LVDConfig(uint8_t IE, uint8_t PWR_LVDLevel)
{
  assert_param(IS_PWR_LVDIE(IE));
  assert_param(IS_PWR_LVDInternal_MODE(PWR_LVDLevel));
  if (!IE) // if internal
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVDES = 0;
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVDS = PWR_LVDLevel;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVDES = 1;
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVDS = PWR_LVDLevel;
  }
  __dekey();
}

/**
  * @name   PWR_LVDCmd
  * @brief  EN: LVD enable control.
  *         CN: LVD使能。
  * @param NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_LVDCmd(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVDEN = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVDEN = 0;
  }
  __dekey();
}

/**
  * @name   PWR_LVRConfig
  * @brief  EN: LVR Low voltage reset point selection.
  *         CN: LVR 低压复位点选择。
  * @param  PWR_LVRLevel: 
  *         EN: Low voltage reset point.
  *         CN: 低压复位点。
  * @retval None
  */
void PWR_LVRConfig(uint32_t PWR_LVRLevel)
{
  assert_param(IS_PWR_LVRLevel(PWR_LVRLevel));

  chipctrl_access();
  CHIPCTRL->PWR_CFG_b.LVRS = PWR_LVRLevel;
  __dekey();
}

/**
  * @name   PWR_LVRCmd
  * @brief  EN: LVR enable control.
  *         CN: LVR使能。
  * @param NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_LVRCmd(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVREN = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CFG_b.LVREN = 0;
  }
  __dekey();
}
#if defined (LCM32F067) || defined (LCM32F063)  || defined (LCM32CF6990)
/**
  * @name   PWR_OPA_BiasCurrentSel
  * @brief  EN: Operational amplifier bias current control.
  *         CN: 运放偏置电流控制。
  * @param Bisa_current: 
  *         EN: Bias current selection.
  *         CN: 偏置电流选择。
  * @retval None
  */
void PWR_OPA_BiasCurrentSel(OPA_TypeDef *OPAx, uint8_t Bisa_current)
{
    if(OPAx == OPA0)
    {
      chipctrl_access();
      CHIPCTRL->PWR_CFG_b.OP_ISEL = Bisa_current << 0;
      __dekey();
    }
    else if(OPAx == OPA1)
    {
      chipctrl_access();
      CHIPCTRL->PWR_CFG_b.OP_ISEL = Bisa_current << 1;
      __dekey();
    }
    else if(OPAx == OPA2)
    {
      chipctrl_access();
      CHIPCTRL->PWR_CFG_b.OP_ISEL = Bisa_current << 2;
      __dekey();
    }
}
#elif defined (LCM32F062)
  /* None OPA */
#endif

/**
  * @name   PWR_LVRClearFlag
  * @brief  EN: Clear the low voltage monitoring reset flag.
  *         CN: 清除低压监测复位标志。
  * @retval None
  */
void PWR_LVRClearFlag(void)
{
  assert_param();
  chipctrl_access();
  CHIPCTRL->RST_CSR_b.LVR_FLAG = 1;
  __dekey();
}
/**
  * @name   PWR_LVRClearFlag
  * @brief  EN: Clear power on/off reset flag.
  *         CN: 清除上电/掉电复位标志。
  * @retval None
  */
void PWR_POR_PDRClearFlag(void)
{
  assert_param();
  chipctrl_access();
  CHIPCTRL->RST_CSR_b.POR_FLAG = 1;
  __dekey();
}

/**
  * @name   PWR_UltraLowPowerDeepSleep
  * @brief  EN: Enable Ultra low power stop mode.
  *         CN: 使能超低功耗停机模式。
  * @param NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_UltraLowPowerDeepSleep(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.ULPDS = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.ULPDS = 0;
  }
  __dekey();
}

/**
  * @name   PWR_FlashPowerDownDeepSleep
  * @brief  EN: Enter deep power failure mode.
  *         CN: flash 进入深度掉电模式 。
  * @param NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_FlashPowerDownDeepSleep(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.FPDS = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.FPDS = 0;
  }
  __dekey();
}

/**
  * @name   PWR_LowPowerCmd
  * @brief  EN: Low power mode enable.
  *         CN: 低功耗模式使能 。
  * @param NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_LowPowerCmd(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.PMUEN = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.PMUEN = 0;
  }
  __dekey();
}

/**
  * @name   PWR_LowPowerDeepSleep
  * @brief  EN: In stop mode, the kernel LDO is in low-power mode.
  *         CN: 停机模式下，内核 LDO 处于低功耗模式模式。
  * @param  NewState: 
  *         EN: new state.
  *         CN: 新状态。
  *             @arg ENABLE
  *             @arg DISABLE
  * @retval None
  */
void PWR_LowPowerDeepSleep(FunctionalState NewState)
{
  if (NewState != DISABLE)
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.LPDS = 1;
  }
  else
  {
    chipctrl_access();
    CHIPCTRL->PWR_CR_b.LPDS = 0;
  }
  __dekey();
}

/**
  * @name   PWR_LDODriverLevel
  * @brief  EN: LDO output drive current capacity mode selection.
  *         CN: LDO 输出驱动电流能力模式选择。
  * @param  PWR_DRV: 
  *         EN: Specify the LDO driver mode to be configured.
  *         CN: 指定要配置的LDO驱动模式。
  *             @arg PWR_LDODRV_10uA
  *             @arg PWR_LDODRV_50uA
  *             @arg PWR_LDODRV_150uA
  *             @arg PWR_LDODRV_200uA
  * @retval None
  */
void PWR_LDODriverLevel(uint8_t PWR_DRV)
{
  chipctrl_access();
  CHIPCTRL->PWR_LDOCR_b.DRV = PWR_DRV;
  __dekey();
}

/**
  * @name   Chipctrl_ReadFLAG
  * @brief  EN: Read LVR POR LVD flag.
  *         CN: 读取LVR POR LVD标志。
  * @param  FLAG: 
  *         EN: Specify the system status flag to be read.
  *         CN: 指定要读取的系统状态标志。
  *             @arg ChipCtrl_FLAG_LVD
  *             @arg ChipCtrl_FLAG_LVR
  *             @arg ChipCtrl_FLAG_POR
  * @retval None
  */
uint8_t Chipctrl_ReadFLAG(uint32_t FLAG)
{
  uint8_t status = 0x00;

  /* Check the parameters */
  assert_param(IS_ChipCtrl_FLAG(FLAG));

  if (FLAG == ChipCtrl_FLAG_LVD)
  {
    status = (uint8_t)CHIPCTRL->STS_b.LVDFLG;
  }
  else if (FLAG == ChipCtrl_FLAG_LVR)
  {
    status = (uint8_t)CHIPCTRL->RST_CSR_b.LVR_FLAG;
    
  }
  else if (FLAG == ChipCtrl_FLAG_POR)
  {
    status = (uint8_t)CHIPCTRL->RST_CSR_b.POR_FLAG;
    
  }
  return status;
}
