/*************************** (C) COPYRIGHT 2017 CXHY ****************************
 * 文件名  ：UltrasonicWave.c
 * 描  述  ：HC-SR04超声波驱动代码     
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2017/08/04 
*********************************************************************************/
#include "IR_Distancer.h"
#include "timer.h"
#include "delay.h"
#include "adc.h"
#include "my_math.h"
#include "data_typedef.h"

#define IR_AdcValSize	100
uint16_t IR_AdcValBuf_1[IR_AdcValSize]; 
uint16_t IR_AdcVal_1 = 0;

uint16_t IR_AdcValBuf_2[IR_AdcValSize];
uint16_t IR_AdcVal_2 = 0;

uint8_t IR_GetAdcValMake = 0;

#define IR_GetDataCount		5

uint8_t ir_Distance1 = 0;
uint8_t ir_dataOutState1 = 0;
uint8_t ir_Distance2 = 0;
uint8_t ir_dataOutState2 = 0;



/*
***********************************************************************
*	函 数 名: show
*	功能说明: 以十六进制显示数组里的内容
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void showBuf(uint16_t num[], uint8_t n)
{
    uint8_t i;
		printf("\r\n");
    for(i=0; i<n; i++)
		{
      printf("%04d ",num[i]);
		}
		printf("\r\n");
}





/*
***********************************************************************
*	函 数 名: IR_GetAdcVal_1
*	功能说明: 获取红外测距传感器ADC值
*	形    参：无	         
*	返 回 值: 无
***********************************************************************
*/
void IR_GetAdcVal_1(void)
{
	Data_collection(IR_AdcValBuf_1, IR_AdcValSize, ADC_Channel_11);
	sort_16(IR_AdcValBuf_1, IR_AdcValSize);           											//对存在缓存中的采集数据进行排序
	IR_AdcVal_1 = average_16(IR_AdcValBuf_1, IR_AdcValSize, 20);				//去掉头和尾后，求平均数
}

/*
***********************************************************************
*	函 数 名: IR_GetAdcVal_2
*	功能说明: 获取红外测距传感器ADC值
*	形    参：无	         
*	返 回 值: 无
***********************************************************************
*/
void IR_GetAdcVal_2(void)
{
	Data_collection(IR_AdcValBuf_2, IR_AdcValSize, ADC_Channel_10);
	sort_16(IR_AdcValBuf_2, IR_AdcValSize);           									//对存在缓存中的采集数据进行排序
	IR_AdcVal_2 = average_16(IR_AdcValBuf_2, IR_AdcValSize, 20);				//去掉头和尾后，求平均数
}

uint8_t distanceMap[] = {	 20, 	 30, 	 40, 	 50, 	 60, 	 70, 	 80,   90, 	100,  110,  120,  130,  140,  150};
float voltageMap[14] = 	{2.49, 1.95, 1.51, 1.21, 1.01, 0.86, 0.76, 0.69, 0.61, 0.53, 0.45, 0.40, 0.34, 0.25};
// float voltageMap[14] = 	{2.50, 1.95, 1.50, 1.20, 1.00, 0.88, 0.77, 0.69, 0.60, 0.55, 0.49, 0.44, 0.38, 0.30};

// float voltageMap[14] = 	{2.44, 1.94, 1.50, 1.20, 1.00, 0.85, 0.74, 0.67, 0.60, 0.52, 0.48, 0.44, 0.39, 0.33};

/*
***********************************************************************
*	函 数 名: LookupTable
*	功能说明: 查表得出对应的距离值
*	形    参：无	         
*	返 回 值: 对应的距离
***********************************************************************
*/
float LookupTable(float vIn, float vMap1, float vMap2, uint8_t disMap1, uint8_t disMap2)
{
	uint8_t disDifVal;													//区间的电压差值
	float vDifVal;															//区间的距离差值
	float vLtscale;															//区间距离比例因子
	float vIntervalVal;													//区间电压值
	float intervalDistance;											//区间的距离
	
	disDifVal = disMap2 - disMap1;
	vDifVal = vMap1 - vMap2;
	vLtscale = disDifVal/vDifVal;
	
	vIntervalVal = vMap1 - vIn;
	intervalDistance = vIntervalVal*vLtscale;
	
// 	printf("\r\ndisDif = %d\r\n", disDifVal);
// 	printf("\r\nvDif = %.2f\r\n", vDifVal);
// 	printf("\r\nvLtscale = %.2f\r\n", vLtscale);
// 	printf("\r\nvIntervalVal = %.2f\r\n", vIntervalVal);
// 	printf("\r\nvInvalVal = %.2f\r\n", intervalDistance);
	
	return disMap1 + intervalDistance;
}

