/*
 * can_comm.c
 *
 *  Created on: Jun 28, 2022
 *      Author: LUBI
 */



/**************INCLUDE BLOCK**************/
#include "can.h"
#include "can_comm.h"
#include "usart.h"


/***********INCLUDE BLOCK END*************/


/***** Data Type, Constant, and Macro Definitions *****/

/* Global variables*/

CAN_RxHeaderTypeDef rx_header, rx_header2;
uint8_t rx_msg[20], error_isolation[10], error_status[10], can2_rx_msg[10];
uint8_t can2TX_msg[8], can2TX_msg_2[8], tx_can2flag = 0;
volatile uint8_t relaysts_ac02sts = 0;
uint16_t IMD_temperature = 0;
uint8_t AC02_stop_flag = 0, Authentication_done;
uint8_t chargestart = 0,fanstart = 0;
volatile char exfault = 0;
uint32_t HVposRes = 0, HVnegRes = 0;
uint32_t HVposRes_1 = 0, HVnegRes_1 = 0;
struct chargersts chrgsts;
/* Extern Data Declarations */
extern volatile uint8_t temp_min, temp_max;
extern volatile uint8_t starttimeouttick, timeoutflag;
//extern int fantimcntr;
extern uint8_t fantimflag;
extern volatile char imd1_timeouttick, imd2_timeouttick; /*imd1_errorFlag,imd2_errorFlag,*/
extern volatile uint8_t Emergency_stop;
uint8_t onstarttimeouttick;

extern volatile char startCAN;
/* Static Data Declarations */
union
{
	unsigned short int word;
	uint32_t dword;
	float dfloat;
	unsigned char byte[4];
}split_int;
//static volatile char debug_buffer[40]={0};
#define C_ON 0xA5
#define C_OFF 0x5A
#define C1_ON 0xA0
#define C2_ON 0xB0
#define C12_ON 0xFA

/***** Data Type, Constant, and Macro Definitions END *****/



/***** Public Function Bodies *****/



/***** Public Function Bodies END *****/

/**
 * @brief Sends Maxwell test CAN messages based on the provided ID.
 *
 * @param id Identifier for selecting the CAN message to send.
 * @return None
 */

/*
void maxwellTest(char id)
{
	CAN_TxHeaderTypeDef tx_header;
	uint8_t boot[]={0x03,0x00,0x00,0x30,0x00,0x00,0x00,0x00};
	uint8_t boot2[]={0x03,0x00,0X00,0x21,0x43,0x48,0x00,0x00};
	tx_header.DLC=8;
	tx_header.IDE = CAN_ID_EXT;
	tx_header.RTR = CAN_RTR_DATA;
	uint32_t mailbox;
	switch (id)
	{
	case 0:

//	tx_header.ExtId=0x06080780;
		tx_header.ExtId=0x0607FF80;

	if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot, &mailbox) != HAL_OK)
	{
		Error_Handler();
	}
	break;
	case 1:

		//tx_header.ExtId=0x06080F80;

		tx_header.ExtId=0X060c1781; //82

		if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot2, &mailbox) != HAL_OK)
		{
			Error_Handler();
		}
		break;

	case 2:


			//tx_header.ExtId=0x06081780;
			tx_header.ExtId=0X060c0781; //80




			if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot2, &mailbox) != HAL_OK)
			{
				Error_Handler();
			}
			break;
	case 3:

			tx_header.ExtId=0x06081F80;



			if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot, &mailbox) != HAL_OK)
			{
				Error_Handler();
			}
			break;
	case 4:


			tx_header.ExtId=0x06082780;




			if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot, &mailbox) != HAL_OK)
			{
				Error_Handler();
			}
			break;
	case 5:

			tx_header.ExtId=0x06082F80;


			if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot, &mailbox) != HAL_OK)
			{
				Error_Handler();
			}
			break;
	case 6:


			tx_header.ExtId=0x06083780;

			if(HAL_CAN_AddTxMessage(&hcan2, &tx_header, boot, &mailbox) != HAL_OK)
			{
				Error_Handler();
			}
			break;

	}
}
*/

/**
 * @brief Sends a CAN message containing temperature data.
 *
 * @return None
 */
#if imd == syn
void can_tx_temperature(void)
{

	CAN_TxHeaderTypeDef tx_header;
	tx_header.DLC=1;
	tx_header.ExtId=0xA100101;
	tx_header.IDE = CAN_ID_EXT;
	tx_header.RTR = CAN_RTR_DATA;

	uint32_t mailbox;
	uint8_t message = 0x80;

	if(HAL_CAN_AddTxMessage(&hcan1, &tx_header, &message, &mailbox) != HAL_OK)
	{
		Error_Handler();
	}
//	while( HAL_CAN_IsTxMessagePending(&hcan1, mailbox));


//	while( HAL_CAN_IsTxMessagePending(&hcan1, mailbox));

//	HAL_UART_Transmit(&huart2, "TX OK", 5, 1000);
}

