// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// File name    : pwm_drv.h
// Version      : V0.1
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#ifndef PWM_DRV_H_
#define PWM_DRV_H_

#include "pwm_reg.h"

#define PWM        ((PWM_TypeDef *)(PWM_BASE_ADDR))

//PWM_PORT DEFINITION
#define PWM_PORT0		0
#define PWM_PORT1		1
#define PWM_PORT2		2
#define PWM_PORT3		3

#define IS_PWM_PORTx(port) (((port) == PWM_PORT0) || \
                            ((port) == PWM_PORT1) || \
                            ((port) == PWM_PORT2) || \
                            ((port) == PWM_PORT3))


//PWM Clock divider
#define PWM_CLK_DIV_1   4
#define PWM_CLK_DIV_2   0
#define PWM_CLK_DIV_4   1
#define PWM_CLK_DIV_8   2
#define PWM_CLK_DIV_16  3
#define IS_PWM_CLK_DIV(div) (((div) == PWM_CLK_DIV_1) || \
                             ((div) == PWM_CLK_DIV_2) || \
                             ((div) == PWM_CLK_DIV_4) || \
                             ((div) == PWM_CLK_DIV_8) || \
                             ((div) == PWM_CLK_DIV_16))


#define IS_PWM_PULLUP_STA(sta) (((sta) == PWM_PULLUP_EN) || \
                                 ((sta) == PWM_PULLUP_DIS))

#define PWM0_INPUT_OUTPUT_EN    do{CCM->PCFG3 |= (1<<0);}while(0)
#define PWM1_INPUT_OUTPUT_EN    do{CCM->PCFG3 |= (1<<1);}while(0)
#define PWM2_INPUT_OUTPUT_EN    do{CCM->PCFG3 |= (1<<2);}while(0)
#define PWM0_INPUT_OUTPUT_DIS   do{CCM->PCFG3 &= ~(1<<0);}while(0)
#define PWM1_INPUT_OUTPUT_DIS   do{CCM->PCFG3 &= ~(1<<1);}while(0)
#define PWM2_INPUT_OUTPUT_DIS   do{CCM->PCFG3 &= ~(1<<2);}while(0)


// ==========================================================
// Bert added

#define PWM_PULLUP_EN   			1
#define PWM_PULLUP_DIS  			0

#define DISABLE		  				0
#define ENABLE	   					1

#define PULL_DOWN		  				0
#define PIULL_UP  					1


#define MODE_ONESHOT					0
#define MODE_AUTOLOAD  				1


#define PWM_CR_CHEN_MASK			(0x01<<0)
#define PWM_CR_CHINV_MASK			(0x01<<2)
#define PWM_CR_CHMOD_MASK			(0x01<<3)
#define PWM_CR_DZEN0_MASK			(0x01<<4)


#define PWM_PR_CP0_MASK				0x00FF
#define PWM_PR_DZI0_MASK     		(0xFF0000U)	


#define PWM_PCR_PDDR_MASK			(0x10000U)
#define PWM_PCR_PULLUP_MASK		(0x00100U)
#define PWM_PCR_PDR_MASK			(0x0001)

/**
 * @brief: PWM Initialization Structure Definition
 */
typedef struct
{
	uint16_t clock_pre_scale;              //!< PWM Clock Pre-scale
   uint8_t clock_divider;    					//!< PWM Input Clock divided
	uint8_t mode;                       	//!< PWM Work Mode
   bool en;                            	//!< PWM Channel Enable State
	bool output_pin_en;							// PWM output enable
	bool output_pull;							 	// PWM output pull
   bool dead_zone_en;           				//!< PWM Dead-Zone Enable State
   uint8_t dead_zone_length;             //!< PWM Dead-Zone Length,dead_zone_length must equal to or below comparator
	uint8_t dutyRatio;
} PWM_InitDataDef;


extern void PWM_Init(PWM_TypeDef *PWMx,uint8_t channel,uint32_t frequency, uint8_t dutyCycle, bool polarity);
extern void PWM_AdjustDutyCycle(PWM_TypeDef *PWMx, uint8_t channel, uint8_t dutyCycle);
extern void PWM_AdjustFrequency(PWM_TypeDef *PWMx, uint8_t channel, uint32_t frequency);

// ==========================================================



