/**
  *********************************************************************************
  *
  * @file  hal_tim.h
  * @brief TIM module driver.
  *	   This is the common part of the TIM initialization
  *
  * @version V1.0
  * @date    06 Nov 2017
  * @author  AE Team
  * @note
  *
  * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
  *
  *********************************************************************************
  */

#ifndef __HAL_TIM_H__
#define __HAL_TIM_H__

#ifdef __cplusplus
 extern "C" {
#endif

#include "utils.h"
#include "hal_dma.h"

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @addtogroup TIM
  * @{
  */

/** @defgroup TIM_Public_Types TIM Public Types
  * @{
  */

/**
  * @brief TIM Counter Mode
  */
typedef enum {
	TIM_COUNTER_MODE_UP      = 0,	/**< Counter mode up */
	TIM_COUNTER_MODE_DOWN    = 1,	/**< Counter mode down */
	TIM_COUNTER_MODE_CENTER1 = 2,	/**< Counter mode center1 */
	TIM_COUNTER_MODE_CENTER2 = 3,	/**< Counter mode center2 */
	TIM_COUNTER_MODE_CENTER3 = 4,	/**< Counter mode center3 */
} tim_counter_mode_t;

/**
  * @brief TIM ClockDivision
  */
typedef enum {
	TIM_CLOCK_DIV1 = 0,	/**< No prescaler is used */
	TIM_CLOCK_DIV2 = 1,	/** Clock is divided by 2 */
	TIM_CLOCK_DIV4 = 2,	/** Clock is divided by 4 */
} tim_clock_division_t;

/**
  * @brief TIM Output Compare and PWM modes
  */
typedef enum {
	TIM_OC_MODE_TIMING         = 0,	/**< Output compare mode is timing */
	TIM_OC_MODE_ACTIVE         = 1,	/**< Output compare mode is active */
	TIM_OC_MODE_INACTIVE       = 2,	/**< Output compare mode is inactive */
	TIM_OC_MODE_TOGGLE         = 3,	/**< Output compare mode is toggle */
	TIM_OC_MODE_FORCE_INACTIVE = 4,	/**< Output compare mode is force inactive */
	TIM_OC_MODE_FORCE_ACTIVE   = 5,	/**< Output compare mode is force active */
	TIM_OC_MODE_PWM1           = 6,	/**< Output compare mode is pwm1 */
	TIM_OC_MODE_PWM2           = 7,	/**< Output compare mode is pwm2 */
} tim_oc_mode_t;

/**
  * @brief TIM Output Compare Polarity
  */
typedef enum {
	TIM_OC_POLARITY_HIGH = 0,	/**< Output compare polarity is high */
	TIM_OC_POLARITY_LOW  = 1,	/**< Output compare polarity is low */
} tim_oc_polarity_t;

/**
  * @brief TIM Complementary Output Compare Polarity
  */
typedef enum {
	TIM_OCN_POLARITY_HIGH = 0,	/**< Complementary output compare polarity is high */
	TIM_OCN_POLARITY_LOW  = 1,	/**< Complementary output compare polarity is low */
} tim_ocn_polarity_t;

/**
  * @brief TIM Output Compare Idle State
  */
typedef enum{
	TIM_OC_IDLE_STATE_RESET = 0,	/**< Output compare idle state is reset */
	TIM_OC_IDLE_STATE_SET   = 1,	/**< Output compare idle state is set */
} tim_oc_idle_state_t;

/**
  * @brief TIM Complementary Output Compare Idle State
  */
typedef enum {
	TIM_OCN_IDLE_STATE_RESET = 0,	/**< Complementary output compare idle state is reset */
	TIM_OCN_IDLE_STATE_SET   = 1,	/**< Complementary output compare idle state is set */
} tim_ocn_idle_state_t;

/**
  * @brief TIM Channel
  */
typedef enum {
	TIM_CHANNEL_1   = 0,	/**< Channel 1 */
	TIM_CHANNEL_2   = 1,	/**< Channel 2 */
	TIM_CHANNEL_3   = 2,	/**< Channel 3 */
	TIM_CHANNEL_4   = 4,	/**< Channel 4 */
	TIM_CHANNEL_ALL = 0xF,	/**< All channel */
} tim_channel_t;

/**
  * @brief TIM One Pulse Mode
  */
typedef enum {
	TIM_OP_MODE_REPETITIVE = 0,	/**< Repetitive */
	TIM_OP_MODE_SINGLE     = 1,	/**< single */
} tim_op_mode_t;

/**
  * @brief TIM One Pulse output channel
  */
typedef enum {
	TIM_OP_OUTPUT_CHANNEL_1 = 0,	/**< One pulse output channal 1 */
	TIM_OP_OUTPUT_CHANNEL_2 = 1,	/**< One pulse output channal 2 */
} tim_op_output_channel_t;

/**
  * @brief  TIM Time base Configuration Structure definition
  */
typedef struct {
	uint32_t prescaler;			/**< Specifies the prescaler value used to divide the TIM clock. */
	tim_counter_mode_t mode;		/**< Specifies the counter mode. */
	uint32_t period;			/**< Specifies the period value to be loaded into ARR at the next update event. */
	tim_clock_division_t clk_div;		/**< Specifies the clock division.*/
	uint32_t re_cnt;			/**< Specifies the repetition counter value. */
} tim_base_init_t;

/**
  * @brief  TIM Output Compare Configuration Structure definition
  */
typedef struct {
	tim_oc_mode_t oc_mode;			/**< Specifies the TIM mode. */
	uint32_t pulse;				/**< Specifies the pulse value to be loaded into the Capture Compare Register. */
	tim_oc_polarity_t oc_polarity;		/**< Specifies the output polarity. */
	tim_ocn_polarity_t ocn_polarity;	/**< Specifies the complementary output polarity. */
	type_func_t oc_fast_en;			/**< Specifies the Fast mode state. */
	tim_oc_idle_state_t oc_idle_state;	/**< Specifies the TIM Output Compare pin state during Idle state. */
	tim_ocn_idle_state_t ocn_idle_state;	/**< Specifies the TIM Output Compare pin state during Idle state. */
} tim_oc_init_t;

/**
  * @brief State structures definition
  */
typedef enum {
	TIM_STATE_RESET   = 0x00,	/**< Peripheral not yet initialized or disabled */
	TIM_STATE_READY   = 0x01,	/**< Peripheral Initialized and ready for use */
	TIM_STATE_BUSY    = 0x02,	/**< An internal process is ongoing */
	TIM_STATE_TIMEOUT = 0x03,	/**< Timeout state */
	TIM_STATE_ERROR   = 0x04,	/**< Reception process is ongoing */
} tim_state_t;

/**
  * @brief Active channel structures definition
  */
typedef enum {
	TIM_ACTIVE_CHANNEL_1       = 0x01,	/**< The active channel is 1 */
	TIM_ACTIVE_CHANNEL_2       = 0x02,	/**< The active channel is 2 */
	TIM_ACTIVE_CHANNEL_3       = 0x04,	/**< The active channel is 3 */
	TIM_ACTIVE_CHANNEL_4       = 0x08,	/**< The active channel is 4 */
	TIM_ACTIVE_CHANNEL_CLEARED = 0x00,	/**< All active channels cleared */
} tim_active_channel_t;

/**
  * @brief  TIM Time Base Handle Structure definition
  */
typedef struct tim_handle_s {
	TIM_TypeDef *perh;		/**< Register base address */
	tim_base_init_t init;		/**< TIM Time Base required parameters */
	tim_active_channel_t ch;	/**< Active channel */
	lock_state_t lock;		/**< Locking object */
	tim_state_t state;		/**< TIM operation state */

	void (*period_elapse_cbk)(struct tim_handle_s *arg);	/**< Period elapse callback */
	void (*delay_elapse_cbk)(struct tim_handle_s *arg);	/**< Delay_elapse callback */
	void (*capture_cbk)(struct tim_handle_s *arg);		/**< Capture callback */
	void (*pwm_pulse_finish_cbk)(struct tim_handle_s *arg);/**< PWM_pulse_finish callback */
	void (*trigger_cbk)(struct tim_handle_s *arg);		/**< Trigger callback */
	void (*break_cbk)(struct tim_handle_s *arg);		/**< Break callback */
	void (*com_cbk)(struct tim_handle_s *arg);		/**< commutation callback */
	void (*error_cbk)(struct tim_handle_s *arg);		/**< Error callback */
} tim_handle_t;


/**
  * @brief TIM Encoder Mode
  */
typedef enum {
	TIM_ENCODER_MODE_TI1  = 1,	/**< encoder mode 1 */
	TIM_ENCODER_MODE_TI2  = 2,	/**< encoder mode 2 */
	TIM_ENCODER_MODE_TI12 = 3,	/**< encoder mode 3 */
} tim_encoder_mode_t;

/**
  * @brief TIM Input Capture Polarity
  */
typedef enum {
	TIM_IC_POLARITY_RISING   = 0,	/**< Input capture polarity rising */
	TIM_IC_POLARITY_FALLING  = 1,	/**< Input capture polarity falling */
	TIM_IC_POLARITY_BOTHEDGE = 3,	/**< Input capture polarity rising and falling */
} tim_ic_polarity_t;

/**
  *@brief TIM Input Capture Selection
  */
typedef enum {
	TIM_IC_SELECT_DIRECTTI   = 1,	/**< IC1 -- TI1 */
	TIM_IC_SELECT_INDIRECTTI = 2,	/**< IC1 -- TI2 */
	TIM_IC_SELECT_TRC        = 3,	/**< IC1 -- TRC */
} tim_ic_select_t;

/**
  * @brief TIM Input Capture Prescaler
  */
typedef enum {
	TIM_IC_PSC_DIV1 = 0,	/**< Capture performed once every 1 events */
	TIM_IC_PSC_DIV2 = 1,	/**< Capture performed once every 2 events */
	TIM_IC_PSC_DIV4 = 2,	/**< Capture performed once every 4 events */
	TIM_IC_PSC_DIV8 = 3,	/**< Capture performed once every 4 events */
} tim_ic_prescaler_t;

/**
  * @brief TIM Encoder Configuration Structure definition
  */
typedef struct {
	tim_encoder_mode_t mode;	/**< Specifies the encoder mode */
	tim_ic_polarity_t ic1_polarity;	/**< Specifies the active edge of the input signal */
	tim_ic_select_t ic1_select;	/**< Specifies the input */
	tim_ic_prescaler_t ic1_psc;	/**< Specifies the Input Capture Prescaler */
	uint32_t ic1_filter;		/**< Specifies the input capture filter */
	tim_ic_polarity_t ic2_polarity;	/**< Specifies the active edge of the input signal */
	tim_ic_select_t ic2_select;	/**< Specifies the input */
	tim_ic_prescaler_t ic2_psc;	/**< Specifies the Input Capture Prescaler */
	uint32_t ic2_filter;		/**< Specifies the input capture filter */
} tim_encoder_init_t;

/**
  * @brief  TIM Input Capture Configuration Structure definition
  */
typedef struct {
	tim_ic_polarity_t ic_polarity;	/**< Specifies the active edge of the input signal */
	tim_ic_select_t ic_select;	/**< Specifies the input */
	tim_ic_prescaler_t ic_psc;	/**< Specifies the Input Capture Prescaler */
	uint32_t ic_filter;		/**< Specifies the input capture filter */
} tim_ic_init_t;

/**
  * @brief  TIM One Pulse Mode Configuration Structure definition
  */
typedef struct {
	tim_oc_mode_t mode;			/**< Specifies the TIM mode */
	uint16_t pulse;				/**< Specifies the pulse value */
	tim_oc_polarity_t oc_polarity;		/**< Specifies the output polarity */
	tim_ocn_polarity_t ocn_polarity;	/**< Specifies the complementary output polarity */
	tim_oc_idle_state_t oc_idle_state;	/**< Specifies the TIM Output Compare pin state during Idle state */
	tim_ocn_idle_state_t ocn_idle_state;	/**< Specifies the TIM Output Compare pin state during Idle state */
	tim_ic_polarity_t ic_polarity;		/**< Specifies the active edge of the input signal */
	tim_ic_select_t ic_select;		/**< Specifies the input */
	uint32_t ic_filter;			/**< Specifies the input capture filter */
} tim_one_pulse_init_t;

/** @brief TIM_ClearInput_Source TIM ClearInput Source
  */
typedef enum {
	TIM_CLEAR_INPUT_NONE  = 1,	/**< Clear input none */
	TIM_CLEAR_INPUT_ETR   = 1,	/**< Clear input etr */
	TIM_CLEAR_INPUT_OCREF = 1,	/**< Clear input ocref */
} tim_clear_input_source_t;

/** @brief TIM_ClearInput_Polarity TIM Clear Input Polarity
  */
typedef enum {
	TIM_CLEAR_INPUT_POLARITY_NONINVERTED = 0,	/**< Polarity for ETRx pin */
	TIM_CLEAR_INPUT_POLARITY_INVERTED    = 1,	/**< Polarity for ETRx pin */
} tim_clear_input_polarity_t;

/** @brief TIM_ClearInput_Polarity TIM Clear Input Polarity
  */
typedef enum {
	TIM_ETR_PSC_DIV1 = 0,	/**< No prescaler is used */
	TIM_ETR_PSC_DIV2 = 1,	/**< ETR input source is divided by 2 */
	TIM_ETR_PSC_DIV4 = 2,	/**< ETR input source is divided by 4 */
	TIM_ETR_PSC_DIV8 = 3,	/**< ETR input source is divided by 8 */
} tim_etr_psc_t;

/**
  * @brief  TIM Clear Input Configuration Handle Structure definition
  */
typedef struct {
	type_func_t state;			/**< TIM clear Input state */
	tim_clear_input_source_t source;	/**< TIM clear Input sources */
	tim_clear_input_polarity_t polarity;	/**< TIM Clear Input polarity */
	tim_etr_psc_t psc;			/**< TIM Clear Input prescaler */
	uint32_t filter;			/**< TIM Clear Input filter */
} tim_clear_input_config_t;

/** @brief TIM Clock Source
  */
typedef enum {
	TIM_CLOCK_SOURCE_ETRMODE2 = 0,	/**< Clock source is etr mode2 */
	TIM_CLOCK_SOURCE_INTERNAL = 1,	/**< Clock source is etr internal */
	TIM_CLOCK_SOURCE_ITR0     = 2,	/**< Clock source is etr itr0 */
	TIM_CLOCK_SOURCE_ITR1     = 3,	/**< Clock source is etr itr1 */
	TIM_CLOCK_SOURCE_ITR2     = 4,	/**< Clock source is etr itr2 */
	TIM_CLOCK_SOURCE_ITR3     = 5,	/**< Clock source is etr itr3 */
	TIM_CLOCK_SOURCE_TI1ED    = 6,	/**< Clock source is etr ti1ed */
	TIM_CLOCK_SOURCE_TI1      = 7,	/**< Clock source is etr ti1 */
	TIM_CLOCK_SOURCE_TI2      = 8,	/**< Clock source is etr ti2 */
	TIM_CLOCK_SOURCE_ETRMODE1 = 9,	/**< Clock source is etr mode1 */
} tim_clock_source_t;

/** @brief TIM Clock Polarity
  */
typedef enum {
	TIM_CLOCK_POLARITY_INVERTED    = 1,	/**< Polarity for ETRx clock sources */
	TIM_CLOCK_POLARITY_NONINVERTED = 0,	/**< Polarity for ETRx clock sources */
	TIM_CLOCK_POLARITY_RISING      = 0,	/**< Polarity for TIx clock sources */
	TIM_CLOCK_POLARITY_FALLING     = 1,	/**< Polarity for TIx clock sources */
	TIM_CLOCK_POLARITY_BOTHEDGE    = 3,	/**< Polarity for TIx clock sources */
} tim_clock_polarity_t;

/**
  * @brief  TIM Clock config Structure definition
  */
typedef struct {
	tim_clock_source_t source;	/**< TIM clock sources */
	tim_clock_polarity_t polarity;	/**< TIM clock polarity */
	tim_etr_psc_t psc;		/**< TIM clock prescaler */
	uint32_t filter;		/**< TIM clock filter */
} tim_clock_config_t;

/**
  * @brief TIM_Slave_Mode TIM Slave Mode
  */
typedef enum {
	TIM_SLAVE_MODE_DISABLE   = 0,	/**< Slave mode is disable */
	TIM_SLAVE_MODE_ENCODER1  = 1,	/**< Slave mode is encoder1 */
	TIM_SLAVE_MODE_ENCODER2  = 2,	/**< Slave mode is encoder2 */
	TIM_SLAVE_MODE_ENCODER3  = 3,	/**< Slave mode is encoder3 */
	TIM_SLAVE_MODE_RESET     = 4,	/**< Slave mode is reset */
	TIM_SLAVE_MODE_GATED     = 5,	/**< Slave mode is gated */
	TIM_SLAVE_MODE_TRIGGER   = 6,	/**< Slave mode is trigger */
	TIM_SLAVE_MODE_EXTERNAL1 = 7,	/**< Slave mode is external1 */
} tim_slave_mode_t;

/**
  * @brief TIM Interrupt Definition
  */
typedef enum {
	TIM_TS_ITR0    = 0,	/**< ITR0 */
	TIM_TS_ITR1    = 1,	/**< ITR1 */
	TIM_TS_ITR2    = 2,	/**< ITR2 */
	TIM_TS_ITR3    = 3,	/**< ITR3 */
	TIM_TS_TI1F_ED = 4,	/**< TI1F_ED */
	TIM_TS_TI1FP1  = 5,	/**< TI1FP1 */
	TIM_TS_TI2FP2  = 6,	/**< TI2FP2 */
	TIM_TS_ETRF    = 7,	/**< ETRF */
} tim_ts_t;

/**
  * @brief  TIM Slave configuration Structure definition
  */
typedef struct {
	tim_slave_mode_t mode;		/**< Slave mode selection */
	tim_ts_t input;			/**< Input Trigger source */
	tim_clock_polarity_t polarity;	/**< Input Trigger polarity */
	tim_etr_psc_t psc;		/**< Input trigger prescaler */
	uint32_t filter;		/**< Input trigger filter */
} tim_slave_config_t;

/**
  * @brief Specifies the event source
  */
typedef enum {
	TIM_EVENT_SOURCE_UPDATE  = (1U << 0),	/**< Event source is update */
	TIM_EVENT_SOURCE_CC1     = (1U << 1),	/**< Event source is channel1 */
	TIM_EVENT_SOURCE_CC2     = (1U << 2),	/**< Event source is channel2 */
	TIM_EVENT_SOURCE_CC3     = (1U << 3),	/**< Event source is channel3 */
	TIM_EVENT_SOURCE_CC4     = (1U << 4),	/**< Event source is channel4 */
	TIM_EVENT_SOURCE_COM     = (1U << 5),	/**< Event source is compare */
	TIM_EVENT_SOURCE_TRIGGER = (1U << 6),	/**< Event source is trigger */
	TIM_EVENT_SOURCE_BREAK   = (1U << 7),	/**< Event source is break */
} tim_event_source_t;

/**
  * @brief TIM Interrupt Definition
  */
typedef enum {
	TIM_IT_UPDATE  = (1U << 0),	/**< Update interrupt bit */
	TIM_IT_CC1     = (1U << 1),	/**< Channel1 interrupt bit */
	TIM_IT_CC2     = (1U << 2),	/**< Channel2 interrupt bit */
	TIM_IT_CC3     = (1U << 3),	/**< Channel3 interrupt bit */
	TIM_IT_CC4     = (1U << 4),	/**< Channel4 interrupt bit */
	TIM_IT_COM     = (1U << 5),	/**< compare interrupt bit */
	TIM_IT_TRIGGER = (1U << 6),	/**< Trigger interrupt bit */
	TIM_IT_BREAK   = (1U << 7),	/**< Break interrupt bit */
} tim_it_t;

/**
  * @brief TIM DMA Request
  */
typedef enum {
	TIM_DMA_UPDATE  = (1U << 0),	/**< DMA request from update */
	TIM_DMA_CC1     = (1U << 1),	/**< DMA request from channel1 */
	TIM_DMA_CC2     = (1U << 2),	/**< DMA request from channel2 */
	TIM_DMA_CC3     = (1U << 3),	/**< DMA request from channel3 */
	TIM_DMA_CC4     = (1U << 4),	/**< DMA request from channel4 */
	TIM_DMA_COM     = (1U << 5),	/**< DMA request from compare */
	TIM_DMA_TRIGGER = (1U << 6),	/**< DMA request from trigger */
} tim_dma_req_t;

/**
  * @brief TIM Flag Definition
  */
typedef enum {
	TIM_FLAG_UPDATE  = (1U << 0),	/**< Update interrupt flag */
	TIM_FLAG_CC1     = (1U << 1),	/**< Channel1 interrupt flag */
	TIM_FLAG_CC2     = (1U << 2),	/**< Channel2 interrupt flag */
	TIM_FLAG_CC3     = (1U << 3),	/**< Channel3 interrupt flag */
	TIM_FLAG_CC4     = (1U << 4),	/**< Channel4 interrupt flag */
	TIM_FLAG_COM     = (1U << 5),	/**< Compare interrupt flag */
	TIM_FLAG_TRIGGER = (1U << 6),	/**< Trigger interrupt flag */
	TIM_FLAG_BREAK   = (1U << 7),	/**< Break interrupt flag */
	TIM_FLAG_CC1OF   = (1U << 9),	/**< Channel1 override state flag */
	TIM_FLAG_CC2OF   = (1U << 10),	/**< Channel2 override state flag */
	TIM_FLAG_CC3OF   = (1U << 11),	/**< Channel3 override state flag */
	TIM_FLAG_CC4OF   = (1U << 12),	/**< Channel4 override state flag */
} tim_flag_t;
/**
  * @}
  */

/** @defgroup TIM_Public_Macros   TIM Public Macros
  * @{
  */
#define CCER_CCxE_MASK		((1U << 0) | (1U << 4) | (1U << 8) | (1U << 12))
#define CCER_CCxNE_MASK		((1U << 2) | (1U << 6) | (1U << 10))

/**
  * @brief  Reset TIM handle state
  */
#define TIM_RESET_HANDLE_STATE(hperh)	((hperh)->state = TIM_STATE_RESET)

/**
  * @brief  Enable the TIM peripheral.
 */
#define TIM_ENABLE(hperh)	((hperh)->perh->CR1.CEN = 1)

/**
  * @brief  Enable the TIM main Output.
  */
#define TIM_MOE_ENABLE(hperh)	((hperh)->perh->BDTR.MOE = 1)

/**
  * @brief  Disable the TIM peripheral.
  */
#define TIM_DISABLE(hperh)                                              \
do {                                                                    \
	if ((((hperh)->perh->CCER.Word & CCER_CCxE_MASK) == 0)		\
           && (((hperh)->perh->CCER.Word & CCER_CCxNE_MASK) == 0))	\
			(hperh)->perh->CR1.CEN = 0;			\
} while(0)

/**
  * @brief  Disable the TIM main Output.
  * @note The Main Output Enable of a timer instance is disabled only if
  *       all the CCx and CCxN channels have been disabled
  */
#define TIM_MOE_DISABLE(hperh)						\
do {                                                                    \
	if ((((hperh)->perh->CCER.Word & CCER_CCxE_MASK) == 0)		\
           && (((hperh)->perh->CCER.Word & CCER_CCxNE_MASK) == 0))	\
			(hperh)->perh->BDTR.MOE = 0;			\
} while(0)

/**
  * @brief  Sets the TIM Autoreload Register value on runtime without calling
  *         another time any Init function.
  */
#define TIM_SET_AUTORELOAD(handle, AUTORELOAD) \
do {                                           \
	(handle)->perh->ARR   = (AUTORELOAD);  \
	(handle)->Init.Period = (AUTORELOAD);  \
} while(0)

/**
  * @brief  Gets the TIM Autoreload Register value on runtime
  */
#define TIM_GET_AUTORELOAD(handle)	((handle)->perh->ARR)
/**
  * @}
  */


/** @defgroup TIM_Private_Macros TIM Private Macros
  * @{
  */
#define IS_TIM_INSTANCE(x)	(((x) == TIM0) || \
                                 ((x) == TIM1) || \
                                 ((x) == TIM2) || \
                                 ((x) == TIM3) || \
                                 ((x) == TIM4) || \
                                 ((x) == TIM5) || \
                                 ((x) == TIM6) || \
                                 ((x) == TIM7))
#define IS_TIM_CC2_INSTANCE(x)	(((x) == TIM0) || \
                                 ((x) == TIM2) || \
                                 ((x) == TIM3) || \
                                 ((x) == TIM6))