/**
 * @brief Sends a CAN message to perform a reset.
 *
 * @return None
 */
void can_tx_reset()
{
		CAN_TxHeaderTypeDef tx_header;
		tx_header.DLC=5;
		tx_header.ExtId=0xA100101;
		tx_header.IDE = CAN_ID_EXT;
		tx_header.RTR = CAN_RTR_DATA;

		uint32_t mailbox;
	uint8_t restart[]={0xc1,0x01,0x23,0x45,0x67};

		if(HAL_CAN_AddTxMessage(&hcan1, &tx_header, restart, &mailbox) != HAL_OK)
		{
			Error_Handler();
		}
//		while( HAL_CAN_IsTxMessagePending(&hcan1, mailbox));

//		while(!HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0));
//
//		if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rx_header, rx_msg) != HAL_OK)
//		{
//				Error_Handler();
//		}
}

/**
 * @brief Sends a CAN message containing vb_max data.
 *
 * @return None
 */
void can_tx_vbmax()
{
	uint8_t vb_max[]={0xf0,0x02,0xf8};
	CAN_TxHeaderTypeDef tx_header;
	tx_header.DLC=3;
	tx_header.ExtId=0xA100101;
	tx_header.IDE = CAN_ID_EXT;
	tx_header.RTR = CAN_RTR_DATA;


	uint32_t mailbox;


		if(HAL_CAN_AddTxMessage(&hcan1, &tx_header, vb_max, &mailbox) != HAL_OK)
		{
			Error_Handler();
		}
		while( HAL_CAN_IsTxMessagePending(&hcan1, mailbox));

//		while(!HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0));
//
//			if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rx_header, rx_msg) != HAL_OK)
//			{
//					Error_Handler();
//			}
}

/**
 * @brief Sends a CAN message containing isolation state data.
 *
 * @return None
 */
void can_tx_Isolation_State()
{
	CAN_TxHeaderTypeDef tx_header;
		tx_header.DLC=1;
		tx_header.ExtId=0xA100101;
		tx_header.IDE = CAN_ID_EXT;
		tx_header.RTR = CAN_RTR_DATA;

		uint8_t message = 0xE0;
		uint32_t mailbox;

		if(HAL_CAN_AddTxMessage(&hcan1, &tx_header, &message, &mailbox) != HAL_OK)
		{
			Error_Handler();
		}
//		while( HAL_CAN_IsTxMessagePending(&hcan1, mailbox));

//		while(!HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0));
//
//			if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rx_header, error_isolation) != HAL_OK)
//			{
//					Error_Handler();
//			}
}

/**
 * @brief Sends a CAN message containing error flag data.
 *
 * @return None
 */
void can_tx_Error_Flag()
{
	CAN_TxHeaderTypeDef tx_header;
	tx_header.DLC=1;
	tx_header.ExtId=0xA100101;
	tx_header.IDE = CAN_ID_EXT;
	tx_header.RTR = CAN_RTR_DATA;

	uint8_t message = 0xE5;

	uint32_t mailbox;

	if(HAL_CAN_AddTxMessage(&hcan1, &tx_header, &message, &mailbox) != HAL_OK)
	{
		Error_Handler();
	}
//	while( HAL_CAN_IsTxMessagePending(&hcan1, mailbox));

//	while(!HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0));
//
//		if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rx_header, error_status) != HAL_OK)
//		{
//				Error_Handler();
//		}
}
#endif
/**
 * @brief Sends a CAN message using CAN2.
 *
 * @return None
 */
void can2_tx_frame(void)
{
	CAN_TxHeaderTypeDef tx_header1;
	tx_header1.DLC = 8;
	tx_header1.ExtId = 0xA100102;
	tx_header1.IDE = CAN_ID_EXT;
	tx_header1.RTR = CAN_RTR_DATA;
	uint32_t mailbox;

//	HAL_UART_Transmit_IT(&huart1,(uint8_t *) "CAN FRAME: ",11);
//	HAL_UART_Transmit_IT(&huart1,&can2TX_msg[0],8);
//	HAL_UART_Transmit_IT(&huart1,(uint8_t *) "\r\n",4);
		if(HAL_CAN_AddTxMessage(&hcan2, &tx_header1, can2TX_msg, &mailbox) != HAL_OK)
		{
			Error_Handler();
		}
//		while( HAL_CAN_IsTxMessagePending(&hcan2, mailbox));

//		while(!HAL_CAN_GetRxFifoFillLevel(&hcan2, CAN_RX_FIFO1));
//
//		if(HAL_CAN_GetRxMessage(&hcan2, CAN_RX_FIFO1, &rx_header2, can2_rx_msg) != HAL_OK)
//		{
//		Error_Handler();
//		}
}

