//*********************************************************************** 
//Copyright (c) 2021   HuaXin Micro-electronics Co.,Ltd 

//HS16F3211
//SLEEP&GREEN
//1.睡眠模式：使用TC0低速定时器唤醒；
//configuration introduction

//designer:LvBuWei
//updata：20210909

//*********************************************************************** 
#include 	"hs23p1820.h" 
#include 	"main.h" 

/*;//******************************************************************
;//进入SLEEP模式，所有时钟均停止工作；
;//进入GREEN模式，Fcpu停止运行，Fosc仍运行，
;	//<例如PWM输出配置时钟源选择Fosc，则此时PWM信号脚仍正常输出PWM波形，但指令停止运行！！！>
;//******************************************************************

;睡眠唤醒方式：
	;1.RESET 复位管脚config:<PB3配置成复位脚即可>
	;2.WDT溢出复位:<程序配置WDT，程序中不清狗，则WDT溢出就会复位>
	;3.INT、INT1中断管脚或者PB端口输入变化唤醒:<硬件配置好即可>
;主要;4.TC0溢出唤醒:<例程主要介绍>
	;5.COMP唤醒:<硬件配置好即可>
*/

unsigned char tmp; 


//****interrupt function****//
void interrupt myIsr(void)    
{ 
	if(FTC0IF) 
	{ 
		FTC0IF = 0; 
		PORTB = PORTB^0xFF;
	} 
	if(FPBIF) 
	{ 
		FPBIF = 0; 
		//PORTB = PORTB^0x01;
	} 
	if(FINTIF) 
	{ 
		FINTIF = 0; 
		//PORTB = PORTB^0x04;
	} 
	if(FCOMINTF) 
	{ 
		FCOMINTF = 0; 
		//PORTB = PORTB^0x04;
	} 	
} 


//****main function****//
void main(void) 
{ 
	GPIO_Init();
	CLR_BANK0_RAM();
	/*SLEEP，wakeup choose*/
	//RESET				//config(hardware reset)
	//WDT_Init();		//when WDT overflow,MCU Reset；
	
	//EXIT_INT_INIT();	//wakeup,goto interrupt or goto next code；
	//PB_CHANGE_INIT();	//wakeup,goto interrupt or goto next code；
	
	TC0_SLEEP_SET();	//wakeup
	
	//CMPCON_Init(MODE1);	//wakeup
	
 	
	while(1) 
	{ 
		CLRWDT  
		TC0_SLEEP_SET();	//wakeup
		PORTB = PORTB^0x0f;		
		DelayUs(1);
	} 
} 
 
 

//*********************************************************************** 
/****WDT overflow reset，have no wakeup funtions****；

这里有一点需要注意，TMR0和WDT有一个预分频分配使能位；
S1.预分频分配给WDT：TMR0的时钟源固定为Fcpu；
	看门狗复位时间config加上<预分频比率选择位PS2:PS0>构成
				config	1:1		1:2		1:4		1:8		1:16	1:32	1:64	1:128
	1档：WDT	4.5ms	4.5ms	9ms		18ms	36ms	72ms	144ms	288ms	576ms
	2档：WDT	18ms	18ms	36ms	72ms	144ms	288ms	576ms	1152ms	2304ms
	3档：WDT	72ms	72ms	144ms	288ms	576ms	1152ms	2304ms	4608ms	9216ms
	4档：WDT	288ms	288ms	576ms	1152ms	2304ms	4608ms	9216ms	18432ms	36864ms		
	
S2.预分频分配给TMR0：
	看门狗复位时间仅有config构成：4.5ms；18ms；72ms；288ms；
*/
void WDT_Init(void) 
{
	CLRWDT
	 
	OPTION= 0b00001001; //-000 1001
						//;Bit7：INT1EDG：外部中断1触发方式选择位（PB1）	;0-falling edge, 1-rising edge
						//;Bit6：INTEDG：外部中断触发方式选择位（PB0）	;0-falling edge, 1-rising edge
						//;Bit2~Bit0：PS2:PS0：预分频比率选择位
	 
//;PCON 
	PCON  = 0b10000000;	//100- ----	
						//;Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
						//;Bit6：EIS: IOB0/INT引脚定义位			;0-DIS, 1-EN
						//;Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN
	
}


