text: /********************************************************************************************************
   * @file	ext_pm.h
   *
   * @brief	This is the header file for B91
   *
   * @author	BLE Group
   * @date	2020
   *
   * @par     Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
   *
   *          Licensed under the Apache License, Version 2.0 (the "License");
   *          you may not use this file except in compliance with the License.
   *          You may obtain a copy of the License at
   *
   *              http://www.apache.org/licenses/LICENSE-2.0
   *
   *          Unless required by applicable law or agreed to in writing, software
   *          distributed under the License is distributed on an "AS IS" BASIS,
   *          WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *          See the License for the specific language governing permissions and
   *          limitations under the License.
   *******************************************************************************************************/
  
  #ifndef DRIVERS_B91_DRIVER_EXT_EXT_PM_H_
  #define DRIVERS_B91_DRIVER_EXT_EXT_PM_H_
  
  #include "../pm.h"
  #include "types.h"
  
  #ifndef	PM_32k_RC_CALIBRATION_ALGORITHM_EN
  #define PM_32k_RC_CALIBRATION_ALGORITHM_EN	1
  #endif
  
  
  
  
  
  
  /**
   * @brief	available wake-up source for customer
   */
  typedef enum {
  	 //not available wake-up source for customer
  	 PM_TIM_RECOVER_START   = BIT(14),
  	 PM_TIM_RECOVER_END     = BIT(15),
  }pm_tim_recover_wakeup_src_e;
  
  
  
  typedef pm_sleep_mode_e 	SleepMode_TypeDef;
  typedef pm_sleep_wakeup_src_e  SleepWakeupSrc_TypeDef;
  
  
  typedef int (*suspend_handler_t)(void);
  typedef void (*check_32k_clk_handler_t)(void);
  typedef unsigned int (*pm_get_32k_clk_handler_t)(void);
  typedef int (*cpu_pm_handler_t)(SleepMode_TypeDef sleep_mode,  SleepWakeupSrc_TypeDef wakeup_src, unsigned int  wakeup_tick);
  typedef unsigned int (*pm_tim_recover_handler_t)(unsigned int);
  
  extern 	cpu_pm_handler_t  		 	cpu_sleep_wakeup;
  extern  suspend_handler_t 		 	func_before_suspend;
  extern  check_32k_clk_handler_t  	pm_check_32k_clk_stable;
  extern  pm_get_32k_clk_handler_t 	pm_get_32k_tick;
  extern  pm_tim_recover_handler_t 	pm_tim_recover;
  
  /**
   * @brief	gpio wakeup level definition
   */
  typedef enum{
  	Level_Low=0,
  	Level_High =1,
  }pm_gpio_wakeup_Level_e;
  
  
  /**
   * @brief   deepsleep wakeup by external xtal
   */
  typedef struct{
  	unsigned char ext_cap_en;    //24xtal  cap
  	unsigned char pad32k_en;
  	unsigned char pm_enter_en;
  	unsigned char rsvd;
  }misc_para_t;
  
  extern  _attribute_aligned_(4) misc_para_t 				blt_miscParam;
  
  #define SYS_NEED_REINIT_EXT32K			    BIT(1)
  #define WAKEUP_STATUS_TIMER_CORE     	    ( WAKEUP_STATUS_TIMER | WAKEUP_STATUS_CORE)
  #define WAKEUP_STATUS_TIMER_PAD		        ( WAKEUP_STATUS_TIMER | WAKEUP_STATUS_PAD)
  
  
  
  void bls_pm_registerFuncBeforeSuspend (suspend_handler_t func );
  
  /**
   * @brief analog register below can store infomation when MCU in deepsleep mode
   * 	      store your information in these ana_regs before deepsleep by calling analog_write function
   * 	      when MCU wakeup from deepsleep, read the information by by calling analog_read function
   * 	      Reset these analog registers only by power cycle
   */
  #define DEEP_ANA_REG0                       0x39 //initial value =0x00
  #define DEEP_ANA_REG1                       0x3a //initial value =0x00
  #define DEEP_ANA_REG2                       0x3b //initial value =0x00
  #define DEEP_ANA_REG3                      	0x3c //initial value =0x00
  #define DEEP_ANA_REG4                       0x3d //initial value =0x00
  #define DEEP_ANA_REG5                       0x3e //initial value =0x00
  #define DEEP_ANA_REG6                       0x3f //initial value =0x0f
  
  /**
   * @brief these analog register can store data in deepsleep mode or deepsleep with SRAM retention mode.
   * 	      Reset these analog registers by watchdog, chip reset, RESET Pin, power cycle
   */
  
  #define DEEP_ANA_REG7                       0x38 //initial value =0xff
  
  //ana3e system used, user can not use
  #define SYS_DEEP_ANA_REG 					PM_ANA_REG_POWER_ON_CLR_BUF0
  
  
  /**
   * @brief      This function serves to set the working mode of MCU based on 32k crystal,e.g. suspend mode, deepsleep mode, deepsleep with SRAM retention mode and shutdown mode.
   * @param[in]  sleep_mode - sleep mode type select.
   * @param[in]  wakeup_src - wake up source select.
   * @param[in]  wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes.
   * @return     indicate whether the cpu is wake up successful.
   */
  int  cpu_sleep_wakeup_32k_rc(SleepMode_TypeDef sleep_mode,  SleepWakeupSrc_TypeDef wakeup_src, unsigned int  wakeup_tick);
  
  /**
   * @brief      This function serves to set the working mode of MCU based on 32k crystal,e.g. suspend mode, deepsleep mode, deepsleep with SRAM retention mode and shutdown mode.
   * @param[in]  sleep_mode - sleep mode type select.
   * @param[in]  wakeup_src - wake up source select.
   * @param[in]  wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes.
   * @return     indicate whether the cpu is wake up successful.
   */
  int  cpu_sleep_wakeup_32k_xtal(SleepMode_TypeDef sleep_mode,  SleepWakeupSrc_TypeDef wakeup_src, unsigned int  wakeup_tick);
  
  
  void pm_sleep_start(void);
  
  
  /**
   * @brief   This function serves to reboot chip.
   * @param   none.
   * @return  none.
   */
  
  void start_reboot(void);
  
  /**
   * @brief   This function serves to recover system timer from tick of internal 32k RC.
   * @param   none.
   * @return  none.
   */
  unsigned int pm_tim_recover_32k_rc(unsigned int now_tick_32k);
  
  /**
   * @brief   This function serves to recover system timer from tick of external 32k crystal.
   * @param   none.
   * @return  none.
   */
  unsigned int pm_tim_recover_32k_xtal(unsigned int now_tick_32k);
  
  /**
   * @brief   This function serves to get the 32k tick.
   * @param   none
   * @return  tick of 32k .
   */
  extern unsigned int get_32k_tick(void);
  
  unsigned int clock_get_digital_32k_tick(void);
  
  /**
   * @brief      This function serves to determine whether wake up source is internal 32k RC.
   * @param[in]  none.
   * @return     none.
   */
  static inline void blc_pm_select_internal_32k_crystal(void)
  {
  	cpu_sleep_wakeup 	 	= cpu_sleep_wakeup_32k_rc;
  	pm_tim_recover  	 	= pm_tim_recover_32k_rc;
  
  	blt_miscParam.pm_enter_en 	= 1; // allow enter pm, 32k rc does not need to wait for 32k clk to be stable
  }
  
  extern void check_32k_clk_stable(void);
  
  /**
   * @brief      This function serves to determine whether wake up source is external 32k RC.
   * @param[in]  none.
   * @return     none.
   */
  static inline void blc_pm_select_external_32k_crystal(void)
  {
  	cpu_sleep_wakeup 	 	= cpu_sleep_wakeup_32k_xtal;
  	pm_check_32k_clk_stable = check_32k_clk_stable;
  	pm_tim_recover		 	= pm_tim_recover_32k_xtal;
  	pm_get_32k_tick 		= get_32k_tick;
  	blt_miscParam.pad32k_en 	= 1; // set '1': 32k clk src use external 32k crystal
  }
  
  
  
  
  /**
   * @brief      This function servers to wake up the cpu from sleep mode.
   * @param[in]  sleep_mode - sleep mode type select.
   * @param[in]  wakeup_src - wake up source select.
   * @param[in]  wakeup_tick - the time of sleep,unit is 31.25us,1ms = 32.
   * @return     indicate whether the cpu is wake up successful.
   */
  int cpu_long_sleep_wakeup_32k_rc(SleepMode_TypeDef sleep_mode,  SleepWakeupSrc_TypeDef wakeup_src, unsigned int  wakeup_tick);
  
  /**
   * @brief      This function serves to determine whether mcu is waked up from deep retention.
   * @param[in]  none.
   * @return     1- yes , 0- no.
   */
  static inline int pm_is_MCU_deepRetentionWakeup(void)
  {
  	return (g_pm_status_info.mcu_status & MCU_STATUS_DEEPRET_BACK);
  }
  
  /**
   * @brief      This function serves to determine whether mcu is waked up by pad.
   * @param[in]  none.
   * @return     1- yes , 0- no.
   */
  static inline int pm_is_deepPadWakeup(void)
  {
  	return g_pm_status_info.is_pad_wakeup;
  }
  
  /**
   * @brief      This function serves to get the status of mcu.
   * @param[in]  none.
   * @return     mcu_status.
   */
  static inline int pm_get_mcu_status(void)
  {
  	return g_pm_status_info.mcu_status;
  }
  
  #define cpu_set_gpio_wakeup				pm_set_gpio_wakeup
  
  
  static inline unsigned int pm_get_latest_offset_cal_time(void)
  {
  	return pmcd.offset_cal_tick;
  }
  
  /**********************************  Internal APIs (not for user)***************************************************/
  extern  unsigned char 		    tl_24mrc_cal;
  extern 	unsigned int 			g_pm_tick_32k_calib;
  extern  unsigned int 			g_pm_tick_cur;
  extern  unsigned int 			g_pm_tick_32k_cur;
  extern  unsigned char       	g_pm_long_suspend;
  extern  unsigned int 			g_pm_multi_addr;
  
  extern	unsigned int 			g_sleep_32k_rc_cnt;
  extern	unsigned int 			g_sleep_stimer_tick;
  
  extern unsigned int	ota_program_bootAddr;
  extern unsigned int	ota_program_offset;
  
  
  #define PM_MIN_SLEEP_US			1500  //eagle
  
  
  #endif /* DRIVERS_B91_DRIVER_EXT_EXT_PM_H_ */
  