#define IS_TIM_CC4_INSTANCE(x)	(((x) == TIM0) || \
                                 ((x) == TIM6))
#define IS_TIM_BREAK_INSTANCE(x) (((x) == TIM0) || \
				  ((x) == TIM2) || \
				  ((x) == TIM3) || \
				  ((x) == TIM6))
#define IS_TIM_PWM_INPUT_INSTANCE(x,y)  \
	((((x) == TIM0) &&		\
	 (((y) == TIM_CHANNEL_1) ||	\
	  ((y) == TIM_CHANNEL_2)))	\
	||				\
	(((x) == TIM2) &&		\
	(((y) == TIM_CHANNEL_1) ||	\
	 ((y) == TIM_CHANNEL_2))) 	\
	||				\
	(((x) == TIM3) &&		\
	(((y) == TIM_CHANNEL_1) ||	\
	 ((y) == TIM_CHANNEL_2))) 	\
	||				\
	(((x) == TIM6) &&		\
	(((y) == TIM_CHANNEL_1) ||	\
	 ((y) == TIM_CHANNEL_2))))

#define IS_TIM_CCX_INSTANCE(x, y)	\
	((((x) == TIM0) &&		\
	 (((y) == TIM_CHANNEL_1) ||	\
	  ((y) == TIM_CHANNEL_2) ||	\
	  ((y) == TIM_CHANNEL_3) ||	\
	  ((y) == TIM_CHANNEL_4)))	\
	||				\
	(((x) == TIM2) &&		\
	(((y) == TIM_CHANNEL_1) ||	\
	 ((y) == TIM_CHANNEL_2))) 	\
	||				\
	(((x) == TIM3) &&		\
	(((y) == TIM_CHANNEL_1) ||	\
	 ((y) == TIM_CHANNEL_2))) 	\
	||				\
	(((x) == TIM6) &&		\
	(((y) == TIM_CHANNEL_1) ||	\
	 ((y) == TIM_CHANNEL_2) ||	\
	 ((y) == TIM_CHANNEL_3) ||	\
	 ((y) == TIM_CHANNEL_4))))	\