//****EXIT_INT configuration****
//;PB0=INT  open
//;PB1=INT1 open
//;***********************************************************************
void EXIT_INT_INIT(void)
{
	OPTION= 0b11000001; // 1100 0001
						//;Bit7：INT1EDG：外部中断1触发方式选择位（PB1）	;0-falling edge, 1-rising edge
						//;Bit6：INTEDG：外部中断触发方式选择位（PB0）	;0-falling edge, 1-rising edge
						//;Bit2~Bit0：PS2:PS0：预分频比率选择位
	

	PCON  = 0b11000000;	//010- ----
						//;Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
						//;Bit6：EIS: IOB0/INT引脚定义位			;0-DIS, 1-EN
						//;Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN
						
	
	TRISB = 0b00000011;	//(0-OUT;1-IN) 
	PHCON = 0b11111100;	//1111 1111 :1-DIS;0-EN  

	FINTIF = 0;
	FINT1IF = 0;	
	
	FINTIE = 1;	
	FINT1IE = 1;		
	
	FGIE  = 1;		//GIE【INTEN.bit7】:global interrupt enable bit

}


//****PB_CHANGE_INT Config****//
//PB input state change can make interrupt;
//PB pin must be set input with up_pull or down_pull;
//WUCON pin must be enable；
void PB_CHANGE_INIT(void)
{
	OPTION= 0b00000001; //-000 0001
						//;Bit7：INT1EDG：外部中断1触发方式选择位（PB1）	;0-falling edge, 1-rising edge
						//;Bit6：INTEDG：外部中断触发方式选择位（PB0）	;0-falling edge, 1-rising edge
						//;Bit2~Bit0：PS2:PS0：预分频比率选择位
		
	//PB3 as example 
	TRISB = 0b00001000;//--00 0000	
	
	//UP_PULL	:bit must be set 
	PHCON = 0b11110111;	//--11 0111 :1-DIS;0-EN  	

	//pin state change interrupt enable
	WUCON = 0b00001000;	//--00 1000	:1-EN;0=DIS 
	
	FPBIF = 0;	//INTIF【INTFLAG.bit1】PB interrupt flag,software reset
	
	FPBIE = 1;	//FPBIE【INTEN.bit1】PB interrupt enable (1=EN,0=DIS)	
	
	FGIE  = 1;	//GIE【INTEN.bit7】:global interrupt enable bit

}