/*
***********************************************************************
*	函 数 名: IR_GetDistanceData
*	功能说明: 取得一次测距值
*	形    参：num -> 对应哪个通道
*	返 回 值: 当前通道的测距值
***********************************************************************
*/
uint8_t IR_GetDistanceData(uint8_t num)
{
	float distanceTemp;
	float adToVdcVal;
	int index = 0;
	
	switch(num)
	{
		case 1:
			IR_GetAdcVal_1();
			
			if(IR_AdcVal_1 < 120)
			{
				return 255;
			}else{
				adToVdcVal = IR_AdcVal_1/4096.0 * 3.34;
// 				printf("\r\nV1 = %1.2f, ADC1 = %d  ", adToVdcVal, IR_AdcVal_1);
			}
			break;
			
		case 2:
			IR_GetAdcVal_2();
			
			if(IR_AdcVal_2 < 120)
			{
				return 255;
			}else{
				adToVdcVal = IR_AdcVal_2/4096.0 * 3.34;
// 				printf("\r\nV2 = %1.2f, ADC2 = %d  ", adToVdcVal, IR_AdcVal_2);
			}
			break;
		
		default:
			break;
	}
	
// 	printf("ADC = %4d, %4d, V = %1.2f\r\n", IR_AdcVal_1, IR_AdcVal_2, adToVdcVal);
	
	for(index = 0; index < 14; index++)
	{
		if(adToVdcVal >= voltageMap[index])
		{
			break;
		}
	}
		
// 		printf("\r\nindex = %d\r\n", index);
	if(index == 0)
	{
		distanceTemp = 20;
	}else if(index == 14){
		distanceTemp = 150;
	}else{
		distanceTemp = LookupTable(adToVdcVal, voltageMap[index-1], voltageMap[index], distanceMap[index-1], distanceMap[index]);
	}
	
// 	printf("D = %d cm\r\n", (uint8_t)distanceTemp);
	
	return distanceTemp;
	
}

/*
***********************************************************************
*	函 数 名: ULT_DataProcessing
*	功能说明: 对采集到缓存的数据处理（对其进行排序后求平均数）
*	形    参：
*       		*p: 需要处理的数组指针
*						n:  数组的长度 
*	返 回 值: 返回最终处理过后的结果
***********************************************************************
*/
uint8_t IR_DataProcessing(uint8_t *p, uint16_t n, uint8_t discardVal)
{
	uint8_t retData = 0;
	
	sort_8(p, n);           											//对存在缓存中的采集数据进行排序
	retData = average_8(p, n, discardVal);				//去掉头和尾后，求平均数
// 	printf("\r\nValue = %d\r\n", retData);
	return retData;
}

/*
***********************************************************************
*	函 数 名: IR_GetDistanceTask_01
*	功能说明: 获取红外测距任务
*	形    参：无
*	返 回 值: 数据处理状态  1：已处理完成可以输出、0：尚未处理完成
***********************************************************************
*/
void IR_GetDistanceTask_01(void)
{
	static uint8_t step = 0x00;
	static uint8_t getDataCnt = 0x00;
	
	static uint8_t newValue = 0x00;
	static uint8_t oleValue = 0x00;
	static uint8_t IR_DistanceDataBuf[IR_GetDataCount];
	
	static timer waitingTimer;
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&waitingTimer, 1);
	}
	
	switch(step)
	{
		case 0x00:
			if(timer_expired(&waitingTimer))
			{
				newValue = IR_GetDistanceData(1);
// 				printf("\r\nValue = %3.1f cm\r\n",(float)newValue);
				step = 0x01;
				timer_restart(&waitingTimer);
			}
			break;
		case 0x01:
			if(DifferenceCompare(newValue, oleValue, 10))		//比较新旧值的差值，（当前值 - 之前值）> 设定值时重新采集数据
			{
				getDataCnt = 0;
			}
// 			printf("\r\nCnt1 = %d, newValue = %d, oleValue = %d\r\n", getDataCnt, newValue, oleValue);
			oleValue = newValue;
			
			IR_DistanceDataBuf[getDataCnt] = newValue;
			getDataCnt++;
			if(IR_GetDataCount == getDataCnt)							//IR_GetDataCount次数据都相差不大，则认为数据已经稳定可以输出
			{
				getDataCnt = 0;
				step = 0x02;										//转到数据处理输出
			}else{
				step = 0x00;	
			}
			break;
			
		case 0x02:
			ir_Distance1 = IR_DataProcessing(IR_DistanceDataBuf, IR_GetDataCount, 0);	
// 			printf("\r\nNo1 ---> %3.1f cm\r\n",(float)ir_Distance1);
			ir_dataOutState1 = 1;
			step = 0x00;
			break;
			
		default:
			step = 0x00;
			break;
	}
}