#define IS_TIM_CCXN_INSTANCE(x, y)	(((x) == TIM0) && \
                                         (((y) == TIM_CHANNEL_1) || \
                                          ((y) == TIM_CHANNEL_2) || \
                                          ((y) == TIM_CHANNEL_3)|| \
					  ((y) == TIM_CHANNEL_4)))
#define IS_TIM_REPETITION_COUNTER_INSTANCE(x)	((x) == TIM0)
#define IS_TIM_CLOCK_DIVISION_INSTANCE(x)	IS_TIM_CC2_INSTANCE(x)

#define IS_TIM_COUNTER_MODE(x)		(((x) == TIM_COUNTER_MODE_UP)      || \
					 ((x) == TIM_COUNTER_MODE_DOWN)    || \
					 ((x) == TIM_COUNTER_MODE_CENTER1) || \
					 ((x) == TIM_COUNTER_MODE_CENTER2) || \
					 ((x) == TIM_COUNTER_MODE_CENTER3))

#define IS_TIM_CLOCK_DIVISION(x) 	(((x) == TIM_CLOCK_DIV1) || \
					 ((x) == TIM_CLOCK_DIV2) || \
					 ((x) == TIM_CLOCK_DIV4))

#define IS_TIM_PWM_MODE(x)		(((x) == TIM_OC_MODE_PWM1) || \
					 ((x) == TIM_OC_MODE_PWM2))

