/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
#include "rtc.h"

#define __STATUS_POWER_ON 1
#define __STATUS_POWER_OFF 2
#define __STATUS_CHARGE_ON 3
#define __STATUS_LOAD_OVERVOLTAGE 4
#define __STATUS_OVERLOAD 5
#define __STATUS_OVERHEATING 6
#define __STATUS_CHARGING_OVERVOLTAGE 7
#define __STATUS_CHARGING_DISCONNET 8
#define __STATUS_HEATING_ON 9
#define __STATUS_HEATING_OFF 10
#define __STATUS_TAKE_BRUSH 11
#define __STATUS_ERROR_1 12
#define __STATUS_ERROR_2 13

#include "generalDefines.h"
#include "stm32f1xx_hal.h"

#include "modDelay.h"
#include "modPowerElectronics.h"
#include "modConfig.h"
#include "modStateOfCharge.h"

#include "driverSWStorageManager.h"

#include "mainDataTypes.h"


#include "DPC_Timeout.h"
#include "GSM.h"

size_t Heap;

modConfigGeneralConfigStructTypedef *generalConfig;
modStateOfChargeStructTypeDef       *generalStateOfCharge;

modPowerElectronicsPackStateTypedef packState;

uint64_t TIM_Clock;
uint64_t Led_Timer;

__IO uint8_t USB_On_Flag;

uint8_t UART_Buffer[1024];
uint8_t UART_Flag;
uint8_t UART_Permission_to_send;

SIM800_Global_Struct SIM800_Struct;
uint8_t CMD_Switch;
SIM800_Op_Commands CMD_SET;

void SIM_Processing();
uint8_t SIM_Module_Init();
SIM800_Op_States SIM_Module_REQUEST(SIM800_Op_Commands* CMD);
__IO uint8_t SS_Ready2Send_Flag;
Time_Struct Current_Time;

__IO uint32_t SS_status_ptr;

//SS_status(1);
//SS_status_ptr++;


uint8_t SS_param() {
	uint8_t result = 0;
	static Time_Struct Event_Time_Stamp;


	//	SIM800_import_time_to_struct(&SIM800_Struct, &SIM800_Struct.BATTERY_DATA.Started_At_Time);
		SIM800_Struct.BATTERY_DATA.Started_At_Time = Event_Time_Stamp;
		SIM800_Struct.BATTERY_DATA.Ended_At_Time = Event_Time_Stamp;

		if(SS_Ready2Send_Flag == 1) {
			RTC_Get_Values(&Event_Time_Stamp);
			SIM800_Struct.BATTERY_DATA.Serial = 20000001;

			SIM800_Struct.BATTERY_DATA.Ended_At_Time.day = Event_Time_Stamp.day;
			SIM800_Struct.BATTERY_DATA.Ended_At_Time.hour = Event_Time_Stamp.hour;
			SIM800_Struct.BATTERY_DATA.Ended_At_Time.minute = Event_Time_Stamp.minute;
			SIM800_Struct.BATTERY_DATA.Ended_At_Time.month = Event_Time_Stamp.month;
			SIM800_Struct.BATTERY_DATA.Ended_At_Time.second = Event_Time_Stamp.second;
			SIM800_Struct.BATTERY_DATA.Ended_At_Time.timezone = Event_Time_Stamp.timezone;
			SIM800_Struct.BATTERY_DATA.Ended_At_Time.year = Event_Time_Stamp.year;
			//SIM800_Struct.BATTERY_DATA.Ended_At_Time = SIM800_Struct.BATTERY_DATA.Event_time;
//			SIM800_Struct.BATTERY_DATA.Ended_At_Time.day = 14;
			SIM800_Struct.BATTERY_DATA.Status_Indication = 14;
			SIM800_Struct.BATTERY_DATA.Energy_Sum = 280;
			SIM800_Struct.BATTERY_DATA.Battery_Level_At_Start = 15;
			SIM800_Struct.BATTERY_DATA.Battery_Level_At_End = 75;
			SIM800_Struct.BATTERY_DATA.Battery_Voltage_At_Start = packState.packVoltage;//packState.cellVoltageLow;
			SIM800_Struct.BATTERY_DATA.Battery_Voltage_At_End = packState.packVoltage - 2;//packState.cellVoltageHigh;
			SIM800_Struct.BATTERY_DATA.Battery_Temperature_At_End = packState.tempBatteryAverage;
			SIM800_Struct.BATTERY_DATA.Maximum_Load_Current = 150;
			SIM800_Struct.BATTERY_DATA.Maximum_Charge_Current = 120;
			SIM800_Struct.BATTERY_DATA.Internal_Resistance = 8.2111011;
			SIM800_Struct.BATTERY_DATA.Moderated = 0;


		//	  SIM800_Struct.BATTERY_DATA.Battery_cond_ID = type;
			  Battery_Data_to_String_Converter(&SIM800_Struct);
			  if(SIM800_Set_Command(&SIM800_Struct, HTTP_PARAMETERS_POST, 30000) == COMMAND_SET) {

				  result = 1;
			  }
		}


	return result;
}


