/*
*********************************************************************************************************
*
*	模块名称 : 光敏电阻检测车模块
*	文件名称 : bsp_photoresistor.c
*	版    本 : V1.0
*	说    明 : 光敏电阻检测车
*
*	修改记录 :
*		版本号  日期       作者    说明
*		v1.0
*
*	Copyright (C)
*
*********************************************************************************************************
*/

#include "bsp_photoresistor.h"
int16_t  thr_pho_resistor_h = 0x174;
int16_t  ph_stable_value = 0;
uint16_t  ph_value[5];
int ph_wave_flag = 0;
int ph_wave_count = 0;
enum STATUS ph_state = 1;
enum STATUS Ph_Dec_in_flag;
enum STATUS ge_state = 1;//地磁是否正常标志
u8 mag_time_count;
int16_t VAL_PHOTO = 0;
int16_t ph_base = 0;
int16_t day_or_night = 0x765;//0x765
int16_t day_or_night2 = 0x200;//0x300
int16_t thr_night = 0x200;//0x300
int16_t thr_day = 0x174;//0x174
uint8_t pho_fault_count = 0;
int geo_wave_flag = 0;
int geo_wave_count = 0;
int no_car_count;
///////////////////////////////////

u8 tmp_thr_pho[10];//光敏阈值存储

/***************************test*************************************/
//////////////////////得到光敏电阻值////////////////////////////////
/***
功能：采集光敏电阻AD值
***/
void get_photoresistor_ad(void)
{
        int i=0;
        ADC_Cmd(ADC1,ENABLE);
        while(i<5)
        {
                ADC_ChannelCmd(ADC1,ADC_Channel_22,ENABLE);
                ADC_SoftwareStartConv(ADC1);
                while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
                ph_value[i++] = ADC_GetConversionValue(ADC1);
                ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
        }
        VAL_PHOTO = (ph_value[1] + ph_value[2] + ph_value[3])/3;
        
        CarRecDataStr.pr[0] = VAL_PHOTO>>8;
        CarRecDataStr.pr[1] = VAL_PHOTO;
        ADC_ChannelCmd(ADC1,ADC_Channel_22,DISABLE);
        ADC_Cmd(ADC1,DISABLE);
}

void judge_ph_state(void)
{
        static uint8_t count = 0;
        if(ph_state == YES)count = 0;
        else
        {
              if(VAL_PHOTO > 0x200)count++;
              if(count>=5)
              {
                      count = 0;
                      ph_state = YES;
              }
        }
}
/////////////////////光敏电阻检测车进入/////////////////////////
/***
输入：first_dec：更新参数的值；next_dec：正常检测
功能：光敏检测车进入
输出：1：有车；0：无车
***/
int ph_car_in(int flag)
{
	static uint8_t dec_car_in_count = 0;//光敏稳定变化计次
	static int16_t ph_in_before = 0;
	if(flag == 1)
	{

		ph_in_before = VAL_PHOTO;//首次更新ad值
		return 3;
	}
	if((ph_base - VAL_PHOTO)>THR_PHO_RESISTOR_H)
	{
                if(abs(VAL_PHOTO - ph_in_before) < THR_PHO_RESISTOR_H/5)
                {
                        dec_car_in_count++;
                        if(dec_car_in_count>=PR_DEC_COUNT)
                        {
                                dec_car_in_count = PR_DEC_COUNT;
                        }
                }
                else
                {
                        dec_car_in_count = 0;
                }
                ph_in_before = VAL_PHOTO;
	}
	else
	{
				dec_car_in_count = 0;
	}

	if(dec_car_in_count>=PR_DEC_COUNT)
	{
                dec_car_in_count = PR_DEC_COUNT;
				ph_stable_value = ph_in_before;//光敏检测车停稳值
				return 1;//检测到车进入
	}
	return 0;
}
//////////////////////光敏检测车离开//////////////////////////
/***
输入：first_dec：对参数进行清零；next_dec：正常检测
功能：光敏检测车离开
输出：1：车离开；0：车未离开
***/
int ph_car_out(int flag)
{
	//thr_pho_resistor_A
	static uint8_t dec_car_out_count=0;
	static int16_t ph_out_before = 0;
	if(flag == 1)
	{
                get_photoresistor_ad();
		ph_out_before = VAL_PHOTO;//首次更新ad值
		dec_car_out_count = 0;
		ph_wave_flag = 0;
		return 3;
	}
	if((VAL_PHOTO - ph_out_before) > THR_PHO_RESISTOR_H)//阈值减小，增加灵敏度
	{
		dec_car_out_count++;
		if(dec_car_out_count>=PR_DEC_COUNT)
		{
			dec_car_out_count = PR_DEC_COUNT;
                        return 1;//检测到车离开
		}
	}
	else
	{
		dec_car_out_count = 0;
                ph_out_before = VAL_PHOTO;
	}
	if((VAL_PHOTO - ph_out_before) > (THR_PHO_RESISTOR_H/2))//光敏在波动
	{
		ph_wave_flag = 1;//有波动
	}
	return 0;//未检测到车离开
}