#define IS_TIM_OC_MODE(x) 		(((x) == TIM_OC_MODE_TIMING)       || \
					 ((x) == TIM_OC_MODE_ACTIVE)       || \
					 ((x) == TIM_OC_MODE_INACTIVE)     || \
					 ((x) == TIM_OC_MODE_TOGGLE)       || \
					 ((x) == TIM_OC_MODE_FORCE_ACTIVE) || \
					 ((x) == TIM_OC_MODE_FORCE_INACTIVE) || \
					 ((x) == TIM_OC_MODE_PWM1) || \
					 ((x) == TIM_OC_MODE_PWM2))

#define IS_TIM_OC_POLARITY(x) 		(((x) == TIM_OC_POLARITY_HIGH) || \
					 ((x) == TIM_OC_POLARITY_LOW))

#define IS_TIM_OCN_POLARITY(x) 		(((x) == TIM_OCN_POLARITY_HIGH) || \
					 ((x) == TIM_OCN_POLARITY_LOW))

#define IS_TIM_OCIDLE_STATE(x) 		(((x) == TIM_OC_IDLE_STATE_RESET) || \
					 ((x) == TIM_OC_IDLE_STATE_SET))

#define IS_TIM_OCNIDLE_STATE(x) 	(((x) == TIM_OCN_IDLE_STATE_RESET) || \
					 ((x) == TIM_OCN_IDLE_STATE_SET))