uint8_t SS_status(uint8_t type) {
	static uint32_t prev_ptr = 0;
	uint8_t result = 0;
	static Time_Struct Event_Time_Stamp;

	//if(SS_status_ptr == prev_ptr){

		//Time_Struct Event_Time_Stamp;

		//RTC_Get_Values(&Event_Time_Stamp);

	//	SIM800_Struct.Sim_HTTP_Data.Event_time = SIM800_Time_To_String(&Event_Time_Stamp);
	//	SIM800_Struct.Sim_HTTP_Data.Event_time = "11";
		//SIM800_Struct.Sim_HTTP_Data.Current_time = SIM800_Time_To_String(&TEST_Time);
		//SIM800_Struct.Sim_HTTP_Data.Event_time = SIM800_Struct.Sim_HTTP_Data.Current_time;

		if(SS_Ready2Send_Flag == 1) {
			RTC_Get_Values(&Event_Time_Stamp);

			  //SIM800_Struct.BATTERY_DATA.Event_time = Event_Time_Stamp;
			SIM800_Struct.BATTERY_DATA.Event_time.day = Event_Time_Stamp.day;
			SIM800_Struct.BATTERY_DATA.Event_time.hour = Event_Time_Stamp.hour;
			SIM800_Struct.BATTERY_DATA.Event_time.minute = Event_Time_Stamp.minute;
			SIM800_Struct.BATTERY_DATA.Event_time.month = Event_Time_Stamp.month;
			SIM800_Struct.BATTERY_DATA.Event_time.second = Event_Time_Stamp.second;
			SIM800_Struct.BATTERY_DATA.Event_time.timezone = Event_Time_Stamp.timezone;
			SIM800_Struct.BATTERY_DATA.Event_time.year = Event_Time_Stamp.year;

			  SIM800_Struct.BATTERY_DATA.Battery_cond_ID = 10;
			  Battery_Data_to_String_Converter(&SIM800_Struct);
			//  SIM800_Struct.Sim_HTTP_Data.Event_time = SIM800_Time_To_String(&Event_Time_Stamp);

			  if(SIM800_Set_Command(&SIM800_Struct, HTTP_EVENT_POST, 30000) == COMMAND_SET) {
				  prev_ptr++;
				  result = 1;
			  }
		}

	//}
	return result;
}


void SS_status_power_on() {
	static uint8_t comp_flag;
	static uint8_t time_flag;

//	if(time_flag == 0) {

//		time_flag = 1;
//	}

	if(comp_flag == 0) {
		if(SS_status(__STATUS_POWER_ON)) {
			comp_flag = 1;
		}
	}
}

__IO uint64_t _global_clock;




/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t check_pilot_flag_history = 1;
uint8_t check_minimum_voltage_flag_history = 1;
uint8_t check_maximum_voltage_flag_history = 1;
uint8_t check_maximum_temp_flag_history = 1;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

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

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc2;

CAN_HandleTypeDef hcan1;
CAN_HandleTypeDef hcan2;

DAC_HandleTypeDef hdac;

SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi3;

UART_HandleTypeDef huart2;

TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim6;

uint8_t OVP_counter = 0;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC2_Init(void);
static void MX_CAN1_Init(void);
static void MX_CAN2_Init(void);
static void MX_DAC_Init(void);
static void MX_SPI1_Init(void);
static void MX_SPI3_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM6_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

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

uint32_t last_usb_call = 0;
void usbTIM(uint8_t OnOff) {
	if(OnOff) {
		USB_On_Flag = 1;
		//HAL_TIM_Base_Start_IT(&htim6);
		last_usb_call = HAL_GetTick();
	} else {
		USB_On_Flag = 0;
		//HAL_TIM_Base_Stop_IT(&htim6);
	}
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//	testsi++;


  if (htim->Instance == TIM2)
    {
  	  TimeoutMng();
  	  TIM_Clock++;
    }
  else if (htim->Instance == TIM6)
    {
  	 // HAL_TIM_Base_Stop_IT(&htim6);
  	//  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL3_Pin);
  	  if(USB_On_Flag){
  	     modUARTTask();
  	  }


  	  //TimeoutMng();


  	//  HAL_TIM_Base_Start_IT(&htim6);
    }
}
#define _ON 1
#define _OFF 0
void charge_switch(uint8_t state) {
	if(state){
		HAL_GPIO_WritePin(Output_5_GPIO_Port, Output_5_Pin, 1);
	} else {
		HAL_GPIO_WritePin(Output_5_GPIO_Port, Output_5_Pin, 0);
	}
}

float export_real_capacity;

void load_switch(uint8_t state) {
	if(state){
		HAL_GPIO_WritePin(Output_4_GPIO_Port, Output_4_Pin, 1);
	} else {
		HAL_GPIO_WritePin(Output_4_GPIO_Port, Output_4_Pin, 0);
	}
}

/* USER CODE END 0 */

uint16_t load_current = 0;
uint16_t charge_current = 0;
float float_current = 0;


#define __MA_WIN_SIZE (500)
#define __MA_ARRAY_QTY 2


uint16_t MA_Filter(uint16_t input, uint8_t array)
{
  uint16_t Result = 0;
  static uint32_t ma_n[__MA_ARRAY_QTY];
  static uint32_t ma_array[__MA_ARRAY_QTY][__MA_WIN_SIZE];
  static uint32_t pre_out[__MA_ARRAY_QTY];

  pre_out[array] = pre_out[array] + (input - ma_array[array][ma_n[array]] );
  ma_array[array][ma_n[array]] = input;
  ma_n[array] = (ma_n[array]+1)% __MA_WIN_SIZE;

  Result = (uint32_t)pre_out[array] / __MA_WIN_SIZE;

  return Result;
}

IWDG_HandleTypeDef handleIWDG;

void mainWatchDogReset(void) {

	HAL_IWDG_Refresh(&handleIWDG);

}
void mainWatchDogInitAndStart(void) {


  handleIWDG.Instance = IWDG;
  handleIWDG.Init.Prescaler = IWDG_PRESCALER_64;
 // handleIWDG.Init.Window = 4095;
  handleIWDG.Init.Reload = 4095;
  if (HAL_IWDG_Init(&handleIWDG) != HAL_OK) {
    Error_Handler();
  }
//  HAL_IWDG_
//  if(HAL_IWDG_Start(&handleIWDG) != HAL_OK) {
//    Error_Handler();
//  }

}

float currentZero_config = 0;
//#define _ADC_ZERO 3033
#define _ADC_ZERO currentZero_config

uint16_t export_adc_average_res = 0;


