/*************************** (C) COPYRIGHT 2020 Ping ****************************
 * 文件名  ：m_s_comm.c
 * 描  述  ：主从MCU通讯处理程序
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2020/03/31
*********************************************************************************/
#include "m_s_comm.h"
#include "device.h"
#include "data_typedef.h"
//#include "distancer.h"

uint8_t M_S_RX_BUF[M_S_RECV_LEN];     		//接收缓冲
uint8_t M_S_TX_BUF[M_S_SEND_LEN];					//发送缓冲

static void M_S_DataDecode(uint8_t *pRxBuf, uint8_t *pTxBuf);

static uint8_t CorrectOverflowDistance(uint8_t rawDistance, uint16_t channelWeight,
																			uint8_t maxVal, uint8_t depthVal)
{
	uint16_t correctedDistance;
	uint16_t measureStart;

	if(rawDistance == 255)
	{
		return 255;
	}

	correctedDistance = (uint16_t)rawDistance + 15;
	measureStart = maxVal - (((uint16_t)depthVal * PerCentSetVal) / 100);

	if(correctedDistance > measureStart)
	{
		correctedDistance = maxVal;
	}

	if((channelWeight < 1700) && (correctedDistance < 75))
	{
		correctedDistance = maxVal;
	}

	return (uint8_t)correctedDistance;
}

/*
***********************************************************************
*	函 数 名: M_S_DataPackingAndSend
*	功能说明: 主从机通讯数据打包及发送
*	形    参:	*pdata -> 需要打包的数据地址，dataLen -> 数据长度
*	返 回 值: 无
***********************************************************************
*/
void M_S_DataPackingAndSend(uint8_t *pdata, uint16_t dataLen)
{
	uint8_t i;
	uint8_t CS = 0x68;
	uint8_t TX_Size = 0;
	
	uint8_t sendDataBuf[128];
	uint8_t dataAddrIndex = 0;
	uint8_t sendDataLen = 0;
	
	sendDataBuf[dataAddrIndex++] = 0xfe; 			//发送前导字节
	sendDataBuf[dataAddrIndex++] = 0xfe; 			
	sendDataBuf[dataAddrIndex++] = 0xfe; 		
	sendDataBuf[dataAddrIndex++] = 0x68; 			//发送帧头
	
	sendDataBuf[dataAddrIndex++] = *pdata; 		//发送地址
	CS += *pdata;
	sendDataBuf[dataAddrIndex++] = 0x68; 			//发送帧头
	CS += 0x68;
	sendDataBuf[dataAddrIndex++] = *(pdata+1); 	//发送帧命令
	CS += *(pdata+1);
	TX_Size = *(pdata+2);											//取出通讯数据长度
	sendDataBuf[dataAddrIndex++] = TX_Size; 	//发送数据长度
	CS += *(pdata+2);
	for(i=0; i<TX_Size; i++) 									//加载发送数据
	{
		sendDataBuf[dataAddrIndex++] = *(pdata+i+3);
		CS += (*(pdata+i+3));
	}
	sendDataBuf[dataAddrIndex++] = CS; 				//发送校验字节
	sendDataBuf[dataAddrIndex++] = 0x16; 			//发送帧尾
	
	sendDataLen = dataAddrIndex;
	
// 	showHex(sendDataBuf, sendDataLen);

	USART2_SendFrameData(sendDataBuf, sendDataLen);
}

/*
***********************************************************************
*	函 数 名: M_S_CommandSend
*	功能说明: 从机向主机发送数据通讯命令
*	形    参:	comNum -> 指令号
*	返 回 值: 无
***********************************************************************
*/
void M_S_CommandSend(uint8_t comNum)
{
	uint8_t dataLen = 0;												//打包后的协议总长度
	uint8_t dataIndex = 0;											//发送的数据下标索引
	
	M_S_TX_BUF[0] = 0x00; 											//设置通讯地址
	M_S_TX_BUF[1] = comNum;											//存入命令码
	
	dataIndex += 3;															//从地址、命令、长度后开始算起
	
	printf("\r\nM->S --> 0x%02X\r\n", comNum);
	
	switch(comNum)
	{
		case 0x01:

			break;
			
		case 0xA1:		//启动称盘校准
			M_S_TX_BUF[dataIndex++] = scaleNum;
			break;
			
		case 0xA5:		//发送称盘校准失败
			break;
		
		default:
			break;
	}
	
	//存入通信数据长度
	M_S_TX_BUF[2] = dataIndex - 3;									//存入通讯数据长度字节
	dataLen = dataIndex;
	
//	printf("\r\nlen = %d\r\n", dataLen);
	M_S_DataPackingAndSend(M_S_TX_BUF, dataLen); 		//按指定规则打包数据然后发送
}

