




/**
  ******************************************************************************
  * @file    BLV_485_Dev_LEDFun.c
  * @author  BLW RCU  development Team
  * @version SongHan
  * @date    2021年12月24日
  * @brief  
	*    C7T滑动条调光 默认为4路   
  ******************************************************************************
  */



#include "BLV_485_Dev_SliderFun.h"



#include "string.h"
#include "SPI_SRAM.h"
#include "usart.h"
#include "check_fun.h"
#include "DBG.h"
#include "rw_logging.h"
#include "SRAM_Variable_Address.h"

#include "includes.h"


/*Slider调光驱动代码*/
#define SLIDER_OUT_CH_MAX  0x03   //Slider调光有3路

#define REPEATSENDTIMEMAX         0x03  //重发次数上限
#define SliderUPLIGHT              100    //最高亮80
#define SliderDOWNLIGHT            0    //最低亮20

#define SliderGRADUALTIME         30   //30  即300ms

#define BLW_Rs485_Slider_3_Num     0x03     //滑动条的回路数

#define BLW_RS485_SLIDER_STATE_UP  0x53     //状态上报

#define BLW_RS485_SLIDER_CTRL      0x56     //反馈灯控制

#define SliderSnMin               0      //最小Sn号
#define SliderSnMax               15     //最大Sn号

//#define DEVSliderTYPE               03           //Slider类型  

/*整体调光宏定义开始*/
#define GLOBAL_STEP_VALUE   0x14   //步进20
#define GLOBAL_MAX_VALUE    0x64   //最大亮度
#define GLOBAL_MIN_VALUE    0x14   //最小亮度

/*整体调光宏定义结束*/

/*本地函数调用开始*/
uint8_t BLW_SliderCycleCtrl(uint32_t dev_addr);           //发送
uint8_t BLW_Rs485_Slider_Check(uint32_t dev_addr,uint32_t data_addr,uint16_t len);  //接收
void BLW_Rs485_Slider_Ctrl(Device_Public_Information_G *BUS_Public, RS485_LED_INFO* Rs485SliderInfo);      //状态控制
void BLW_Rs485_Slider_Way_Ctrl(Device_Public_Information_G *BUS_Public, RS485_LED_INFO* Rs485LEDInfo);  //方式控制
void BLW_Rs485_Slider_Read(Device_Public_Information_G *BUS_Public, RS485_LED_INFO* Rs485LEDInfo);   //读取当前亮度

uint8_t Dev_Slider_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType);

void BLW_Slider_RecAsk(uint8_t *data, uint8_t DataLen, Device_Public_Information_G *BUS_Public);
void BLW_Slider_Rs485_Swi_Pro(uint8_t *data, RS485_LED_INFO *Rs485LED,uint32_t dev_addr);

/*本地函数调用结束*/

/*******************************************************************************
* Function Name  : BLW_RS485_Slider_Data_Init 
* Description    : 添加设备到链表 - 轮询设备
* Input          : 
	type	: 添加的设备类型
	addr	: 添加的设备地址
	polling_cf		：设备的轮询数据发送回调函数
	processing_cf	：设备的数据处理回调函数
* Return         : None
*******************************************************************************/
void BLW_RS485_Slider_Data_Init(Device_Public_Information_G *BUS_Public, RS485_LED_INFO *Rs485LED, uint16_t LoopNum)
{
	BUS_Public->polling_cf = (uint32_t)&BLW_SliderCycleCtrl;
	BUS_Public->processing_cf = (uint32_t)&BLW_Rs485_Slider_Check; 
	
	BUS_Public->DevFunInfo.Dev_Input_Type_Get = Dev_Slider_InType_Get;
	BUS_Public->DevFunInfo.Dev_Output_Ctrl = NULL;
	if(LoopNum >= SLIDER_OUT_CH_MAX)   //输出回路超过范围
	{
		Rs485LED->LEDLoopValidNum = SLIDER_OUT_CH_MAX;
	}
	else if(0x00 == LoopNum)
	{
		Rs485LED->LEDLoopValidNum = 0x01;
	}
	else              //未超过范围
	{
		Rs485LED->LEDLoopValidNum = LoopNum;
	}
	
	Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"添加Slider设备，回路:%d", Rs485LED->LEDLoopValidNum);

	