void can2_tx_frame_2(void)
{
	CAN_TxHeaderTypeDef tx_header1;
	tx_header1.DLC = 8;
	tx_header1.ExtId = 0xA100100; // CHANGED ACCORDING TO FIRMWARE
	tx_header1.IDE = CAN_ID_EXT;
	tx_header1.RTR = CAN_RTR_DATA;
	uint32_t mailbox;

//	HAL_UART_Transmit_IT(&huart1,(uint8_t *) "CAN FRAME: ",11);
//	HAL_UART_Transmit_IT(&huart1,&can2TX_msg[0],8);
//	HAL_UART_Transmit_IT(&huart1,(uint8_t *) "\r\n",4);
	if(HAL_CAN_AddTxMessage(&hcan2, &tx_header1, can2TX_msg_2, &mailbox) != HAL_OK)
	{
		Error_Handler();
	}
//		while( HAL_CAN_IsTxMessagePending(&hcan2, mailbox));

//		while(!HAL_CAN_GetRxFifoFillLevel(&hcan2, CAN_RX_FIFO1));
//
//		if(HAL_CAN_GetRxMessage(&hcan2, CAN_RX_FIFO1, &rx_header2, can2_rx_msg) != HAL_OK)
//		{
//		Error_Handler();
//		}
}

/**
 * @brief Configures CAN filter.
 *
 * @return None
 */

void can_filterconfig(void)
{
	/*This filter will allow all messages through, regardless of the ID (because the mask is all zeros and all bits are ignored).*/
	CAN_FilterTypeDef canfilter;
	canfilter.FilterActivation = CAN_FILTER_ENABLE;
	canfilter.FilterBank = 0;
	canfilter.FilterFIFOAssignment = CAN_RX_FIFO0;
	canfilter.FilterIdHigh = 0X0000;
	canfilter.FilterIdLow = 0X0000;
	canfilter.FilterMaskIdHigh = 0X0000;
	canfilter.FilterMaskIdLow = 0X0000;
	canfilter.FilterMode = CAN_FILTERMODE_IDMASK;
	canfilter.FilterScale = CAN_FILTERSCALE_32BIT;

	if( HAL_CAN_ConfigFilter(&hcan1, &canfilter) != HAL_OK)
	{
		Error_Handler();
	}

//	canfilter.FilterBank = 0;
//	canfilter.FilterFIFOAssignment = CAN_RX_FIFO1;
//	if( HAL_CAN_ConfigFilter(&hcan2, &canfilter) != HAL_OK)
//	{
//		Error_Handler();
//	}
}
#if imd == syn

void can_filterconfig(void)
{
	CAN_FilterTypeDef canfilter;

	// Convert 29-bit CAN ID to the 32-bit format used by the filter
	    uint32_t can_id_1 = 0x18FF5050 << 3;
	    uint32_t can_id_2 = 0x18FF5051 << 3;

	canfilter.FilterActivation = CAN_FILTER_ENABLE;
	canfilter.FilterBank = 0;
	canfilter.FilterFIFOAssignment = CAN_RX_FIFO0;
	 // Set the FilterId to the first CAN ID
	canfilter.FilterIdHigh = (uint16_t)(can_id_1 >> 16);
	canfilter.FilterIdLow = (uint16_t)(can_id_1 & 0xFFFF);

	// Set the mask to allow the last bit to differ
	canfilter.FilterMaskIdHigh = 0xFFFF;
	canfilter.FilterMaskIdLow = 0xFFF8; // Accept both 0x18FF5050 and 0x18FF5051

	canfilter.FilterMode = CAN_FILTERMODE_IDMASK;
	canfilter.FilterScale = CAN_FILTERSCALE_32BIT;

	if( HAL_CAN_ConfigFilter(&hcan1, &canfilter) != HAL_OK)
	{
		Error_Handler();
	}

//	canfilter.FilterBank = 0;
//	canfilter.FilterFIFOAssignment = CAN_RX_FIFO1;
//	if( HAL_CAN_ConfigFilter(&hcan2, &canfilter) != HAL_OK)
//	{
//		Error_Handler();
//	}
}
#endif
/**
 * @brief Configures CAN2 filter.
 *
 * @return None
 */
