#ifndef __TIM_H__
#define __TIM_H__
#include <stdbool.h>
#include "common.h"

#define TIMER_CHAN_MAX_NUM   8u
#define	TIM_SUCC             0u
#define	TIM_ERR              1u


#define TIM_Index_Channel0     0x00u    
#define TIM_Index_Channel1     0x01u    
#define TIM_Index_Channel2     0x02u    
#define TIM_Index_Channel3     0x03u    
#define TIM_Index_Channel4     0x04u  
#define TIM_Index_Channel5     0x05u  
#define TIM_Index_Channel6     0x06u  
#define TIM_Index_Channel7     0x07u  
#define IS_TIM_CHANIDEX(CHANIDX)		((CHANIDX < 0x08))

#define TIM_Channel_0     0x01u    
#define TIM_Channel_1     0x02u    
#define TIM_Channel_2     0x04u    
#define TIM_Channel_3     0x08u    
#define TIM_Channel_4     0x10u    
#define TIM_Channel_5     0x20u    
#define TIM_Channel_6     0x40u    
#define TIM_Channel_7     0x80u    
#define IS_TIM_CHANNEL(CHAN)		(( CHAN != 0x00))
#define IS_TIM_CHANNEL0(CHAN)		(CHAN == TIM_Channel_0)

/** @defgroup TTM_Polarity 
  * @{
  */
#define TTM_Polarity_High(CHAN)  	(0x00u)  
#define TTM_Polarity_Low(CHAN) 	    (CHAN)  

typedef enum
{
	TTM_Chan_None 	= 0x00u, //when choose it will not use multi-tim combination
	TTM_Chan_0 		= 0x01u,
	TTM_Chan_2 		= 0x04u, 
#if defined(BAT32G1XX_80PIN) || defined(BAT32G1XX_100PIN)
	TTM_Chan_4 		= 0x10u, 
#endif	
}TTM_Master_Chan_t; //multi-channels function, even channel must be setted as master channel,it can choose one or more even channel as master channels

#if defined(BAT32G1XX_80PIN) || defined(BAT32G1XX_100PIN)
#define IS_TTM_Master_Chan(Master_Chan) (((Master_Chan & 0xEA) == 0x00) && ( Master_Chan != 0x00))
#else
#define IS_TTM_Master_Chan(Master_Chan) (((Master_Chan & 0xFA) == 0x00) && ( Master_Chan != 0x00))
#endif

typedef enum
{
	TIM_NEGEDGE 	= 0x00u,  // falling edge of TI
	TIM_POSEDGE 	= 0x01u,  // rising edge of TI 
	TIM_BOTHEDGE	= 0x02u, //  both edge of TI 
}TIM_Edge_t;

#define TIM_CLK0_MASK	0x000F
#define TIM_CLK1_MASK	0x00F0
#define TIM_CLK2_MASK	0x0300
#define TIM_CLK3_MASK	0x3000