void Get_Shunt_Current() {


	static uint16_t adc;
	static uint16_t adc_average[100];
	static uint8_t adc_average_cnt = 0;
	static uint32_t adc_average_sum = 0;
	static uint32_t adc_average_res = 0;
	currentZero_config = generalConfig->shuntLCFactor;

	HAL_ADC_Start(&hadc2);
		  adc_average_res = MA_Filter((HAL_ADC_GetValue(&hadc2)), 1);
		  export_adc_average_res = adc_average_res;
		  //export_adc_average_res = 3033;


			  if(adc_average_res >= _ADC_ZERO){
				  if((adc_average_res - _ADC_ZERO) > 10) { // load
				  			  //load_current = (adc_average_res - 3060) * 0.34;
				  			  float_current = (adc_average_res - _ADC_ZERO) * 0.777;
				  			  float_current = -float_current;
				  } else {
					  load_current = 0;
					  charge_current = 0;
					  float_current = 0;
				  }
			  } else {
				  if ((_ADC_ZERO - adc_average_res) > 10) {
				  			  //charge_current = ;
				  			  float_current = (_ADC_ZERO - adc_average_res) * 0.777;//charge_current;
				  		  } else {
				  			  load_current = 0;
				  			  charge_current = 0;
				  			  float_current = 0;
				  		  }
			  }

}

void USB_Check_Timeout() {
	  if((HAL_GetTick() - last_usb_call) > 10000) {
		  usbTIM(0);

	  }
}



uint8_t Check_Pilot(){ // 1 - charging // 0 - no charging
	uint8_t res = 0;

	 if(HAL_GPIO_ReadPin(Input_3_GPIO_Port, Input_3_Pin)){
		HAL_GPIO_WritePin(Charging_GPIO_Port, Charging_Pin, 0); // charging
		res = 1;
		return res;

	 } else {
		HAL_GPIO_WritePin(Charging_GPIO_Port, Charging_Pin, 1); // no charging
		res = 0;
		OVP_counter = 0;
		return res;
	 }
}

float cellVoltageLow_Minimum = 0;
float cellVoltageLow_Minimum_Hyst = 0;
float cellVoltageHigh_Maximum = 0;
float cellVoltageHigh_Maximum_Hyst = 0;
float maxChargeCurrent = 0;
float maxLoadCurrent = 0;

float maxTemperature = 0;
float maxTemperature_Hyst = 0;

/*
 *
		modCommandsPrintf("NoOfCells                  : %u",generalConfig->noOfCellsSeries);
		modCommandsPrintf("batteryCapacity            : %.2fAh",generalConfig->batteryCapacity);
		modCommandsPrintf("cellHardUnderVoltage       : %.3fV",generalConfig->cellHardUnderVoltage);
		modCommandsPrintf("cellHardOverVoltage        : %.3fV",generalConfig->cellHardOverVoltage);
		modCommandsPrintf("cellLCSoftUnderVoltage     : %.3fV",generalConfig->cellLCSoftUnderVoltage);
		modCommandsPrintf("cellSoftOverVoltage        : %.3fV",generalConfig->cellSoftOverVoltage);
		modCommandsPrintf("cellBalanceStart           : %.3fV",generalConfig->cellBalanceStart);
 */

uint8_t Check_Maximum_Voltage(){ // 0 - voltage too high // 1 - voltage normal
	static uint8_t res = 1;
	static uint8_t error_counter = 0;
	static uint8_t first_time_normal_flag = 0;
	static uint8_t first_time_error_flag = 0;
	static uint32_t timer_to_normal = 0;
	static uint32_t timer_to_error = 0;
	// 2.2C maximum
	//if(packState.cellVoltageHigh >= 3.65){
		if(packState.cellVoltageHigh >= cellVoltageHigh_Maximum){

		timer_to_normal = 0;
		first_time_normal_flag = 0;
		if(first_time_error_flag == 0) {
			error_counter++;
			first_time_error_flag = 1;
			timer_to_error = HAL_GetTick();
			OVP_counter++;
		} else if ( (( (HAL_GetTick()) - timer_to_error) > 2000) ) {

			res = 0;
		}

	//} else if (packState.cellVoltageHigh < 3.5) {
	} else if (packState.cellVoltageHigh < cellVoltageHigh_Maximum_Hyst) {
		timer_to_error = 0;
		first_time_error_flag = 0;

		if (first_time_normal_flag == 0) {
			first_time_normal_flag = 1;
			timer_to_normal = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_normal) > 5000) ) {
			if(OVP_counter < 3) {
				res = 1;
			}
		}

	}

	return res;
}




uint8_t Check_Minimum_Voltage(){ // 0 - voltage too low // 1 - voltage normal
	static uint8_t res = 1;
	static uint8_t error_counter = 0;
	static uint8_t first_time_normal_flag = 0;
	static uint8_t first_time_error_flag = 0;
	static uint32_t timer_to_normal = 0;
	static uint32_t timer_to_error = 0;
	// 2.2C maximum
	//if(packState.cellVoltageLow <= 2.5){
	if(packState.cellVoltageLow <= cellVoltageLow_Minimum){
		timer_to_normal = 0;
		first_time_normal_flag = 0;

		if(first_time_error_flag == 0) {
			error_counter++;
			first_time_error_flag = 1;
			timer_to_error = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_error) > 2000) ) {
			//check_minimum_voltage_flag_history = 0;
			res = 0;
		}

	//} else if (packState.cellVoltageLow > 2.7) {
	} else if (packState.cellVoltageLow > cellVoltageLow_Minimum_Hyst) {
		timer_to_error = 0;
		first_time_error_flag = 0;

		if (first_time_normal_flag == 0) {
			first_time_normal_flag = 1;
			timer_to_normal = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_normal) > 5000) ) {
			res = 1;
		}

	}

	return res;
}

uint8_t Check_Maximum_Charge_Current(){ // 0 - current too high // 1 - normal
	static uint8_t res = 1;
	static uint8_t error_counter = 0;
	static uint8_t first_time_normal_flag = 0;
	static uint8_t first_time_error_flag = 0;
	static uint32_t timer_to_normal = 0;
	static uint32_t timer_to_error = 0;
	// 1C
	//if(float_current >= 144){
	if(float_current >= maxChargeCurrent){

		timer_to_normal = 0;
		first_time_normal_flag = 0;
		if(first_time_error_flag == 0) {
			error_counter++;
			first_time_error_flag = 1;
			timer_to_error = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_error) > 2000) ) {
			res = 0;
		}

	//} else if (float_current < 144) {
	} else if (float_current < maxChargeCurrent) {

		timer_to_error = 0;
		first_time_error_flag = 0;

		if (first_time_normal_flag == 0) {
			first_time_normal_flag = 1;
			timer_to_normal = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_normal) > 5000) ) {

			res = 1;
		}

	}

	return res;
}