void can2_filterconfig(void)
{
	/*
	 * This filter is configured to allow only messages with an extended identifier (29-bit) that matches the mask and ID criteria to pass through.
	 * The ExtId (0xA105695) specifies the base identifier.
	 * CAN_ID_EXT sets the IDE flag (the bit that signals the use of an extended identifier in CAN)
	 */
	CAN_FilterTypeDef canfilter2;
	uint32_t ExtId = 0xA105695;
	canfilter2.FilterActivation = CAN_FILTER_ENABLE;
	canfilter2.FilterBank = 14;
	canfilter2.FilterFIFOAssignment = CAN_RX_FIFO0;
	canfilter2.FilterIdHigh = ((ExtId << 3) >> 16) & 0xffff;	//makes the filter sensitive to the upper portion of the ExtId
	canfilter2.FilterIdLow = ((ExtId << 3) & 0xffff) | CAN_ID_EXT;	//makes the filter specifically target extended identifiers (29-bit) rather than standard (11-bit) identifiers
	canfilter2.FilterMaskIdHigh = 0x1FFF;	//filter will require an exact match for the upper 13 bits
	canfilter2.FilterMaskIdLow = 0XFFFF;	//filter will require an exact match for lower 16 bits
//	canfilter2.FilterMaskIdHigh = ((ExtId << 3) >> 16) &0xffff;
//	canfilter2.FilterMaskIdLow = (ExtId << 3) &0xffff| CAN_ID_EXT;
	canfilter2.FilterMode = CAN_FILTERMODE_IDMASK;
	canfilter2.FilterScale = CAN_FILTERSCALE_32BIT;

	if( HAL_CAN_ConfigFilter(&hcan2, &canfilter2) != HAL_OK)
		Error_Handler();
}

/**
 * @brief Callback function invoked when a message is pending in CAN1 RX FIFO0.
 *
 * @param hcan Pointer to a CAN_HandleTypeDef structure that contains the configuration information for the specified CAN.
 * @return None
 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance == CAN1)
	{
		if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rx_header, rx_msg) != HAL_OK)
			Error_Handler();

#if imd == syn
		if(rx_msg[0] == 0xe5)
		{
			if(rx_msg[1] != 4)
			{
			can2TX_msg[can2TX_stsbits] = rx_msg[1];
			can2TX_msg[can2TX_errorFlag] = rx_msg[2];
			}
		}
		else if(rx_msg[0] == 0xe0)
		{
		can2TX_msg[can2TX_ele_isolationMSB] = rx_msg[2];
		can2TX_msg[can2TX_ele_isolationLSB] = rx_msg[3];
		}
		else if(rx_msg[0] == 0x80)
		{
			/*int NUM = (rx_msg[3] << 8) | (rx_msg[4]);
		can2TX_msg[can2TX_temperaturebyte1]=(uint8_t)NUM/1000;
		can2TX_msg[can2TX_temperaturebyte2]=0;*/
#if defined(imdtemp)
		can2TX_msg[can2TX_temperaturebyte1] = rx_msg[3];
		can2TX_msg[can2TX_temperaturebyte2] = rx_msg[4];
#endif
		}
#elif imd == gq			//qg imd
		if (rx_header.ExtId == 0x18ff5050)
		{
			imd1_timeouttick = 75;
			can2TX_msg[can2TX_stsbits] = rx_msg[0];
			HVposRes= HVnegRes  = 0;
			HVposRes=((rx_msg[2] << 8) | rx_msg[3]);
			HVnegRes=((rx_msg[4] << 8) | rx_msg[5]);
			//TODO check with IMD GQ document
			 if(HVposRes >= HVnegRes)
			 {
				 can2TX_msg[can2TX_ele_isolationMSB]=rx_msg[4]; //send gun1 DC- isolation
				 can2TX_msg[can2TX_ele_isolationLSB]=rx_msg[5]; //send gun1 DC- isolation
			 }
			 else
			 {
				 can2TX_msg[can2TX_ele_isolationMSB]=rx_msg[2]; //send gun1 DC+ isolation
				 can2TX_msg[can2TX_ele_isolationLSB]=rx_msg[3]; //send gun1 DC+ isolation
			 }
			can2TX_msg[can2TX_errorFlag]= 0;
		}
		else if(rx_header.ExtId == 0x18ff5051)
		{
			imd2_timeouttick = 75;
			can2TX_msg[can2TX_stsbits_IMD2]=rx_msg[0];
			HVposRes_1= HVnegRes_1  = 0;
			HVposRes_1=((rx_msg[2] << 8) | rx_msg[3]);
			HVnegRes_1=((rx_msg[4] << 8) | rx_msg[5]);
			//TODO check with IMD GQ document
			 if(HVposRes_1 >= HVnegRes_1)
			 {
				 can2TX_msg[can2TX_ele_isolationMSB_IMD2]=rx_msg[4]; //send gun2 DC- isolation
				 can2TX_msg[can2TX_ele_isolationLSB_IMD2]=rx_msg[5]; //send gun2 DC- isolation
			 }
			 else
			 {
				 can2TX_msg[can2TX_ele_isolationMSB_IMD2]=rx_msg[2]; //send gun2 DC+ isolation
				 can2TX_msg[can2TX_ele_isolationLSB_IMD2]=rx_msg[3]; //send gun2 DC+ isolation
			 }
			can2TX_msg[can2TX_errorFlag_IMD2]= 0;
		}