#define IS_TIM_CHANNELS(x) 		(((x) == TIM_CHANNEL_1) || \
					((x) == TIM_CHANNEL_2) || \
					((x) == TIM_CHANNEL_3) || \
					((x) == TIM_CHANNEL_4) || \
					((x) == TIM_CHANNEL_ALL))

#define IS_TIM_OP_MODE(x) 		(((x) == TIM_OP_MODE_REPETITIVE) || \
					 ((x) == TIM_OP_MODE_SINGLE))
#define IS_TIM_OP_OUTPUT_CH(x) 		(((x) == TIM_OP_OUTPUT_CHANNEL_1) || \
					 ((x) == TIM_OP_OUTPUT_CHANNEL_2))

#define IS_TIM_ENCODER_MODE(x) 		(((x) == TIM_ENCODER_MODE_TI1) || \
					 ((x) == TIM_ENCODER_MODE_TI2) || \
					 ((x) == TIM_ENCODER_MODE_TI12))
#define IS_TIM_IC_POLARITY(x) 		(((x) == TIM_IC_POLARITY_RISING) || \
					 ((x) == TIM_IC_POLARITY_FALLING) || \
					 ((x) == TIM_IC_POLARITY_BOTHEDGE))
#define IS_TIM_IC_SELECT(x) 		(((x) == TIM_IC_SELECT_DIRECTTI) || \
					 ((x) == TIM_IC_SELECT_INDIRECTTI) || \
					 ((x) == TIM_IC_SELECT_TRC))