uint8_t Check_Maximum_Load_Current(){ // // 0 - current too high // 1 - normal
	static uint8_t res = 1;
	static uint8_t error_counter = 0;
	static uint8_t first_time_normal_flag = 0;
	static uint8_t first_time_error_flag = 0;
	static uint32_t timer_to_normal = 0;
	static uint32_t timer_to_error = 0;
	// 2.2C maximum
	//if(float_current <= -315){
	if(float_current <= -maxLoadCurrent){
		timer_to_normal = 0;
		first_time_normal_flag = 0;
		if(first_time_error_flag == 0) {
			error_counter++;
			first_time_error_flag = 1;
			timer_to_error = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_error) > 2000) ) {
			res = 0;
		}

	//} else if (float_current > -315) {
	} else if (float_current > -maxLoadCurrent) {
		timer_to_error = 0;
		first_time_error_flag = 0;

		if (first_time_normal_flag == 0) {
			first_time_normal_flag = 1;
			timer_to_normal = HAL_GetTick();
		} else if (  (( (HAL_GetTick()) - timer_to_normal) > 5000) ) {

			res = 1;
		}

	}

	return res;
}

uint8_t Check_Maximum_Temp() { // 0 - too hot // 1 - normal
	static uint8_t res = 1;
	static uint8_t error_counter = 0;
	static uint8_t first_time_normal_flag = 0;
	static uint8_t first_time_error_flag = 0;
	static uint32_t timer_to_normal = 0;
	static uint32_t timer_to_error = 0;
	// 2.2C maximum
	if(packState.tempBatteryHigh >= maxTemperature){
		timer_to_normal = 0;
		first_time_normal_flag = 0;
		if(first_time_error_flag == 0) {
			error_counter++;
			first_time_error_flag = 1;
			timer_to_error = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_error) > 5000) ) {
			res = 0;
		}

	} else if (packState.tempBatteryHigh < maxTemperature_Hyst) {
		timer_to_error = 0;
		first_time_error_flag = 0;

		if (first_time_normal_flag == 0) {
			first_time_normal_flag = 1;
			timer_to_normal = HAL_GetTick();
		} else if ( (( (HAL_GetTick()) - timer_to_normal) > 5000) ) {

			res = 1;
		}

	}

	return res;
}

void Display_Control() {
	uint32_t voltage_out = 0;
// 2700 - 100%
	// x - soc
	// soc = 100x/2700
	// x = 2700soc/100
	 // voltage_out =  packState.SoC * 100 / 2685;
	//voltage_out =  100 * 100 / 2685;
		//voltage_out =  100 * 4.95 / 100 * 2685 / 4.95;

//	voltage_out = 2685 * packState.SoC / 100;
		voltage_out = 2481 * packState.SoC / 100;

	//voltage_out = 2481 * 6 / 100;
//	voltage_out = 2400;


	//voltage_out = 2685 * 100 / 100;
		//voltage_out = 2685;

	  HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
	  HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,voltage_out);
}

void Do_Balance() {
	if (packState.cellVoltageMisMatch > 0) {

	}
}

void heart_beat(){
	static uint32_t timer = 0;
	if(( (HAL_GetTick()) - timer ) > 500) {
		  //HAL_GPIO_TogglePin(HL3_GPIO_Port, HL3_Pin);
		  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL3_Pin);
		//  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL1_Pin);
		  //HAL_GPIO_TogglePin(HL2_GPIO_Port, HL2_Pin);
		  timer = HAL_GetTick();
	}
}

	uint8_t load_switch_state = 0;
	uint8_t charge_switch_state = 0;
/**
  * @brief  The application entry point.
  * @retval int
  */

	uint8_t Pilot_Status = 0;
	uint8_t Maximum_Charge_Current_Status = 0;
	uint8_t Maximum_Voltage_Status = 0;
	uint8_t Maximum_Temp_Status = 0;
	uint8_t Maximum_Load_Current_Status = 0;
	uint8_t Minimum_Voltage_Status = 0;


void Check_Status() {

	Pilot_Status = Check_Pilot();
	Maximum_Charge_Current_Status = Check_Maximum_Charge_Current();
	Maximum_Voltage_Status = Check_Maximum_Voltage();
	Maximum_Temp_Status = Check_Maximum_Temp();
	Maximum_Load_Current_Status = Check_Maximum_Load_Current();
	Minimum_Voltage_Status = Check_Minimum_Voltage();

}

void updateLimitsFromMem(){
	/*
	    uint8_t cellVoltageLow_Minimum = 0;
		uint8_t cellVoltageLow_Minimum_Hyst = 0;
		uint8_t cellVoltageHigh_Maximum = 0;
		uint8_t cellVoltageHigh_Maximum_Hyst = 0;
		uint8_t maxChargeCurrent = 0;
		uint8_t maxLoadCurrent = 0;
	 */

	//modPowerElectronicsGeneralConfigHandle->cellBalanceStart
	/*
	 cellHardUnderVoltage
cellHardOverVoltage
cellSoftOverVoltage
cellLCSoftUnderVoltage
maxAllowedCurrent
maxMismatchThreshold


		modCommandsPrintf("NoOfCells                  : %u",generalConfig->noOfCellsSeries);
		modCommandsPrintf("batteryCapacity            : %.2fAh",generalConfig->batteryCapacity);
		modCommandsPrintf("cellHardUnderVoltage       : %.3fV",generalConfig->cellHardUnderVoltage);
		modCommandsPrintf("cellHardOverVoltage        : %.3fV",generalConfig->cellHardOverVoltage);
		modCommandsPrintf("cellLCSoftUnderVoltage     : %.3fV",generalConfig->cellLCSoftUnderVoltage);
		modCommandsPrintf("cellSoftOverVoltage        : %.3fV",generalConfig->cellSoftOverVoltage);
		modCommandsPrintf("cellBalanceStart           : %.3fV",generalConfig->cellBalanceStart);

	 */

    cellVoltageLow_Minimum = generalConfig->cellHardUnderVoltage;
	cellVoltageLow_Minimum_Hyst = generalConfig->cellLCSoftUnderVoltage;
	cellVoltageHigh_Maximum = generalConfig->cellHardOverVoltage;
	cellVoltageHigh_Maximum_Hyst = generalConfig->cellSoftOverVoltage;
	maxChargeCurrent = generalConfig->maxAllowedCurrent;
	maxLoadCurrent = generalConfig->maxMismatchThreshold;


	maxTemperature = generalConfig->allowedTempBattChargingMax;
	maxTemperature_Hyst = generalConfig->allowedTempBattChargingMin;
}

