//*********************************************************************** 
//Copyright (c) 2024   HuaXin Micro-electronics Co.,Ltd 
//
//HS16P2811 
//T4PWM
//configuration introduction
//芯片T4定时器PWM功能，时钟源选Fcpu
//designer:华芯微MCU组
//updata：20241105
//***********************************************************************  
//RAM: 176*8bytes
//ROM: 2K
//STACK: 8-level
//*********************************************************************** 
#include 	"main.h"		


//--------------------------------------------------------------------------------------------------
/*
	     ╔══════╗　 ╔══════╗
	VDD  ╬1 ●   ╚═══╝    16╬   GND
	PA7  ╬2              15╬   PA0
	PA6  ╬3              14╬   PA1
	PA5  ╬4              13╬   PA2
	PA4  ╬5              12╬   PA3
	PC5  ╬6              11╬   PC0
	PC4  ╬7              10╬   PC1
	PC3  ╬8              9 ╬   PC2
         ╚═════════════════╝
*/
//--------------------------------------------------------------------------------------------------

unsigned char T4PWM_CNT=0;
unsigned char T4_Mode = 0;

//--------------------------------------------------------------------------------------------------
//Timer4-define
#define  iT4_1_rate		7
#define  iT4_2_rate		6
#define  iT4_4_rate		5
#define  iT4_8_rate		4
#define  iT4_16_rate	3
#define  iT4_32_rate	2
#define  iT4_64_rate	1
#define  iT4_128_rate	0

#define  iT4_val		500

/**
 * @ brief:	//T4_Timer-Fcpu
 * @ note: 定时器初始化函数,Fcpu
 * @ param:	rate-分频,timer_val-初值
 * @ retval:null
 */
void T4_Timer_Fcpu_Init(unsigned char rate, unsigned int timer_val)
{
	T4TH = (0x3ff-timer_val)/256;
	T4TL = (0x3ff-timer_val)%256;
	
	T4C1 = 0;	//-0-0 -000
	T4C1|=(rate&0x07);
		//bit6:T4OUT0   
			//0 = T4PWM输出不受影响;-√//1 = T4PWM 输出全低电平 
		//bit4:T4CKS0 T4定时器时钟源选择
			//0 = Fcpu/2;-√			//1 = Fosc
		//bit2~0:T4CK<2:0>
			//111 = 1分频		110 = 2分频
			//101 = 4分频		100 = 8分频
			//011 = 16分频		010 = 32分频
			//001 = 64分频		000 = 128分频
		
	T4C0 = 0x80;	//1--0 0-0-
		//bit7:T4REN  定时器总使能;		
			//0 = 禁止;		//1 = 使能-√
		//bit4:T4PWMINV  T4PWM 输出极性;
			//0 = 不取反;	//1 = 取反
		//bit3:T4BUZEN  T4BUZZER 输出使能(T4PWMEN需使能)
			//0 = 禁止;			//1 = 允许
		//bit1:T4PWMEN 输出使能
			//0 = 禁止;			//1 = 启动
	T4IF = 0;
	T4IE = 1;
	PEIE = 1;
	GIE = 1;	
}
 
 

/**
 * @ brief:	//T4_Timer-Fosc
 * @ note: 定时器初始化函数,Fosc
 * @ param:	rate-分频,timer_val-初值
 * @ retval:null
 */
void T4_Timer_Fosc_Init(unsigned char rate, unsigned int timer_val)
{
	T4TH = (0x3ff-timer_val)/256;
	T4TL = (0x3ff-timer_val)%256;
	
	T4C1 = 0;	//-0-0 -000
	T4C1|=(1<<4);	//Fosc
	T4C1|=(rate&0x07);//分频系数
		//bit6:T4OUT0   
			//0 = T4PWM输出不受影响;-√//1 = T4PWM 输出全低电平 
		//bit4:T4CKS0 T4定时器时钟源选择
			//0 = Fcpu/2;			//1 = Fosc-√
		//bit2~0:T4CK<2:0>
			//111 = 1分频		110 = 2分频
			//101 = 4分频		100 = 8分频
			//011 = 16分频		010 = 32分频
			//001 = 64分频		000 = 128分频
		
	T4C0 = 0x80;	//1--0 0-0-
		//bit7:T4REN  定时器总使能;		
			//0 = 禁止;		//1 = 使能-√
		//bit4:T4PWMINV  T4PWM 输出极性;
			//0 = 不取反;	//1 = 取反
		//bit3:T4BUZEN  T4BUZZER 输出使能(T4PWMEN需使能)
			//0 = 禁止;			//1 = 允许
		//bit1:T4PWMEN 输出使能
			//0 = 禁止;			//1 = 启动
	T4IF = 0;
	T4IE = 1;
	PEIE = 1;
	GIE = 1;	
}