#endif

	}
	else if(hcan->Instance == CAN2)
	{
		if(HAL_CAN_GetRxMessage(&hcan2, CAN_RX_FIFO0, &rx_header2, can2_rx_msg) != HAL_OK)
		{
			Error_Handler();
		}
		if (!startCAN)
		{
			return;
		}
		else
		{
//			startCAN = 0;
			if(rx_header2.ExtId == 0xA105695)
			{
				if(can2_rx_msg[0] < 100)		//temp_minimum
				{
					temp_min = can2_rx_msg[0];
				}
				else
				{
					temp_min = 35;
				}
				if(can2_rx_msg[3] < 100) 		//Temp_maximum
				{
					temp_max = can2_rx_msg[3];
				}
				else
				{
					temp_max = 55;
				}

				if((can2_rx_msg[1] == C_ON) && (!Emergency_stop))	//AC MAIN CONTACTOR
				{
					if(++onstarttimeouttick > 5)
					{
						AC_MAIN_ON;
						onstarttimeouttick = 5;
						starttimeouttick = 30;
					}
				}
				else if(can2_rx_msg[1] == C_OFF)
				{
					onstarttimeouttick = 0;
					if(++starttimeouttick > 30)
					{
						AC_MAIN_OFF;
						starttimeouttick = 30;
					}
				}

				if(can2_rx_msg[2] == C_ON) // DC MAIN CONTACTOR
				{
					DC_MAIN_GUN_1_ON;
					fanstart = 1;
					chrgsts.charging_G1 = 1;
	//				chargestart=1;
				}
				else
				{
					if(can2_rx_msg[2] == C_OFF) //
					{
						DC_MAIN_GUN_1_OFF;
						fanstart = 0;
						chrgsts.charging_G1 = 0;                          //CHANGE BY RONAK
						/*if(chargestart == 1)
						{
							chargestart = 0;
							fantimflag = 1;
						}*/
					}
				}
				if(can2_rx_msg[4] == C1_ON) // FAULT INNDICATOR //RESET SWITCH
				{
					chrgsts.G1_fault = 1;
					chrgsts.G2_fault = 0;
				}

				else if(can2_rx_msg[4] == C2_ON)
				{
					chrgsts.G2_fault = 1;
					chrgsts.G1_fault = 0;
				}
				else if(can2_rx_msg[4] == C12_ON)
				{
					chrgsts.G1_fault = 1;
					chrgsts.G2_fault = 1;
				}
				else
				{
					if(can2_rx_msg[4] == C_OFF)
					{
						chrgsts.G1_fault = 0;
						chrgsts.G2_fault = 0;
					}
				}

				if(can2_rx_msg[5] == C_ON) // LOAD SHARING CONTACTOR 5&6
				{
					LOAD_SHARING_ON;
				}
				else
				{
					if(can2_rx_msg[5] == C_OFF) // LOAD SHARING CONTACTOR 5&6
					{
						LOAD_SHARING_OFF;
					}
				}

				if(can2_rx_msg[6] == C_ON)
				{
					NVIC_SystemReset(); 	//hard reset the system
				}
				else
				{

				}
				if(can2_rx_msg[7] == C_ON)
				{
					DC_MAIN_GUN_2_ON;
					fanstart = 1;
					chrgsts.charging_G2 = 1;
				}
				else
				{
					if(can2_rx_msg[7] == C_OFF)
					{
						DC_MAIN_GUN_2_OFF;
						chrgsts.charging_G2 = 0;
						fanstart = 0;
					}
				}
				tx_can2flag = 1;
			}
		}
	}
}

/**
 * @brief Callback function invoked when a CAN error occurs.
 *
 * @param hcan Pointer to a CAN_HandleTypeDef structure that contains the configuration information for the specified CAN.
 * @return None
 */
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{


}