#define IS_TIM_IC_PSC(x) 		(((x) == TIM_IC_PSC_DIV1) || \
					 ((x) == TIM_IC_PSC_DIV2) || \
					 ((x) == TIM_IC_PSC_DIV4) || \
					 ((x) == TIM_IC_PSC_DIV8))
#define IS_TIM_IC_FILTER(x) 		((x) <= 0xF)

#define IS_TIM_CLEAR_INPUT_SOURCE(x) 	(((x) == TIM_CLEAR_INPUT_NONE) || \
					 ((x) == TIM_CLEAR_INPUT_ETR) || \
					 ((x) == TIM_CLEAR_INPUT_OCREF))
#define IS_TIM_CLEAR_INPUT_POLARITY(x) 	(((x) == TIM_CLEAR_INPUT_POLARITY_NONINVERTED) || \
					 ((x) == TIM_CLEAR_INPUT_POLARITY_INVERTED))
#define IS_TIM_ETR_PSC(x) 		(((x) == TIM_ETR_PSC_DIV1) || \
					 ((x) == TIM_ETR_PSC_DIV2) || \
					 ((x) == TIM_ETR_PSC_DIV4) || \
					 ((x) == TIM_ETR_PSC_DIV8))
#define IS_TIM_CLOCK_SOURCE(x) 		(((x) == TIM_CLOCK_SOURCE_ETRMODE2) || \
					 ((x) == TIM_CLOCK_SOURCE_INTERNAL) || \
					 ((x) == TIM_CLOCK_SOURCE_ITR0) || \
					 ((x) == TIM_CLOCK_SOURCE_ITR1) || \
					 ((x) == TIM_CLOCK_SOURCE_ITR2) || \
					 ((x) == TIM_CLOCK_SOURCE_ITR3) || \
					 ((x) == TIM_CLOCK_SOURCE_TI1ED) || \
					 ((x) == TIM_CLOCK_SOURCE_TI1) || \
					 ((x) == TIM_CLOCK_SOURCE_TI2) || \
					 ((x) == TIM_CLOCK_SOURCE_ETRMODE1))