/**
 * @ brief:	//T4_PWM_Fcpu_Init
 * @ note: PWM初始化函数,Fcpu,T4OUT0间歇测试
 * @ param:	rate-分频,timer_val-初值
 * @ retval:null
 */
void T4_PWM_Fcpu_Init(unsigned char rate, unsigned int timer_val)
{
	PWMSEL1= (2<<2);	//---- 00**
		//bit3~2:T3PWM<1:0>
			//00 = PC3					01 = PA2 输出 T4PWM
			//10 = PA7 输出T4PWM		11 = 无
			
	//PWM 周期
	T4PH = timer_val/256;
	T4PL = timer_val%256;
	
	//duty
	T4DH = 100/256;
	T4DL = 100%256;

	T4C1 = 0x00;	//-0-0 -000
	T4C1|=(rate&0x07);	
		//bit6:T4OUT0   
			//0 = T4PWM输出不受影响;-√//1 = T4PWM 输出全低电平 
		//bit4:T4CKS0 T4定时器时钟源选择
			//0 = Fcpu/2;	-√		//1 = Fosc
		//bit2~0:T4CK<2:0>
			//111 = 1分频		110 = 2分频
			//101 = 4分频		100 = 8分频
			//011 = 16分频		010 = 32分频
			//001 = 64分频		000 = 128分频
	
	T4C0 = 0;	//1--0 0-1-
	T4C0|= (1<<1);	//
	T4C0|= (1<<7);	//
		//bit7:T4REN  定时器总使能;		
			//0 = 禁止;			//1 = 使能-√
		//bit4:T4PWMINV  T4PWM 输出极性;
			//0 = 不取反;-√		//1 = 取反
		//bit3:T4BUZEN  T4BUZZER 输出使能(T4PWMEN需使能)
			//0 = 禁止;			//1 = 允许
		//bit1:T4PWMEN 输出使能
			//0 = 禁止;			//1 = 启动-√
	T4IF = 0;
	T4IE = 1;
	PEIE = 1;
	GIE = 1;	
}


/**
 * @ brief:	//T4_PWM_Fosc_INV
 * @ note: PWM初始化函数,Fosc,INV
 * @ param:	rate-分频,timer_val-初值
 * @ retval:null
 */
void T4_PWM_Fosc_INV_Init(unsigned char rate, unsigned int timer_val)
{
	PWMSEL1= (1<<2);	//---- 00**
		//bit3~2:T3PWM<1:0>
			//00 = PC3					01 = PA2 输出 T4PWM
			//10 = PA7 输出T4PWM		11 = 无
			
	//PWM 周期
	T4PH = timer_val/256;
	T4PL = timer_val%256;
	
	//duty
	T4DH = 100/256;
	T4DL = 100%256;

	T4C1 = 0x00;	//-0-0 -000
	T4C1|=(1<<4);	//Fosc
	T4C1|=(rate&0x07);	
		//bit6:T4OUT0   
			//0 = T4PWM输出不受影响;-√//1 = T4PWM 输出全低电平 
		//bit4:T4CKS0 T4定时器时钟源选择
			//0 = Fcpu/2;			//1 = Fosc-√
		//bit2~0:T4CK<2:0>
			//111 = 1分频		110 = 2分频
			//101 = 4分频		100 = 8分频
			//011 = 16分频		010 = 32分频
			//001 = 64分频		000 = 128分频
	
	T4C0 = 0;	//1--0 0-1-
	T4C0|= (1<<1);	//
	T4C0|= (1<<4);	//inv
	T4C0|= (1<<7);	//
		//bit7:T4REN  定时器总使能;		
			//0 = 禁止;			//1 = 使能-√
		//bit4:T4PWMINV  T4PWM 输出极性;
			//0 = 不取反;		//1 = 取反-√
		//bit3:T4BUZEN  T4BUZZER 输出使能(T4PWMEN需使能)
			//0 = 禁止;	-√		//1 = 允许
		//bit1:T4PWMEN 输出使能
			//0 = 禁止;			//1 = 启动-√
	T4IF = 0;
	T4IE = 1;
	PEIE = 1;
	GIE = 1;	
}