/**********判断白天和晚上*************/
/***
功能：白天晚上自动识别
***/
void judge_day_night(int flag)
{


		static int ph_value_sum_count = 0;
		static int32_t  ph_value_sum = 0;
                if(flag == 1)
                {
                        ph_value_sum_count = 0;
                        ph_value_sum = 0;
                }
                get_photoresistor_ad();
                ph_value_sum_count++;
                ph_value_sum = ph_value_sum + VAL_PHOTO;
                if(ph_value_sum_count >= 30)
                {
                        ph_value_sum = ph_value_sum/ph_value_sum_count;
                        if(ph_stable_value - ph_value_sum > DAY_OR_NIGHT2)
                        {
                                thr_pho_resistor_h = THR_night;
                                ph_stable_value = ph_value_sum;
                        }
                        else if(ph_value_sum - ph_stable_value > DAY_OR_NIGHT2)
                        {
                                thr_pho_resistor_h = THR_day;
                                ph_stable_value = ph_value_sum;
                        }
                        ph_value_sum = 0;
                        ph_value_sum_count = 0;
                }
}
/******电压采集******/
#define DecreaseValue1 (0.04/1000.0)
#define DecreaseValue2 (0.3/1000.0)


double BatVoltage[2] = {0};
uint32_t MotorRunCount = 0;
int BatValue=0;
u8 ttt;
void BatVolDec(u8 state)
{
     int i=0;
     double temp=0;
     ADC_ChannelCmd(ADC1, ADC_Channel_0, ENABLE);
     for(i=0;i<5;i++)
     {
         ADC_SoftwareStartConv(ADC1);
         while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);
         BatValue += ADC_GetConversionValue(ADC1);
     }
     ADC_ChannelCmd(ADC1, ADC_Channel_0, DISABLE);
     BatValue = BatValue/5;

     if(state==1)
     {
          BatVoltage[0] = BatValue*10.0/308.0;
     }
     else if(state==2)
     {
          if((BatVoltage[0]*308.0/10)<((5.8-0.65)/2.0/3.3*4096))
          {
              temp = DecreaseValue2;
          }
          else
          {
              temp = DecreaseValue1;
          }
          temp = MotorRunCount*(temp/3.3*4096)*10.0/308.0;
          temp = BatVoltage[0]-temp;
          BatVoltage[1] = temp;
          BatVoltage[0] = BatVoltage[1];
     }
     else if(state==3)
     {
          BatVoltage[0] = (BatValue*10.0/308.0);
          if((BatVoltage[1]<BatVoltage[0])&&(BatVoltage[1]!=0))
          {
              BatVoltage[0] = BatVoltage[1];
          }
     }
     else
     {
          ;
     }
     BatValue = 0;
     MotorRunCount = 0;
}