//	Add_POLL_Device_To_List2(BUS_Public,(uint8_t *)Rs485LED,sizeof(RS485_LED_INFO));
}




/*******************************************************************************
* Function Name  : BLW_LEDCycleCtrl 
* Description    : BLWLED调光轮询兼控制发送函数
*******************************************************************************/
uint8_t BLW_SliderCycleCtrl(uint32_t dev_addr) 
{
	uint8_t i;     //用于遍历所有回路
	uint8_t Ret = RS485OCCUPYNOTIME;
	Device_Public_Information_G BUS_Public;
	RS485_LED_INFO Rs485LEDInfo;
	uint8_t KeepFlag = 0x00;
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);	//拷贝所有共有数据
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485LEDInfo,sizeof(RS485_LED_INFO),dev_addr+Dev_Privately);
	
	for(i = 0; i < Rs485LEDInfo.LEDLoopValidNum; i++)
	{
		if(Rs485LEDInfo.DevSendBuf_last[i] != Rs485LEDInfo.DevSendBuf[i])
		{
			Rs485LEDInfo.LEDCtrlFlag = 0x01;
			Rs485LEDInfo.LEDCtrlCnt = REPEATSENDTIMEMAX;
			memcpy(Rs485LEDInfo.DevSendBuf_last, Rs485LEDInfo.DevSendBuf, Rs485LEDInfo.LEDLoopValidNum);   //同步这组数据
			break;
		} 
	}
	
	for(i = 0; i < Rs485LEDInfo.LEDLoopValidNum; i++)
	{
		if(Rs485LEDInfo.DevRecBufLast[i] != Rs485LEDInfo.DevRecBuf[i])
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"滑动条产生变化：回路:%d, 亮度:%d!!",i, Rs485LEDInfo.DevRecBuf[i]);
			if(Rs485LEDInfo.DevRecBuf[i] > Rs485LEDInfo.DevRecBufLast[i])
			{
				Rs485LEDInfo.DevReadBuf[i] = 0x01;                //调光回路变化
			}	
			else
			{
				Rs485LEDInfo.DevReadBuf[i] = 0x02;                //调光回路变化
			}
			
			Rs485LEDInfo.DevRecBufLast[i] = Rs485LEDInfo.DevRecBuf[i];
			
			KeepFlag = 0x01;   
		}
	}

	if(0x01 == Rs485LEDInfo.LEDCtrlFlag)
	{
		if(0x00 != Rs485LEDInfo.LEDCtrlCnt)
		{
			Rs485LEDInfo.LEDCtrlCnt--; 
		}
		else
		{
			Rs485LEDInfo.LEDCtrlFlag = 0x00;
		}
		BLW_Rs485_Slider_Ctrl(&BUS_Public, &Rs485LEDInfo);           //状态控制
		Ret = RS485OCCUPYTIME;
	}
	
	if(RS485OCCUPYTIME == Ret)
	{
		KeepFlag = 0x01;
		if(Rs485LEDInfo.DevSendCnt > REPEATSENDTIMEMAX)
		{
			if(Rs485LEDInfo.DevOffline != DEV_IS_OFFLINE)
			{	
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Rs485Slider DEV_IS_OFFLINE");
				LOG_Device_Online_Record(DEV_LEDTYPE,BUS_Public.addr,LogInfo_Device_Offline);	//记录设备离线
			}
			Rs485LEDInfo.DevOffline = DEV_IS_OFFLINE;   //离线
			if(Rs485LEDInfo.DevOffline != Rs485LEDInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
			{
				Rs485LEDInfo.DevOfflineLast = Rs485LEDInfo.DevOffline;	//更新上一次在线状态
				Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
			}
		}
		else
		{
			Rs485LEDInfo.DevSendCnt++;   //
		}
		
		/*通讯统计*/
		BLV_Communication_Record(&Rs485LEDInfo.comm_record,0x01,0x00);
		//Rs485LEDInfo.inquire_tick = SysTick_1ms; 		//有轮询数据，才要这时间戳
	}
	
	if(0x01 == KeepFlag)
	{
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485LEDInfo, sizeof(RS485_LED_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&Rs485LEDInfo,sizeof(RS485_LED_INFO),dev_addr+Dev_Privately);
	

		//Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"LED crc_val:%02X\r\n",crc_val);
	}

	return Ret;
}

