/*
 * can_communication.c
 *
 *  Created on: Mar 12, 2025
 *      Author: janek
 */

#include "can_communication.h"
#include "channel_control.h"
#include "current_monitoring.h"
#include "plausibility_check.h"

rx_status_frame rxstate = {};
volatile uint8_t canmsg_received = 0;
extern enable_gpios update_ports;
extern current_measurements current_measurements_adc_val;
extern uint8_t error_data[16];


extern uint32_t lastheartbeat;
extern int inhibit_SDC;

void can_init(CAN_HandleTypeDef* hcan){
	ftcan_init(hcan);
	ftcan_add_filter(0x00, 0x00);			// no filter
}

void can_sendloop(){
	static uint8_t additionaltxcounter = 0;

	uint8_t status_data[3];
	status_data[0] = update_ports.porta.porta;
	status_data[1] = update_ports.portb.portb;
	status_data[2] = !inhibit_SDC;
	ftcan_transmit(TX_STATUS_MSG_ID, status_data, 3);

	uint8_t data[8];

	switch (additionaltxcounter) {
	case 0:
		data[0] = current_measurements_adc_val.alwayson >> 8;
		data[1] = current_measurements_adc_val.alwayson & 0xFF;
		data[2] = current_measurements_adc_val.misc >> 8;
		data[3] = current_measurements_adc_val.misc & 0xFF;
		data[4] = current_measurements_adc_val.inverter >> 8;
		data[5] = current_measurements_adc_val.inverter & 0xFF;
		data[6] = current_measurements_adc_val.sdc >> 8;
		data[7] = current_measurements_adc_val.sdc & 0xFF;
		ftcan_transmit(CUR_CHANNELS_1_ID, data, 8);
		break;

	case 1:
		data[0] = current_measurements_adc_val.acc_cooling >> 8;
		data[1] = current_measurements_adc_val.acc_cooling & 0xFF;
		data[2] = current_measurements_adc_val.ts_cooling >> 8;
		data[3] = current_measurements_adc_val.ts_cooling & 0xFF;
		data[4] = current_measurements_adc_val.acu >> 8;
		data[5] = current_measurements_adc_val.acu & 0xFF;
		data[6] = current_measurements_adc_val.epsc >> 8;
		data[7] = current_measurements_adc_val.epsc & 0xFF;
		ftcan_transmit(CUR_CHANNELS_2_ID, data, 8);
		break;

	case 2:
		data[0] = current_measurements_adc_val.ebs1 >> 8;
		data[1] = current_measurements_adc_val.ebs1 & 0xFF;
		data[2] = current_measurements_adc_val.ebs2 >> 8;
		data[3] = current_measurements_adc_val.ebs2 & 0xFF;
		data[4] = current_measurements_adc_val.ebs3 >> 8;
		data[5] = current_measurements_adc_val.ebs3 & 0xFF;
		data[6] = current_measurements_adc_val.drs >> 8;
		data[7] = current_measurements_adc_val.drs & 0xFF;
		ftcan_transmit(CUR_CHANNELS_3_ID, data, 8);
		break;

	case 3:
		data[0] = current_measurements_adc_val.lidar >> 8;
		data[1] = current_measurements_adc_val.lidar & 0xFF;
		data[2] = current_measurements_adc_val.lvms_v >> 8;
		data[3] = current_measurements_adc_val.lvms_v & 0xFF;
		data[4] = current_measurements_adc_val.asms_v >> 8;
		data[5] = current_measurements_adc_val.asms_v & 0xFF;
		data[6] = current_measurements_adc_val.epsc_precharge >> 8;											// not used (transmits 313)
		data[7] = current_measurements_adc_val.epsc_precharge & 0xFF;											// not used (transmits 313)
		ftcan_transmit(CUR_CHANNELS_4_ID, data, 8);
		break;

	default:
		break;
	}

	additionaltxcounter = (additionaltxcounter + 1) % 4;
}

void can_error_report(){

	static int error_loop = 0;
	uint8_t data[8];

	switch (error_loop){
		case 0:								// 1 = error   0 = no error
			data[0] = error_data[0];		// SDC-Status
			data[1] = error_data[1];		// power draw critical (550W)
			data[2] = error_data[2];		// power limit (> 600W)
			data[3] = error_data[3];		// acc-cooling false OFF
			data[4] = error_data[4];		// ts-cooling false OFF
			data[5] = error_data[5];		// drs false OFF
			data[6] = error_data[6];		// acu false OFF
			data[7] = error_data[7];		// epsc false OFF
			ftcan_transmit(ERROR_ID, data, 8);
			break;

		case 1:								// 3 = error   2 = no error
			data[8] = error_data[8];		// inverter false OFF
			data[9] = error_data[9];		// lidar false OFF
			data[10] = error_data[10];		// misc false OFF
			data[11] = error_data[11];		// always on false OFF
			data[12] = error_data[12];		// sdc false OFF
			data[13] = error_data[13];		// ebs1 false OFF
			data[14] = error_data[14];		// ebs2 false OFF
			data[15] = error_data[15];		// ebs3 false OFF
			ftcan_transmit(ERROR_ID, data, 8);
			break;

		default:
			break;
		}
	error_loop = (error_loop + 1) % 2;
}

void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t* data){
	canmsg_received = 1;
	if((id == RX_STATUS_MSG_ID) && (datalen == 3)){
		rxstate.iostatus.porta.porta	= data[0];
		rxstate.iostatus.portb.portb	= data[1];
		rxstate.checksum				= data[2];
	}

	if (id == RX_STATUS_HEARTBEAT){
		lastheartbeat = HAL_GetTick();
		inhibit_SDC = 0;
	}
}