float Brush_Minimum_SoC = 0;
uint8_t Brush_Default_State = 0;

void Brush_Control() {
	//Output_2_Pin GPIO_PIN_2
	//Output_2_GPIO_Port GPIOE

	Brush_Minimum_SoC = generalConfig->minimalPrechargePercentage;
	Brush_Default_State = generalConfig->timeoutLCPreCharge;

	if(packState.SoC < Brush_Minimum_SoC) {
		HAL_GPIO_WritePin(Output_2_GPIO_Port, Output_2_Pin, !Brush_Default_State);
	} else {
		HAL_GPIO_WritePin(Output_2_GPIO_Port, Output_2_Pin, Brush_Default_State);
	}
}

void modem_init(){

	  SIM800_Var_Init(&SIM800_Struct);
	  HTTP_Data_Init(&SIM800_Struct);
	  DPC_TO_Init();
	//  HAL_Delay(2000);
	  HAL_UARTEx_ReceiveToIdle_IT(&huart2, (uint8_t*)UART_Buffer, 1023);
	  DPC_TO_Set(TO_LED,1000);
	  DPC_TO_Set(TO_UART,100);
	  DPC_TO_Set(TO_SIM_TIMEOUT, 60000);

	  HAL_GPIO_WritePin(GSM_RST_GPIO_Port, GSM_RST_Pin, GPIO_PIN_SET);

	  SIM800_Struct.Default_Longitude = "-115.812477";
	  SIM800_Struct.Default_Latitude = "37.236992";


//	  SIM800_Struct.Sim_HTTP_Data.Serial_Number = "20000054";
//	  SIM800_Struct.Sim_HTTP_Data.Battery_Condition_ID = "2";
//	  SIM800_Struct.Sim_HTTP_Data.Event_time = "2021-11-10T17:59:12+0000";
//	  SIM800_Struct.Sim_HTTP_Data.Started_At_Time = "2021-11-10T17:59:12+0000";
//	  SIM800_Struct.Sim_HTTP_Data.Ended_At_Time = "2021-11-10T18:59:12+0000";
//	  SIM800_Struct.Sim_HTTP_Data.Status_Indication = "13";
//	  SIM800_Struct.Sim_HTTP_Data.Energy_Sum = "290";
//	  SIM800_Struct.Sim_HTTP_Data.Battery_Level_At_Start= "10";
//	  SIM800_Struct.Sim_HTTP_Data.Battery_Level_At_End = "99";
//	  SIM800_Struct.Sim_HTTP_Data.Battery_Voltage_At_Start = "23.1";
//	  SIM800_Struct.Sim_HTTP_Data.Battery_Voltage_At_End = "28.0";
//	  SIM800_Struct.Sim_HTTP_Data.Battery_Temperature_At_End= "25";
//	  SIM800_Struct.Sim_HTTP_Data.Maximum_Load_Current = "160";
//	  SIM800_Struct.Sim_HTTP_Data.Maximum_Charge_Current = "120";
//	  SIM800_Struct.Sim_HTTP_Data.Internal_Resistance = "8.2111011";
//	  SIM800_Struct.Sim_HTTP_Data.Moderated = "false";

		SIM800_Struct.BATTERY_DATA.Serial = 20000001;
		SIM800_Struct.BATTERY_DATA.Battery_cond_ID = 5;
		SIM800_Struct.BATTERY_DATA.Event_time.day = 21;
		SIM800_Struct.BATTERY_DATA.Event_time.month = 12;
		SIM800_Struct.BATTERY_DATA.Event_time.year = 21;
		SIM800_Struct.BATTERY_DATA.Started_At_Time = SIM800_Struct.BATTERY_DATA.Event_time;
		SIM800_Struct.BATTERY_DATA.Started_At_Time.day = 13;
		SIM800_Struct.BATTERY_DATA.Ended_At_Time = SIM800_Struct.BATTERY_DATA.Event_time;
		SIM800_Struct.BATTERY_DATA.Ended_At_Time.day = 14;
		SIM800_Struct.BATTERY_DATA.Status_Indication = 14;
		SIM800_Struct.BATTERY_DATA.Energy_Sum = 280;
		SIM800_Struct.BATTERY_DATA.Battery_Level_At_Start = 15;
		SIM800_Struct.BATTERY_DATA.Battery_Level_At_End = 75;
		SIM800_Struct.BATTERY_DATA.Battery_Voltage_At_Start = 23.6;
		SIM800_Struct.BATTERY_DATA.Battery_Voltage_At_End = 27.5;
		SIM800_Struct.BATTERY_DATA.Battery_Temperature_At_End = 22;
		SIM800_Struct.BATTERY_DATA.Maximum_Load_Current = 150;
		SIM800_Struct.BATTERY_DATA.Maximum_Charge_Current = 120;
		SIM800_Struct.BATTERY_DATA.Internal_Resistance = 8.2111011;
		SIM800_Struct.BATTERY_DATA.Moderated = 0;

		Battery_Data_to_String_Converter(&SIM800_Struct);
		//HAL_GPIO_WritePin(GSM_RST_GPIO_Port, GSM_RST_Pin, GPIO_PIN_RESET);

//	  SS_status(__STATUS_POWER_ON);

}

