/************************************************************************************************/
/**
* @file               std_lptim.h
* @author             MCU Ecosystem Development Team
* @brief              LPTIM STD库驱动头文件。
*                     提供LPTIM相关的STD库操作函数声明、数据类型以及常量的定义。
*
*
**************************************************************************************************
* @attention
* Copyright (c) CEC Huada Electronic Design Co.,Ltd. All rights reserved.
*
**************************************************************************************************
*/

/*避免头文件重复引用*/
#ifndef STD_LPTIM_H
#define STD_LPTIM_H

/************************************************************************************************/
/** 
* @addtogroup STD_Driver
* @{
*/

/**
* @defgroup LPTIM LPTIM
* @brief 低功耗定时器的STD库驱动
* @{
*/
/************************************************************************************************/



#ifdef __cplusplus
 extern "C" {
#endif
     
/*------------------------------------------includes--------------------------------------------*/
#include "std_common.h"


/*------------------------------------type define-----------------------------------------------*/
     
/************************************************************************************************/
/**
* @defgroup LPTIM_Types LPTIM Types
* @brief    LPTIM数据类型定义
* @{
*/
/************************************************************************************************/
/**
* @brief  LPTIM初始化结构体定义
*/
typedef struct
{
    uint32_t clock_source;               /**< LPTIM工作时钟源选择                              
                                                    @arg LPTIM_CLK_SRC_INT...                       */
    
    uint32_t prescaler;                  /**< LPTIM预分频器系数选择                                  
                                                    @arg LPTIM_PRESCALER_DIV1...                    */
    
    uint32_t count_source;               /**< LPTIM计数时钟源选择                                   
                                                    @arg LPTIM_COUNTER_CLK_INT...                   */
}std_lptim_init_t;

/** 
* @} 
*/

/*--------------------------------------------define--------------------------------------------*/

/************************************************************************************************/
/**
* @defgroup LPTIM_Constants LPTIM Constants
* @brief    LPTIM常量定义及宏定义
* @{
*
*/
/************************************************************************************************/

/* 计数器计数模式 */
#define LPTIM_COUNT_CONTINUOUS          LPTIM_CR_CNTSTRT            /**< 连续计数模式    */
#define LPTIM_COUNT_SINGLE              LPTIM_CR_SNGSTRT            /**< 单次计数模式    */

/* 计数时钟源选择 */
#define LPTIM_COUNTER_CLK_INT           (0x00000000U)               /**< 内部时钟源计数     */
#define LPTIM_COUNTER_CLK_EXT           LPTIM_CFG_COUNT_MODE        /**< 外部时钟源计数     */

/* LPTIM PSC预分频器分频系数选择 */
#define LPTIM_PRESCALER_DIV1            LPTIM_CFG_PRESC_1           /**< PSC预分频器1分频   */
#define LPTIM_PRESCALER_DIV2            LPTIM_CFG_PRESC_2           /**< PSC预分频器2分频   */
#define LPTIM_PRESCALER_DIV4            LPTIM_CFG_PRESC_4           /**< PSC预分频器4分频   */
#define LPTIM_PRESCALER_DIV8            LPTIM_CFG_PRESC_8           /**< PSC预分频器8分频   */
#define LPTIM_PRESCALER_DIV16           LPTIM_CFG_PRESC_16          /**< PSC预分频器16分频  */
#define LPTIM_PRESCALER_DIV32           LPTIM_CFG_PRESC_32          /**< PSC预分频器32分频  */
#define LPTIM_PRESCALER_DIV64           LPTIM_CFG_PRESC_64          /**< PSC预分频器64分频  */
#define LPTIM_PRESCALER_DIV128          LPTIM_CFG_PRESC_128         /**< PSC预分频器128分频 */

/* LPTIM工作时钟源选择 */
#define LPTIM_CLK_SRC_INT               (0x00000000U)                       /**< LPTIM时钟源选择内部时钟     */
#define LPTIM_CLK_SRC_EXT               LPTIM_CFG_CKSEL                     /**< LPTIM时钟源选择外部时钟     */

/* LPTIM外部时钟有效极性选择 */
#define LPTIM_EXTCLK_POL_RISING         (0x00000000U)                       /**< LPTIM外部时钟上升沿有效   */
#define LPTIM_EXTCLK_POL_FALLING        LPTIM_CFG_CKPOL_FALLING             /**< LPTIM外部时钟上升沿有效   */
#define LPTIM_EXTCLK_POL_BOTH           LPTIM_CFG_CKPOL_RISING_FALLING      /**< LPTIM外部时钟任意边沿有效 */

/* LPTIM DMA请求源 */
#define LPTIM_DMA_REQUEST_ARR           LPTIM_IER_ARR_DMAEN                 /**< 自动重载匹配DMA请求       */

/* LPTIM中断源 */
#define LPTIM_INTERRUPT_ARRM            LPTIM_IER_ARRM_IE                   /**< 自动重载匹配中断使能      */

/* LPTIM中断状态标志 */
#define LPTIM_FLAG_ARRM                 LPTIM_ISR_ARRM                      /**< 自动重载匹配标志          */

/* LPTIM中断清除标志 */
#define LPTIM_CLEAR_ARRM                LPTIM_ICR_ARRM_CF                   /**< 自动重载匹配标志清零      */

/** 
* @} 
*/

/*-------------------------------------------functions------------------------------------------*/
/************************************************************************************************/
/**
* @defgroup LPTIM_External_Functions LPTIM External Functions
* @brief    LPTIM对外函数
* @{
*
*/
/************************************************************************************************/
/** 
* @brief  使能LPTIM
* @param  lptimx LPTIM外设
* @note   在LPTIM使能位置位后，需要两个计数器周期后才能生效
* @retval 无
*/
__STATIC_INLINE void std_lptim_enable(LPTIM_t *lptimx)
{
    lptimx->CR |= LPTIM_CR_ENABLE;
}

/** 
* @brief  禁止LPTIM
* @param  lptimx LPTIM外设
* @retval 无
*/
__STATIC_INLINE void std_lptim_disable(LPTIM_t *lptimx)
{
    lptimx->CR &= (~LPTIM_CR_ENABLE);
}

/** 
* @brief  配置LPTIM计数模式
* @param  lptimx LPTIM外设
* @param  operate_mode 计数模式选择
*             @arg LPTIM_COUNT_CONTINUOUS:    连续计数模式
*             @arg LPTIM_COUNT_SINGLE:        单次计数模式
* @note   必须使能LPTIM后才能启动计数器计数
* @retval 无
*/
__STATIC_INLINE void std_lptim_start_counter(LPTIM_t *lptimx, uint32_t operate_mode)
{
    MODIFY_REG(lptimx->CR, (LPTIM_CR_CNTSTRT | LPTIM_CR_SNGSTRT), operate_mode);
}

/** 
* @brief  设置LPTIM自动重装载值
* @param  lptimx LPTIM外设
* @param  auto_reload 自动重装载值（该变量的范围为0x0~0xFFFF）
* @retval 无
*/
__STATIC_INLINE void std_lptim_set_auto_reload(LPTIM_t *lptimx, uint32_t auto_reload)
{
    lptimx->ARR = auto_reload;
}

/** 
* @brief  获取LPTIM自动重装载值
* @param  lptimx LPTIM外设
* @retval uint32_t 自动重装载值（该变量的范围为0x0~0xFFFF）
*/
__STATIC_INLINE uint32_t std_lptim_get_auto_reload(LPTIM_t *lptimx)
{
    return (lptimx->ARR);
}

/** 
* @brief  获取LPTIM计数值
* @param  lptimx LPTIM外设
* @note   当LPTIM为异步时钟计数时，为确保获取正确的计数值，需要确保两次读取的计数值一致。
* @retval uint32_t LPTIM计数值（该变量的范围为0x0~0xFFFF）
*/
__STATIC_INLINE uint32_t std_lptim_get_count(LPTIM_t *lptimx)
{
    return (lptimx->CNT);
}

/** 
* @brief  设置LPTIM计数时钟源
* @param  lptimx LPTIM外设
* @param  counter_clk_src 计数时钟来源
*             @arg LPTIM_COUNTER_CLK_INT: 计数器在内部时钟每个有效边沿递增
*             @arg LPTIM_COUNTER_CLK_EXT: 计数器在LPTIMx_IN1上输入的外部时钟每个有效边沿递增
* @retval 无
*/
__STATIC_INLINE void std_lptim_set_counter_clk_source(LPTIM_t *lptimx, uint32_t counter_clk_src)
{
    MODIFY_REG(lptimx->CFG, LPTIM_CFG_COUNT_MODE, counter_clk_src);
}

/** 
* @brief  获取LPTIM计数时钟源
* @param  lptimx LPTIM外设
* @retval uint32_t 计数时钟来源
*             @arg LPTIM_COUNTER_CLK_INT: 计数器在内部时钟每个有效边沿递增
*             @arg LPTIM_COUNTER_CLK_EXT: 计数器在LPTIMx_IN1上输入的外部时钟每个有效边沿递增
*/
__STATIC_INLINE uint32_t std_lptim_get_counter_clk_source(LPTIM_t *lptimx)
{
    return (lptimx->CFG & LPTIM_CFG_COUNT_MODE);
}


/** 
* @brief  设置LPTIM预分频器分频系数
* @param  lptimx LPTIM外设 
* @param  prescaler 预分频系数选择
*             @arg LPTIM_PRESCALER_DIV1
*             @arg LPTIM_PRESCALER_DIV2
*             @arg LPTIM_PRESCALER_DIV4
*             @arg ...
*             @arg LPTIM_PRESCALER_DIV128
* @retval 无
*/
__STATIC_INLINE void std_lptim_set_prescaler(LPTIM_t *lptimx, uint32_t prescaler)
{
    MODIFY_REG(lptimx->CFG, LPTIM_CFG_PRESC, prescaler);
}

/** 
* @brief  获取LPTIM预分频器分频系数
* @param  lptimx LPTIM外设
* @retval uint32_t 预分频系数选择
*             @arg LPTIM_PRESCALER_DIV1
*             @arg LPTIM_PRESCALER_DIV2
*             @arg LPTIM_PRESCALER_DIV4
*             @arg ...
*             @arg LPTIM_PRESCALER_DIV128
*/
__STATIC_INLINE uint32_t std_lptim_get_prescaler(LPTIM_t *lptimx)
{
    return (lptimx->CFG & LPTIM_CFG_PRESC);
}

/** 
* @brief  选择LPTIM工作时钟源
* @param  lptimx LPTIM外设
* @param  clock_source LPTIM工作时钟源选择
*             @arg LPTIM_CLK_SRC_INT: 选择内部时钟源
*             @arg LPTIM_CLK_SRC_EXT: 选择外部时钟源
* @retval 无
*/
__STATIC_INLINE void std_lptim_set_clock_source(LPTIM_t *lptimx, uint32_t clock_source)
{
    MODIFY_REG(lptimx->CFG, LPTIM_CFG_CKSEL, clock_source);
}

/** 
* @brief  获取LPTIM工作时钟源
* @param  lptimx LPTIM外设   
* @retval uint32_t LPTIM工作时钟源选择
*             @arg LPTIM_CLK_SRC_INT: 选择内部时钟源
*             @arg LPTIM_CLK_SRC_EXT: 选择外部时钟源
*/
__STATIC_INLINE uint32_t std_lptim_get_clock_source(LPTIM_t *lptimx)
{
    return (lptimx->CFG & LPTIM_CFG_CKSEL);
}

/** 
* @brief  配置外部时钟源极性
* @param  lptimx LPTIM外设
* @param  polarity 外部时钟有效极性
*             @arg LPTIM_EXTCLK_POL_RISING:   外部时钟源上升沿有效
*             @arg LPTIM_EXTCLK_POL_FALLING:  外部时钟源下降沿有效
*             @arg LPTIM_EXTCLK_POL_BOTH:     外部时钟源任意边沿有效
* @note   当选择任意边沿有效时，LPTIMx必须选择内部时钟源，且内部时钟频率大于等于外部时钟频率的4倍
* @retval 无
*/
__STATIC_INLINE void std_lptim_set_external_clk_polarity(LPTIM_t *lptimx, uint32_t polarity)
{
    MODIFY_REG(lptimx->CFG, LPTIM_CFG_CKPOL, polarity);
}

/** 
* @brief  获取外部时钟源极性
* @param  lptimx LPTIM外设
* @retval uint32_t LPTIM时钟源极性
*             @arg LPTIM_EXTCLK_POL_RISING:   外部时钟源上升沿有效
*             @arg LPTIM_EXTCLK_POL_FALLING:  外部时钟源下降沿有效
*             @arg LPTIM_EXTCLK_POL_BOTH:     外部时钟源任意边沿有效
*/
__STATIC_INLINE uint32_t std_lptim_get_external_clk_polarity(LPTIM_t *lptimx)
{
    return (lptimx->CFG & LPTIM_CFG_CKPOL);
}

/** 
* @brief  使能LPTIMx DMA请求
* @param  lptimx LPTIM外设  
* @param  dma_req LPTIM DMA请求源
*             @arg LPTIM_DMA_REQUEST_ARR:     自动重载匹配DMA请求
* @retval 无
*/
__STATIC_INLINE void std_lptim_dma_request_enable(LPTIM_t *lptimx, uint32_t dma_req)
{
    lptimx->IER |= dma_req;
}

/** 
* @brief  禁止LPTIMx DMA请求
* @param  lptimx LPTIM外设  
* @param  dma_req LPTIM DMA请求源
*             @arg LPTIM_DMA_REQUEST_ARR:     自动重载匹配DMA请求
* @retval 无
*/
__STATIC_INLINE void std_lptim_dma_request_disable(LPTIM_t *lptimx, uint32_t dma_req)
{
    lptimx->IER &= (~dma_req);
}

/** 
* @brief  获取LPTIMx DMA请求使能状态
* @param  lptimx LPTIM外设  
* @param  dma_req LPTIM DMA请求源
*             @arg LPTIM_DMA_REQUEST_ARR:   自动重载匹配DMA请求
* @retval bool DMA请求源使能状态
*             @arg true:  DMA请求源使能
*             @arg false: DMA请求源禁止
*/
__STATIC_INLINE bool std_lptim_get_dma_request_status(LPTIM_t *lptimx, uint32_t dma_req)
{
    return ((lptimx->IER & dma_req) == dma_req);
}

/** 
* @brief  使能LPTIMx中断
* @param  lptimx LPTIM外设  
* @param  interrupt LPTIM中断源
*             @arg LPTIM_INTERRUPT_ARRM:      自动重载匹配中断
* @retval 无
*/
__STATIC_INLINE void std_lptim_interrupt_enable(LPTIM_t *lptimx, uint32_t interrupt)
{
    lptimx->IER |= interrupt;
}

/** 
* @brief  禁止LPTIMx中断
* @param  lptimx LPTIM外设   
* @param  interrupt LPTIM中断源
*             @arg LPTIM_INTERRUPT_ARRM:      自动重载匹配中断
* @retval 无
*/
__STATIC_INLINE void std_lptim_interrupt_disable(LPTIM_t *lptimx, uint32_t interrupt)
{
    lptimx->IER &= (~interrupt);
}

/** 
* @brief  获取LPTIMx中断状态
* @param  lptimx LPTIM外设  
* @param  interrupt LPTIM中断源
*             @arg LPTIM_INTERRUPT_ARRM:      自动重载匹配中断
* @retval bool LPTIM中断源使能状态
*             @arg true:中断使能
*             @arg false:中断禁止
*/
__STATIC_INLINE bool std_lptim_get_interrupt_status(LPTIM_t *lptimx, uint32_t interrupt)
{
    return ((lptimx->IER & interrupt) == interrupt);
}

/** 
* @brief  获取LPTIMx状态标志位
* @param  lptimx LPTIM外设
* @param  flag LPTIM状态标志位
*             @arg LPTIM_FLAG_ARRM:        自动重载匹配标志
* @retval bool LPTIM标志位的状态
*             @arg true: 标志位置位
*             @arg false:标志位清除
*/
__STATIC_INLINE bool std_lptim_get_flag(LPTIM_t *lptimx, uint32_t flag)
{
    return ((lptimx->ISR & flag) == flag);
}

/** 
* @brief  清除LPTIMx状态标志位
* @param  lptimx LPTIM外设
* @param  flag LPTIM状态标志位
*             @arg LPTIM_CLEAR_ARRM:        自动重载匹配标志
* @retval 无
*/
__STATIC_INLINE void std_lptim_clear_flag(LPTIM_t *lptimx, uint32_t flag)
{
    lptimx->ICR = flag;
}



/* LPTIM初始化相关函数 */
void std_lptim_deinit(LPTIM_t *lptimx);
void std_lptim_init(LPTIM_t *lptimx, std_lptim_init_t *lptim_init_param);

/* LPTIM结构体初始化相关函数 */
void std_lptim_struct_init(std_lptim_init_t *lptim_init_struct);

/** 
* @} 
*/



#ifdef __cplusplus
}
#endif

/** 
* @}
*/

/** 
* @}
*/
     
#endif /* STD_LPTIM_H */
