/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  * GQ IMD 1 : 1-OFF | 2-OFF | 3-ON | 4-OFF
  * GQ IMD 2 : 1-ON  | 2-OFF | 3-ON | 4-ON
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "can.h"
#include "dma.h"
#include "iwdg.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "math.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "can_comm.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define GUN1_BLUE_LED_ON	{HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_3); HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_2); HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);}
#define GUN1_GREEN_LED_ON 	{HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_3); HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_2);}
#define GUN1_RED_LED_ON 	{HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_2); HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_3);}

#define GUN2_BLUE_LED_ON	{HAL_TIM_PWM_Stop_IT(&htim4, TIM_CHANNEL_4); HAL_TIM_PWM_Stop_IT(&htim4, TIM_CHANNEL_3); HAL_TIM_PWM_Start_IT(&htim4, TIM_CHANNEL_2);}
#define GUN2_GREEN_LED_ON 	{HAL_TIM_PWM_Stop_IT(&htim4, TIM_CHANNEL_4); HAL_TIM_PWM_Stop_IT(&htim4, TIM_CHANNEL_2); HAL_TIM_PWM_Start_IT(&htim4, TIM_CHANNEL_3);}
#define GUN2_RED_LED_ON 	{HAL_TIM_PWM_Stop_IT(&htim4, TIM_CHANNEL_2); HAL_TIM_PWM_Stop_IT(&htim4, TIM_CHANNEL_3); HAL_TIM_PWM_Start_IT(&htim4, TIM_CHANNEL_4);}


/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

//--------------CAN PARAMETERS---------

//char moduleTest_flag = 0;
// modulueno = 0;

//-------------ACTYPE 2 PARAMETERS-----------
volatile int adc_init = 0;
uint8_t CURRENT_STATE = 0;
uint8_t count_A = 0, count_B = 0, count_C = 0, count_D = 0;

#define ADC_BUFFER_SIZE 5
extern volatile uint8_t adcsmp;
volatile uint16_t adcValues[ADC_BUFFER_SIZE];
uint16_t averaging[ADC_BUFFER_SIZE][10], sensor_value[ADC_BUFFER_SIZE];

uint32_t ch1_averaging = 0, ch2_averaging = 0, ch3_averaging = 0,
		ch4_averaging = 0, ch5_averaging = 0;
volatile float tempvolt[ADC_BUFFER_SIZE];
volatile uint8_t tempsen[ADC_BUFFER_SIZE];

volatile uint8_t temp_min = 35, temp_max = 55;
uint8_t adccmpl = 0, offset = 30, stop_fanpwm = 0;
float vt_factor = 2.657;
uint8_t redsts = 0, bluests = 0, greensts = 0, change = 0, redsts1 = 0, bluests1 = 0, greensts1 = 0;
extern uint8_t fanstart;
extern volatile char tempchange;
extern uint16_t Dutycycle;
unsigned char ImdRx[12] = { 0 };
//static volatile char debug_buffer[40] = {0};
unsigned char tx[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
void Read_temp(void);
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

//void AC_TYPE2(void);
//void adc_check();
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
	/* USER CODE BEGIN 1 */

	/* USER CODE END 1 */

	/* MCU Configuration--------------------------------------------------------*/

	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

	HAL_Init();
	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* Configure the system clock */
	SystemClock_Config();

	/* USER CODE BEGIN SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_DMA_Init();
	MX_USART1_UART_Init();
	MX_RTC_Init();
	MX_TIM2_Init();
	MX_ADC2_Init();
	MX_CAN1_Init();
	MX_CAN2_Init();
	MX_TIM3_Init();
	MX_TIM4_Init();
	MX_IWDG_Init();
	MX_TIM5_Init();
	/* USER CODE BEGIN 2 */
	ALL_RELAYOFF;
	//  start_fan();
	//UNCOMMENT IF CAN RX IT IS REQUIRED //
	if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_BUSOFF ) != HAL_OK)
		Error_Handler();

	if(HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_BUSOFF ) != HAL_OK)
		Error_Handler();

	can_filterconfig();
	can2_filterconfig();

	HAL_CAN_Start(&hcan1);
	HAL_CAN_Start(&hcan2);

	HAL_TIM_Base_Start_IT(&htim5);
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_Delay(1000);
	HAL_UART_Receive_DMA(&huart1, (uint8_t*) ImdRx, 8);