void hueta(){
// entre 1000 ms
	if (DPC_TO_Check(TO_LED)==TO_OUT_TOOK){
			HAL_GPIO_TogglePin(HL2_GPIO_Port, HL2_Pin);
			DPC_TO_Set(TO_LED,1000);


			if (CMD_Switch==0) CMD_SET = GET_GPS_COORDINATES;
			else if (CMD_Switch==1) CMD_SET = HTTP_EVENT_POST;
			else if (CMD_Switch==2) CMD_SET = HTTP_PARAMETERS_POST;
			else CMD_Switch=0;

		//	if (SIM800_Set_Command(&SIM800_Struct, CMD_SET, 30000)==COMMAND_SET){
		//		HAL_GPIO_TogglePin(HL4_GPIO_Port, HL4_Pin);
		//		CMD_Switch++;
		//	}
		}

		SIM800_Processing(&SIM800_Struct, &UART_Buffer);

}

uint8_t SS_Sync_Time(){

	static uint8_t comp_flag = 0;
	static uint64_t last_ask = 0;
	static uint8_t asked = 0;

	if( asked == 0 ) {
		  if(SIM800_Set_Command(&SIM800_Struct, GET_TIME, 30000) == COMMAND_SET){
			  if(SIM800_Struct.Sim_Stages_List == READY_TO_OPERATE) {
				  SIM800_import_time_to_struct(&SIM800_Struct, &Current_Time);
				  RTC_Set_Values(&Current_Time);

				  asked = 1;
				  last_ask = HAL_GetTick();

				  comp_flag = 1;
			  }
		  }
	} else if( (asked == 1) && ((HAL_GetTick() - last_ask) >= 30000) ) {
		asked = 0;
		comp_flag = 0;
	}

	return comp_flag;
}


uint8_t SS_Sync_GPS(){

	static uint8_t comp_flag = 0;
	static uint64_t last_ask = 0;
	static uint8_t asked = 0;

	if( asked == 0 ) {
		  if(SIM800_Set_Command(&SIM800_Struct, GET_GPS_COORDINATES, 30000) == COMMAND_SET){
			  if(SIM800_Struct.Sim_Stages_List == READY_TO_OPERATE) {

				  asked = 1;
				  last_ask = HAL_GetTick();

				  comp_flag = 1;
			  }
		  }
	} else if( (asked == 1) && ((HAL_GetTick() - last_ask) >= 30000) ) {
		asked = 0;
		comp_flag = 0;
	}

	return comp_flag;
}

void SS_Pilot_Status_ON(){
	  static uint8_t prev_pilot = 0;
	  static uint8_t pilot_changed = 0;
	  static uint8_t param_flag = 0;

	  if (prev_pilot != Pilot_Status)  {
			  pilot_changed = 1;
	  }

	  if( (pilot_changed) && (param_flag == 0) ){
		  if( SS_status(__STATUS_CHARGE_ON) ){
			  pilot_changed = 0;
			  prev_pilot = Pilot_Status;
			  param_flag = 1;
		  }
	  }

	  if( (pilot_changed == 0) && (param_flag == 1) ){
		  if( SS_param() ){
			 // pilot_changed = 0;
			  param_flag = 0;
		  }
	  }
}


void SS_Pilot_Status_OFF(){
	  static uint8_t prev_pilot = 0;
	  static uint8_t pilot_changed = 0;
	  static uint8_t param_flag = 0;

	  if (prev_pilot != Pilot_Status)  {
			  pilot_changed = 1;
	  }


	  if( (pilot_changed) && (param_flag == 0) ){
		  if( SS_status(__STATUS_CHARGING_DISCONNET) ){
			  pilot_changed = 0;
			  prev_pilot = Pilot_Status;
			  param_flag=1;
		  }
	  }

	  if( (pilot_changed == 0) && (param_flag == 1) ){
		  if( SS_param() ){
			 // pilot_changed = 0;
			  param_flag = 0;
		  }
	  }
}

#define __GRT_PERIOD 1800000

void Global_Reset_Timer(uint32_t time) {
	  if (TIM_Clock>=time){
		  NVIC_SystemReset();
	  }
}

#define __TO_TIME_ON 30000
#define __TO_TIME_OFF 60000

void Test_Output(uint32_t time_on, uint32_t time_off) {
	  static uint32_t last_switch_time = 0;
	  static uint8_t state = 0;

	  if( (state == 0) && ( (HAL_GetTick() - last_switch_time) > time_on) ) {
		  HAL_GPIO_WritePin(Output_3_GPIO_Port, Output_3_Pin, GPIO_PIN_SET);
		  state = 1;
		  last_switch_time = HAL_GetTick();
	  }

	  if( (state == 1) && ( (HAL_GetTick() - last_switch_time) > time_off) ) {
		  HAL_GPIO_WritePin(Output_3_GPIO_Port, Output_3_Pin, GPIO_PIN_RESET);
		  state = 2;
		  last_switch_time = HAL_GetTick();
	  }

}