//****TC0 overflow：TC0 choose low clock，TC0 interruot must be set****//
void TC0_SLEEP_SET(void)
{
	/*TC0 ：8bit/16bit  
	Config：4Mhz 4' 
	*/ 
//Tc0 init   
	TC0L=0X51;  	
  
 	TC0M = 0x64;	//0110 0100;//Fcpu 4'-16bit-  
	TC0M = 0x60;	//0110 0000;//Fcpu 4'-8bit-;
					//Bit7：TC0TR:TC0 启动控制位。
					//;Bit6~Bit4：TC0S[2:0]:TC0 分频选择位
					//;Bit3：TCCKS:TC0 时钟信号控制位
					//;Bit2：T16SEL:8/16 位溢出位选择。仅当所有 PWMEN = 0 且 BUZ=0 时有效
					//;Bit1：BUZ:BUZ 输出使能位
					//;Bit0：PWM0:PWM0 使能位
	//TC0IF: TC0 overflow flag,software reset 
	 
	CLRWDT     
	FWDTE=0;  
	FTC0IF=0;    
	FTC0IE=1;    
	FTC0TR=1;    
	FGIE=0; 
	
	OSCM=0X53;		//-101 1011   
					//;Bit6：WAKEMODE：睡眠唤醒后系统时钟选择位;0=InsideLowRC,1=HighRC
					//;Bit5：GREENEN：绿色模式使能位		;0=GeneralMode，1=GreenMode
					//;Bit4：SLT0CON：TC0低速时钟控制位(用于唤醒睡眠、绿色);0=HighRC,1=LowRC
					//;Bit3：SLCON：内外低速时钟控制位	;0=OpenLowRC,1=CloseLowRC
					//;Bit2：XTSEL：内外低速选择位		;0=InsideLowRC,1=OutSideLowRC
					//;Bit1：STPHX：内部高速振荡器控制位	;0=Work,1=Stop
					//;Bit0：CLKMD：系统时钟模式控制位	;0=GeneralMode，1=LowMode 
	NOP   
	SLEEP  
	 
	while(FTC0IF==0);    
	FTC0IF=0;    
	    
	CLRWDT    
	FWDTE=1;    
	FTC0IE=0;    
	FTC0TR=0;    
    
	OSCM=0X40; 
					//;Bit6：WAKEMODE：睡眠唤醒后系统时钟选择位;0=InsideLowRC,1=HighRC
					//;Bit5：GREENEN：绿色模式使能位		;0=GeneralMode，1=GreenMode
					//;Bit4：SLT0CON：TC0低速时钟控制位(用于唤醒睡眠、绿色);0=HighRC,1=LowRC
					//;Bit3：SLCON：内外低速时钟控制位	;0=OpenLowRC,1=CloseLowRC
					//;Bit2：XTSEL：内外低速选择位		;0=InsideLowRC,1=OutSideLowRC
					//;Bit1：STPHX：内部高速振荡器控制位	;0=Work,1=Stop
					//;Bit0：CLKMD：系统时钟模式控制位	;0=GeneralMode，1=LowMode 
}



//****CMPCON configuration****//
/*
CMPCON'+'positive choose：External base input "PB0" or internal base ；
CMPCON'-'negative choose: VDD、PB4、PB6、PB1；
*/
/*
program_1：CMPCON'-'negative CONFIG{VDD}；CMPCON'+'positive CONFIG internal base；
program_2：CMPCON'-'negative CONFIG{PIN}；CMPCON'+'positive CONFIG internal base；
program_3：CMPCON'-'negative CONFIG{PIN}；CMPCON'+'positive CONFIG External base input "PB0"；
*/
void CMPCON_Init(unsigned char mode)
{
	if(mode==MODE1)		//program_1：CMPCON'-'negative config[VDD]D；CMPCON'+'positive config internal base ;
	{
		CMPM = 0x10;	//-001 0000 //CMPCON'-'negative CONFIG[VDD]；XRVSEL=1；VRS<3:0>=0；(voltage of cmopare:4.69);
						//;Bit6~Bit5：CPIINS[1:0]: 比较器负端输入选择
						//;Bit4：XRVSEL 比较电压点档位选择
						//;Bit3~Bit0：负端电压档位选择
		CMPCON= 0xD4;	//1*11 010- //System clock；3-clock delay；'+'positive config internal base 1.25V；polarity not contrary；
						//;/bit1:COPOL	比较器输出极性选择	
						//;/bit2:CVEN		比较器+端
						//;/bit3:CPEN		比较器+端
						//;/bit4:CODEB	输出滤波	
						//;/bit5:FTCKS	输出使能滤波时钟选择	
						//;/bit6:CMPIF	比较器转换标志	
						//;/bit7:CMPEN	CMP 使能位
	}
	else if(mode == MODE2)//program_2：CMPCON'-'negative config[pin]；CMPCON'+'positive config internal base；
	{
		CMPM = 0x70;	//-111 0000 //CMPCON'-'negative CONFIG[PB1]；XRVSEL=1；VRS<3:0>=0；(voltage of cmopare:4.69)
						//;Bit6~Bit5：CPIINS[1:0]: 比较器负端输入选择
						//;Bit4：XRVSEL 比较电压点档位选择
						//;Bit3~Bit0：负端电压档位选择
		CMPCON= 0xD4;	//1*11 010- //System clock；3-clock delay；'+'positive config internal base 1.25V；polarity not contrary；
						//;/bit1:COPOL	比较器输出极性选择	
						//;/bit2:CVEN		比较器+端
						//;/bit3:CPEN		比较器+端
						//;/bit4:CODEB	输出滤波	
						//;/bit5:FTCKS	输出使能滤波时钟选择	
						//;/bit6:CMPIF	比较器转换标志	
						//;/bit7:CMPEN	CMP 使能位
	}
	else if(mode == MODE3)//program_3：CMPCON'-'negative config[pin]；CMPCON'+'positive config External base input "PB0"；
	{
		CMPM = 0x70;	//-111 0000 //CMPCON'-'negative CONFIG[PB1]；XRVSEL=1；VRS<3:0>=0；(voltage of cmopare：Calculated from external base PB0)
						//;Bit6~Bit5：CPIINS[1:0]: 比较器负端输入选择
						//;Bit4：XRVSEL 比较电压点档位选择
						//;Bit3~Bit0：负端电压档位选择
		CMPCON= 0xD8;	//1*11 100- //System clock；3-clock delay；+positive config External base(PB0)；polarity not contrary
						//;/bit1:COPOL	比较器输出极性选择	
						//;/bit2:CVEN		比较器+端
						//;/bit3:CPEN		比较器+端
						//;/bit4:CODEB	输出滤波	
						//;/bit5:FTCKS	输出使能滤波时钟选择	
						//;/bit6:CMPIF	比较器转换标志	
						//;/bit7:CMPEN	CMP 使能位；
	}
	
	FCOMINTF = 0;	//CMPCON overflow flag
	FCOMINTEN = 1; 	//CMPCON overflow enable bit(1=EN,0=DIS)
		
	FGIE  = 1;		//【INTEN.bit7】GIE:global interrupt enable bit  
}