#if target == gun1
	start_fan();
#endif
	//fanstart = 3;
	HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adcValues, 5);
#if target == gun1
	HAL_Delay(5000);
//	HAL_UART_Transmit_IT(&huart1, (uint8_t *) "Version:3.1\n", 12);
	//USER_OUT1_ON;
	if(USER_IN3_READ) AC_MAIN_ON;		//AC main supply ON //NEGATIVE
#endif
	bluests = 1;
	bluests1 = 1;
	change = 1;
	//	USER_OUT6_ON;//positive
	//  B_LED_ON;	//IN AC supply indication
	//  R_LED_OFF;	//RED OFF
	//  G_LED_OFF; // GREEN OFF
	//  can_tx_vbmax();
	//  can_tx();
	/* USER CODE END 2 */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
#if imd == syn
	can_tx_reset();
	HAL_Delay(200);
	can_tx_vbmax();
	HAL_Delay(50);
#endif
	adc_init = 1;
	//moduleTest_flag = 1;

	while (1)
	{
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */
		HAL_IWDG_Refresh(&hiwdg); //uncomment

		if(tx_can2flag)
		{
			can2_tx_frame_2();
			HAL_Delay(10);
			tx_can2flag = 0;
		}
		if(imdFrameTxFlag)
		{
			can2_tx_frame();
			HAL_Delay(10);
			imdFrameTxFlag = 0;
		}

#if imd == syn
		if(IMD_rstflag)
		{
			/*
			can_tx_reset();
			HAL_Delay(50);
			can_tx_vbmax();
			HAL_Delay(50); */
			//can2_tx_frame();
			//HAL_Delay(50);
			IMD_rstflag = 0;
		}
		else if(IMD_statusupdateflag)
		{
			can_tx_Isolation_State();
			HAL_Delay(50);
			can_tx_Error_Flag();
			HAL_Delay(50);
			IMD_statusupdateflag = 0;
		}
		else if(IMD_temperflag)
		{
			can_tx_temperature();
			IMD_temperflag = 0;
		}
#endif

		if(change == 1)
		{
			change = 0;
			if(redsts == 1)
			{
				GUN1_RED_LED_ON;
				GUN2_RED_LED_ON;
			}
			else if(greensts == 1)
			{
				GUN1_GREEN_LED_ON;
			}
			else if(bluests == 1)
			{
				GUN1_BLUE_LED_ON;
			}
			if(redsts1 == 1)
			{
				GUN2_RED_LED_ON;
			}
			else if(bluests1 == 1)
			{
				GUN2_BLUE_LED_ON;
			}
			else if(greensts1 == 1)
			{
				GUN2_GREEN_LED_ON;
			}
		}
		//if(fanstart==1)
		//{
		//	start_fan();
		//	fanstart=2;
		//}
		//else if(fanstart ==3)
		//{
		////	stop_fan();
		//	stop_fanpwm=1;
		//	fanstart=0;
		//}
#if target == gun1

		if(tempchange == 1)
		{
			tempchange = 0;
			if(chrgsts.charging_G1 == 1 || fanstart == 1 || chrgsts.charging_G2 == 1)
			{
				stop_fanpwm = 0;
				Dutycycle = 0;
			}
			else if(tempsen[0] >= temp_max)
			{
				stop_fanpwm = 0;
				Dutycycle = 0;
			}
			else if(tempsen[0] < temp_max && (tempsen[0] > temp_min))
			{
				Dutycycle = (uint16_t)(100 -((tempsen[0] - temp_min) / 0.15));
				stop_fanpwm = 0;
			}
			else
			{
				Dutycycle = 100;
				stop_fanpwm = 1;
			}
		}
#endif

		if(adcsmp == 1)
		{
			adcsmp = 0;
		//	Read_temp();
		}
//		AC_TYPE2();
//		if(moduleTest_flag)
//		{
//			maxwellTest(modulueno);
//			moduleTest_flag=0;
//		}
//		AC_TYPE2();
	}

	/* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 6;
  RCC_OscInitStruct.PLL.PLLN = 96;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	  Error_Handler();

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
    Error_Handler();
}

/* USER CODE BEGIN 4 */