typedef enum
{
	TIM_CLK0_Div1     = 0x0000u,  //Operation clock slection FCLK/ 2^0
	TIM_CLK0_Div2     = 0x0001u,	//Operation clock slection FCLK/ 2^1		
	TIM_CLK0_Div4     = 0x0002u,  //Operation clock slection FCLK/2^2
	TIM_CLK0_Div8     = 0x0003u,  //Operation clock slection FCLK/2^3
	TIM_CLK0_Div16    = 0x0004u,  //Operation clock slection FCLK/2^4
	TIM_CLK0_Div32    = 0x0005u,  //Operation clock slection FCLK/2^5
	TIM_CLK0_Div64    = 0x0006u,  //Operation clock slection FCLK/2^6
	TIM_CLK0_Div128   = 0x0007u,  //Operation clock slection FCLK/2^7
	TIM_CLK0_Div256   = 0x0008u,  //Operation clock slection FCLK/2^8
	TIM_CLK0_Div512   = 0x0009u,  //Operation clock slection FCLK/2^9
	TIM_CLK0_Div1024  = 0x000Au,  //Operation clock slection FCLK/2^10
	TIM_CLK0_Div2048  = 0x000Bu,  //Operation clock slection FCLK/2^11
	TIM_CLK0_Div4096  = 0x000Cu,  //Operation clock slection FCLK/2^12
	TIM_CLK0_Div8192  = 0x000Du,  //Operation clock slection FCLK/2^13
	TIM_CLK0_Div16384 = 0x000Eu,	//Operation clock slection FCLK/2^14
	TIM_CLK0_Div32768 = 0x000Fu,  //Operation clock slection FCLK/2^15
}TIM_Clk0_t;
#define IS_TIM_CLK0(DIV) ((DIV & ~TIM_CLK0_MASK) == 0)
typedef enum
{
	TIM_CLK1_Div1     = 0x0000u,  //Operation clock slection FCLK/ 2^0
	TIM_CLK1_Div2     = 0x0010u,	//Operation clock slection FCLK/ 2^1		
	TIM_CLK1_Div4     = 0x0020u,  //Operation clock slection FCLK/2^2
	TIM_CLK1_Div8     = 0x0030u,  //Operation clock slection FCLK/2^3
	TIM_CLK1_Div16    = 0x0040u,  //Operation clock slection FCLK/2^4
	TIM_CLK1_Div32    = 0x0050u,  //Operation clock slection FCLK/2^5
	TIM_CLK1_Div64    = 0x0060u,  //Operation clock slection FCLK/2^6
	TIM_CLK1_Div128   = 0x0070u,  //Operation clock slection FCLK/2^7
	TIM_CLK1_Div256   = 0x0080u,  //Operation clock slection FCLK/2^8
	TIM_CLK1_Div512   = 0x0090u,  //Operation clock slection FCLK/2^9
	TIM_CLK1_Div1024  = 0x00A0u,  //Operation clock slection FCLK/2^10
	TIM_CLK1_Div2048  = 0x00B0u,  //Operation clock slection FCLK/2^11
	TIM_CLK1_Div4096  = 0x00C0u,  //Operation clock slection FCLK/2^12
	TIM_CLK1_Div8192  = 0x00D0u,  //Operation clock slection FCLK/2^13
	TIM_CLK1_Div16384 = 0x00E0u,	//Operation clock slection FCLK/2^14
	TIM_CLK1_Div32768 = 0x00F0u,  //Operation clock slection FCLK/2^15
}TIM_Clk1_t;
#define IS_TIM_CLK1(DIV) ((DIV & ~TIM_CLK1_MASK) == 0)

typedef enum
{
	TIM_CLK2_Div2  = 0x0000u,
	TIM_CLK2_Div4  = 0x0100u,
	TIM_CLK2_Div16 = 0x0200u,
	TIM_CLK2_Div64 = 0x0300u,
}TIM_Clk2_t;
#define IS_TIM_CLK2(DIV) ((DIV & ~TIM_CLK2_MASK) == 0)

typedef enum
{
	TIM_CLK3_Div256    = 0x0000u,
	TIM_CLK3_Div1024   = 0x1000u,
	TIM_CLK3_Div4096   = 0x2000u,
	TIM_CLK3_Div16384  = 0x3000u,
}TIM_Clk3_t;
#define IS_TIM_CLK3(DIV) ((DIV & ~TIM_CLK3_MASK) == 0)

typedef enum
{
	TIM_Selection_Slave       = 0x0000u,  //config for channel2 4 or 6
	TIM_Selection_Bits16      = 0x0000u,  //config for channel 1 or 3
	TIM_Selection_Bits8       = 0x0800u,  //config for channel 1 or 3
	TIM_Selection_Master      = 0x0800u,   //config for channel 2 4 or 6
}TIM_Selection_t;

typedef enum
{
	TIM_Trigger_Software 		= 0x0000u,     // only software trigger start is valid
	TIM_Trigger_IputEdge 		= 0x0100u,     // TImn valid input edge is used as a start or capture trigger 
	TIM_Trigger_BothEdge 		= 0x0200u,     //TImn input edges are used as a start or capture trigger 
	TIM_Trigger_UseMaster_Int 	= 0x0400u,  //when slave channel use master channel's interrupt
}TIM_Trigger_t;
typedef enum
{
	TIM_Pulse_Falling   		= 0x0000u,      // measure falling edge interval of TI
	TIM_Pulse_Rising 			= 0x0040u,      // measure rising edge interval of TI 
	TIM_Pulse_Both 	 			= 0x0080u,      // measure both edge interval of TI 
	TIM_Pulse_Both_Width_Low 	= 0x0080u, // measure low level width of TI 
	TIM_Pulse_Both_Width_High	= 0x00C0u, // measure high level width of TI 
}TIM_Pulse_t;                           

typedef enum
{
	TIM_Mode_PWM_Master 	= 0x0000u,
	TIM_Mode_Interval   	= 0x0001u,
	TIM_Mode_Square     	= 0x0002u,
	TIM_Mode_DivFreq    	= 0x0003u,
	TIM_Mode_PluseInterval 	= 0x0004u,
	TIM_Mode_EventCount    	= 0x0006u,
	TIM_Mode_DelayCount    	= 0x0008u,
	TIM_Mode_SinglePulse   	= 0x0008u,
	TIM_Mode_Measure       	= 0x000Cu,
}TIM_Mode_t;