/*
***********************************************************************
*	函 数 名: OverflowDataCorrection1
*	功能说明: 满溢数据修正
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
static void OverflowDataCorrection1(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static uint16_t preweight = 0;
	uint16_t tempDate = 0;
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if((weight1 > 2000) && (getDistance1) < 65)				//满溢超过90%，且重量达到10kg,则强行就数据进行修正，直到重量变轻为5kg以下
			{
				printf("\r\nNo.1开始数据修正！\r\n");
				
				preweight = weight1;
				getDistance1 = 55;
				nextStatus = 0x01;
				break;
			}
			break;
			
		case 0x01:
			if(weight1 < preweight)
			{
				tempDate = preweight - weight1;
			}else{
				tempDate = 0;
			}
			
			if(tempDate > 500)			//重量变轻（即收运拉出内桶）
			{
				
				printf("\r\nNo.1数据取消修正！\r\n");
				nextStatus = 0x00;
				break;
			}else{
				getDistance1 = 55;
			}
			break;
			
		default:
			nextStatus = 0x00;
			break;
	}
}

/*
***********************************************************************
*	函 数 名: OverflowDataCorrection1
*	功能说明: 满溢数据修正
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
static void OverflowDataCorrection2(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static uint16_t preweight = 0;
	uint16_t tempDate = 0;
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if((weight2 > 2000) && (getDistance2) < 65)				//满溢超过90%，且重量达到10kg,则强行就数据进行修正，直到重量变轻为5kg以下
			{
				printf("\r\nNo.2开始数据修正！\r\n");
				
				preweight = weight2;
				getDistance2 = 55;
				nextStatus = 0x01;
				break;
			}
			break;
			
		case 0x01:
			if(weight2 < preweight)
			{
				tempDate = preweight - weight2;
			}else{
				tempDate = 0;
			}
			
			if(tempDate > 500)		//重量变轻（即收运拉出内桶）
			{
				printf("\r\nNo.2数据取消修正！\r\n");
				nextStatus = 0x00;
				break;
			}else{
				getDistance2 = 55;
			}
			break;
			
		default:
			nextStatus = 0x00;
			break;
	}
}


/*
***********************************************************************
*	函 数 名: M_S_DataDecode
*	功能说明: 主从机通讯数据解析
*	形    参:	*pRxBuf -> 接收缓存的地址，*pTxBuf -> 发送数据缓存地址 
*	返 回 值: 无
***********************************************************************
*/
static void M_S_DataDecode(uint8_t *pRxBuf, uint8_t *pTxBuf)
{
	uint8_t comNum = 0;							//主从机指令码
	
	comNum = *(pRxBuf+1);
	
// 	printf("\r\nS->M <-- 0x%02X\r\n", comNum);
	switch(comNum)														//通讯命令译码
	{			
		case 0x01:			//收到从机MCU2发送过来的称重、测距、光电开关状态数据
			weight1 = *(pRxBuf+3) << 8;
			weight1 |= *(pRxBuf+4);
		
			weight2 = *(pRxBuf+5) << 8;
			weight2 |= *(pRxBuf+6);
		
			weight3 = *(pRxBuf+7) << 8;
			weight3 |= *(pRxBuf+8);
		
			weight4 = *(pRxBuf+9) << 8;
			weight4 |= *(pRxBuf+10);
			
			//测距数据
			//根据硬件接口连接线顺序进行转换
#ifdef FOUR_CHANNEL_AND_HARMFUL
//------------------------------------------------------------------->			

			if(updateDistanceMark == 0)		//投放过程不更新测距值
			{
				getDistance1 = CorrectOverflowDistance(*(pRxBuf+11), weight1,
																							 devChannel1DisMaxVal, devChannel1DisDepthVal);
				getDistance2 = CorrectOverflowDistance(*(pRxBuf+12), weight2,
																							 devChannel2DisMaxVal, devChannel2DisDepthVal);
				getDistance3 = CorrectOverflowDistance(*(pRxBuf+13), weight3,
																							 devChannel3DisMaxVal, devChannel3DisDepthVal);
				getDistance4 = CorrectOverflowDistance(*(pRxBuf+14), weight4,
																							 devChannel4DisMaxVal, devChannel4DisDepthVal);

				outputDistance1 = getDistance1;
				outputDistance2 = getDistance2;
				outputDistance3 = getDistance3;
				outputDistance4 = getDistance4;

				printf("\r\nGet D1=%d, D2=%d, D3=%d, D4=%d\r\n",
							 getDistance1, getDistance2, getDistance3, getDistance4);
			}
//<-------------------------------------------------------------------
			
			//测距数据经过补尝
//			if(updateDistanceMark == 0)		//投放过程不更新测距值
//			{
//				tempData1 = *(pRxBuf+11);
//				tempData2 = *(pRxBuf+12);
//				
//				//取出第1路测距数据
//				if(tempData1 == 255)
//				{
//					getDistance1 = 255;
//				}else{
//					tempData1 += 35;					//根据安装高度补偿距离值
//					
//					if(tempData1 > distanceParamAtStart)
//					{
//						getDistance1 = devChannel1DisMaxVal;
//					}else{
//						getDistance1 = tempData1;
//					}
//				}
//				
//				//20230727修改，满溢数据修正
//				OverflowDataCorrection1();
//				
//				if((weight1 < 1500) && (getDistance1) > 80)
//				{
//					getDistance1 = devChannel1DisMaxVal;
//				}
//				
//				//20230524修改，换红外传感器及调整安装高度不做多次采集处理
//				outputDistance1 = getDistance1;
//				
////				distanceBuf1[distanceCnt1++] = getDistance1;
////				if(distanceCnt1 >= DISTANCE_CNT_MAX)
////				{
////					distanceCnt1 = DISTANCE_CNT_MAX - 1;
////					printf("\r\nCnt1 >= MAX\r\n");
////				}
//				
//				//取出第2路测距数据
//				if(tempData2 == 255)
//				{
//					getDistance2 = 255;
//				}else{
//					tempData2 += 35;					//根据安装高度补偿距离值
//					
//					if(tempData2 > distanceParamAtStart)
//					{
//						getDistance2 = devChannel1DisMaxVal;
//					}else{
//						getDistance2 = tempData2;
//					}
//				}
//				
//				//20230727修改，满溢数据修正
//				OverflowDataCorrection2();
//				
//				if((weight2 < 1500) && (getDistance2) > 80)
//				{
//					getDistance2 = devChannel2DisMaxVal;
//				}
//				
//				//20230524修改，换红外传感器及调整安装高度不做多次采集处理
//				outputDistance2 = getDistance2;
//				
////				distanceBuf2[distanceCnt2++] = getDistance2;
////				if(distanceCnt2 >= DISTANCE_CNT_MAX)
////				{
////					distanceCnt2 = DISTANCE_CNT_MAX - 1;
////					printf("\r\nCnt2 >= MAX\r\n");
////				}
//				
//				
//				getDistance3 = *(pRxBuf+13);
//				getDistance4 = *(pRxBuf+14);
//				
//				printf("\r\nGet D1=%d, D2=%d\r\n", getDistance1, getDistance2);
//			}
			
//			getDistance1 = *(pRxBuf+11);
//			getDistance2 = *(pRxBuf+12);
//			getDistance3 = *(pRxBuf+13);
//			getDistance4 = *(pRxBuf+14);
#else
			getDistance1 = *(pRxBuf+11);
			getDistance4 = *(pRxBuf+12);
			getDistance2 = *(pRxBuf+13);
			getDistance3 = *(pRxBuf+14);
#endif
			
			//主板温度
			temperature_C = *(pRxBuf+15);
			
			//收运门状态
			getRecycleClearDoorMark = *(pRxBuf+16);
			
			//外部温度
			temperature_A = *(pRxBuf+17);
			
			//接近开关状态
			switchKey1Status = *(pRxBuf+18);
			switchKey2Status = *(pRxBuf+19);
			
			getMcu2SensorDataMark = 1;								//标志接收到数据，由外部读取后清除
			break;
		
		case 0x02:		//MCU2检测到的光电开关状态数据（用于当按键使用）
			optoKeyStatus = *(pRxBuf+3);
			break;
			
		case 0x03:		//GPS定位信息
			gpsConnectSta = *(pRxBuf+3);							//GPS模块硬件连接状态
			gpsStatus = *(pRxBuf+4);									//GPS定位状态
			gpsEW = *(pRxBuf+5);											//经度方向（0->E-东,W-西）
			gpsLon = *(pRxBuf+6) << 24;								//经度（已放大1000000倍）
			gpsLon |= *(pRxBuf+7) << 16;
			gpsLon |= *(pRxBuf+8) << 8;
			gpsLon |= *(pRxBuf+9);
			gpsNS = *(pRxBuf+10);											//纬度方向（0->N-北,1->S-南）
			gpsLat = *(pRxBuf+11) << 24;							//纬度（已放大1000000倍）
			gpsLat |= *(pRxBuf+12) << 16;
			gpsLat |= *(pRxBuf+13) << 8;
			gpsLat |= *(pRxBuf+14);
			
			getGpsStatus = 1;
			break;
			
		case 0xA2:		//取得校准零点
			receiveScaleNum = *(pRxBuf+3);
			switch(receiveScaleNum)
			{
				case 1:
					getCalibraZeroMark1 = 1;
					break;
					
				case 2:
					getCalibraZeroMark2 = 1;
					break;
					
				default:
					break;
			}
			
			break;
			
		case 0xA3:		//校准完成
			receiveScaleNum = *(pRxBuf+3);
			switch(receiveScaleNum)
			{
				case 1:
					getCalibraParamOkMark1 = 1;
					break;
					
				case 2:
					getCalibraParamOkMark2 = 1;
					break;
					
				default:
					break;
			}
			
			break;
			
		default: 			//其他命令
			break;
	}
}

/*
***********************************************************************
*	函 数 名: M_S_DataDecodeTask
*	功能说明: 主从机数据通讯解析处理任务
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void M_S_DataDecodeTask(void)
{
	if(USART2_RX_STA == 0xfd)													//有接收到主机发送的数据
	{
		M_S_DataDecode(USART2_RX_BUF, USART2_TX_BUF); 	//解释返回的数据
		
		memset(USART2_RX_BUF, 0x00, USART2_RECV_LEN);		//清除缓存内容
		USART2_RX_STA = 0;
	}
}

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