void BLW_Slider_RecAsk(uint8_t *data, uint8_t DataLen, Device_Public_Information_G *BUS_Public)
{
	uint8_t SendBuf[6];
	
	memcpy(SendBuf, data, DataLen);
	
	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"滑动条发送数据,端口:%d!!", BUS_Public->port);
	
	MCU485_SendString(BUS_Public->port,SendBuf,DataLen);
}
/*BLW_Slider接收判断*/
void BLW_Slider_Rs485_Swi_Pro(uint8_t *data, RS485_LED_INFO *Rs485LED,uint32_t dev_addr)
{
	uint8_t i;
	Device_Public_Information_G BUS_Public;
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);
	if(Rs485LED->DevOffline != DEV_IS_ONLINE)
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Rs485LED DEV_IS_ONLINE");
		LOG_Device_Online_Record(DEV_LEDTYPE,SRAM_Read_Byte(dev_addr+Dev_Addr),LogInfo_Device_Online);	//记录设备在线
	}
	Rs485LED->DevSendCnt = 0x00;                                     //收到回复就清计数
	Rs485LED->DevOffline = DEV_IS_ONLINE;    //设备在线
	if(Rs485LED->DevOffline != Rs485LED->DevOfflineLast)	//当前在线状态不等于上一次在线状态
	{
		Rs485LED->DevOfflineLast = Rs485LED->DevOffline;	//更新上一次在线状态
		Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
	}
	BLV_Communication_Record(&Rs485LED->comm_record,0x02,0x01);		//记录通讯成功
	
	switch(data[1])   //读
	{
		case BLW_RS485_SLIDER_STATE_UP: 		 //状态上报
			for(i = 0x00; i < Rs485LED->LEDLoopValidNum; i++)
			{
				Rs485LED->DevRecBuf[i] = data[2+i];
			}
			break;
		case BLW_RS485_SLIDER_CTRL:    //控制回复
			Rs485LED->LEDCtrlFlag = 0x00;   
			break;
		default:
			
			break;
	}
}


#define RECDATALENMAX  (BLW_Rs485_Slider_3_Num+3)
#define IsMyData     0x00
#define IsNotMyData  0x01
/*******************************************************************************
* Function Name  : BLW_Rs485_LED_Check 
* Description    : BLWLED调光接收数据处理函数
* Input          : 
	dev_addr	: 设备信息地址
	data_addr	: 数据地址
	len			：数据长度
* Return         : 
	0x00：处理成功
	0x01：处理失败
*******************************************************************************/
uint8_t BLW_Rs485_Slider_Check(uint32_t dev_addr,uint32_t data_addr,uint16_t len)
{
	//Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"BLW_Rs485_LED_Check\r\n");
	uint8_t rev = IsNotMyData;
	uint8_t data[RECDATALENMAX];	
	RS485_LED_INFO Rs485LED;
	Device_Public_Information_G BUS_Public;
	uint8_t crc_val;  //校验
	
	if(len > RECDATALENMAX)
	{
//		Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"滑动条接收数据长度超出范围!!\r\n");
		return rev;     //长度
	}	
//	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"滑动条接收处理判断");

	SRAM_DMA_Read_Buff(data,len,data_addr);   //拷贝485数据
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);		
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485LED,sizeof(RS485_LED_INFO),dev_addr+Dev_Privately);
		
//	uint8_t LED_addr = SRAM_Read_Byte(dev_addr+Dev_Addr);  //485地址
//	uint8_t crc_val = data[len];        //保存校验
	
	if((data[0] != BUS_Public.addr) || (len != Rs485LED.LEDLoopValidNum+3))	   //地址不对 或者回路数不对
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"滑动条 地址不对或回路数不对，地址:%d,地址:%d RCU本地回路数:%d 外设回路数:%d!!",BUS_Public.addr, data[0], Rs485LED.LEDLoopValidNum, (len-3));
		return rev;				//校验文件头
	}
