/*
 * msp_OBD.c
 *
 *  Created on: Oct 26, 2023
 *      Author: shiya
 *      主要功能：
 *  	1.配置跳转进入bootloader
 *  	2.周期性上传GV
 *  		——每2ms上传一帧报文
 *  		——循环上传报文
 *  	3.配置GV上传选项
 *  		——可选择上传那一个元素
 *  		——默认不上传
 *  	4.设置CV的值(响应CAN总线)(单个写入)
 *  		——判断与之前数值不同，就写入到eeprom中
 *  	5.读取CV的值(响应CAN总线)(单个)
 *  	6.配置CV的值全部更新入EEPROM
 *  	8.从EEPROM读取CV的值
 *  		——在GF_MSP_OBD_Init()中执行读取更新

 *  	1. 0x110，
 *  		—— 1字节0x55，复位重新尝试进入bootloader；
 *  	2. 0x120，配置CV的值
 *  		—— 1-2字节，对应 CV Index，uint16_t
 *  		—— 3-6字节，对应CV的值
 *  	3. 0x121，请求读取CV的值
 *  		—— 1-2字节，对应 CV Index，uint16_t
 *  	4. 0x122，返回CV的值
 *  		—— 1-2字节，对应 CV Index，uint16_t
 *  		—— 3-6字节，对应CV的值
 *  	5. 0x130，配置GV的输出
 *  		—— 1-2字节，对应 GV Index，uint16_t
 *  		—— 3-4字节，对应 GV Index的长度，设置连续的GV输出
 *  		—— 5  字节，0为发送禁止，1为单次查询，2为周期性查询 uint8_t
 *  	6. 0x132，输出GV的值
 *  		—— 1-2字节，对应 GV Index，uint16_t
 *  		—— 3-6字节，对应GV的值
 */
#include "MSP/msp_OBD.h"
#include "BHBF_ROBOT.h"

#define DF_MSP_OBD_GV_Num (sizeof(GV)/4) //GV元素个数
#define DF_MSP_OBD_CV_Num (sizeof(CV)/4) //CV元素个数

#define DF_MSP_FDCAN_ID_Boot 0x110
#define DF_MSP_FDCAN_ID_SetCV 0x120
#define DF_MSP_FDCAN_ID_ReadCV 0x121
#define DF_MSP_FDCAN_ID_SendCV 0x122
#define DF_MSP_FDCAN_ID_ConfigGV 0x130
#define DF_MSP_FDCAN_ID_SendGV 0x132

uint32_t V_MSP_OBD_GVsend_Index; //循环上传GV的索引
uint8_t V_MSP_OBD_GVsend_EN[DF_MSP_OBD_GV_Num]; //是否上传对应的GV变量
uint8_t V_MSP_OBD_FDCAN_CH;

int32_t* P_MSP_OBD_Point_to_GV;
int32_t* P_MSP_OBD_Point_to_CV;

uint8_t MSP_OBD_Set_CV(uint32_t CV_Index,int32_t CV_Value);
uint8_t MSP_OBD_EE_Read_CV(uint32_t CV_Index,int32_t* CV_Value);
uint8_t MSP_OBD_EE_Write_CV(uint32_t CV_Index,int32_t CV_Value);
uint8_t MSP_OBD_CV_InitEE(void);
uint8_t MSP_OBD_CV_Update(void);

void MSP_OBD_Jump_Bootloader(void)
{
	HAL_NVIC_SystemReset();
}

uint8_t MSP_OBD_EE_Read_CV(uint32_t CV_Index,int32_t* CV_Value)
{
	uint8_t _u8array[4];
	int32_t* _i32point;
	if(GF_BSP_EEPROM_ReadBytes(_u8array, CV_Index*4, 4) != 1)
	{
		return 0;
	}
	_i32point = (int32_t*)&_u8array;
	*CV_Value = *_i32point;
	return 1;
}

uint8_t MSP_OBD_EE_Write_CV(uint32_t CV_Index,int32_t CV_Value)
{
	uint8_t* _u8array;
	_u8array=(uint8_t*)(&P_MSP_OBD_Point_to_CV[CV_Index]);
	return(GF_BSP_EEPROM_WriteBytes(_u8array, CV_Index*4, 4));
}

uint8_t GF_MSP_OBD_Init(uint8_t FDCAN_CH)
{
	V_MSP_OBD_FDCAN_CH = FDCAN_CH;
	P_MSP_OBD_Point_to_GV = (int32_t*)&GV;
	P_MSP_OBD_Point_to_CV = (int32_t*)&CV;

	memset(&V_MSP_OBD_GVsend_EN, 0, DF_MSP_OBD_GV_Num);

	V_MSP_OBD_GVsend_Index=0;

	if(GF_BSP_EEPROM_CheckOK() != 1)
	{
		return 0;
	}
	if(MSP_OBD_CV_Update() != 1)
	{
		return 0;
	}
	if(GF_BSP_Interrupt_Add_CallBack(DF_BSP_InterCall_FDCAN2_RxFifo0Callback,GF_MSP_OBD_Rx_CallBack) !=1)
	{
		return 0;
	}
	return 1;
}

//设置CV的值，如果不同就写入到eeprom中
uint8_t MSP_OBD_Set_CV(uint32_t CV_Index,int32_t CV_Value)
{
	if(CV_Index >= DF_MSP_OBD_CV_Num)
	{
		return 0;
	}
	if(P_MSP_OBD_Point_to_CV[CV_Index] != CV_Value)
	{
		P_MSP_OBD_Point_to_CV[CV_Index] = CV_Value;
		return(MSP_OBD_EE_Write_CV(CV_Index,CV_Value));
	}
	return 1;
}