/**
 * @brief Reads the temperature from the ADC values.
 *
 * This function reads the temperature values from the ADC and calculates the corresponding temperatures.
 * It also updates the CAN message with temperature data.
 */
void Read_temp(void)
{
#if defined(debugmode)
	static char buff[100] = {0};
	float sensorVal;
	float tempVolta = 0, tempseno = 0, tempseno1 = 0, tempseno2 = 0, tempseno3 = 0;
#endif

	static uint8_t temp, i, j, avgcnt = 0;		//used "uint8_t" to remove "array subscript has type 'char'" warning

	HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&adcValues, 5);

	averaging[0][avgcnt] = adcValues[0];
	averaging[1][avgcnt] = adcValues[1];
	averaging[2][avgcnt] = adcValues[2];
	averaging[3][avgcnt] = adcValues[3];
	averaging[4][avgcnt] = adcValues[4];

	avgcnt++;

	if(avgcnt > 9)
	{
		avgcnt = 0;
		for(i = 0; i < 10; i++)
		{
			for(j = 0; j < i; j++)
			{
				if(averaging[0][j] > averaging[0][j+1])
				{
					temp = averaging[0][j];
					averaging[0][j] = averaging[0][j+1];
					averaging[0][j+1] = temp;
				}
			}
		}

		sensor_value[0] = ((averaging[0][4] + averaging[0][5] + averaging[0][6] + averaging[0][7]) / 4);
		tempvolt[0] = (float) (sensor_value[0] * (3.3 / 4096));	//scales the ADC value to the voltage range [0, 3.3V]
		tempsen[0] = (uint8_t) (((tempvolt[0] * 100) / vt_factor) - offset); // CHANGED BY RONAK
		can2TX_msg_2[can2TX_exhaustfan] = (int) tempsen[0];
//	 	int length = sprintf((char *)debug_buffer, "volt:%2f Temp:%02d\r\n",tempvolt[0], can2TX_msg[can2TX_exhaustfan]);
//		HAL_UART_Transmit_IT(&huart1, debug_buffer, length);
#if defined(debugmode)
//	tempVolta=tempvolt[0];
	tempseno = tempsen[0];
#endif
		for(i = 0; i < 10; i++)
		{
			for(j = 0; j < i; j++)
			{
				if(averaging[1][j] > averaging[1][j+1])
				{
					temp = averaging[1][j];
					averaging[1][j] = averaging[1][j+1];
					averaging[1][j+1] = temp;
				}
			}
		}

		sensor_value[1] = ((averaging[1][4] + averaging[1][5] + averaging[1][6] + averaging[1][7]) / 4);
		tempvolt[1] = (float)(sensor_value[1] * (3.3 / 4096));
		tempsen[1] = (uint8_t)(((tempvolt[1] * 100) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcpostemp] = (int)tempsen[1];

#if defined(debugmode)
		//tempVolta=tempvolt[1];
		tempseno1 = tempsen[1];
#endif
		for(i = 0; i < 10; i++)
		{
			for(j = 0; j < i; j++)
			{
				if(averaging[2][j] > averaging[2][j+1])
				{
					temp = averaging[2][j];
					averaging[2][j] = averaging[2][j+1];
					averaging[2][j+1] = temp;
				}
			}
		}
		sensor_value[2] = ((averaging[2][4] + averaging[2][5] + averaging[2][6] + averaging[2][7]) / 4);
		tempvolt[2] = (float)(sensor_value[2] * (3.3/4096));
		tempsen[2] = (uint8_t)(((tempvolt[2] * 100) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcnegtemp] = (int)tempsen[2];
#if defined(debugmode)
		//tempVolta=tempvolt[0];
		tempseno2 = tempsen[2];

		//int lclcnt= sprintf(buff,"ADC count: %u \r\n Volatge Count: %f \r\n temp: %f \r\n ",sensorVal,tempVolta,tempseno);
		int lclcnt = sprintf(buff, "temp1: %f \r\n temp2: %f \r\n temp3: %f \r\n", tempseno, tempseno1, tempseno2);
		HAL_UART_Transmit_IT(&huart1, (uint8_t*)&buff, lclcnt);
#endif
		for(i = 0; i < 10; i++)
		{
			for(j = 0; j < i-1; j++)
			{
				if(averaging[3][j] > averaging[3][j+1])
				{
					temp = averaging[3][j];
					averaging[3][j] = averaging[3][j+1];
					averaging[3][j+1] = temp;
				}
			}
		}

		sensor_value[3] = ((averaging[3][4] + averaging[3][5] + averaging[3][6] + averaging[3][7]) / 4);
		tempvolt[3] = (float)(sensor_value[3] * (3.3/4096));
		tempsen[3] = (uint8_t)(((tempvolt[3]*100) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcpostemp_2] = (int)tempsen[3];

		for(i = 0; i < 10; i++)
		{
			for(j = 0; j < i-1; j++)
			{
				if(averaging[4][j] > averaging[4][j+1])
				{
					temp = averaging[4][j];
					averaging[4][j] = averaging[4][j+1];
					averaging[4][j+1] = temp;
				}
			}
		}
		sensor_value[4] = ((averaging[4][4] + averaging[4][5] + averaging[4][6] + averaging[4][7]) / 4);
		tempvolt[4] = (float)(sensor_value[4] * (3.3 / 4096));
		tempsen[4] = (uint8_t)(((tempvolt[4] * 100) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcnegtemp_2] = (int)tempsen[4];
//	#if defined(debugmode)
//			//tempVolta=tempvolt[2];
//			tempseno3=tempsen[3];
//	#endif
	}
//	adcValues[0] = adcValues[1] =adcValues[2]=adcValues[3]=0;
//while(adccmpl ==0)
	adccmpl = 0;
}

/**
  * @brief  ADC conversion complete callback.
  * @param  hadc: pointer to the ADC handle structure
  * @retval None
  */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	static uint8_t avgcnt = 0;
	HAL_ADC_Start_DMA(&hadc2, (uint32_t*) adcValues, 5);

	ch1_averaging += adcValues[3];
	ch2_averaging += adcValues[2];
	ch3_averaging += adcValues[1];
	ch4_averaging += adcValues[0];
	ch5_averaging += adcValues[4];

	avgcnt++;
	if(avgcnt > 9)
	{
		avgcnt = 0;

		tempvolt[0] = (float)(ch1_averaging * (3.3 / 4096));	//scales the ADC value to the voltage range [0, 3.3V]
		tempsen[0] = (uint8_t)(((tempvolt[0] * 10) / vt_factor) - offset); // CHANGED BY RONAK
		can2TX_msg_2[can2TX_exhaustfan] = (int)tempsen[0];
		ch1_averaging = 0;

	#if defined(debugmode)
		tempseno = tempsen[0];
	#endif

		tempvolt[1] = (float)(ch2_averaging * (3.3 / 4096));
		tempsen[1] = (uint8_t)(((tempvolt[1] * 10) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcpostemp] = (int)tempsen[1];
		ch2_averaging = 0;

	#if defined(debugmode)
		tempseno1 = tempsen[1];
	#endif

		tempvolt[2] = (float)(ch3_averaging * (3.3/4096));
		tempsen[2] = (uint8_t)(((tempvolt[2] * 10) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcnegtemp] = (int)tempsen[2];
		ch3_averaging = 0;

	#if defined(debugmode)
		tempseno2 = tempsen[2];
	#endif

		tempvolt[3] = (float)(ch4_averaging * (3.3/4096));
		tempsen[3] = (uint8_t)(((tempvolt[3]*10) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcpostemp_2] = (int)tempsen[3];
		ch4_averaging = 0;

	#if defined(debugmode)
		tempseno3 = tempsen[3];
	#endif

		tempvolt[4] = (float)(ch5_averaging * (3.3 / 4096));
		tempsen[4] = (uint8_t)(((tempvolt[4] * 10) / vt_factor) - offset);
		can2TX_msg_2[can2TX_dcnegtemp_2] = (int)tempsen[4];
		ch5_averaging = 0;
	}
}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