/*******************************************************************************
* Function Name  : PWM_OutputInit
* Description    : PWM输出初始化，输出脉冲
* Input          : - PWMx : PWM channel；where x can be 0, 1, 2, 3 to select the PWM peripheral.
*                  - PWM_Prescaler: PWM预分频值
*                  - PWM_Csr：Clock Source Selection
*                             取值：PWM_CLK_DIV_1、PWM_CLK_DIV_16、PWM_CLK_DIV_8、PWM_CLK_DIV_4、PWM_CLK_DIV_2
*                  - PWM_Period：PWM Counter/Timer Loaded Value, data range : 65535~0 (Unit : 1 PWM clock cycle)
*                                One PWM cycle width = PWM_Period + 1
*                  - PWM_Width：PWM Comparator Register Value;data range : 65535~0 (Unit : 1 PWM clock cycle)
*                               used to determine PWM output duty ratio
*                               PWM_Width >= PWM_Period : PWM output is always high
*                               PWM_Width >= PWM_Period : PWM output high = (PWM_Width + 1) unit
*                               PWM_Width = 0 : PWM output high = 1 unit
*                  - PWM_CHxINV_Flg：Timer  Inverter ON/OFF flag
*                                    1 = Inverter ON
*                                    0 = Inverter OFF
*
* Output         : None
* Return         : None
*******************************************************************************/
extern void PWM_OutputInit(UINT8 PWMx, UINT8 PWM_Prescaler, UINT8 PWM_Csr, UINT16 PWM_Period,  UINT16 PWM_Width, UINT8 PWM_CHxINV_Flg);

/*******************************************************************************
* Function Name  : PWM_InputInit
* Description    : PWM输入初始化，可触发中断
* Input          : - - PWMx : PWM channel；where x can be 0, 1, 2, 3 to select the PWM peripheral.
*                  - PWM_Prescaler: PWM预分频值
*                  - PWM_Csr：Clock Source Selection
*                             取值：PWM_CLK_DIV_1、PWM_CLK_DIV_16、PWM_CLK_DIV_8、PWM_CLK_DIV_4、PWM_CLK_DIV_2
*                  - PWM_Period：PWM Counter/Timer Loaded Value, data range : 65535~0 (Unit : 1 PWM clock cycle)
*                                One PWM cycle width = PWM_Period + 1
*
* Output         : None
* Return         : None
*******************************************************************************/
extern void PWM_InputInit(UINT8 PWMx, UINT8 pwm_prescaler, UINT8 pwm_csr,UINT16 pwm_period);

/*******************************************************************************
* Function Name  : PWM_ISR
* Description    : PWM中断处理函数
* Input          : - None
*
* Output         : None
* Return         : None
*******************************************************************************/
extern void PWM_ISR(void);

/*******************************************************************************
* Function Name  : PWM_Start
* Description    : PWM打开
* Input          : - PWMx : PWM channel；where x can be 0, 1, 2, 3 to select the PWM peripheral.
*
* Output         : None
* Return         : None
*******************************************************************************/
extern void PWM_Start(UINT8 PWMx);

/*******************************************************************************
* Function Name  : PWM_Stop
* Description    : PWM关闭
* Input          : - PWMx : PWM channel；where x can be 0, 1, 2, 3 to select the PWM peripheral.
*
* Output         : None
* Return         : None
*******************************************************************************/
extern void PWM_Stop(UINT8 PWMx);


/*******************************************************************************
* Function Name  : PWM_ConfigGpio
* Description    : PWM配置成GPIO用途
* Input          : - PWMx: PWM channel；where x can be 0, 1, 2 to select the PWM peripheral.
*
*                  - SPI_Dir：设置GPIO方向   GPIO_OUTPUT：输出  GPIO_INPUT：输入
*                  - PullUp_En：设置相应的脚上拉使能
*                               PWM_PULLUP_EN:  enable上拉
*                               PWM_PULLUP_DIS: disable上拉
*
* Output         : None
* Return         : None
******************************************************************************/
INT8 PWM_ConfigGpio(UINT8 PWMx, UINT8 GPIO_Dir, UINT8 PullUp_En);


/*******************************************************************************
* Function Name  : PWM_ReadGpioData
* Description    : 获取PWMx对应引脚的电平
* Input          : - PWMx: PWM channel；where x can be 0, 1, 2 to select the PWM peripheral.
*                  - PWM_Port: 0,1,2,3
*
* Output         : None
* Return         : Bit_SET:高电平  Bit_RESET：低电平  -1：fail
******************************************************************************/
INT8 PWM_ReadGpioData(UINT8 PWMx);

/*******************************************************************************
* Function Name  : PWM_WriteGpioData
* Description    : 设置PWMx对应引脚的电平
* Input          : - PWMx: PWM channel；where x can be 0, 1, 2 to select the PWM peripheral.
*                  - PWM_Port: 0,1,2,3
*                  - bitVal：设置的电平，Bit_SET：设置为高电平  Bit_RESET：设置为低电平
*
* Output         : None
* Return         : 0: 设置成功    other：设置失败
******************************************************************************/
INT8 PWM_WriteGpioData(UINT8 PWMx, UINT8 bitVal);

#endif /* PWM_DRV_H_ */