/**
 * @ brief:	//T4_Buz-Fosc
 * @ note: BUZ初始化函数,Fosc
 * @ param:	rate-分频,timer_val-初值
 * @ retval:null
 */
void T4_BUZ_Fosc_Init(unsigned char rate, unsigned int timer_val)
{
	PWMSEL1= (1<<2);	//---- 01**
		//bit3~2:T4PWM4S<1:0>
			//00 = PC3 输出T4PWM4		01 = PA2 输出 T4PWM4
			//10 = PA7 输出T4PWM4		11 = null
			
	//BUZ-周期
	T4PH = timer_val/256;
	T4PL = timer_val%256;

	T4C1 = 0x00;	//-0-0 -111
	T4C1|=(1<<4);	//Fosc
	T4C1|=(rate & 0x07);
		//bit6:T4OUT0   
			//0 = T4PWM输出不受影响;//1 = T4PWM 输出全低电平 
		//bit4:T4CKS0 T4定时器时钟源选择
			//0 = Fcpu/2;			//1 = Fosc-√
		//bit2~0:T4CK<2:0>
			//111 = 1分频		110 = 2分频
			//101 = 4分频		100 = 8分频
			//011 = 16分频		010 = 32分频
			//001 = 64分频		000 = 128分频
		
	T4C0 = 0;	//1--0 0-1-
	T4C0|= (1<<1);	//
	T4C0|= (1<<3);	//buz
	T4C0|= (1<<7);	//
		//bit7:T4REN  定时器总使能;		
			//0 = 禁止;		//1 = 使能-√
		//bit4:T4PWMINV  T4PWM 输出极性;
			//0 = 不取反;	//1 = 取反
		//bit3:T4BUZEN  T4BUZZER 输出使能(T4PWMEN需使能)
			//0 = 禁止;			//1 = 允许-√
		//bit1:T4PWMEN 输出使能
			//0 = 禁止;			//1 = 启动-√
	T4IF = 0;
	T4IE = 1;
	PEIE = 1;
	GIE = 1;	
}



/**
 * @ brief:	main
 * @ param:	null
 * @ retval:null
 */
unsigned int Duty_BUF;
void main(void) 
{
	System_Init();
	GPIO_Init();
	CLR_RAM_EveryBank();

	T4_Mode = 2;
	Duty_BUF = iT4_val;
	switch(T4_Mode)	
	{
		case 0: T4_Timer_Fcpu_Init(iT4_1_rate,iT4_val);			break;			
		case 1: T4_Timer_Fosc_Init(iT4_1_rate,iT4_val);			break;
		
		case 2: T4_PWM_Fcpu_Init(iT4_1_rate,iT4_val);			break;
		case 3: T4_PWM_Fosc_INV_Init(iT4_1_rate,iT4_val);		break;
		
		case 4: T4_BUZ_Fosc_Init(iT4_1_rate,iT4_val);			break;
		default: break;
	}	
	
	while(1) 
	{ 
		CLRWDT();  
		//PORTA = PORTA^0xff;	
		PORTC = PORTC^0x02;		
		DelayUs(100);
		DelayUs(100);
		DelayUs(100);
		switch(T4_Mode)
		{ 
			case 2:	PORTA ^= (1<<1);	break;	
			default: break; 
		}
		
		Duty_BUF++;
		if(Duty_BUF > iT4_val)
		{
			Duty_BUF = 0;
		}
		T4DH = Duty_BUF/256;
		T4DL = Duty_BUF%256;
	} 
} 


/**
 * @ brief:	GPIO Init
 * @ param:	null
 * @ retval:null
 */
void GPIO_Init(void) 
{
//;PORTA
	PORTA = 0b00000000;		//0000 0000	//端口输出赋值
	TRISA = 0b00000000;		//0000 0000	:0-OUT;1-IN 	//输入输出配置
	PAODCON = 0b00000000;	//0000 0000 :1-EN;0-DIS 	//开漏配置
	PAHCON = 0b11111111;	//1111 1111 :1-DIS;0-EN 	//内部上拉配置
	PADCON = 0b11111111;	//1111 1111 :1-DIS;0-EN 	//内部下拉配置
	WUACON = 0b00000000;	//0000 0000	:1-EN;0=DIS 	//端口唤醒配置
		
//;PORTC
	PORTC = 0b00000000;		//--00 0000	//端口输出赋值
	TRISC = 0b00000000;		//--00 0000	:0-OUT;1-IN 	//输入输出配置
	PCDCON = 0b11111111;	//--11 1111 :1-DIS;0-EN		//内部下拉配置
	PCHCON = 0b11111111;	//--11 1111 :1-DIS;0-EN 	//内部上拉配置
} 