//	Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"滑动条地址判断通过");

	crc_val = SOR_CRC(data, len-1);  //和校验data[DataLen-1];

	
	if(crc_val == data[len-1])   //校验通过
	{
//		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"滑动条校验判断通过");
		switch(data[1])
		{
			case BLW_RS485_SLIDER_STATE_UP:   //按键上报
				BLW_Slider_RecAsk(data, len, &BUS_Public);    
			case BLW_RS485_SLIDER_CTRL:   //反馈灯控制
				rev = IsMyData;
				BLW_Slider_Rs485_Swi_Pro(data, &Rs485LED,dev_addr);
			
				/*日志记录*/
				LOG_Device_COMM_Control_Reply_Record(BUS_Public.port,BUS_Public.baud,data,len);
				break;
		}
		if(IsMyData == rev)  //自己的数据就保存
		{
			BUS_Public.check = 0x00;
			BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485LED, sizeof(RS485_LED_INFO));
			SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
			SRAM_DMA_Write_Buff((uint8_t *)&Rs485LED,sizeof(RS485_LED_INFO),dev_addr+Dev_Privately);
		
		}
	}
//	else {
//		Dbg_Print(DBG_BIT_DEVICE_STATUS_bit,"滑动条 SOR_CRC Fail ,crc_val:%02X SOR_CRC:%02X!!\r\n",crc_val,data[len-1]);
//		
//	}
	
	return rev;
}




#define SliderCTRLSENDLEN     (BLW_Rs485_Slider_3_Num+0x03)      //发送数组长度为回路数加3  最大长度
/**
	* @name BLW 4路 集中调光控制函数
	* @para
	*   dev_addr     设备起始地址   
	* @return         无
  * @attention      发送循环里调用，变量已经被判断
	*/
void BLW_Rs485_Slider_Ctrl(Device_Public_Information_G *BUS_Public, RS485_LED_INFO* Rs485LEDInfo)
{
//	uint8_t i;
	uint8_t SendLen;
	                                        //地址  命令  光圈寄存器
	uint8_t SendBuf[SliderCTRLSENDLEN];  // = {0x01, BLW_RS485_SLIDER_CTRL, 0x00, 0x00, 0x00};  //定义7个字节数组
	SendLen = Rs485LEDInfo->LEDLoopValidNum+0x03;

	SendBuf[0] = BUS_Public->addr;   // 
	SendBuf[1] = BLW_RS485_SLIDER_CTRL;
	memcpy(&SendBuf[2], Rs485LEDInfo->DevSendBuf, Rs485LEDInfo->LEDLoopValidNum);
	
	SendBuf[SendLen-1] = SOR_CRC(SendBuf,SendLen-1);

//	memcpy(&SendBuf[14], &Rs485LEDInfo->DevSendBuf[0], Rs485LEDInfo->LEDLoopValidNum);  //指示灯控制
//	SendBuf[5] = CheckSum_Overlook_Check(SendBuf, SliderCTRLSENDLEN, 5);	
		
	MCU485_SendString(BUS_Public->port,SendBuf,SendLen);

	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record(BUS_Public->port,BUS_Public->baud,SendBuf,SendLen);
}


/**
*@name 开关输入检测函数
*@para
*  DevAddr      设备地址
*  DevInputLoop 回路输入地址  范围1~LED_OUT_CH_MAX  
*  DevInputType 输入类型
*/

uint8_t Dev_Slider_InType_Get(uint32_t DevAddr, uint16_t DevInputLoop, uint16_t DevInputType)
{
	Device_Public_Information_G BUS_Public;
	RS485_LED_INFO Rs485LEDInfo;
	uint8_t Ret = CtrlInvalid;         //控制无效
	
	
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAddr);				
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485LEDInfo,sizeof(RS485_LED_INFO),DevAddr+Dev_Privately);/*拷贝设备私有信息*/
	
	if(DevInputLoop >= Rs485LEDInfo.LEDLoopValidNum)
	{
		return Ret;
	}
	
	if(DevInputType == Rs485LEDInfo.DevReadBuf[DevInputLoop])
	{
		Dbg_Println(DBG_BIT_LOGIC_STATUS_bit,"滑动条动作清空：%04X  Event:%04X",DevInputType,Rs485LEDInfo.DevReadBuf[DevInputLoop]);
		
		Rs485LEDInfo.DevReadBuf[DevInputLoop] = KeyNoAction;
		Ret = CtrlValid;
	
		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485LEDInfo, sizeof(RS485_LED_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAddr);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&Rs485LEDInfo,sizeof(RS485_LED_INFO),DevAddr+Dev_Privately);

	}
	
	return Ret;
}