#if defined(BAT32G1XX_80PIN) || defined(BAT32G1XX_100PIN)
#define IS_TIM(TIMx)		(TIMx == TM40 || TIMx == TM81) 
#else
#define IS_TIM(TIMx)		(TIMx == TM40) 
#endif
#define TIM_StartInt_Disable                 ((uint8_t)0x00) //Interrupt disable
#define TIM_StartInt_Enable         		 ((uint8_t)0x01) //Interrupt enable

typedef enum
{
	TIM4_CH0_Input_TI00 = 0x00u,  // intput signal of timeer input pin (TI00) 
	TIM4_CH0_Input_ELC  = 0x10u,  // event input signal from ELC 
	TIM4_CH1_Input_TI01 = 0x00u,  // input signal of timer input pin (TI01)
	TIM4_CH1_Input_ELC  = 0x01u,  //event input signal from ELC 
	TIM4_CH1_Input_fIL 	= 0x04u,  // low-speed on-chip oscillator clock (fIL) 
	TIM4_CH1_Input_fSUB	= 0x05u,  // subsystem clock (fSUB) 
}TIM4_Input_t;

typedef struct
{	
	uint8_t TIM_Channel;       /*!< Specifies the TIM channel. This parameter can be a value of @ref TTM_Channel_t */
	
	TIM_Pulse_t TIM_Pulse_Edge;	   /*!< Specifies the TIM pluse edge This parameter can be a value of @ref TIM_Pulse_t */

	uint16_t TIM_Period[TIMER_CHAN_MAX_NUM];  /*!< Specifies the period value to be loaded into the active
	                                   Auto-Reload Register at the next update event.This parameter must be a number between 0x0000 and 0xFFFF.	*/ 
									   	
	uint16_t TIM_ClkDivision;     /*!< Specifies the clock division of different TIM channel
	                                  This parameter can be a value of @ref TIM_Clkx_t */

	uint16_t TIM_Selection_Master; /*!< Selection of  master of channle n or selection of 16 bits timer or 8bits timer
								  This parameter can be a value of @ref TTM_Master_Chan_t */

	uint16_t TIM_Slave_Polarity; /*!< Selection polarity of  slave channle ,it decides the valid level of PWM waves
								  This parameter can be a value of @ref TTM_Polarity */
								  	
	uint16_t TIM_Trigger; 	     /*!< setting of start trigger or capture trigger of channle n
									This parameter can be a value of @ref TIM_Trigger_t */
									  
	uint16_t TIM_Mode; 	         /*!< Specifies the TIM work mode of different TIM channel
									      This parameter can be a value of @ref TIM_Mode_t */

	uint8_t TIM_StartInt;	      /*!< whether interrupt is generated when counting is started .*/

	TIM4_Input_t TIM4_Input;	  /*!< Specifies the input signal for channel of timer  
									  This parameter can be a value of @ref TIM_Input_t */
											
}TIM_InitTypeDef;       


#define TM_CLOCK_SELECT_CKM0             (0x0000U) // operation clock CK0 set by PRS register 
#define TM_CLOCK_SELECT_CKM1             (0x8000U) // operation clock CK1 set by PRS register 
#define TM_CLOCK_SELECT_CKM2             (0x4000U) // operation clock CK2 set by PRS register 
#define TM_CLOCK_SELECT_CKM3             (0xC000U) // operation clock CK3 set by PRS register 
/* Counter overflow status of channel n (OVF) */
#define _0000_TM4_OVERFLOW_NOT_OCCURS     (0x0000U) // overflow does not occur 
#define _0001_TM4_OVERFLOW_OCCURS         (0x0001U) // overflow occurs 


void TIM_Start(TMx_Type* TMx, uint8_t ChxIdx);
void TIM_Stop(TMx_Type* TMx, uint8_t ChxIdx);
void TIM_Cmd(TMx_Type* TMx, uint8_t ChxIdx, FunctionalState state);
void TIM_SetCounter(TMx_Type* TMx, uint8_t ChxIdx,uint16_t counter);
bool TIM_GetStatus(TMx_Type* TMx, uint8_t ChxIdx);
int TIM_Init(TMx_Type* TMx,TIM_InitTypeDef *TIM_InitStruct);
uint32_t TIM_GetPulsePeriod(TMx_Type* TMx, uint8_t ChxIdx);
uint32_t TIM_GetPulseWidth(TMx_Type* TMx,  uint8_t ChxIdx);

#endif