int main(void)
{

	static uint32_t last_ss = 0;
  /* USER CODE BEGIN 1 */
	// balance >3.6, 0.06 in charge state

	// TODO:
	// check balance
	// check watchdog
	// how to update firmware without clean flash
	// add serial number
	// sileint mode for debug, remove after power off
	// 	INDICATOR: toggle led if >=5
	// capacity from last 100%
	// soh calc // when charge connected
	// save states of conditions to control switches
	// send status of state to PC
	// remaining capacity in current charging time // compare remaining capacity to total
	// current in interface
	// state of balance
	// set current sensor to zero
	// --time delay at all positions in charge/discharge
	// maximum capcacity: (Ah in - Ah out) when 3.65 -soh
	//
	// check balance resistors - some cells are dummy some are note



	// 15:19 start charge
	//


	// test soc
	// what about soh
	// turn off due current due time - charge/discharge
	// check current coef
	// balance
	// each cell viewer
	// serial number of battery

	// switch off 2.5, switch on 2.7

	// switch off 3.65, switch on 3.45

	/* conditions to turn on load switch:
	 * no pilot
	 * min battery voltage > 2.7
	 * max battery voltage < 3.65
	 */
	// turn on load switch if: pilot && voltage<max && current<max
	// turn off low/high, hysteresis, time after turn off, calc errors


  /* 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();
  //HAL_Delay(2000);

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
//  HAL_GPIO_WritePin(GSM_RST_GPIO_Port, GSM_RST_Pin, GPIO_PIN_RESET);

	HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_SET);
	HAL_Delay(1000);
	HAL_GPIO_WritePin(HL2_GPIO_Port, HL2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL3_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(HL5_GPIO_Port, HL5_Pin, GPIO_PIN_RESET);
	HAL_Delay(1000);


  MX_RTC_Init();

  MX_ADC2_Init();

 // MX_CAN1_Init();
//HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, 1);
//  MX_CAN2_Init();
  MX_DAC_Init();

  MX_SPI1_Init();
//  MX_SPI3_Init();
  MX_USART2_UART_Init();
  MX_USB_DEVICE_Init();
  MX_TIM6_Init();
  MX_TIM2_Init();
 // mainWatchDogInitAndStart();
  //HAL_Delay(2000);
  modem_init();

  /* USER CODE BEGIN 2 */

	generalConfig            = modConfigInit();																// Tell EEPROM the needed size for ConfigStruct
	generalStateOfCharge     = modStateOfChargeInit(&packState,generalConfig);								// Tell EEPROM the needed size for StatOfChargeStruct
	driverSWStorageManagerInit();																			// Initializes EEPROM Memory
	modConfigStoreAndLoadDefaultConfig();																	// Store default config if needed -> load config from EEPROM
	modStateOfChargeStoreAndLoadDefaultStateOfCharge();														// Determin SoC from cell voltage if needed -> load StateOfCharge from EEPROM

	modPowerStateSetConfigHandle(generalConfig);

	modCommandsInit(&packState,generalConfig);



	modUARTInit();																	  												// Will act on UART message requests
	modPowerElectronicsInit(&packState,generalConfig);
	modOperationalStateInit(&packState,generalConfig,generalStateOfCharge);


 // HAL_GPIO_TogglePin(HL2_GPIO_Port, HL2_Pin);
  /* Infinite loop */
 // uint8_t testDataToSend[8];
//  for (uint8_t i = 0; i < 8; i++)
//  {
 //     testDataToSend[i] = i;
 // }

	//run after uart
	HAL_TIM_Base_Start_IT(&htim6);
	HAL_TIM_Base_Start_IT(&htim2);
  /* USER CODE BEGIN WHILE */

  while (1)
  {
	  //NVIC_SystemReset();
	//  mainWatchDogReset();
	//  hueta(); //PRIMER EPTA

	  SIM800_Processing(&SIM800_Struct, &UART_Buffer);

	  Global_Reset_Timer(__GRT_PERIOD);

	  Test_Output(__TO_TIME_ON, __TO_TIME_OFF);


	  if(SIM800_Struct.Sim_Main_States.GPRS_Established == 1) {
		  HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
		  if( SS_Sync_Time() ){
			  SS_Ready2Send_Flag = 1;
		  }

		  SS_Sync_GPS();

//		  if( (HAL_GetTick() - last_ss) > 10000 ) {
			  SS_status_power_on();
//			  last_ss = HAL_GetTick();
//		  }

	  }
	  else HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);


	//  HAL_Delay(100);


	  heart_beat();

	  Get_Shunt_Current();
	  USB_Check_Timeout();

	  updateLimitsFromMem();

	  // indicator control
	  Display_Control();
//	  packState.cellVoltageHigh;



//		Pilot_Status = Check_Pilot();
//		Maximum_Charge_Current_Status = Check_Maximum_Charge_Current();
//		Maximum_Voltage_Status = Check_Maximum_Voltage();
//		Maximum_Temp_Status = Check_Maximum_Temp();
//		Maximum_Load_Current_Status = Check_Maximum_Load_Current();
//		Minimum_Voltage_Status = Check_Minimum_Voltage();

	  Check_Status();

	  //Pilot_Status 1 - charge
	  SS_Pilot_Status_ON();
	  SS_Pilot_Status_OFF();


		if ( ((Pilot_Status) == 1) &&  						// charge
			 ((Maximum_Charge_Current_Status) == 1) && 		// current above max
			 ((Maximum_Voltage_Status) == 1) &&    			// voltage above max
			 ((Maximum_Temp_Status) == 1) ) {   				// temp above max


			charge_switch(_ON);
			load_switch(_OFF);

			charge_switch_state = 1;
			load_switch_state = 0;

		} else if ( ((Pilot_Status) == 0) &&  					// no charge
				   ((Maximum_Load_Current_Status) == 1) &&     // current above max
				   ((Minimum_Voltage_Status) == 1) &&      	// voltage higher min
				   ((Maximum_Temp_Status) == 1) ) {        	// temp above max

			load_switch(_ON);
			charge_switch(_OFF);

			charge_switch_state = 0;
			load_switch_state = 1;

		} else {

			if( (Check_Maximum_Voltage() == 0) &&
			    (Check_Pilot()           == 1) )		{
				modStateOfChargeVoltageEvent(EVENT_FULL);
			}

			load_switch(_OFF);
			charge_switch(_OFF);

			charge_switch_state = 0;
			load_switch_state = 0;
		}

		Brush_Control();


		// try to comment out state task !!!
	//	modPowerStateTask();

		// try to comment out state task !!!
	//	modOperationalStateTask();

	//modPowerElectronicsCellMonitorsEnableBalanceResistors(0x00);
		//modPowerElectronicsCellMonitorsEnableBalanceResistors(0x00000f80);

		// balance is disable
		if(modPowerElectronicsTask())
			// !!! check how works eeprom save !!! // Handle power electronics task
			modStateOfChargeProcess();

																							// If there is new data handle SoC estimation
	//	mainWatchDogReset();

  }
  /* USER CODE END 3 */
}

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

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
  RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
  RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
  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_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC
                              |RCC_PERIPHCLK_USB;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV3;




  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the Systick interrupt time
  */
  __HAL_RCC_PLLI2S_ENABLE();
}

