#include "c.h"
#include "math.h"
#include "stdlib.h"

int room_temp;
int copper_temp;
	
/********************ADC设备*/
extern ADC_HandleTypeDef hadc;
#define set_filtering_times 50
struct 
{
	//ADC_HandleTypeDef *device;
	int filtering_times;
	unsigned long adc_filtering[2];
	int adc_value[2];
}ADCC;
/********************红外线接收设备*/
#define read_infrared  HAL_GPIO_ReadPin(INFRARED_GPIO_Port,INFRARED_Pin)       //讀取引腳電平
struct 
{
	uint8_t buff[5];
	uint8_t new_flag:1;
	
}infrared;
/*******************按钮*/
struct
{
	uint8_t down:1;
	uint8_t pow:1;
	uint8_t up:1;
	uint8_t down_l:1;
	uint8_t pow_l:1;
	uint8_t up_l:1;
	

}button;
/*********************压缩机*/
struct
{
	uint32_t last_off_time;
	uint8_t flag:1;
	uint8_t flag_:1;
	uint8_t lock:1;
}comper;
/*********************设置*/
struct 
{
	int temp;
	int auto_temp;
	uint8_t mode;
	uint8_t fan_speed;
	uint8_t fan_swing;
	uint32_t times;
	uint8_t times_hours;
	uint8_t times_off:1;
	uint8_t times_on:1;
	uint8_t sleep:1;
	uint8_t fan_auto:1;

}sett;
/*********************风摆*/
struct
{
	int set_step;
	int now_step;
	uint32_t delay_time;
	uint8_t lock:1;
}stepp;
const uint8_t swing_tab[4]={0x80,0x40,0x20,0x10};
void Sand_Byte_to_swing_595(uint8_t h)
{
	ds_in_or_out(1);
	hc595_ds(0);
	hc595_sc_swing(0);
	hc595_sh(0);
	for(char a=0;a<8;a++)
	{
		if((h<<a)&0x80)
		{
			hc595_ds(1);
		}else
		{
			hc595_ds(0);
		}
		hc595_sc_swing(1);
		hc595_sc_swing(0);
	}
	hc595_sh(1);
	hc595_sh(0);
}
void Stepper_Motor_Control()
{
	if(HAL_GetTick()>stepp.delay_time)
	{
		stepp.delay_time+=10;
		if(stepp.lock==0)
		{
			if(stepp.now_step==stepp.set_step)
			{
				Sand_Byte_to_swing_595(0);
			}else
			{
				if(stepp.now_step>stepp.set_step)
				{
					stepp.now_step--;
				}else
				{
					stepp.now_step++;
				}
				Sand_Byte_to_swing_595(~swing_tab[stepp.now_step%4]);			
			}		
		}else
		{
			Sand_Byte_to_swing_595(0);
		}		
	}

}

const uint8_t temp_tab[15]={0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0};
const uint8_t time_tab[15]={0x08,0x04,0x0c,0x02,0x0a,0x06,0x0e,0x01,0x09,0x80,0x88,0x84,0x8c,0x82,0x8a};
uint8_t chack_temp(const uint8_t *t,uint8_t i)
{	
	i=i&0xf0;
	for(char a=0;a<15;a++)
	{
		if(t[a]==i)
		{
			return a;
		}
	}
	return 15;
}

double adc_to_temp(uint16_t adc)
{
		double val=adc;
		double fenya=(val/4096)*5;                                //计算分压，基准电压5V，        
		// 欧姆定律 r/100=fenya/(5-fenya)
		double r=fenya/(5-fenya)*100000;                          //通过分压计算热敏电阻阻值,下拉电阻为10k，                         
		return ( 1/(log(r/100000) /3950 + 1/(25+273.15))-273.15); //公式法，热敏电阻β值3950，通过热敏电阻阻值计算温度，
}


void cool()
{
	vr(0);  //四通阀关闭
	heat(0);//辅助制热关闭
	if(room_temp<=sett.temp)
	{
		comper.flag=0;
	}else
	{
		if(room_temp>sett.temp+3)
		{
			comper.flag=1;//压缩机开启
		}
	}
}