/*
***********************************************************************
*	函 数 名: IR_GetDistanceTask_02
*	功能说明: 获取红外测距任务
*	形    参：无
*	返 回 值: 数据处理状态  1：已处理完成可以输出、0：尚未处理完成
***********************************************************************
*/
void IR_GetDistanceTask_02(void)
{
	static uint8_t step = 0x00;
	static uint8_t getDataCnt = 0x00;
	
	static uint8_t newValue = 0x00;
	static uint8_t oleValue = 0x00;
	static uint8_t IR_DistanceDataBuf[IR_GetDataCount];
	
	static timer waitingTimer;
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&waitingTimer, 1);
	}
	
	switch(step)
	{
		case 0x00:
			if(timer_expired(&waitingTimer))
			{
				newValue = IR_GetDistanceData(2);
// 				printf("\r\nValue = %3.1f cm\r\n",(float)newValue);
				step = 0x01;
				timer_restart(&waitingTimer);
			}
			break;
		case 0x01:
			if(DifferenceCompare(newValue, oleValue, 10))		//比较新旧值的差值，（当前值 - 之前值）> 设定值时重新采集数据
			{
				getDataCnt = 0;
			}
// 			printf("\r\nCnt2 = %d, newValue = %d, oleValue = %d\r\n", getDataCnt, newValue, oleValue);
			oleValue = newValue;
			
			IR_DistanceDataBuf[getDataCnt] = newValue;
			getDataCnt++;
			if(IR_GetDataCount == getDataCnt)							//10次数据都相差不大，则认为数据已经稳定可以输出
			{
				getDataCnt = 0;
				step = 0x02;										//转到数据处理输出
			}else{
				step = 0x00;	
			}
			break;
			
		case 0x02:
			ir_Distance2 = IR_DataProcessing(IR_DistanceDataBuf, IR_GetDataCount, 0);	
// 			printf("\r\nNo2 ---> %3.1f cm\r\n",(float)ir_Distance2);
			ir_dataOutState2 = 1;
			step = 0x00;
			break;
			
		default:
			step = 0x00;
			break;
	}
}

// /*
// ***********************************************************************
// *	函 数 名: IR_GetDistanceTask
// *	功能说明: 红外测距任务
// *	形    参：无
// *	返 回 值: 无
// ***********************************************************************
// */
// void IR_GetDistanceTask(void)
// {
// 	static uint8_t ULT_getDataStatus = 0x00;
// 	
// 	static uint8_t distance_1 = 255;
// 	static uint8_t distance_2 = 255;
// 	
// 	static timer waitingTimer;
// 	static timer responsTimer;
// 	static uint8_t timer_ok = 0;
// 	
// 	if(timer_ok == 0)
// 	{
// 		timer_ok = 1;
// 		timer_set(&waitingTimer, CLOCK_SECOND*2);
// 		timer_set(&responsTimer, 3);
// 	}
// 	
// 	switch(ULT_getDataStatus)
// 	{
// 		case 0x00:
// 			if(timer_expired(&waitingTimer))
// 			{
// 				ULT_getDataStatus = 0x01;
// 			}
// 			break;
// 			
// 		case 0x01:
// 			distance_1 = IR_GetDistanceData(1);
// // 			if(dataOutState1 == 1)			//第一路测距数据采集成功
// // 			{
// // 				dataOutState1 = 0;
// 				ULT_getDataStatus = 0x02;
// // // 				printf("\r\n第1路采集OK\r\n");
// // 			}
// 			break;
// 			
// 		case 0x02:
// 			distance_2 = IR_GetDistanceData(2);
// // 			if(dataOutState2 == 1)			//第一路测距数据采集成功
// // 			{
// // 				dataOutState2 = 0;
// 				ULT_getDataStatus = 0x03;
// // // 				printf("\r\n第2路采集OK\r\n");
// // 			}
// 			break;
// 			
// 		case 0x03:
// 			getDistance1 = distance_1;
// 			getDistance2 = distance_2;
// 			
// // 			printf("\r\n测距：No1 = %3.1f cm, ", (float)distance_1);
// // 			printf("No2 = %3.1f cm\r\n", (float)distance_2);
// // 			printf("No3 = %3.1f cm, ", (float)distance3);
// // 			printf("No4 = %3.1f cm\r\n", (float)distance4);
// 			ULT_getDataStatus = 0x00;
// 			timer_restart(&waitingTimer);
// 			break;
// 	}
// }

/******************** (C) COPYRIGHT 2017 CXHY *****END OF FILE*******************/
