/*************************** (C) COPYRIGHT 2017 Ping ****************************
 * 文件名  ：scale.c
 * 描  述  ：称驱动程序    
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2017/03/06 
*********************************************************************************/
#include "usart1.h"
#include "scale.h"
#include "timer.h"
#include "usart4.h"
#include "usart5.h"
#include "m_s_comm.h"

//秤电源输出控制引脚定义
#define SCALE_POWER_PerClock			RCC_APB2Periph_GPIOA
#define SCALE_POWER_PORT					GPIOA		
#define SCALE_POWER_PIN						GPIO_Pin_1

uint16_t weight1 = 0;									//第一路秤所称得的重量，放大100倍，单位kg
uint16_t weight2 = 0;
uint16_t weight3 = 0;
uint16_t weight4 = 0;

uint8_t calibrationScaleNum = 0;		//校准称盘编码
uint8_t sendScaleNum = 0;						//发送称盘编码
uint8_t calibrationErrorMark = 0;		//校准称盘失败

uint8_t weightingState1 = 0;					//称重的状态，当为1时表示收到称重，由外部程序读取后清除
uint8_t weightingState2 = 0;
uint8_t weightingState3 = 0;
uint8_t weightingState4 = 0;		


uint8_t getCalibraDataMark1 = 0;			//取得校准指令数据
uint8_t getCalibraZeroMark1 = 0;			//取得校准零点
uint8_t getCalibraParamOkMark1 = 0;		//取得校准完成

uint8_t getCalibraDataMark2 = 0;
uint8_t getCalibraZeroMark2 = 0;
uint8_t getCalibraParamOkMark2 = 0;

uint8_t calibrationParam1[16];		//校准时接收到的数据
uint8_t calibrationParam2[16];

void ScaleCmdRun1(uint8_t* pRxBuf);
void ScaleCmdRun2(uint8_t* pRxBuf);
void ScaleCmdDecodeTask(void);