/*
enum //TIME_STATE//时刻表
{
    T_10s            = 2,//10s
    T_20s         = 5,//20s
    T_40s          = 10,//40s
    T_60s            = 15,//1minute
    T_200s    = 50,//200s
    T_5m          = 75,//5mintutes
	NO_CAR                = 76//5mintutes+
};
*/
/***
输入：计数值
功能：时刻判断
输出：具体时刻

***/
static int judge_time_state(int time)
{
	if(time<T_30s)
	{
		time = T_30s;
	}
	else if(time<T_40s)//40s
	{
		time = T_40s;
	}
	else if(time==T_40s*2||time==(T_40s*3)||time==(T_40s*4))//200s
	{
		time=SELF_ADAPTION_TIMR;
	}
	else if(time<T_200s)//小于200s
	{
		time=T_200s;
	}
	else if(time<=T_5m)//<5分钟
	{
		time=T_5m;
	}
	else if(time>=NO_CAR)//>5minutes
	{
		time=NO_CAR;
	}
	return time;
}
/****
输入：无
功能：检测车进入

输出：0：未检测到车进入；1：光敏检测到车进入；2：地磁检测到车进入；3：光敏和地磁都检测到车进入
****/
static int common_dec_car_in(void)
{
	int i = 0,j = 0;
	i = ph_car_in(next_dec);
	j = geomag_car_in();
	if(i==0&&j==0)
	{
		return 0;//未检测到车进入
	}
	else if(i==1&&j==0)
	{

                asm("NOP");
		return 1;//光敏检测到车进入
	}
	else if(i==0&&j==1)
	{
                asm("NOP");
		return 2;//地磁检测到车进入
	}
	else if(i==1&&j==1)
	{
                asm("NOP");
		return 3;//地磁光敏都检测到车进入
	}
	return 0;
}
/***
输入：光敏状态，地磁状态
功能：光敏，地磁状态判断
输出：0：都坏，1：只光敏好，2：只地磁好，3：都好
***/
static int ge_ph_state(int ph_state_i,int ge_state_j)
{
	if(ph_state_i==0&&ge_state_j==0)
	{
		return 0;
	}
	else if(ph_state_i==1&&ge_state_j==0)
	{
		return 1;
	}
	else if(ph_state_i==0&&ge_state_j==1)
	{
		return 2;
	}
	else if(ph_state_i==1&&ge_state_j==1)
	{
		return 3;
	}
	return 0;
}

/***
功能：
***/
void wave_time_check(void)
{
        if(geo_wave_flag == 1)//有波动
        {
                geo_wave_count ++;
                if(geo_wave_count>=4)
                {
                       geo_wave_count = 4;
                }
        }
        else
        {
                geo_wave_count = 0;
        }

        if(ph_wave_flag == 1)
        {
                ph_wave_count ++;
                if(ph_wave_count>=4)
                {
                       ph_wave_count = 4;
                }
        }
        else
        {
                ph_wave_count = 0;
        }
}
/***
输入：无
功能:检测车离开
输出：1：检测到车离开；0：未检测到车离开
***/
static int common_dec_car_out()
{
        //protect_count
	int i = 0,j = 0;
	i = ph_car_out(next_dec);
	j = geomag_car_out(next_dec);
        if(i==0)geo_wave_flag = 0;
        wave_time_check();
	if((i==1&&j==1)||(i==1&&geo_wave_flag==1)||(j==1&&ph_wave_flag==1))
	{
                if((i==1&&geo_wave_flag==1)&&geo_wave_count<4)
                {
                        return 0;//bsp_DelayMS(15000);
                }
                else if((j==1&&ph_wave_flag==1)&&ph_wave_count<4)
                {
                        return 0;//bsp_DelayMS(15000);
                }
                ph_wave_count = 0;
                geo_wave_count = 0;
                return 1;//检测到车离开
	}
	return 0;
}
/*行程开关*/
#define GPIOP_TRAVELSWITCH_K1   GPIOB
#define GPIOB_TRAVELSWITCH_K1   GPIO_Pin_0
/**
*获取行程开关状态，锁关闭时，立起来，返回1；锁打开时，返回0
*/
u8 GetSysStatus(void)
{

	if(GPIO_ReadInputDataBit( GPIOP_TRAVELSWITCH_K1, GPIOB_TRAVELSWITCH_K1 ) == RESET)
	{
		if(GPIO_ReadInputDataBit( GPIOP_TRAVELSWITCH_K1, GPIOB_TRAVELSWITCH_K1 ) == RESET)
		return 0;
	}
	if(GPIO_ReadInputDataBit( GPIOP_TRAVELSWITCH_K1, GPIOB_TRAVELSWITCH_K1 ) != RESET)
	{
		if(GPIO_ReadInputDataBit( GPIOP_TRAVELSWITCH_K1, GPIOB_TRAVELSWITCH_K1 ) != RESET)
		return 1;
	}

	return 2;

}

