/* 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"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "can_comm.h"
#include "modbus.h"
/* USER CODE END Includes */

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

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define GUN1_RED_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_BLUE_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_RED_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_BLUE_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-----------
//uint16_t cp_val = 0;
//uint32_t adc1_dat[3];
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];
volatile int averaging[ADC_BUFFER_SIZE][10], sensor_value[ADC_BUFFER_SIZE];
volatile float tempvolt[ADC_BUFFER_SIZE];
volatile uint8_t tempsen[ADC_BUFFER_SIZE];
volatile char update_modbus = 1;

volatile uint8_t temp_min = 35, temp_max = 55;
uint8_t adccmpl = 0, offset = 30, stop_fanpwm = 0;
float vt_factor = 2.657;
volatile uint8_t redsts = 0, bluests = 0, greensts = 0, change = 0, bluests1 = 0, greensts1 = 0;
extern uint8_t fanstart;
extern volatile char tempchange;
extern uint16_t Dutycycle;

extern volatile uint8_t SWstatus;
extern volatile uint8_t SWstatus_2;

//static volatile char debug_buffer[40] = {0};

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);

#if target == gun1
	start_fan();
#endif
	//fanstart = 3;
	HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adcValues, 5);
	HAL_UART_Receive_DMA(&huart1,(uint8_t*)rxmsg,9);
#if target == gun1
	HAL_Delay(5000);
	HAL_UART_Transmit_IT(&huart1, (uint16_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 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(imdFrameTxFlag == 1)
		{
			if(redsts == 1)
			{
				redsts = 0;
				bluests = 0;
				greensts = 1;
			}
			else if(greensts == 1)
			{
				greensts = 0;
				bluests = 1;
				redsts = 0;
			}
			else if(bluests == 1)
			{
				bluests =greensts= 0;
				redsts = 1;
			}
			else
			{
				redsts = 1;
			}

			txmsg[0] = 1;
			txmsg[1] = 0x10;
			txmsg[2] = 0x0000;
			//for IMD txmsg[3]
			txmsg[4] = SWstatus;
			txmsg[11] = CRC16((unsigned char *)txmsg, 20);

			unsigned char transmit[10]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
			// HAL_UART_Transmit_DMA(&huart1, (uint16_t*)txmsg, 24);
			HAL_UART_Transmit(&huart1, (uint8_t*)transmit,sizeof(transmit),0xffff);

			HAL_Delay(10);
			can2_tx_frame();
			txmsg[3] = 0x00;
			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;
				GUN2_GREEN_LED_ON;
			}
			else if(bluests == 1)
			{
				GUN1_BLUE_LED_ON;
				GUN2_BLUE_LED_ON;
			}
		}

#if target == gun1

		if(tempchange == 1)
		{
			tempchange = 0;
			if(txmsg[5] == 0x0000)
			{
				ALL_RELAYON;
				txmsg[5] = 0x007F;
			}
			else if(txmsg[5] == 0x007F)
			{
				ALL_RELAYOFF
				txmsg[5] = 0x0000;
			}
			else
			{
				txmsg[5] = 0x0000;
			}
		}
#endif

		if(adcsmp == 1)
		{
			adcsmp = 0;
			Read_temp();
		}
	}

	/* 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
	 	txmsg[6] = (int)tempsen[0];

#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);
		txmsg[7] = (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);
		txmsg[8] = (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);
		txmsg[9] = (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);
		txmsg[10] = (int)tempsen[4];
	}
	adccmpl = 0;
}

/**
  * @brief  ADC conversion complete callback.
  * @param  hadc: pointer to the ADC handle structure
  * @retval None
  */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
//	HAL_ADC_Start_DMA(&hadc2, (uint32_t*) adcValues, 4);
//	sensorVal=adcValues[0];
//	tempvolt[0]=(float)(sensorVal*(3.3/4096));
//	tempsen[0]=(float)((tempvolt[0]*100)/vt_factor)+offset;
//	adcValues[0] = adcValues[1] =adcValues[2]=adcValues[3]=0;
	adccmpl = 1;
 }

/* 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 */
