/*
 * j1939.c
 *
 *  Created on: May 3, 2024
 *      Author: colorbass
 */

#include "main.h"
#include "j1939.h"
#include "charger_gbt.h"
#include "string.h"
#include "can.h"
#include "edcan.h"

extern GBT_BCL_t GBT_ReqPower;
extern GBT_BCL_t GBT_CurrPower;

j_receive_t j_rx;

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	CAN_RxHeaderTypeDef RxHeader;
	uint8_t RxData[8] = {0,};

    if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK)
    {
    	if((RxHeader.ExtId & 0x00FFFF) == ((J_ID_SE << 8) | J_ID_EV)){  // SA, DA match
    		switch ((RxHeader.ExtId>>8) & 0x00FF00){

    		case 0xEC00: //PGN Connection Management Message
    			if(RxData[0] == 16){ //Request to Send
					/* Set the RTS values */
    				j_rx.size = RxData[1] | (RxData[2]<<8);
    				j_rx.packet = 1;
    				j_rx.packets = RxData[3];
    				j_rx.step = 2; //TODO
    				j_rx.step_cts_remain = j_rx.step;
    				j_rx.PGN = (RxData[7] << 16) | (RxData[6] << 8) | RxData[5];
    				if(j_rx.size<256) { //TODO: valid check
    					J_SendCTS(j_rx);
    					j_rx.state = 1;
    				}
    			}
    			if(RxData[0] == 255){ //Connection Abort
    				j_rx.state = 0;
    			}

    			//if(RxData[0] == 32){}//Broadcast Announce Message
    			/*
    			 * 1CEC56F4  10 31 00 07 07 00 02 00
    			 * 1CECF456  11 02 01 FF FF 00 02 00
    			 * 1CEB56F4  01 01 01 00 03 46 05 40
    			 * 1CEC56F4  FF FF FF FF FF 00 00 00
    			 */

    			break;

    		case 0xEB00: //PGN Data Message
    			if(j_rx.state != 1) break;
    			if((RxData[0]>0) && (RxData[0]<35)){ //Array limit check
    				if(j_rx.packet == RxData[0]){	//step check
    					memcpy (&j_rx.data[(RxData[0]-1)*7], &RxData[1],7);
    					j_rx.packet++;
						if(j_rx.packet > j_rx.packets){
							//End of transmission
							J_SendACK(j_rx);

							j_rx.state = 2;
						}else{
							if(j_rx.step_cts_remain > 0) j_rx.step_cts_remain--;
							if(j_rx.step_cts_remain == 0){
								J_SendCTS(j_rx);
								j_rx.step_cts_remain = 2;
							}
						}
    				}
    			}
    			break;

    		case 0x1E00: //PGN BEM (ERROR)
			//Error force stop
    			EDCAN_printf(LOG_WARN, "BEM Received, force stopping...\n");
    			EDCAN_printf(LOG_WARN, "BEM: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
    			EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
    			GBT_ForceStop();
    			break;

    		case 0x1900: //PGN BST (STOP)
    			//Normal stop
    			EDCAN_printf(LOG_WARN, "BST Received, stopping...\n");
    			EDCAN_printf(LOG_WARN, "BST: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
    			EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
    			GBT_Stop(GBT_CST_BMS_ACTIVELY_SUSPENDS);

    			break;

    		default:
    			if(j_rx.state == 0){//TODO protections
					//Short packet
					j_rx.size = RxHeader.DLC;
					j_rx.packet = 1;
					j_rx.packets = 1;
					j_rx.step = 1;
					j_rx.step_cts_remain = 0;
					j_rx.PGN = (RxHeader.ExtId>>8) & 0x00FF00;
					j_rx.state = 2;
					memcpy (j_rx.data, RxData, j_rx.size);
    			}
    		}
    	}
    }
}

void GBT_CAN_ReInit(){
	HAL_CAN_Stop(&hcan1);
	MX_CAN1_Init();
	HAL_CAN_Start(&hcan1);
	HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
	GBT_CAN_FilterInit();
}

void J_SendPacket(uint32_t PGN, uint8_t pri, uint8_t DLC, uint8_t *data){

        CAN_TxHeaderTypeDef tx_header;
        uint32_t tx_mailbox;

        tx_header.ExtId = (pri << 26) | (PGN << 8) | (J_ID_EV << 8) | J_ID_SE;
        tx_header.RTR = CAN_RTR_DATA;
        tx_header.IDE = CAN_ID_EXT;
        tx_header.DLC = DLC;

        //TODO buffer wait
        HAL_CAN_AddTxMessage(&hcan1, &tx_header, data, &tx_mailbox);
        //HAL_Delay(2);

}

//void J_SendPacketLong(){
//	//TODO (no need)
//}

// J1939 sequence Clear To Send packet
void J_SendCTS(j_receive_t rx){

	//if(rx.packets <= rx.packet) return; TODO
    uint8_t data[8];
	data[0] = 17; //CONTROL_BYTE_TP_CM_CTS
	data[1] = rx.step;//total_number_of_packages_transmitted
	if (rx.step > (rx.packets - rx.packet+1)) data[1] = rx.packets - rx.packet+1;
	data[2] = rx.packet;//next_packet_number_transmitted
	data[3] = 0xFF; /* Reserved */
	data[4] = 0xFF;
	data[5] = rx.PGN;
	data[6] = rx.PGN >> 8;
	data[7] = rx.PGN >> 16;

	J_SendPacket(0x00EC00, 7, 8, data);
}

// J1939 sequence ACK packet
void J_SendACK(j_receive_t rx){//uint32_t PGN, uint8_t step, uint8_t packet){

    uint8_t data[8];
	data[0] = 19; //CONTROL_BYTE_TP_CM_ACK
	data[1] = j_rx.size;
	data[2] = j_rx.size>>8;
	data[3] = j_rx.packets;
	data[4] = 0xFF;//TODO
	data[5] = rx.PGN;
	data[6] = rx.PGN >> 8;
	data[7] = rx.PGN >> 16;

	J_SendPacket(0x00EC00, 7, 8, data);
}

void GBT_CAN_FilterInit(){
	  CAN_FilterTypeDef  sFilterConfig;

	  sFilterConfig.FilterBank = 0;
	  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
	  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
	  sFilterConfig.FilterIdHigh = 0x0000;
	  sFilterConfig.FilterIdLow = 0x0000;
	  sFilterConfig.FilterMaskIdHigh = 0x0000;
	  sFilterConfig.FilterMaskIdLow = 0x0000;
	  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
	  sFilterConfig.FilterActivation = ENABLE;
	  //sFilterConfig.SlaveStartFilterBank = 14;
	  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
	  {
	    Error_Handler();
	  }

}