void dehumi()
{
	vr(0);
	heat(0);
	if(copper_temp<=3) //无视设定温度，使铜管保持在3-5度
	{
		comper.flag=0;
	}else
	{
		if(copper_temp>6)
		{
			comper.flag=1;
		}
	}	
}

void fan()
{
	vr(0);
	heat(0);
	comper.flag=0;
}

void hot()
{
	vr(1);				
	if(room_temp>=sett.temp)
	{
		comper.flag=0;
		heat(0);
	}else
	{
		if(room_temp<sett.temp+3)
		{
			comper.flag=1;
			heat(1);
		}
	}
}

void c()
{
	char buzzer_busy;

	
	Sand_Byte_to_swing_595(0x00);
	
	srand(1234);
	
	panel.led_red=1;
	panel.set_temp=24;
	add_a_note(1,1,500);
	buzzer_io(0);
	comp(0);
	heat(0);
	out_fan(0);
	vr(0);
	swing(0);
	fan_l(0);
	fan_m(0);
	fan_h(0);

	sett.mode=255;	
	sett.fan_speed=0xc0;
	sett.auto_temp=25;
	sett.sleep=0;
	stepp.set_step=400;
	while(1)
	{
	panel.led_red=1;
	/*外部输入*/
		//*adc读取 并计滤波 并计算温度*/
			///*获取两个通道*/
			for(char a=0;a<2;a++)
			{
				HAL_ADC_Start(&hadc);
				while(HAL_ADC_PollForConversion(&hadc,0xffff)!=HAL_OK);
				ADCC.adc_filtering[a]+=HAL_ADC_GetValue(&hadc);               //把读到的值加到滤波缓存				
			}
			HAL_ADC_Stop(&hadc);	
			///*开始滤波*/
			ADCC.filtering_times+=1;                                       //每采样加一次记一次
			if(ADCC.filtering_times==set_filtering_times)                  //当达到设定的滤波采样次数
			{
				ADCC.filtering_times=0;
				ADCC.adc_value[0]=ADCC.adc_filtering[0]/set_filtering_times; //就除于采样次数
				ADCC.adc_filtering[0]=0;
				ADCC.adc_value[1]=ADCC.adc_filtering[1]/set_filtering_times;
				ADCC.adc_filtering[1]=0;	
			}
			room_temp=adc_to_temp(ADCC.adc_value[0]);   //室内温度         //得到滤波后的值，计算对应温度
			copper_temp=adc_to_temp(ADCC.adc_value[1]); //铜管温度
			
		//*红外线接收到数据 开始解码*/		
			if(infrared.new_flag==1)
			{
				infrared.new_flag=0;
				if(infrared.buff[4]==0x30)
				{
					if(infrared.buff[0]&0x10)
					{
						sett.mode=infrared.buff[0]>>5;
					}else
					{
						sett.mode=255;
					}							
					sett.temp=chack_temp(temp_tab,infrared.buff[1])+16;//设置温度				
					if((infrared.buff[2]&0xe0)==0)
					{
						sett.fan_auto=1;
					}else
					{
						sett.fan_auto=0;
						sett.fan_speed=(infrared.buff[2]&0xe0);
					}				
					sett.fan_swing=(infrared.buff[2]&0x10)>>4;	

					sett.sleep=infrared.buff[2]&0x1;
					
					if(infrared.buff[2]&0x08)
					{
						sett.times_on=0;
						sett.times_off=1;
					}else if(infrared.buff[2]&0x04)
					{
						sett.times_on=1;
						sett.times_off=0;
						sett.times=HAL_GetTick();
					}else
					{
						sett.times_on=0;
						sett.times_off=0;
						sett.times=HAL_GetTick();
					}
					
					sett.times_hours=chack_temp(time_tab,infrared.buff[3])+1;
					
					if(buzzer_busy==0)
					{
						add_a_note(1,1,50);
					}				
				}								
			}
		//*强制启动按钮被按下*/
			if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
			{
				comper.lock=0;
			}
		//*面板按钮*/
			if(button.pow_l==0)
			{
				if(panel.flag_s2_t==1)
				{
					button.pow=1;
					button.pow_l=1;
					add_a_note(1,1,50);
					sett.sleep=0;
				}
			}else
			{
				button.pow=0;
				if(panel.flag_s2_t==0)
				{
					button.pow_l=0;
				}
				
			}

			if(button.down_l==0)
			{
				if(panel.flag_s1_t==1)
				{
					button.down=1;
					button.down_l=1;
					add_a_note(1,1,50);
					sett.sleep=0;
				}
			}else
			{
				button.down=0;
				if(panel.flag_s1_t==0)
				{
					button.down_l=0;
				}
				
			}			
			
			if(button.up_l==0)
			{
				if(panel.flag_s3_t==1)
				{
					button.up=1;
					button.up_l=1;
					add_a_note(1,1,50);
					sett.sleep=0;
				}
			}else
			{
				button.up=0;
				if(panel.flag_s3_t==0)
				{
					button.up_l=0;
				}
				
			}			
			
			
			
			
		if(button.pow==1)
		{
			if(sett.mode==255)
			{
				sett.mode=1;
				sett.times_off=0;
				sett.times_on=0;
			}else
			{
				sett.mode=255;
				sett.times_off=0;
				sett.times_on=0;
			}
		}
	/*业务逻辑*/
			
		panel.now_temp=room_temp;//当前温度直接显示到面板
		panel.set_temp=sett.temp;	
		//**********************模式控制*/
		switch(sett.mode)
		{			
			case 255:  //关机模式
				//*************关闭所有继电器
				comper.flag=0;
				heat(0);
				out_fan(0);
				vr(0);
				swing(0);
				fan_l(0);
				fan_m(0);
				fan_h(0);
				stepp.lock=0;
				stepp.set_step=400;
				panel.now_temp=noe;//关闭显示
				panel.set_temp=noe;
				break;
			case 1:  //自动模式
				if(button.down==1)
				{
					sett.auto_temp--;
				}
				if(button.up==1)
				{
					sett.auto_temp++;
				}
				sett.temp=sett.auto_temp;     //设置温度25
				if(room_temp>(sett.auto_temp+3))  //房间温度大于28
				{
					cool();         //模式设为制冷
				}else if(room_temp<(sett.auto_temp-5)) //房间温度小于20
				{
					hot();         //设为制热
				}else
				{
					fan();					//房间21-27度吹风模式
				}			
				break;
			case 0:  //制冷模式
					if(button.down==1)
					{
						sett.temp--;
					}
					if(button.up==1)
					{
						sett.temp++;
					}
					cool();
				break;
			case 4:  //除湿模式
					if(button.down==1)
					{
						sett.temp--;
					}
					if(button.up==1)
					{
						sett.temp++;
					}
					dehumi();
				break;
			case 2:  //吹风
					fan();
					panel.set_temp=noe;
				break;		
			case 6:  //制热模式
					if(button.down==1)
					{
						sett.temp--;
					}
					if(button.up==1)
					{
						sett.temp++;
					}
					hot();
				break;	
		}
		//*********************温度设置范围*/
		if(sett.temp>30){sett.temp=30;}
		if(sett.temp<16){sett.temp=16;}
		if(sett.auto_temp>30){sett.auto_temp=30;}
		if(sett.auto_temp<16){sett.auto_temp=16;}
		//***********************风扇控制*/
		if(sett.mode!=255)  //非关机状态
		{
			out_fan(1);
			if(sett.fan_auto==1)
			{
				if(((rand()%60000))==0)
				{
					sett.fan_speed=0xc0;
				}else if(((rand()%60000))==0)
				{
					sett.fan_speed=0x40;
				}else if(((rand()%60000))==0)
				{
					sett.fan_speed=0x80;
				}
			}
			
			if(sett.fan_speed==0xc0)
			{
				fan_h(0);
				fan_m(0);
				fan_l(1);      //先关闭无关继电器，最后再开启需要的继电器
			}
			if(sett.fan_speed==0x40)
			{
				fan_h(0);				
				fan_l(0);
				fan_m(1);
			}
			if(sett.fan_speed==0x80)
			{				
				fan_m(0);
				fan_l(0);
				fan_h(1);
			}				
			
		//*****************风摆控制*/
		if(sett.fan_swing==1)
		{
			swing(1);
			stepp.lock=0;
			if(stepp.now_step==stepp.set_step)
			{
				if(stepp.set_step<=0)
				{
					stepp.set_step=400;
				}else if(stepp.set_step>=400)
				{
					stepp.set_step=0;
				}
			}
		}else
		{
			stepp.lock=1;
			swing(0);
		}

		if(sett.sleep==1)
		{
			panel.led_green=0;
			panel.led_red=0;
			panel.set_temp=noe;
			panel.now_temp=noe;
		}
		
		if(sett.times_off)
		{
			if(HAL_GetTick()>sett.times+(sett.times_hours*1000*60))
			{
				sett.mode=255;
				sett.times_off=0;
			}
			if(HAL_GetTick()&0x200)
			{
				panel.led_red=0;
			}
		}
		}else
		{
			if(sett.times_on)
			{
				if(HAL_GetTick()>sett.times+(sett.times_hours*1000*60))
				{
					sett.mode=1;
					sett.times_on=0;
				}
			if(HAL_GetTick()&0x200)
			{
				panel.led_red=0;
			}
			}		
		}

	/*状态机服务*/	
		//**********************压缩机保护*/
		if((comper.lock==0)&&(comper.flag_==0)&&(comper.flag==1))  //解锁状态压缩机由关闭到打开
		{
			comper.flag_=1;
			comp(1);                                                 //直接启动压缩机
			panel.led_green=1;
		}
		if((comper.lock==0)&&(comper.flag_==1)&&(comper.flag==0))  //解锁状态压缩机由打开到关闭
		{
			comper.flag_=0;
			comp(0);																								//直接启动压缩机
			panel.led_green=0;
			comper.lock=1;																					//上锁
			comper.last_off_time=HAL_GetTick();											//记录关闭的时间
		}
		if((comper.lock==1)&&(HAL_GetTick()>comper.last_off_time+180000)) //上锁状态且时间过去180秒
		{
			comper.lock=0;																									//解锁
		}
		//*******************/
		panel_scan_server();							//面板扫描显示
		buzzer_busy=buzzer_play_server(); //蜂鸣器控制
		Stepper_Motor_Control();
	}
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{	
	uint32_t time_a=0,time_b=0;
	//time_out=HAL_GetTick()+20;        //設置n ms內完成讀取  防止while卡死
	#define timeout 50000
	switch(GPIO_Pin)
	{
		case INFRARED_Pin:	
			Sand_Byte_to_595(0xff,0xff);
			while(read_infrared==0)
			{
				
				time_a++;if(time_a>timeout){return;}
			}        //第一個數據是模塊的開始傳輸標誌  這個數據直接略過
			time_a=0;
			while(read_infrared==1)
			{
				
				time_a++;if(time_a>timeout){return;}
			}        //第一個數據是模塊的開始傳輸標誌  這個數據直接略過
			time_a=0;
			for(uint8_t a=0;a<5;a++)                                    
			{
				for(uint8_t b=0;b<8;b++)                                    
				{
						while(read_infrared==0){time_a++;if(time_a>timeout){return;}}   //等待總線被拉高,并且对基准计时
						while(read_infrared==1){time_b++;if(time_b>timeout){return;}}   //總線被拉低,并且计时拉低时间
						infrared.buff[a]<<=1;                                						//先高位 所以向左移（就是这里，先左移）動
						if(time_b>(time_a*2))                                    				//讀取時間 如果時間大於40us 
						{
							infrared.buff[a]|=0x01;                                       //說明這一位數據是1  給到最低位（再或操作）
						}
								time_a=0;
								time_b=0;
				}
			}
			infrared.new_flag=1;
			break;		
	}
}