//配置CV的值全部更新入EEPROM，仅首次使用时需要
uint8_t MSP_OBD_CV_InitEE(void)
{
	for(uint8_t i=0; i<DF_MSP_OBD_CV_Num; i++)
	{
		if(MSP_OBD_EE_Write_CV(i, P_MSP_OBD_Point_to_CV[i]) != 1)
		{
			return 0;
		}
	}
	return 1;
}

//从EEPROM读取CV的值，每次上电需要；
uint8_t MSP_OBD_CV_Update(void)
{
	for(uint8_t i=0; i<DF_MSP_OBD_CV_Num; i++)
	{
		if(MSP_OBD_EE_Read_CV(i, &(P_MSP_OBD_Point_to_CV[i])) != 1)
		{
			return 0;
		}
	}
	return 1;
}

//FDCAN的报文接收中断函数调用
void GF_MSP_OBD_Rx_CallBack()
{
	uint8_t _Rbuf[8];
	uint8_t _Tbuf[8];
	uint32_t _ID_A_T;
	FDCAN_RxHeaderTypeDef CAN_RX_HDR;
	uint16_t _Index;
	uint16_t _Set_length;
	int32_t _Value;
	FDCAN_HandleTypeDef *hfdcan;
	if(V_MSP_OBD_FDCAN_CH==1)
	{
		hfdcan = &hfdcan1;
	}
	else
	{
		hfdcan = &hfdcan2;
	}

	if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &CAN_RX_HDR, _Rbuf)== HAL_OK)
	{
		_ID_A_T=CAN_RX_HDR.Identifier;
		switch(_ID_A_T)
		{
			case DF_MSP_FDCAN_ID_Boot:
				if(_Rbuf[0] == 0x55)
				{
					MSP_OBD_Jump_Bootloader();
				}
			break;
			case DF_MSP_FDCAN_ID_SetCV:
				_Index = (((uint16_t)_Rbuf[1])<<8) + _Rbuf[0];
				if(_Index < DF_MSP_OBD_CV_Num)
				{
					_Value = (int32_t)(((uint32_t)_Rbuf[5])<<24 | ((uint32_t)_Rbuf[4])<<16 |((uint32_t)_Rbuf[3])<<8 |(uint32_t)_Rbuf[2]);
					if(P_MSP_OBD_Point_to_CV[_Index] != _Value)
					{
						P_MSP_OBD_Point_to_CV[_Index] = _Value;
						MSP_OBD_EE_Write_CV(_Index, _Value);
					}
				}
			break;
			case DF_MSP_FDCAN_ID_ReadCV:
				_Index = (((uint16_t)_Rbuf[1])<<8) + _Rbuf[0];
				if(_Index < DF_MSP_OBD_CV_Num)
				{
					_Tbuf[0] = _Rbuf[0];
					_Tbuf[1] = _Rbuf[1];
					_Tbuf[2] = (uint8_t)(P_MSP_OBD_Point_to_CV[_Index]);
					_Tbuf[3] = (uint8_t)(P_MSP_OBD_Point_to_CV[_Index]>>8);
					_Tbuf[4] = (uint8_t)(P_MSP_OBD_Point_to_CV[_Index]>>16);
					_Tbuf[5] = (uint8_t)(P_MSP_OBD_Point_to_CV[_Index]>>24);
					GF_BSP_FDCAN_Senddata(V_MSP_OBD_FDCAN_CH, DF_MSP_FDCAN_ID_SendCV, 6, _Tbuf);
				}
			break;
			case DF_MSP_FDCAN_ID_ConfigGV:
				_Index = (((uint16_t)_Rbuf[1])<<8) + _Rbuf[0];
				_Set_length = (((uint16_t)_Rbuf[3])<<8) + _Rbuf[2];
				if(_Index < DF_MSP_OBD_GV_Num)
				{
					if(_Index + _Set_length > DF_MSP_OBD_GV_Num)
					{
						_Set_length = DF_MSP_OBD_GV_Num - _Index;
					}
						for(uint16_t i=0;i<_Set_length;i++)
						{
							V_MSP_OBD_GVsend_EN[_Index+i]=_Rbuf[4];
						}
				}
			break;
			default:

			break;
		}
	}
}

//
//2ms执行一次，周期上传GV数值
void GF_MSP_OBD_Run_Timer(void)
{
	uint8_t _Tbuf[8];
	uint16_t i;
	for(i=V_MSP_OBD_GVsend_Index; i<DF_MSP_OBD_GV_Num; i++)
	{
		if(V_MSP_OBD_GVsend_EN[i] != 0)
		{
			_Tbuf[0] = (uint8_t)i;
			_Tbuf[1] = (uint8_t)(i>>8);
			_Tbuf[2] = (uint8_t)(P_MSP_OBD_Point_to_GV[i]);
			_Tbuf[3] = (uint8_t)(P_MSP_OBD_Point_to_GV[i]>>8);
			_Tbuf[4] = (uint8_t)(P_MSP_OBD_Point_to_GV[i]>>16);
			_Tbuf[5] = (uint8_t)(P_MSP_OBD_Point_to_GV[i]>>24);
			GF_BSP_FDCAN_Senddata(V_MSP_OBD_FDCAN_CH, DF_MSP_FDCAN_ID_SendGV, 6, _Tbuf);
			if(V_MSP_OBD_GVsend_EN[i] == 1)
			{
				V_MSP_OBD_GVsend_EN[i] = 0;
			}
			i++;
			break;
		}
	}
	V_MSP_OBD_GVsend_Index = i;

	if(V_MSP_OBD_GVsend_Index >= DF_MSP_OBD_GV_Num)
	{
		V_MSP_OBD_GVsend_Index=0;
	}
}