#define IS_TIM_CLOCK_POLARITY(x) 	(((x) == TIM_CLOCK_POLARITY_INVERTED) || \
					 ((x) == TIM_CLOCK_POLARITY_NONINVERTED) || \
					 ((x) == TIM_CLOCK_POLARITY_RISING) || \
					 ((x) == TIM_CLOCK_POLARITY_FALLING) || \
					 ((x) == TIM_CLOCK_POLARITY_BOTHEDGE))

#define IS_TIM_SLAVE_MODE(x)	(((x) == TIM_SLAVE_MODE_DISABLE) || \
				 ((x) == TIM_SLAVE_MODE_ENCODER1) || \
				 ((x) == TIM_SLAVE_MODE_ENCODER2) || \
				 ((x) == TIM_SLAVE_MODE_ENCODER3) || \
				 ((x) == TIM_SLAVE_MODE_RESET) || \
				 ((x) == TIM_SLAVE_MODE_GATED) || \
				 ((x) == TIM_SLAVE_MODE_TRIGGER) || \
				 ((x) == TIM_SLAVE_MODE_EXTERNAL1))

#define IS_TIM_EVENT_SOURCE(x)	(((x) == TIM_EVENT_SOURCE_UPDATE) || \
				 ((x) == TIM_EVENT_SOURCE_CC1) || \
				 ((x) == TIM_EVENT_SOURCE_CC2) || \
				 ((x) == TIM_EVENT_SOURCE_CC3) || \
				 ((x) == TIM_EVENT_SOURCE_CC4) || \
				 ((x) == TIM_EVENT_SOURCE_COM) || \
				 ((x) == TIM_EVENT_SOURCE_TRIGGER) || \
				 ((x) == TIM_EVENT_SOURCE_BREAK))

#define IS_TIM_TS(x)	(((x) == TIM_TS_ITR0) || \
                         ((x) == TIM_TS_ITR1) || \
                         ((x) == TIM_TS_ITR2) || \
                         ((x) == TIM_TS_ITR3) || \
                         ((x) == TIM_TS_TI1F_ED) || \
                         ((x) == TIM_TS_TI1FP1) || \
                         ((x) == TIM_TS_TI2FP2) || \
                         ((x) == TIM_TS_ETRF))

#define IS_TIM_IT(x)	(((x) == TIM_IT_UPDATE) || \
                         ((x) == TIM_IT_CC1) || \
                         ((x) == TIM_IT_CC2) || \
                         ((x) == TIM_IT_CC3) || \
                         ((x) == TIM_IT_CC4) || \
                         ((x) == TIM_IT_COM) || \
                         ((x) == TIM_IT_TRIGGER) || \
                         ((x) == TIM_IT_BREAK))

#define IS_TIM_DMA_REQ(x)	(((x) == TIM_DMA_UPDATE) || \
                                 ((x) == TIM_DMA_CC1) || \
                                 ((x) == TIM_DMA_CC2) || \
                                 ((x) == TIM_DMA_CC3) || \
                                 ((x) == TIM_DMA_CC4) || \
                                 ((x) == TIM_DMA_COM) || \
                                 ((x) == TIM_DMA_TRIGGER))