//****GPIO configuration****//
void GPIO_Init(void) 
{
	OPTION= 0b000000000;//00-- -000	
						//;Bit7：INT1EDG：外部中断1触发方式选择位（PB1）;0-falling edge, 1-rising edge
						//;Bit6：INTEDG：外部中断触发方式选择位（PB0）	;0-falling edge, 1-rising edge			
						//;Bit2~Bit0：PS2:PS0：预分频比率选择位

	PCON  = 0b10100000;	//101- ----		
						//;Bit7：WDTE: WDT（看门狗定时器）使能位	;0-DIS, 1-EN
						//;Bit6：EIS: IOB0/INT引脚定义位			;0-DIS, 1-EN
						//;Bit5：LVREN: 低电压复位使能位			;0-DIS, 1-EN
			
//PORTB //----------------------------------------------------------------------

	PORTB = 0b00000000;	

	TRISB = 0b00000000;	//(0-OUT;1-IN) 	
	
	PBIC0 = 0b00000000;	//--11 1111 :1-EN;0-DIS
	
	WUCON = 0b00000000;	//--00 0000	:1-EN;0=DIS 

	PDCON = 0b00000000;	//1111 ---- :1-DIS;0-EN
	
	ODCON = 0b00000000;	//--11 -111 :1-EN;0-DIS

	PHCON = 0b11111111;	//--11 1111 :1-DIS;0-EN 	
	
	PORTB = 0b00000000;	
	 //----------------------------------------------------------------------
} 



//****************************************************  
//CLR_BANK0_RAM: 
//C中嵌入ASM，指令操作特殊寄存器前面需要加下划线“_”;
//****************************************************    
void CLR_BANK0_RAM(void)
{
#asm  
	MOVLW	0X3F
	MOVWF	040H
	MOVLW	0X7F
	MOVWF	_FSR
	
BANK0_RAM_CLR_LOOP:	
	CLRF	_INDF
	DECF	_FSR,F
	DECFSZ	040H,F
	GOTO	BANK0_RAM_CLR_LOOP		
#endasm	   
}


//****delay function****// 
//;Fcpu=1MHz;DelayUs = 11+7x     
void DelayUs(unsigned char delayUs)     
{      
	while(delayUs--);    
} 