void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 71;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}


static void MX_TIM6_Init(void)
{

  /* USER CODE BEGIN TIM6_Init 0 */

  /* USER CODE END TIM6_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM6_Init 1 */

  /* USER CODE END TIM6_Init 1 */
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 71;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 999;
  htim6.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM6_Init 2 */

  /* USER CODE END TIM6_Init 2 */

}

/**
  * @brief ADC2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC2_Init(void)
{

  /* USER CODE BEGIN ADC2_Init 0 */

  /* USER CODE END ADC2_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC2_Init 1 */

  /* USER CODE END ADC2_Init 1 */
  /** Common config
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_10;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */

  /* USER CODE END ADC2_Init 2 */

}

/**
  * @brief CAN1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_CAN1_Init(void)
{

  /* USER CODE BEGIN CAN1_Init 0 */

  /* USER CODE END CAN1_Init 0 */

  /* USER CODE BEGIN CAN1_Init 1 */

  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 16;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_1TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = DISABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN1_Init 2 */

  /* USER CODE END CAN1_Init 2 */

}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
	if ( huart->Instance == USART2){
		SIM800_Interrupt_Handler(&SIM800_Struct,(uint8_t*)UART_Buffer,Size);
		HAL_UARTEx_ReceiveToIdle_IT(&huart2, (uint8_t*)UART_Buffer, 1023);
	}
}

/**
  * @brief CAN2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_CAN2_Init(void)
{

  /* USER CODE BEGIN CAN2_Init 0 */

  /* USER CODE END CAN2_Init 0 */

  /* USER CODE BEGIN CAN2_Init 1 */

  /* USER CODE END CAN2_Init 1 */
  hcan2.Instance = CAN2;
  hcan2.Init.Prescaler = 16;
  hcan2.Init.Mode = CAN_MODE_NORMAL;
  hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan2.Init.TimeSeg1 = CAN_BS1_1TQ;
  hcan2.Init.TimeSeg2 = CAN_BS2_1TQ;
  hcan2.Init.TimeTriggeredMode = DISABLE;
  hcan2.Init.AutoBusOff = DISABLE;
  hcan2.Init.AutoWakeUp = DISABLE;
  hcan2.Init.AutoRetransmission = DISABLE;
  hcan2.Init.ReceiveFifoLocked = DISABLE;
  hcan2.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN2_Init 2 */

  /* USER CODE END CAN2_Init 2 */

}

/**
  * @brief DAC Initialization Function
  * @param None
  * @retval None
  */
static void MX_DAC_Init(void)
{

  /* USER CODE BEGIN DAC_Init 0 */

  /* USER CODE END DAC_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC_Init 1 */

  /* USER CODE END DAC_Init 1 */
  /** DAC Initialization
  */
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  {
    Error_Handler();
  }
  /** DAC channel OUT1 config
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN DAC_Init 2 */

  /* USER CODE END DAC_Init 2 */

}

/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief SPI3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI3_Init(void)
{

  /* USER CODE BEGIN SPI3_Init 0 */

  /* USER CODE END SPI3_Init 0 */

  /* USER CODE BEGIN SPI3_Init 1 */

  /* USER CODE END SPI3_Init 1 */
  /* SPI3 parameter configuration*/
	  hspi3.Instance = SPI3;
	  hspi3.Init.Mode = SPI_MODE_MASTER;
	  hspi3.Init.Direction = SPI_DIRECTION_2LINES;
	  hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
	  hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
	  hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
	  hspi3.Init.NSS = SPI_NSS_HARD_OUTPUT;
	  hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
	  hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
	  hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
	  hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	  hspi3.Init.CRCPolynomial = 7;
  if (HAL_SPI_Init(&hspi3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI3_Init 2 */

  /* USER CODE END SPI3_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOE, Output_2_Pin|Output_3_Pin|Output_4_Pin|Output_5_Pin
                          |GSM_RST_Pin|HL4_Pin|HL5_Pin|HL3_Pin|HL2_Pin|Output_0_Pin
                          |Output_1_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SPI3_CS_GPIO_Port, SPI3_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(Charging_GPIO_Port, Charging_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : Output_2_Pin Output_3_Pin Output_4_Pin Output_5_Pin
                           HL3_Pin HL2_Pin Output_0_Pin Output_1_Pin */
  GPIO_InitStruct.Pin = Output_2_Pin|Output_3_Pin|Output_4_Pin|Output_5_Pin
		  |HL5_Pin|HL3_Pin|HL4_Pin|HL2_Pin|Output_0_Pin|Output_1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pin : PE6 */
  GPIO_InitStruct.Pin = GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pin : SD_CD_Pin */
  GPIO_InitStruct.Pin = SD_CD_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(SD_CD_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : SPI3_CS_Pin */
  GPIO_InitStruct.Pin = SPI3_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(SPI3_CS_GPIO_Port, &GPIO_InitStruct);

//	GPIO_InitStruct.Pin = LTC6804_CS_Pin;
//GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
//GPIO_InitStruct.Pull = GPIO_NOPULL;
//GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
//GPIO_InitStruct.Alternate = 0;
//HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : Input_1_Pin Input_2_Pin Input_3_Pin */
  GPIO_InitStruct.Pin = Input_1_Pin|Input_2_Pin|Input_3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /*Configure GPIO pin : GSM_RST_Pin */
  GPIO_InitStruct.Pin = GSM_RST_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GSM_RST_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : SD_CS_Pin */
  GPIO_InitStruct.Pin = SD_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(SD_CS_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : Charging_Pin */
  GPIO_InitStruct.Pin = Charging_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(Charging_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

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

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