/***
输入：无
功能：各时间段，地磁和光敏配合检测车进入及离开
输出：无
***/

uint8_t DelayTime4s = 0;
void time_state(void)
{
        char printf_buff[100];
	int time = 0;
	int dec_flag = 0;
        if(DelayTime4s)return;
        DelayTime4s = 4;
        if(LOW_POWER_TEST)return;
	if((LIMIT_READ)||(QMC5883LStr.DataOkFlag == 0)||(LockCarState.MotorActResults == FALL_ERROR)||(LockCarState.MotorActResults == RISE_OK)||((LockCarState.MotorCmd!=CmdIdle)))return;	
	mag_time_count++;       
        //BeepStart(1,0);
        //UsartPrint(QMC5883LStr.QMC_CUR_ROPORT,6);
        QMC5883LStr.DataOkFlag = FALSE;
	get_photoresistor_ad();
        judge_ph_state();
        if(HC_DEBUG){
            sprintf(printf_buff,"Tim:%d;P_BASE:%d,P_CUR:%d;QMC_BASE:X=%d,Z=%d;QMC_CUR:X=%d,Z=%d;car_state = %d\r\n",mag_time_count,ph_base,VAL_PHOTO,QMC5883LStr.QMC_BASE[0],QMC5883LStr.QMC_BASE[2],QMC5883LStr.QMC_CUR[0],QMC5883LStr.QMC_CUR[2],CarRecDataStr.CarState);
            int i = 0;
            while(printf_buff[i]!='\n')
              UsartPrint(&printf_buff[i++],1);
        }
        //UsartPrint(&mag_time_count,1);
	if(CarRecDataStr.CarState==0)
	{
		time = judge_time_state(mag_time_count);
                if(mag_time_count<=T_4s)
                {
                    no_car_count = 0;
                    memcpy(QMC5883LStr.QMC_BASE,QMC5883LStr.QMC_CUR,3*sizeof(int16_t));
                    ph_base = VAL_PHOTO;
                    if(ph_base<0x200)ph_state = NO;
                    BeepStart(1,0);
                    
                }
                if(time>T_30s)
                {
                        dec_flag = common_dec_car_in();
                }
		switch(time)
		{
                        case T_30s:
                        {

                                return;
                        }
                        case T_40s:
                        {
                                if(dec_flag == 2||dec_flag == 3)
                                {
                                  have_car_send();
                                }
                                break;
                        }
                        case SELF_ADAPTION_TIMR:
                        {
                                geomag_self_adaption();
                                break;
                        }
                        case T_200s:
                        {
                                if(dec_flag == 2||dec_flag == 3)
                                {
                                      have_car_send();
                                }
                                break;
                        }
                        case T_5m:
                        {
                                if(dec_flag == 1||dec_flag == 2||dec_flag == 3)have_car_send();
                                break;
                        }
                        case NO_CAR:
                        {
                                NO_car_deal();
                                
                                break;
                        }
                        default:
                                break;
		}

	}
	else//检测车离开
	{

                if(mag_time_count < T_3M)//前三分钟不检测车离开
                {
                        return;
                }
                else
                {
                        mag_time_count = T_3M;
                }

		switch(ge_ph_state(ph_state,ge_state))
		{
		case 0://光敏地磁都故障
			break;
		case 1://单光敏检测
		{
			judge_day_night(next_dec);//白天晚上自动识别
			if(ph_car_out(next_dec))
			{
				NO_car_deal();
			}
			break;
		}
		case 2://单地磁检测
		{
			if(geomag_car_out(next_dec))
                        {
                              NO_car_deal();
                        }
			break;
		}
		case 3://地磁光敏配合检测
		{
			judge_day_night(next_dec);
			if(common_dec_car_out())
                        {
                                NO_car_deal();
                                asm("NOP");

                        }
			break;
		}
		default:
			break;
		}
	}
}