/*
***********************************************************************
*	函 数 名: Scale_Init
*	功能说明: 称 电源控制IO口初始化
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void ScaleInit(void)
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(SCALE_POWER_PerClock, ENABLE);			//使能时钟

	//秤电源输出控制引脚配置
	GPIO_InitStructure.GPIO_Pin = SCALE_POWER_PIN;				 				
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(SCALE_POWER_PORT, &GPIO_InitStructure);
	
	GPIO_ResetBits(SCALE_POWER_PORT, SCALE_POWER_PIN);
	
	//打开秤电源
	ScalePowerON(1);
}

/*
***********************************************************************
*	函 数 名: ScalePowerON
*	功能说明: 打开称电源
*	形    参：选择哪一路秤称电源打开
*	返 回 值: 无
***********************************************************************
*/
void ScalePowerON(uint8_t whichOne)
{
	switch(whichOne)
	{
		case 1:
			GPIO_SetBits(SCALE_POWER_PORT, SCALE_POWER_PIN);
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: ScalePowerOFF
*	功能说明: 关闭称电源
*	形    参：whichOne -> 选择哪一路秤称电源打开
*	返 回 值: 无
***********************************************************************
*/
void ScalePowerOFF(uint8_t whichOne)
{
	switch(whichOne)
	{
		case 1:
			GPIO_ResetBits(SCALE_POWER_PORT, SCALE_POWER_PIN);
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: WeightStrToHex
*	功能说明: 重量字符串数据转成16进制数字（放大100倍 ）
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
uint16_t WeightStrToHex(u8* data)
{
	uint16_t res = 0;
	
	res = (data[0] - 48)*10000 + (data[1] - 48)*1000 + (data[2] - 48)*100 + (data[4] - 48)*10 + (data[5] - 48);
	return res;
}

/*
***********************************************************************
*	函 数 名: WeightDetection1
*	功能说明: 第一路重量检测
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void WeightDetection1(void)
{
	if(USART3_RX_STA == 0xfd)
	{
		weight1 = WeightStrToHex(USART3_RX_BUF);		//取出当前秤所称得的总重量
		USART3_RX_STA = 0x00;
		weightingState1 = 1;												//标记已经收到重量数据，由外部程序读取后清除
	}
}

/*
***********************************************************************
*	函 数 名: WeightDetection2
*	功能说明: 第二路重量检测
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void WeightDetection2(void)
{
	if(USART1_RX_STA == 0xfd)
	{
		weight2 = WeightStrToHex(USART1_RX_BUF);		//取出当前秤所称得的总重量
		USART1_RX_STA = 0x00;
		weightingState2 = 1;												//标记已经收到重量数据，由外部程序读取后清除
	}
}

/*
***********************************************************************
*	函 数 名: WeightDetection3
*	功能说明: 第三路重量检测
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void WeightDetection3(void)
{
	if(USART4_RX_STA == 0xfd)
	{
		weight3 = WeightStrToHex(USART4_RX_BUF);		//取出当前秤所称得的总重量
		USART4_RX_STA = 0x00;
		weightingState3 = 1;												//标记已经收到重量数据，由外部程序读取后清除
	}
}

/*
***********************************************************************
*	函 数 名: WeightDetection4
*	功能说明: 第二路重量检测
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void WeightDetection4(void)
{
	if(USART5_RX_STA == 0xfd)
	{
		weight4 = WeightStrToHex(USART5_RX_BUF);		//取出当前秤所称得的总重量
		USART5_RX_STA = 0x00;
		weightingState4 = 1;												//标记已经收到重量数据，由外部程序读取后清除
	}
}

/*
***********************************************************************
*	函 数 名: GetWeight
*	功能说明: 取得秤上面的重量
*	形    参：无
*	返 回 值: 无（调用此函数后会改变全局变量currentWeight、currentWeight2）
***********************************************************************
*/
void GetWeight(void)
{
	if(weightingState1 == 1)									//有检测到投放重量，读取重量后清除
	{
		weightingState1 = 0;
		printf("\r\n当前秤1重量为：%2.2f Kg\r\n", (float)(weight1)/100);
	}
	if(weightingState2 == 1)								//有检测到投放重量，读取重量后清除
	{
		weightingState2 = 0;
		printf("\r\n当前秤2重量为：%2.2f Kg\r\n", (float)(weight2)/100);
	}
	
	if(weightingState3 == 1)								//有检测到投放重量，读取重量后清除
	{
		weightingState3 = 0;
		printf("\r\n当前秤3重量为：%2.2f Kg\r\n", (float)(weight3)/100);
	}
	
	if(weightingState4 == 1)								//有检测到投放重量，读取重量后清除
	{
		weightingState4 = 0;
		printf("\r\n当前秤4重量为：%2.2f Kg\r\n", (float)(weight4)/100);
	}
}

/*
***********************************************************************
*	函 数 名: GetWeight
*	功能说明: 取得秤上面的重量
*	形    参：无
*	返 回 值: 无（调用此函数后会改变全局变量currentWeight、currentWeight2）
***********************************************************************
*/
void SendCalibraCmd(uint8_t num)
{
	uint8_t cmd[10] = {0xfe, 0xfe, 0xfe, 0x68, 0x00, 0x68, 0xa1, 0x00, 0x71, 0x16};
	
	switch(num)
	{
		case 1:
			USART3_SendFrameData(cmd, 10);
			break;
			
		case 2:
			USART1_SendFrameData(cmd, 10);
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: ScaleCmdRun1
*	功能说明: 称盘校准指令执行
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void ScaleCmdRun1(uint8_t* pRxBuf)
{
	uint8_t proNum;
	
	proNum = *(pRxBuf+1);
	
	printf("\r\nS1 <-- 0x%02X\r\n", proNum);
	switch(proNum)														//通讯命令译码
	{			
		case 0xA2:		//收到校准零点
			getCalibraZeroMark1 = 1;
			sendScaleNum = 1;
			M_S_CommandSend(0xA2);
			break;
			
		case 0xA3:
			getCalibraParamOkMark1 = 1;
			sendScaleNum = 1;
			M_S_CommandSend(0xA3);
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: ScaleCmdRun2
*	功能说明: 称盘校准指令执行
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void ScaleCmdRun2(uint8_t* pRxBuf)
{
	uint8_t proNum;
	
	proNum = *(pRxBuf+1);
	
	printf("\r\nS2 <-- 0x%02X\r\n", proNum);
	switch(proNum)														//通讯命令译码
	{			
		case 0xA2:		//收到校准零点
			getCalibraZeroMark2 = 1;
			sendScaleNum = 2;
			M_S_CommandSend(0xA2);
			break;
			
		case 0xA3:
			getCalibraParamOkMark2 = 1;
			sendScaleNum = 2;
			M_S_CommandSend(0xA3);
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: ScaleCmdDecodeTask
*	功能说明: 称重模块操作指令解码任务
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void ScaleCmdDecodeTask(void)
{
	if(getCalibraDataMark1 == 1)										//有接收到数据
	{
		ScaleCmdRun1(calibrationParam1); 							//解释返回的数据
		getCalibraDataMark1 = 0;
	}
	
	if(getCalibraDataMark2 == 1)										//有接收到数据
	{
		ScaleCmdRun2(calibrationParam2); 							//解释返回的数据
		getCalibraDataMark2 = 0;
	}
}

void CalibrationErrorHandler(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static timer waitingTimer;
	
	static uint8_t timer_ok = 0;
	if(timer_ok == 0)
	{
		timer_ok = 1;
		
		timer_set(&waitingTimer, CLOCK_SECOND*1);
	}
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if(calibrationErrorMark == 1)
			{
				calibrationErrorMark = 0;
				
				printf("\r\n称盘校准失败!\r\n");
				ScalePowerOFF(1);
				timer_restart(&waitingTimer);
				nextStatus = 0x01;
				break;
			}
			break;
			
		case 0x01:
			if(timer_expired(&waitingTimer))
			{
				ScalePowerON(1);
				nextStatus = 0x00;
				break;
			}
			break;
			
		default:
			break;
			
	}
}

/*
***********************************************************************
*	函 数 名: WeightDetectionTask
*	功能说明: 重量检测任务
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void WeightDetectionTask(void)
{
	WeightDetection1();
	WeightDetection2();
	WeightDetection3();
	WeightDetection4();
	ScaleCmdDecodeTask();
	CalibrationErrorHandler();
}

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