#define IS_TIM_FLAG(x)	(((x) == TIM_FLAG_UPDATE) || \
                         ((x) == TIM_FLAG_CC1) || \
                         ((x) == TIM_FLAG_CC2) || \
                         ((x) == TIM_FLAG_CC3) || \
                         ((x) == TIM_FLAG_CC4) || \
                         ((x) == TIM_FLAG_COM) || \
                         ((x) == TIM_FLAG_TRIGGER) || \
                         ((x) == TIM_FLAG_BREAK) || \
                         ((x) == TIM_FLAG_CC1OF) || \
                         ((x) == TIM_FLAG_CC2OF) || \
                         ((x) == TIM_FLAG_CC3OF) || \
                         ((x) == TIM_FLAG_CC4OF))
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions
  * @{
  */
/** @addtogroup TIM_Public_Functions_Group1
  * @{
  */
/* Time Base functions */
hal_status_t tim_base_init(tim_handle_t *hperh);
void tim_base_reset(tim_handle_t *hperh);
void tim_base_start(tim_handle_t *hperh);
void tim_base_stop(tim_handle_t *hperh);
void tim_base_start_by_it(tim_handle_t *hperh);
void tim_base_stop_by_it(tim_handle_t *hperh);
#ifdef HAL_DMA
hal_status_t tim_base_start_by_dma(tim_handle_t *hperh, dma_handle_t *hdma,
                                  uint16_t *buf, uint32_t len, uint8_t dma_ch);
void tim_base_stop_by_dma(tim_handle_t *hperh);
#endif
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group2
  * @{
  */
/* Timer Output Compare functions */
hal_status_t tim_oc_init(tim_handle_t *hperh);
void tim_oc_start(tim_handle_t *hperh, tim_channel_t ch);
void tim_oc_stop(tim_handle_t *hperh, tim_channel_t ch);
void tim_oc_start_by_it(tim_handle_t *hperh, tim_channel_t ch);
void tim_oc_stop_by_it(tim_handle_t *hperh, tim_channel_t ch);
#ifdef HAL_DMA
hal_status_t tim_oc_start_by_dma(tim_handle_t *hperh, tim_channel_t ch,
                      dma_handle_t *hdma, uint16_t *buf, uint32_t len, uint8_t dma_ch);
void tim_oc_stop_by_dma(tim_handle_t *hperh, tim_channel_t ch);
#endif
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group3
  * @{
  */
/* Timer PWM functions */
hal_status_t tim_pwm_init(tim_handle_t *hperh);
void tim_pwm_start(tim_handle_t *hperh, tim_channel_t ch);
void tim_pwm_stop(tim_handle_t *hperh, tim_channel_t ch);
void tim_pwm_start_by_it(tim_handle_t *hperh, tim_channel_t ch);
void tim_pwm_stop_by_it(tim_handle_t *hperh, tim_channel_t ch);
void tim_pwm_set_freq(tim_handle_t *hperh, uint16_t freq);
void tim_pwm_set_duty(tim_handle_t *hperh, tim_channel_t ch, uint16_t duty);
void tim_pwm_set_input(tim_handle_t *hperh, tim_channel_t ch);
#ifdef HAL_DMA
hal_status_t tim_pwm_start_by_dma(tim_handle_t *hperh, tim_channel_t ch,
                      dma_handle_t *hdma, uint16_t *buf, uint32_t len, uint8_t dma_ch);
void tim_pwm_stop_by_dma(tim_handle_t *hperh, tim_channel_t ch);
#endif
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group4
  * @{
  */
/* Timer Input Capture functions */
hal_status_t tim_ic_init(tim_handle_t *hperh);
void tim_ic_start(tim_handle_t *hperh, tim_channel_t ch);
void tim_ic_stop(tim_handle_t *hperh, tim_channel_t ch);
void tim_ic_start_by_it(tim_handle_t *hperh, tim_channel_t ch);
void tim_ic_stop_by_it(tim_handle_t *hperh, tim_channel_t ch);
#ifdef HAL_DMA
hal_status_t tim_ic_start_by_dma(tim_handle_t *hperh, tim_channel_t ch,
                      dma_handle_t *hdma, uint16_t *buf, uint32_t len, uint8_t dma_ch);
void tim_ic_stop_by_dma(tim_handle_t *hperh, tim_channel_t ch);
#endif
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group5
  * @{
  */
/* Timer One Pulse functions */
hal_status_t tim_one_pulse_init(tim_handle_t *hperh, tim_op_mode_t mode);
void tim_one_pulse_start(tim_handle_t *hperh, tim_op_output_channel_t ch);
void tim_one_pulse_stop(tim_handle_t *hperh, tim_op_output_channel_t ch);
void tim_one_pulse_start_by_it(tim_handle_t *hperh, tim_op_output_channel_t ch);
void tim_one_pulse_stop_by_it(tim_handle_t *hperh, tim_op_output_channel_t ch);
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group6
  * @{
  */
/* Timer encoder functions */
hal_status_t tim_encoder_init(tim_handle_t *hperh,  tim_encoder_init_t *config);
void tim_encoder_start(tim_handle_t *hperh, tim_channel_t ch);
void tim_encoder_stop(tim_handle_t *hperh, tim_channel_t ch);
void tim_encoder_start_by_it(tim_handle_t *hperh, tim_channel_t ch);
void tim_encoder_stop_by_it(tim_handle_t *hperh, tim_channel_t ch);
#ifdef HAL_DMA
hal_status_t tim_encoder_start_by_dma(tim_handle_t *hperh, tim_channel_t ch,
                           dma_handle_t *hdma1, dma_handle_t *hdma2, uint16_t *buf1,
			   uint16_t *buf2, uint32_t len, uint8_t dma_ch1, uint8_t dma_ch2);
void tim_encoder_stop_by_dma(tim_handle_t *hperh, tim_channel_t ch);
#endif
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group7
  * @{
  */
/* Control functions */
hal_status_t tim_oc_config_channel(tim_handle_t *hperh, tim_oc_init_t* config, tim_channel_t ch);
hal_status_t tim_ic_config_channel(tim_handle_t *hperh, tim_ic_init_t* config, tim_channel_t ch);
hal_status_t tim_one_pulse_config_channel(tim_handle_t *hperh, tim_one_pulse_init_t *config,
                                                   tim_channel_t ch_out,  tim_channel_t ch_in);
hal_status_t tim_config_oc_ref_clear(tim_handle_t *hperh, tim_clear_input_config_t *config, tim_channel_t ch);
hal_status_t tim_config_clock_source(tim_handle_t *hperh, tim_clock_config_t *config);
hal_status_t tim_config_ti1_input(tim_handle_t *hperh, uint32_t ti1_select);
hal_status_t tim_slave_config_sync(tim_handle_t *hperh, tim_slave_config_t *config);
hal_status_t tim_slave_config_sync_by_it(tim_handle_t *hperh, tim_slave_config_t *config);
hal_status_t tim_generate_event(tim_handle_t *hperh, tim_event_source_t event);
uint32_t tim_read_capture_value(tim_handle_t *hperh, tim_channel_t ch);
void tim_irq_handle(tim_handle_t *hperh);
void tim_dma_req_config(tim_handle_t *hperh, tim_dma_req_t req, type_func_t state);
void tim_interrupt_config(tim_handle_t *hperh, tim_it_t it, type_func_t state);
it_status_t tim_get_it_status(tim_handle_t *hperh, tim_it_t it);
flag_status_t tim_get_flag_status(tim_handle_t *hperh, tim_flag_t flag);
void tim_clear_flag_status(tim_handle_t *hperh, tim_flag_t flag);
/**
  * @}
  */

/** @addtogroup TIM_Public_Functions_Group8
  * @{
  */
/* State functions */
tim_state_t tim_get_state(tim_handle_t *hperh);
/**
  * @}
  */
/**
  * @}
  */

/**
  * @}
  */
/**
  * @}
  */

#ifdef __cplusplus
}
#endif

#endif /* __HAL_TIM_H__ */