/**
 * @ brief:	System_Init
 * @ param:	null
 * @ retval:null
 */ 
void System_Init(void)
{
	OPTION = 0b000000000;	 //-0-- ----
			//bit6:INTEDG：外部中断触发方式选择位（PC1）	;0-falling edge, 1-rising edge
			
	INTCON = 0b00000000;	//00-0 0-00
			//bit7:GIE 全局中断使能位
			//bit6:PEIE 外设总中断使能位
			//bit4:INTIE 外部中断使能位(PC1)
			//bit3:PAIE PORTA输入变化中断使能位
			//bit1:INTIF 外部中断标志位
			//bit0:PAIF PORTA输入变化中断标志位			
	
	PCON  = 0b10110000;		//1-1- ----	
			//Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
			//Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN
				
	PIE1 = 0B00000000;		//-0-- ---0 
			//Bit6:ADCIE ADC中断使能位
			//Bit0:T1IE 定时器T1中断使能位 
			
	PIR1 = 0B00000000;		//-0-- ---0 
			//Bit6:ADCIE ADC转换完成标志位
			//Bit0:T1IE 定时器T1溢出标志位 
			
	PIE2 = 0B00000000;	//---- -0-0
			//Bit1:T3IE 定时器T3中断使能位
			//Bit2:T4IE 定时器T4中断使能位
			//Bit5:C1IE 比较器C1中断使能位
			
	PIR2 = 0B00000000;	//---- -0-0
			//Bit1:T3IE 定时器T3溢出标志位,软件清0
			//Bit2:T4IE 定时器T4溢出标志位,软件清0
			//Bit5:C1IE 比较器C1输出变化时被置位,软件清0
}


/**
 * @ brief:	CLR_RAM_EveryBank
 * @ note
 *  @对用户寄存器进行清0操作 
 *  @分BANK区清楚 
 *  @嵌入汇编操作 
 *  @IRP:FSR7:	间接寻址寻址空间（充分理解 间接寻址操作原理）
 *  @	0 0		BANK0
 *  @	0 1		BANK1
 *  @	1 0		BANK2
 *  @	1 1		BANK3
 * @ param:	null
 * @ retval:null
 */     
void CLR_RAM_EveryBank(void)
{
	#asm   
		MOVLW	0x5F  //个数
		MOVWF	0x20  //个数存放地址 
		MOVLW 	0x7F  //REG从后往前 清理 
		MOVWF	_FSR,F 
	CLR_RAM_LOOP:   
		CALL	CLR_RAM_Demo
		
		DECF	_FSR,F   
		DECFSZ	0X20,F   
		GOTO	CLR_RAM_LOOP
		
		CALL	CLR_RAM_Demo
		RETURN
		
	CLR_RAM_Demo:	
	//	0 1		BANK1
		//BCF	_STATUS,7	//IRP
		BSF		_FSR,7		//01:BANK1
		CLRF	_INDF  
		
	//	0 0		BANK0
		//BCF	_STATUS,7	//IRP
		BCF		_FSR,7		//00:BANK0
		CLRF	_INDF
		
		RETURN
	#endasm	
}   

/**
 * @ brief:	Delay
 * @ note
 *  @ Fcpu=1MHz;DelayUs = 11+7x
 *  @ 不同时钟Fcpu，注意时间差异
 * @ param:	null
 * @ retval:null
 */
//****delay function****// 
void DelayUs(unsigned char delayUs)
{
	while(delayUs--);
}

//==============================================
//1.>中断函数
//;Bank0~3 编译系统会自动切换,用户不需要手动切换; 
//==============================================
void interrupt myIsr(void)    
{   
	//----User Code ----/
	#if 1
	if(T4IF)	//T4
	{
		T4IF = 0;
		
		PORTC = PORTC ^ 0x01;
		
		//T4TH = (0x3ff-iT4_val)/256;
		//T4TL = (0x3ff-iT4_val)%256;
		
		T4PWM_CNT++;
		if(T4PWM_CNT > 10)
		{
			T4PWM_CNT = 0;
			//T4C1 ^= (1<<4); //时钟源 切换,Fcpu/2 or Fosc
			T4_Mode++;			
		}
	}
	#endif
}