/* 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"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "stdint.h"
#include "generalDefines.h"
#include "stm32f1xx_hal.h"
#include "modDelay.h"
#include "modFlash.h"
#include "modPowerElectronics.h"
#include "modConfig.h"
#include "modStateOfCharge.h"
#include "modUART.h"
#include "driverSWStorageManager.h"
#include "mainDataTypes.h"
#include "DPC_Timeout.h"
#include "GSM.h"
#include "time.h"

#include "../../Libs/CAN/can.h"
#include "../../Libs/CAN/can_messenger.h"

#include "SD_Card.h"

#define LoByte(param) ((uint8_t *)&param)[0]
#define HiByte(param) ((uint8_t *)&param)[1]

#define LoLoWord(param) ((uint16_t *)&param)[0]
#define LoHiWord(param) ((uint16_t *)&param)[1]
#define HiLoWord(param) ((uint16_t *)&param)[2]
#define HiHiWord(param) ((uint16_t *)&param)[3]

#define LoWord(param) ((uint32_t *)&param)[0]
#define HiWord(param) ((uint32_t *)&param)[1]

#define __DEEP_DISCHARGE_RATIO	0.8						//As a percent of undervoltage
#define __STATUS_POWER_ON 1
#define __STATUS_POWER_OFF 2
#define __STATUS_CHARGE_ON 3							//Pilot contact exist
#define __STATUS_CELL_UNDERVOLTAGE 4					//Cell below discharge level
#define __STATUS_OVERLOAD 5								//Load current too high
#define __STATUS_OVERHEATING 6							//Temp too high
#define __STATUS_CHARGING_OVERVOLTAGE 7					//Cell voltage above max level
#define __STATUS_CHARGING_DISCONNECT 8					//Pilot contact disconnect
#define __STATUS_HEATING_ON 9							//
#define __STATUS_HEATING_OFF 10							//
#define __STATUS_TAKE_BRUSH 11							//Brush is in the upper state
#define __STATUS_ERROR_1 12
#define __STATUS_ERROR_2 13

#define __GLSTATUS_SHUTDOWN 1
#define __GLSTATUS_IDLE 2
#define __GLSTATUS_WORKING 3
#define __GLSTATUS_CHARGING 4
#define __GLSTATUS_ERROR 5


#define __DEFAULT_BATTERY_RESISTANCE 0.0
#define __BACKUP_TIMEOUT 30000
#define __GRT_PERIOD 600000//3600000
#define __DELAY_FOR_SIM 30000
//#define __GRT_PERIOD 600000

#define _ON 1
#define _OFF 0

#define __BLINK_INIT 			1000
#define __BLINK_GSM_AND_SD_OK 	500
#define __BLINK_SD_OK_NO_GSM 	250
#define __BLINK_GSM_OK_NO_SD 	750
#define __BLINK_ERROR			100

#define __SD_BUFFER_MAX_VAL		8
#define __SS_BUFFER_MAX_VAL		8

#define __FILENAME_UPDATE_TIMEOUT 10000

size_t Heap;

modConfigGeneralConfigStructTypedef *generalConfig;
modStateOfChargeStructTypeDef       *generalStateOfCharge;

modPowerElectronicsPackStateTypedef packState;

uint16_t LED_Blink_Delay;

uint64_t TIM_Clock;
uint64_t TIM3_Clock;
uint64_t Led_Timer;
uint64_t HTTP_timer;
uint8_t service_sw;

__IO uint8_t USB_On_Flag;

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

SD_CARD_Global_Struct SD_Global_Struct;

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;
__IO uint8_t SD_Ready2Send_Flag;

Time_Struct Test_time;
Time_Struct Current_Time;
Time_Struct SW_OFF_time;

__IO uint32_t SS_status_ptr;

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;
uint8_t Deep_Discharge_Status = 0;
uint8_t Brush_Status = 0;
uint64_t Battery_Serial;

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;

typedef struct{

	uint64_t Last_time_param_send;
	uint64_t Last_time_status_send;
	uint64_t Last_data_update_time;
	uint64_t Last_data_backup_time;

	uint8_t Status_History_Buffer[__SS_BUFFER_MAX_VAL+2];
	Time_Struct Status_History_time[__SS_BUFFER_MAX_VAL+2];
	uint8_t Status_flag[16];

	uint8_t Active_State; //idle/working/charging/error
	uint8_t Previous_Active_State;
	uint8_t Load_Params_After_Reboot;
	Battery_Data_Struct Actual_data;
	Battery_Data_Struct Param_History_Buffer[__SS_BUFFER_MAX_VAL+2];
	uint8_t Param_History_Buffer_Counter;
	uint8_t Param_History_Buffer_Position;
	uint8_t Param_History_Sending_Counter;
	uint8_t Param_Flag[16];
	uint16_t Battery_Level_At_Start;
	float Battery_Voltage_At_Start;
	float Max_Charge_Current;
	float Max_Load_Current;


	uint8_t Status_History_Buffer_Counter;
	uint8_t Status_History_Buffer_Position;
	uint8_t Status_History_Sending_Counter;

	Time_Struct Started_at_time;
	Time_Struct Ended_at_time;
	Time_Struct Event_time;

	float Remaining_SOC_at_Start;

	Time_Struct Shutdown_time;
	Time_Struct Shutdown_prev_state_start_time;

}SimStatus_Struct_Typedef;

SimStatus_Struct_Typedef SimStatus_Struct;

typedef struct{
	uint64_t Last_SD_Update_Time;
	uint64_t Last_time_param_send;
	uint64_t Last_time_status_send;

	uint8_t Status_History_Buffer[__SD_BUFFER_MAX_VAL+2];
	Time_Struct Status_History_time[__SD_BUFFER_MAX_VAL+2];
	uint8_t Status_flag[16];

	uint8_t Status_History_Buffer_Counter;
	uint8_t Status_History_Buffer_Position;
	uint8_t Status_History_Sending_Counter;

	uint8_t Param_History_Buffer_Counter;
	uint8_t Param_History_Buffer_Position;
	uint8_t Param_History_Sending_Counter;
	Battery_Data_Struct Param_History_Buffer[__SD_BUFFER_MAX_VAL+2];

	uint8_t Active_State; //idle/working/charging/error
	uint8_t Previous_Active_State;
	uint8_t Load_Params_After_Reboot;

	float Remaining_SOC_at_Start;

	Time_Struct Started_at_time;
	Time_Struct Ended_at_time;
	Time_Struct Event_time;
	Time_Struct Shutdown_time;
	Time_Struct Shutdown_prev_state_start_time;


}SD_CARD_Struct_Typedef;

SD_CARD_Struct_Typedef SD_CARD_Struct;

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

__IO uint64_t _global_clock;

uint8_t load_switch_state = 0;
uint8_t charge_switch_state = 0;

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

float Brush_Minimum_SoC = 0;
uint8_t Brush_Default_State = 0;

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;

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 htim3;
TIM_HandleTypeDef htim6;

uint8_t OVP_counter = 0;

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

uint64_t output_control_clock = 0;
bool need_shunt_charging_contractor = false;
uint64_t shunt_charging_contractor_clock = 0;



#define __MA_WIN_SIZE (500)
#define __MA_ARRAY_QTY 2


/* Private function prototypes -----------------------------------------------*/
void Total_DeInit();
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);
static void MX_TIM3_Init(void);
static void MX_TIM2_Init(void);

uint8_t SS_status(uint8_t type, Time_Struct* Event_time);
void Status_Save(uint8_t Type);
void Status_Clear(uint8_t Type);
void Save_data_to_Backup();
void Restore_shutdown_data();
void updateLimitsFromMem();


void modem_init();

uint8_t SS_param(Battery_Data_Struct* Source_Data);
void Parameters_Save();
void Update_parameters_for_sim();
void Parameters_Send_to_Buf(uint8_t State);
void Set_Shutdown_Data();

uint8_t SD_status(uint8_t type, Time_Struct* Event_time);
void SD_Status_Clear(uint8_t Type);
uint8_t SD_param(Battery_Data_Struct* Source_Data);
void SD_Params_Send_to_Buf(uint8_t State);
uint8_t SD_Mount();
void SD_Event_and_Param_Processing();
void SD_Card_data_init();
void SD_Status_Save(uint8_t Type);
uint8_t SD_Umount();
void SD_Update_Filename(SD_CARD_Global_Struct* source );

uint32_t last_usb_call = 0;






//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;
////		}
////	}
//}


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)
{
	if (htim->Instance == TIM2)
	{
		TimeoutMng();
		TIM_Clock++;
	}
	else if (htim->Instance == TIM3)
	{
		if (TIM3_Clock % 10 == 0)
		{
			CAN_TransmitRTR(CAN_BMS_HEARTBEAT, 8, &hcan2);
		}

        if (TIM3_Clock % 4 == 0)
        {
//        	transmitCanPacketFromQueue(can1_transmit_queue, &can1_transmit_queue_size, &hcan1);
        	transmitCanPacketFromQueueCan1();
        }
#include "../../Libs/Utils/micros.h"
        if (TIM3_Clock % 3 == 0)
        {
            volatile u32_t measure = 0;
//            StartCodeMeasure();
//        	transmitCanPacketFromQueue(can2_transmit_queue, &can2_transmit_queue_size, &hcan2);
        	transmitCanPacketFromQueueCan2();
//            StopCodeMeasure(&measure);
//            __NOP();
        }

		TIM3_Clock++;
	}
	else if (htim->Instance == TIM6)
    {
		libPacketTimerFunc();
		modUARTTask();
    }
}

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 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();
//  }

}

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 + generalConfig->floatCurrentK1) * generalConfig->floatCurrentK2;
			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 + generalConfig->floatCurrentK1) * generalConfig->floatCurrentK2;
		} 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;
	 }
}



/*
 *
		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_Deep_Discharge(){ // 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 * __DEEP_DISCHARGE_RATIO){
		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 * __DEEP_DISCHARGE_RATIO) {
		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 ) > LED_Blink_Delay) {
		  //HAL_GPIO_TogglePin(HL3_GPIO_Port, HL3_Pin);
		  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL5_Pin);
		//  HAL_GPIO_TogglePin(HL3_GPIO_Port, HL1_Pin);
		  //HAL_GPIO_TogglePin(HL2_GPIO_Port, HL2_Pin);
		  timer = HAL_GetTick();
	}
}

void Check_Status() {

	Get_Shunt_Current();
	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();
	Deep_Discharge_Status = Check_Deep_Discharge();


	if (Pilot_Status && float_current<0){ //charge current should be positive
		float_current = -float_current;
	}
	else if (!Pilot_Status && float_current>0){ //load current should be negative
		float_current = -float_current;
	}

	if (float_current>0) {
		charge_current = float_current;
		load_current = 0;
	}
	else if (float_current<0) {
		load_current = -float_current;
		charge_current = 0;
	}



}

void Check_Events_and_Parameters(){

	if (TIM_Clock - SimStatus_Struct.Last_data_update_time>1000){
		SimStatus_Struct.Last_data_update_time = TIM_Clock;
		Update_parameters_for_sim();


	}
	if (TIM_Clock- SimStatus_Struct.Last_data_backup_time>__BACKUP_TIMEOUT){
		Save_data_to_Backup();
		SimStatus_Struct.Last_data_backup_time = TIM_Clock;
	}


	//Generating HTTP Events
	if (Pilot_Status) {
		Status_Save(__STATUS_CHARGE_ON);
		SD_Status_Save(__STATUS_CHARGE_ON);
		Status_Clear(__STATUS_CHARGING_DISCONNECT);
		SD_Status_Clear(__STATUS_CHARGING_DISCONNECT);
	}
	else if (!Pilot_Status) {
		Status_Save(__STATUS_CHARGING_DISCONNECT);
		SD_Status_Save(__STATUS_CHARGING_DISCONNECT);
		Status_Clear(__STATUS_CHARGE_ON);
		SD_Status_Clear(__STATUS_CHARGE_ON);
	}

	if (Maximum_Load_Current_Status) {
		Status_Clear(__STATUS_OVERLOAD);
		SD_Status_Clear(__STATUS_OVERLOAD);
	}
	else if (!Maximum_Load_Current_Status) {
		Status_Save(__STATUS_OVERLOAD);
		SD_Status_Save(__STATUS_OVERLOAD);
	}

	if (Maximum_Voltage_Status) {
		Status_Clear(__STATUS_CHARGING_OVERVOLTAGE);
		SD_Status_Clear(__STATUS_CHARGING_OVERVOLTAGE);
	}
	else if (!Maximum_Voltage_Status) {
		Status_Save(__STATUS_CHARGING_OVERVOLTAGE);
		SD_Status_Save(__STATUS_CHARGING_OVERVOLTAGE);
	}

	if (Minimum_Voltage_Status) {
		Status_Clear(__STATUS_CELL_UNDERVOLTAGE);
		SD_Status_Clear(__STATUS_CELL_UNDERVOLTAGE);
	}
	else if (!Minimum_Voltage_Status) {
		Status_Save(__STATUS_CELL_UNDERVOLTAGE);
		SD_Status_Save(__STATUS_CELL_UNDERVOLTAGE);
	}

	if (Maximum_Temp_Status) {
		Status_Clear(__STATUS_OVERHEATING);
		SD_Status_Clear(__STATUS_OVERHEATING);
	}
	else if (!Maximum_Temp_Status) {
		Status_Save(__STATUS_OVERHEATING);
		SD_Status_Save(__STATUS_OVERHEATING);
	}

	if (Brush_Status) {
		Status_Save(__STATUS_TAKE_BRUSH);
		SD_Status_Save(__STATUS_TAKE_BRUSH);
	}
	else if (!Brush_Status) {
		Status_Clear(__STATUS_TAKE_BRUSH);
		SD_Status_Clear(__STATUS_TAKE_BRUSH);
	}

	//Generating HTTP Params

	if (Pilot_Status){
		SimStatus_Struct.Active_State = __GLSTATUS_CHARGING;
	}
	else if(!Pilot_Status && load_current>0){
		SimStatus_Struct.Active_State = __GLSTATUS_WORKING;
	}
	else SimStatus_Struct.Active_State = __GLSTATUS_IDLE;

	if(SimStatus_Struct.Active_State!=SimStatus_Struct.Previous_Active_State){
		Parameters_Send_to_Buf(SimStatus_Struct.Previous_Active_State);
		SD_Params_Send_to_Buf(SimStatus_Struct.Previous_Active_State);
		Parameters_Save();
		SimStatus_Struct.Last_time_param_send= TIM_Clock;
	}
	if (TIM_Clock-SimStatus_Struct.Last_time_param_send>600000){
		SimStatus_Struct.Last_time_param_send= TIM_Clock;
		Parameters_Send_to_Buf(SimStatus_Struct.Active_State);
		SD_Params_Send_to_Buf(SimStatus_Struct.Active_State);
		Parameters_Save();
	}


	if (SimStatus_Struct.Active_State==__GLSTATUS_CHARGING){
		if (SimStatus_Struct.Max_Charge_Current < charge_current) SimStatus_Struct.Max_Charge_Current = charge_current;
		SimStatus_Struct.Max_Load_Current = 0;
	}
	else if (SimStatus_Struct.Active_State==__GLSTATUS_WORKING || SimStatus_Struct.Active_State==__GLSTATUS_IDLE ){
		if (SimStatus_Struct.Max_Load_Current < load_current) SimStatus_Struct.Max_Load_Current = load_current;
		SimStatus_Struct.Max_Charge_Current = 0;
	}


}

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

//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);
//		Brush_Status = 1; //Brush is Up
//	} else {
//		HAL_GPIO_WritePin(Output_2_GPIO_Port, Output_2_Pin, Brush_Default_State);
//		Brush_Status = 0; //Brush is down
//	}
//}

void outputControl()
{
	if ((TIM_Clock - output_control_clock) < 100)
	{
		return;
	}

	// 2 output handle
	if (generalConfig->chargeBatteryOutputChecked)
	{
		GPIO_PinState chargeContactorState = HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_5);
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, chargeContactorState);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_RESET);
	}

	// 3 output handle
	if (!generalConfig->brushOrShuntMode) // brush mode
	{
		if (packState.SoC <= generalConfig->brushUsageSocThreshold)
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, generalConfig->brushOrShuntOutputChecked ? GPIO_PIN_RESET : GPIO_PIN_SET);
		else
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, generalConfig->brushOrShuntOutputChecked ? GPIO_PIN_SET : GPIO_PIN_RESET);

		Brush_Status = HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_1);
	}
	else // shunt mode
	{
		if (generalConfig->brushOrShuntOutputChecked)
		{
			GPIO_PinState loadContactorState = HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4);
			if (loadContactorState == GPIO_PIN_SET && !need_shunt_charging_contractor)
			{
				need_shunt_charging_contractor = true;
				shunt_charging_contractor_clock = TIM_Clock;
			}

			if (loadContactorState == GPIO_PIN_SET && need_shunt_charging_contractor &&
				(TIM_Clock - shunt_charging_contractor_clock) >= generalConfig->shuntChargingContactorDelay * 1000)
			{
				HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);
			}

			if (loadContactorState == GPIO_PIN_RESET)
			{
				HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
				need_shunt_charging_contractor = false;
			}
		}
		else
		{
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
			need_shunt_charging_contractor = false;
		}
	}

	// 4 output handle
	if (generalConfig->coolingOutputChecked)
	{
		if (packState.tempBatteryHigh <= generalConfig->coolingStopThreshold)
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);

		if (packState.tempBatteryHigh >= generalConfig->coolingStartThreshold)
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);
	}

	// 5 output handle
	if (generalConfig->heatingOutputChecked)
	{
		if (packState.tempBatteryLow >= generalConfig->heatingStopThreshold)
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);

		if (packState.tempBatteryLow <= generalConfig->heatingStartThreshold)
			HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
	}

	output_control_clock = TIM_Clock;
}

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.Default_Longitude = "5.257022";
	  SIM800_Struct.Default_Latitude = "50.527822";

		SIM800_Struct.BATTERY_DATA.Serial = Battery_Serial;
		SIM800_Struct.BATTERY_DATA.Battery_cond_ID = 5;
		RTC_Get_Values(&SIM800_Struct.BATTERY_DATA.Event_time);
		RTC_Get_Values(&SIM800_Struct.BATTERY_DATA.Started_At_Time);
		RTC_Get_Values(&SIM800_Struct.BATTERY_DATA.Ended_At_Time);
		SIM800_Struct.BATTERY_DATA.Status_Indication = 1;
		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 SD_Card_data_init(){
	SD_Card_Var_Init(&SD_Global_Struct);
	memcpy(&SD_Global_Struct.BATTERY_DATA, &SIM800_Struct.BATTERY_DATA, sizeof(SIM800_Struct.BATTERY_DATA));
	DPC_TO_Set(TO_SD_Filename, __FILENAME_UPDATE_TIMEOUT);
}

void SD_Status_Save(uint8_t Type){
	if (SD_Global_Struct.SD_CARD_ChipDetect){
		if (!SD_CARD_Struct.Status_flag[Type]){
			if (TIM_Clock-SD_CARD_Struct.Last_time_status_send>1000 || Type==__STATUS_POWER_OFF || Type==__STATUS_POWER_ON){
				SD_CARD_Struct.Status_flag[Type] = 1;
				SD_CARD_Struct.Status_History_Buffer[SD_CARD_Struct.Status_History_Buffer_Position]=Type;
				if (Type==2) memcpy(&SD_CARD_Struct.Status_History_time[SD_CARD_Struct.Status_History_Buffer_Position], &SD_CARD_Struct.Shutdown_time, sizeof(SD_CARD_Struct.Shutdown_time));
				else RTC_Get_Values(&SD_CARD_Struct.Status_History_time[SD_CARD_Struct.Status_History_Buffer_Position]);
				SD_CARD_Struct.Status_History_Buffer_Counter++;
				SD_CARD_Struct.Status_History_Buffer_Position++;
				SD_CARD_Struct.Last_time_status_send=TIM_Clock;
			}
		}
	}

	if (SD_CARD_Struct.Status_History_Buffer_Counter>9) SD_CARD_Struct.Status_History_Buffer_Counter=9;
	if (SD_CARD_Struct.Status_History_Buffer_Position>9) SD_CARD_Struct.Status_History_Buffer_Position=9;
}

void Status_Save(uint8_t Type){
	if (SS_Ready2Send_Flag){
		if (!SimStatus_Struct.Status_flag[Type]){
			if (TIM_Clock-SimStatus_Struct.Last_time_status_send>1000 || Type==__STATUS_POWER_OFF || Type==__STATUS_POWER_ON){
				SimStatus_Struct.Status_flag[Type] = 1;
				SimStatus_Struct.Status_History_Buffer[SimStatus_Struct.Status_History_Buffer_Position]=Type;
				if (Type==2) memcpy(&SimStatus_Struct.Status_History_time[SimStatus_Struct.Status_History_Buffer_Position], &SimStatus_Struct.Shutdown_time, sizeof(SimStatus_Struct.Shutdown_time));
				else RTC_Get_Values(&SimStatus_Struct.Status_History_time[SimStatus_Struct.Status_History_Buffer_Position]);
				SimStatus_Struct.Status_History_Buffer_Counter++;
				SimStatus_Struct.Status_History_Buffer_Position++;
				SimStatus_Struct.Last_time_status_send=TIM_Clock;
			}
		}
	}

	if (SimStatus_Struct.Status_History_Buffer_Counter>__SS_BUFFER_MAX_VAL) SimStatus_Struct.Status_History_Buffer_Counter=__SS_BUFFER_MAX_VAL;
	if (SimStatus_Struct.Status_History_Buffer_Position>__SS_BUFFER_MAX_VAL) SimStatus_Struct.Status_History_Buffer_Position=__SS_BUFFER_MAX_VAL;
}

void Status_Clear(uint8_t Type){
	if (SimStatus_Struct.Status_flag[Type]){
		SimStatus_Struct.Status_flag[Type]=0;
	}
}

void SD_Status_Clear(uint8_t Type){
	if (SD_CARD_Struct.Status_flag[Type]){
		SD_CARD_Struct.Status_flag[Type]=0;
	}
}

void SD_Event_and_Param_Processing(){

		if (SD_CARD_Struct.Status_History_Buffer_Counter!=0){

			if (SD_Global_Struct.Mount_Flag){
				if (SD_status(SD_CARD_Struct.Status_History_Buffer[SD_CARD_Struct.Status_History_Sending_Counter],  &SD_CARD_Struct.Status_History_time[SD_CARD_Struct.Status_History_Sending_Counter])){
					SD_CARD_Struct.Status_History_Buffer_Counter--;
					SD_CARD_Struct.Status_History_Sending_Counter++;
					if (SD_CARD_Struct.Status_History_Sending_Counter>9) SD_CARD_Struct.Status_History_Sending_Counter=0;
					if (SD_CARD_Struct.Status_History_Buffer_Counter==0){
						SD_CARD_Struct.Status_History_Sending_Counter=0;
						SD_CARD_Struct.Status_History_Buffer_Position=0;
					}
				}
			}
			else {
				SD_Mount();
			}
		}

		else if (SD_CARD_Struct.Param_History_Buffer_Counter!=0){
			if (SD_Global_Struct.Mount_Flag){
				if (SD_param(&SD_CARD_Struct.Param_History_Buffer[SD_CARD_Struct.Param_History_Sending_Counter])){
					SD_CARD_Struct.Param_History_Buffer_Counter--;
					SD_CARD_Struct.Param_History_Sending_Counter++;
					if (SD_CARD_Struct.Param_History_Sending_Counter>5) SD_CARD_Struct.Param_History_Sending_Counter=0;
					if(SD_CARD_Struct.Param_History_Buffer_Counter==0){
						SD_CARD_Struct.Param_History_Sending_Counter=0;
						SD_CARD_Struct.Param_History_Buffer_Position=0;
					}
				}
			}
			else {
				SD_Mount();
			}
		}
		else {
			if (SD_Global_Struct.Mount_Flag){
				SD_Global_Struct.Mount_Flag = !SD_Umount();
			}
		}

	if (SD_CARD_Struct.Param_History_Buffer_Counter==0){
		SD_CARD_Struct.Param_History_Sending_Counter=0;
		SD_CARD_Struct.Param_History_Buffer_Position=0;
	}

	if (SD_CARD_Struct.Status_History_Buffer_Counter==0){
		SD_CARD_Struct.Status_History_Sending_Counter=0;
		SD_CARD_Struct.Status_History_Buffer_Position=0;
	}

}

void SS_Event_and_Param_Processing(){

	if (SimStatus_Struct.Status_History_Buffer_Counter!=0){

		if (SS_status(SimStatus_Struct.Status_History_Buffer[SimStatus_Struct.Status_History_Sending_Counter], &SimStatus_Struct.Status_History_time[SimStatus_Struct.Status_History_Sending_Counter])){
			SimStatus_Struct.Status_History_Buffer_Counter--;
			SimStatus_Struct.Status_History_Sending_Counter++;
			if (SimStatus_Struct.Status_History_Sending_Counter>9) SimStatus_Struct.Status_History_Sending_Counter=0;
			if (SimStatus_Struct.Status_History_Buffer_Counter==0){
				SimStatus_Struct.Status_History_Sending_Counter=0;
				SimStatus_Struct.Status_History_Buffer_Position=0;
			}
		}
	}
	else if (SimStatus_Struct.Param_History_Buffer_Counter!=0){

		if (SS_param(&SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Sending_Counter])){
			SimStatus_Struct.Param_History_Buffer_Counter--;
			SimStatus_Struct.Param_History_Sending_Counter++;
			if (SimStatus_Struct.Param_History_Sending_Counter>5) SimStatus_Struct.Param_History_Sending_Counter=0;
			if(SimStatus_Struct.Param_History_Buffer_Counter==0){
				SimStatus_Struct.Param_History_Sending_Counter=0;
				SimStatus_Struct.Param_History_Buffer_Position=0;
			}
		}
	}

	if (SimStatus_Struct.Param_History_Buffer_Counter==0){
		SimStatus_Struct.Param_History_Sending_Counter=0;
		SimStatus_Struct.Param_History_Buffer_Position=0;
	}

	if (SimStatus_Struct.Status_History_Buffer_Counter==0){
		SimStatus_Struct.Status_History_Sending_Counter=0;
		SimStatus_Struct.Status_History_Buffer_Position=0;
	}
}

uint8_t SS_param(Battery_Data_Struct* Source_Data) {
	uint8_t result = 0;
	Battery_Data_Struct Service_Struct;

	Service_Struct = *Source_Data;

	//memcpy(&SIM800_Struct.BATTERY_DATA, Source_Data, sizeof(*Source_Data));

	SIM800_Struct.BATTERY_DATA.Battery_Level_At_End = Source_Data->Battery_Level_At_End;
	SIM800_Struct.BATTERY_DATA.Battery_Level_At_Start = Source_Data->Battery_Level_At_Start;
	SIM800_Struct.BATTERY_DATA.Battery_Temperature_At_End = Source_Data->Battery_Temperature_At_End;
	SIM800_Struct.BATTERY_DATA.Battery_Voltage_At_End = Source_Data->Battery_Voltage_At_End;
	SIM800_Struct.BATTERY_DATA.Battery_Voltage_At_Start = Source_Data->Battery_Voltage_At_Start;
	SIM800_Struct.BATTERY_DATA.Energy_Sum = Source_Data->Energy_Sum;
	SIM800_Struct.BATTERY_DATA.Internal_Resistance = Source_Data->Internal_Resistance;
	SIM800_Struct.BATTERY_DATA.Maximum_Charge_Current = Source_Data->Maximum_Charge_Current;
	SIM800_Struct.BATTERY_DATA.Maximum_Load_Current = Source_Data->Maximum_Load_Current;
	SIM800_Struct.BATTERY_DATA.Moderated = Source_Data->Moderated;
	SIM800_Struct.BATTERY_DATA.Serial = Source_Data->Serial;
	SIM800_Struct.BATTERY_DATA.Status_Indication = Source_Data->Status_Indication;

	memcpy(&SIM800_Struct.BATTERY_DATA.Ended_At_Time, &Service_Struct.Ended_At_Time, sizeof(Service_Struct.Ended_At_Time));
	memcpy(&SIM800_Struct.BATTERY_DATA.Started_At_Time, &Service_Struct.Started_At_Time, sizeof(Service_Struct.Started_At_Time));

	//Battery_Data_to_String_Converter(&SIM800_Struct);
	if(SIM800_Set_Command(&SIM800_Struct, HTTP_PARAMETERS_POST, 60000) == COMMAND_SET) {
	  result = 1;
	}
	return result;
}


uint8_t SD_status(uint8_t type, Time_Struct* Event_time){
	uint8_t result = 0;
	memcpy(&SD_Global_Struct.BATTERY_DATA.Event_time, Event_time, sizeof(*Event_time));
	SD_Global_Struct.BATTERY_DATA.Battery_cond_ID = type;
	Battery_Data_to_CSV_Converter(&SD_Global_Struct, &SD_Global_Struct.CSV_DATA);

	if(SD_Set_Command(&SD_Global_Struct,SD_OP_WRITE_STATUS, 10000) == SD_COMMAND_SET) {
	  result = 1;
	}
	return result;
}

uint8_t SD_param(Battery_Data_Struct* Source_Data){
	uint8_t result = 0;
	Battery_Data_Struct Service_Struct;

	Service_Struct = *Source_Data;

	SD_Global_Struct.BATTERY_DATA.Battery_Level_At_End = Source_Data->Battery_Level_At_End;
	SD_Global_Struct.BATTERY_DATA.Battery_Level_At_Start = Source_Data->Battery_Level_At_Start;
	SD_Global_Struct.BATTERY_DATA.Battery_Temperature_At_End = Source_Data->Battery_Temperature_At_End;
	SD_Global_Struct.BATTERY_DATA.Battery_Voltage_At_End = Source_Data->Battery_Voltage_At_End;
	SD_Global_Struct.BATTERY_DATA.Battery_Voltage_At_Start = Source_Data->Battery_Voltage_At_Start;
	SD_Global_Struct.BATTERY_DATA.Energy_Sum = Source_Data->Energy_Sum;
	SD_Global_Struct.BATTERY_DATA.Internal_Resistance = Source_Data->Internal_Resistance;
	SD_Global_Struct.BATTERY_DATA.Maximum_Charge_Current = Source_Data->Maximum_Charge_Current;
	SD_Global_Struct.BATTERY_DATA.Maximum_Load_Current = Source_Data->Maximum_Load_Current;
	SD_Global_Struct.BATTERY_DATA.Moderated = Source_Data->Moderated;
	SD_Global_Struct.BATTERY_DATA.Serial = Source_Data->Serial;
	SD_Global_Struct.BATTERY_DATA.Status_Indication = Source_Data->Status_Indication;

	memcpy(&SD_Global_Struct.BATTERY_DATA.Ended_At_Time, &Service_Struct.Ended_At_Time, sizeof(Service_Struct.Ended_At_Time));
	memcpy(&SD_Global_Struct.BATTERY_DATA.Started_At_Time, &Service_Struct.Started_At_Time, sizeof(Service_Struct.Started_At_Time));

	Battery_Data_to_CSV_Converter(&SD_Global_Struct, &SD_Global_Struct.CSV_DATA);

	if(SD_Set_Command(&SD_Global_Struct,SD_OP_WRITE_PARAM, 10000) == SD_COMMAND_SET) {
	  result = 1;
	}
	return result;
}


uint8_t SD_Mount(){
	uint8_t result = 0;
	if(SD_Set_Command(&SD_Global_Struct,SD_OP_MOUNT, 10000) == SD_COMMAND_SET) {
		result = 1;
	}
	return result;
}

uint8_t SD_Umount(){
	uint8_t result = 0;
	if(SD_Set_Command(&SD_Global_Struct,SD_OP_UMOUNT, 10000) == SD_COMMAND_SET) {
		result = 1;
	}
	return result;
}

uint8_t SS_status(uint8_t type, Time_Struct* Event_time) {
	static uint32_t prev_ptr = 0;
	uint8_t result = 0;

	SIM800_Struct.BATTERY_DATA.Event_time.day = Event_time->day;
	SIM800_Struct.BATTERY_DATA.Event_time.hour = Event_time->hour;
	SIM800_Struct.BATTERY_DATA.Event_time.minute = Event_time->minute;
	SIM800_Struct.BATTERY_DATA.Event_time.month = Event_time->month;
	SIM800_Struct.BATTERY_DATA.Event_time.second = Event_time->second;
	SIM800_Struct.BATTERY_DATA.Event_time.timezone = Event_time->timezone;
	SIM800_Struct.BATTERY_DATA.Event_time.year = Event_time->year;
	SIM800_Struct.BATTERY_DATA.Battery_cond_ID = type;
	//Battery_Data_to_String_Converter(&SIM800_Struct);

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

	return result;
}

void Update_parameters_for_sim(){
//	float Service;
	RTC_Get_Values(&SimStatus_Struct.Actual_data.Ended_At_Time);

	SimStatus_Struct.Actual_data.Battery_Level_At_End = (uint16_t) packState.SoC;
	SimStatus_Struct.Actual_data.Battery_Voltage_At_End = packState.packVoltage;
	SimStatus_Struct.Actual_data.Battery_Temperature_At_End = (uint16_t) packState.tempBatteryAverage;
	//Service = abs(SimStatus_Struct.Remaining_SOC_at_Start - packState.SoCCapacityAh);
	//SimStatus_Struct.Actual_data.Energy_Sum = (uint16_t) Service;
	SimStatus_Struct.Actual_data.Energy_Sum = (uint16_t) packState.SoCCapacityAh;
	SimStatus_Struct.Actual_data.Internal_Resistance = __DEFAULT_BATTERY_RESISTANCE;
	SimStatus_Struct.Actual_data.Moderated = 0;
	SimStatus_Struct.Actual_data.Maximum_Charge_Current = (uint16_t) SimStatus_Struct.Max_Charge_Current;
	SimStatus_Struct.Actual_data.Maximum_Load_Current = (uint16_t) SimStatus_Struct.Max_Load_Current;
	SimStatus_Struct.Actual_data.Battery_Level_At_Start = SimStatus_Struct.Battery_Level_At_Start;
	SimStatus_Struct.Actual_data.Battery_Voltage_At_Start = SimStatus_Struct.Battery_Voltage_At_Start;
	memcpy(&SimStatus_Struct.Actual_data.Started_At_Time, &SimStatus_Struct.Started_at_time, sizeof(SimStatus_Struct.Started_at_time));
}

void SD_Params_Send_to_Buf(uint8_t State){
	//if (SD_Global_Struct.Mount_Flag){
		if (packState.serial_number==0) SD_Global_Struct.BATTERY_DATA.Serial = Battery_Serial;
		else SD_Global_Struct.BATTERY_DATA.Serial = packState.serial_number;

		memcpy(&SD_CARD_Struct.Param_History_Buffer[SD_CARD_Struct.Param_History_Buffer_Position], &SimStatus_Struct.Actual_data, sizeof(SimStatus_Struct.Actual_data));
		SD_CARD_Struct.Param_History_Buffer[SD_CARD_Struct.Param_History_Buffer_Position].Status_Indication=State;

		if (SD_CARD_Struct.Param_History_Buffer_Counter <= __SD_BUFFER_MAX_VAL){
			SD_CARD_Struct.Param_History_Buffer_Counter++;
			SD_CARD_Struct.Param_History_Buffer_Position++;
		}

		if (SD_CARD_Struct.Param_History_Buffer_Counter>__SD_BUFFER_MAX_VAL) SD_CARD_Struct.Param_History_Buffer_Counter=__SD_BUFFER_MAX_VAL;
		if (SD_CARD_Struct.Param_History_Buffer_Position>__SD_BUFFER_MAX_VAL) SD_CARD_Struct.Param_History_Buffer_Position=__SD_BUFFER_MAX_VAL;

	//}
}

void Parameters_Send_to_Buf(uint8_t State){
	//if (SS_Ready2Send_Flag){

			if (packState.serial_number==0) SimStatus_Struct.Actual_data.Serial = Battery_Serial;
			else SimStatus_Struct.Actual_data.Serial = packState.serial_number;
		//if (!SimStatus_Struct.Param_Flag[State]){
		//	SimStatus_Struct.Param_Flag[State] = 1;

//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Status_Indication=State;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Battery_Level_At_Start = SimStatus_Struct.Battery_Level_At_Start;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Battery_Voltage_At_Start = SimStatus_Struct.Battery_Voltage_At_Start;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Started_At_Time = SimStatus_Struct.Started_at_time;
//
//			RTC_Get_Values(&SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Ended_At_Time);
//
//			if (packState.serial_number==0) SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Serial = __DEFAULT_BATTERY_SERIAL;
//			else SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Serial = packState.serial_number;
//
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Battery_Level_At_End = (uint16_t) packState.SoC;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Battery_Voltage_At_End =  packState.packVoltage;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Battery_Temperature_At_End = (uint16_t) packState.tempBatteryAverage;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Energy_Sum = (uint16_t) packState.SoCCapacityAh;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Internal_Resistance = __DEFAULT_BATTERY_RESISTANCE;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Moderated = 0;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Maximum_Charge_Current = (uint16_t) SimStatus_Struct.Max_Charge_Current;
//			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Maximum_Load_Current = (uint16_t) SimStatus_Struct.Max_Load_Current;

			memcpy(&SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position], &SimStatus_Struct.Actual_data, sizeof(SimStatus_Struct.Actual_data));
			SimStatus_Struct.Param_History_Buffer[SimStatus_Struct.Param_History_Buffer_Position].Status_Indication=State;

			if (SimStatus_Struct.Param_History_Buffer_Counter <= __SS_BUFFER_MAX_VAL){
				SimStatus_Struct.Param_History_Buffer_Counter++;
				SimStatus_Struct.Param_History_Buffer_Position++;
			}

			if (SimStatus_Struct.Param_History_Buffer_Counter>__SS_BUFFER_MAX_VAL) SimStatus_Struct.Param_History_Buffer_Counter=__SS_BUFFER_MAX_VAL;
			if (SimStatus_Struct.Param_History_Buffer_Position>__SS_BUFFER_MAX_VAL) SimStatus_Struct.Param_History_Buffer_Position=__SS_BUFFER_MAX_VAL;


		//}

//			SimStatus_Struct.Previous_Active_State = SimStatus_Struct.Active_State;
//			RTC_Get_Values(&SimStatus_Struct.Started_at_time);
//			SimStatus_Struct.Battery_Level_At_Start = (uint16_t) packState.SoC;
//			SimStatus_Struct.Battery_Voltage_At_Start =  packState.packVoltage;
//			SimStatus_Struct.Remaining_SOC_at_Start = packState.SoCCapacityAh;
	//}
}

void Parameters_Save(){
	//if (SS_Ready2Send_Flag){

		SimStatus_Struct.Previous_Active_State = SimStatus_Struct.Active_State;
		RTC_Get_Values(&SimStatus_Struct.Started_at_time);
		SimStatus_Struct.Battery_Level_At_Start = (uint16_t) packState.SoC;
		SimStatus_Struct.Battery_Voltage_At_Start =  packState.packVoltage;
		SimStatus_Struct.Remaining_SOC_at_Start = packState.SoCCapacityAh;
	//}
}


void Save_data_to_Backup(){
	Time_Struct CurrentTime;
//	Time_Struct Previous_time;
	struct tm tm_CurrenttimeStruct = {0};
	struct tm tm_PrevtimeStruct = {0};
	time_t Unixtime1;
	time_t Unixtime2;
	uint64_t Unixtime_delta;

	uint16_t Service_var;
//	float Service_float;

	RTC_Get_Values(&CurrentTime);

	tm_CurrenttimeStruct.tm_year = CurrentTime.year+2000-1900;
	tm_CurrenttimeStruct.tm_mon = CurrentTime.month-1;
	tm_CurrenttimeStruct.tm_mday = CurrentTime.day;
	tm_CurrenttimeStruct.tm_hour = CurrentTime.hour;
	tm_CurrenttimeStruct.tm_min = CurrentTime.minute;
	tm_CurrenttimeStruct.tm_sec = CurrentTime.second;

	tm_PrevtimeStruct.tm_year = SimStatus_Struct.Started_at_time.year+2000-1900;
	tm_PrevtimeStruct.tm_mon = SimStatus_Struct.Started_at_time.month-1;
	tm_PrevtimeStruct.tm_mday = SimStatus_Struct.Started_at_time.day;
	tm_PrevtimeStruct.tm_hour = SimStatus_Struct.Started_at_time.hour;
	tm_PrevtimeStruct.tm_min = SimStatus_Struct.Started_at_time.minute;
	tm_PrevtimeStruct.tm_sec = SimStatus_Struct.Started_at_time.second;

	Unixtime1 = mktime(&tm_CurrenttimeStruct);

	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, LoLoWord(Unixtime1));
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, LoHiWord(Unixtime1));
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, HiLoWord(Unixtime1));
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, HiHiWord(Unixtime1));

	Unixtime2 = mktime(&tm_PrevtimeStruct);

	Unixtime_delta = (uint16_t) (Unixtime1 - Unixtime2);
	if (Unixtime_delta>0xFFFFFFFF) Unixtime_delta=0;

	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR9, LoLoWord(Unixtime_delta));
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR10, LoHiWord(Unixtime_delta));
	//HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR11, HiLoWord(Unixtime2));
	//HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR12, HiHiWord(Unixtime2));

	//Prev State and Temp
	Service_var = SimStatus_Struct.Active_State;
	Service_var = Service_var<<8;
	Service_var = Service_var + (uint8_t) packState.tempBatteryAverage;
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, Service_var);

	//Battery SOC levels
	Service_var = (uint8_t) packState.SoC;
	Service_var = Service_var<<8;
	Service_var = Service_var + (uint8_t) SimStatus_Struct.Battery_Level_At_Start;
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR6, Service_var);

	//Battery Voltage levels
	Service_var = (uint8_t) packState.packVoltage;
	Service_var = Service_var<<8;
	Service_var = Service_var + (uint8_t) SimStatus_Struct.Battery_Voltage_At_Start;
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR7, Service_var);

	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR8, SimStatus_Struct.Actual_data.Energy_Sum);

}

void Restore_shutdown_data(){
	uint16_t HiHiPart;
	uint16_t HiLoPart;
	uint16_t LoLoPart;
	uint16_t LoHiPart;

//	uint32_t LoPart;
//	uint32_t HiPart;
	time_t Unixtime;
	uint32_t Time_delta;
	struct tm tm_timeStruct = {0};

	//HAL_PWR_EnableBkUpAccess();

	LoLoPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
	LoHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
	HiLoPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);
	HiHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);

	Unixtime = HiHiPart;
	Unixtime = Unixtime<<16;
	Unixtime = Unixtime + HiLoPart;
	Unixtime = Unixtime<<16;
	Unixtime = Unixtime + LoHiPart;
	Unixtime = Unixtime<<16;
	Unixtime = Unixtime + LoLoPart;

	tm_timeStruct = *(localtime(&Unixtime));

	if(Unixtime < 0x386D4380){
		SimStatus_Struct.Shutdown_time.year = 0;
		SimStatus_Struct.Shutdown_time.month = 1;
		SimStatus_Struct.Shutdown_time.day = 1;
		SimStatus_Struct.Shutdown_time.hour = 0;
		SimStatus_Struct.Shutdown_time.minute = 0;
		SimStatus_Struct.Shutdown_time.second = 0;

	  } else {

		SimStatus_Struct.Shutdown_time.year = tm_timeStruct.tm_year+1900-2000;
		SimStatus_Struct.Shutdown_time.month = tm_timeStruct.tm_mon+1;
		SimStatus_Struct.Shutdown_time.day = tm_timeStruct.tm_mday;
		SimStatus_Struct.Shutdown_time.hour = tm_timeStruct.tm_hour;
		SimStatus_Struct.Shutdown_time.minute = tm_timeStruct.tm_min;
		SimStatus_Struct.Shutdown_time.second = tm_timeStruct.tm_sec;
	  }

	LoLoPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR9);
	LoHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR10);
//	HiLoPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR11);
//	HiHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR12);

//	Unixtime = HiHiPart;
//	Unixtime = Unixtime<<16;
//	Unixtime = Unixtime + HiLoPart;
//	Unixtime = Unixtime<<16;
	Time_delta = LoHiPart;
	Time_delta = Time_delta<<16;
	Time_delta = Time_delta + LoLoPart;

	Unixtime = Unixtime - Time_delta;

	tm_timeStruct = *(localtime(&Unixtime));

	if(Unixtime < 0x386D4380){
		SimStatus_Struct.Shutdown_prev_state_start_time.year = 0;
		SimStatus_Struct.Shutdown_prev_state_start_time.month = 1;
		SimStatus_Struct.Shutdown_prev_state_start_time.day = 1;
		SimStatus_Struct.Shutdown_prev_state_start_time.hour = 0;
		SimStatus_Struct.Shutdown_prev_state_start_time.minute = 0;
		SimStatus_Struct.Shutdown_prev_state_start_time.second = 0;

	} else {

		SimStatus_Struct.Shutdown_prev_state_start_time.year = tm_timeStruct.tm_year+1900-2000;
		SimStatus_Struct.Shutdown_prev_state_start_time.month = tm_timeStruct.tm_mon+1;
		SimStatus_Struct.Shutdown_prev_state_start_time.day = tm_timeStruct.tm_mday;
		SimStatus_Struct.Shutdown_prev_state_start_time.hour = tm_timeStruct.tm_hour;
		SimStatus_Struct.Shutdown_prev_state_start_time.minute = tm_timeStruct.tm_min;
		SimStatus_Struct.Shutdown_prev_state_start_time.second = tm_timeStruct.tm_sec;
	}

	HiHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);
	SimStatus_Struct.Active_State = HiByte(HiHiPart);
	SimStatus_Struct.Actual_data.Battery_Temperature_At_End = LoByte(HiHiPart);

	HiHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR6);
	SimStatus_Struct.Actual_data.Battery_Level_At_End = HiByte(HiHiPart);
	SimStatus_Struct.Actual_data.Battery_Level_At_Start = LoByte(HiHiPart);

	HiHiPart = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR7);
	SimStatus_Struct.Actual_data.Battery_Voltage_At_End = HiByte(HiHiPart);
	SimStatus_Struct.Actual_data.Battery_Voltage_At_Start = LoByte(HiHiPart);

	SimStatus_Struct.Actual_data.Energy_Sum = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR8);

	memcpy(&SimStatus_Struct.Actual_data.Started_At_Time, &SimStatus_Struct.Shutdown_prev_state_start_time, sizeof(SimStatus_Struct.Shutdown_prev_state_start_time));
	memcpy(&SimStatus_Struct.Actual_data.Ended_At_Time, &SimStatus_Struct.Shutdown_time, sizeof(SimStatus_Struct.Shutdown_time));
}

void Set_Shutdown_Data(){
	memcpy(&SimStatus_Struct.Actual_data.Started_At_Time, &SimStatus_Struct.Actual_data.Ended_At_Time, sizeof(SimStatus_Struct.Actual_data.Ended_At_Time));
	//memcpy(&SimStatus_Struct.Actual_data.Ended_At_Time, &Current_Time, sizeof(Current_Time));
	RTC_Get_Values(&SimStatus_Struct.Actual_data.Ended_At_Time);
	SimStatus_Struct.Actual_data.Energy_Sum = (uint16_t) packState.SoCCapacityAh;
	SimStatus_Struct.Actual_data.Battery_Voltage_At_Start = SimStatus_Struct.Actual_data.Battery_Voltage_At_End;
	SimStatus_Struct.Actual_data.Battery_Voltage_At_End =  packState.packVoltage;
	SimStatus_Struct.Actual_data.Battery_Level_At_Start = SimStatus_Struct.Actual_data.Battery_Level_At_End;
	SimStatus_Struct.Actual_data.Battery_Level_At_End =  (uint16_t) packState.SoC;
	SimStatus_Struct.Actual_data.Battery_Temperature_At_End = (uint16_t) packState.tempBatteryAverage;
}



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, 60000) == 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;
				  if (Current_Time.year < 20){
					  comp_flag=0;
					  asked=0;
				  }
			  }
		  }
	} else if( (asked == 1) && ((HAL_GetTick() - last_ask) >= 600000) ) {
		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, 60000) == 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) >= 600000) ) {
		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_DISCONNECT) ){
////			  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 Global_Reset_Timer(uint32_t time) {
	  if (TIM_Clock>=time){
		  NVIC_SystemReset();
	  }
}

#define __TO_TIME_ON 60000
#define __TO_TIME_OFF 300000

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 = 0;
		  last_switch_time = HAL_GetTick();
	  }

}

//void SD_Card_Processing(){
//
//	fres = f_mount(&FatFs, "", 1); //1=mount now
//	if (fres != FR_OK) {
//		while(1);
//	}
//
//	fres = f_getfree("", &free_clusters, &getFreeFs);
//	if (fres != FR_OK) {
//		HAL_GPIO_WritePin(HL5_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
//	}
//
//	total_sectors = (getFreeFs->n_fatent - 2) * getFreeFs->csize;
//	free_sectors = free_clusters * getFreeFs->csize;
//
//
//	fres = f_open(&fil, "test.csv", FA_WRITE | FA_OPEN_ALWAYS | FA_CREATE_ALWAYS);
//	if (fres == FR_OK){
//		f_puts("STM32 SD Card I/O Example via SPI\n", &fil);
//	}
//
//	if(f_close(&fil) != FR_OK){
//		HAL_GPIO_WritePin(HL5_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
//	}
//
//	if(f_mount(NULL, "", 1) != FR_OK){
//		HAL_GPIO_WritePin(HL5_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
//	}
//}
void UpdateGSMParamsFromConfig(){
	SetParametersFromConfig(&SIM800_Struct,generalConfig);
}


void SD_Update_Filename(SD_CARD_Global_Struct* source ){

	Time_Struct rtc_time;
	uint32_t Raw;

	char* csvtxt=".csv";
	char* stringptr=&source->Raw_var[0];
	//char* test1_ptr=&test1[0];


//	istr=strstr(source->FileName,".csv");
//	FN=atoi(istr-4);
//	FN_month=(uint8_t)(FN/100);
//	Raw=FN_month*100;
//	FN_year=(uint8_t)(FN-Raw);

	RTC_Get_Values(&rtc_time);

	if (rtc_time.year<20){
		rtc_time.year=01;
		rtc_time.month=01;
	}

//	if ((FN_year==rtc_time.year) && (FN_month==rtc_time.month)){
//		source->Filename_Check_Done=1;
//	}
//	else {
		Raw = rtc_time.month;
		Raw=Raw*100;
		Raw=Raw+rtc_time.year;
		itoa(Raw,stringptr,sizeof(Raw)+6);
		//strcat(stringptr,"%s");
		//strncpy(source->FileName,stringptr,sizeof(stringptr));
		strcpy(source->FileName,stringptr);
		strcat(source->FileName,csvtxt);
		source->Filename_Check_Done=1;
//	}


}

void Total_DeInit(){
	MX_FATFS_DeInit();
	HAL_TIM_Base_DeInit(&htim2);
	HAL_TIM_Base_DeInit(&htim3);
	HAL_TIM_Base_DeInit(&htim6);
	MX_USB_DEVICE_DeInit();
	HAL_UART_DeInit(&huart2);
	HAL_SPI_DeInit(&hspi1);
	//HAL_SPI_DeInit(&hspi3);
	HAL_DAC_DeInit(&hdac);
	HAL_ADC_DeInit(&hadc2);
	HAL_RTC_DeInit(&hrtc);

	  __HAL_RCC_GPIOE_CLK_DISABLE();
	  __HAL_RCC_GPIOC_CLK_DISABLE();
	  __HAL_RCC_GPIOA_CLK_DISABLE();
	  __HAL_RCC_GPIOB_CLK_DISABLE();
	  __HAL_RCC_GPIOD_CLK_DISABLE();
}




int main(void)
{
//	uint8_t result;
	//	uint8_t Pinstate;
//	static uint32_t last_ss = 0;
	/* USER CODE BEGIN 1 */

	//SCB->VTOR = 0x0800F000;
	/* 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();
	//  modFlashJumpToBootloader();
	//jumpToBootLoader();

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


	//	jumpToBootLoader();

	MX_RTC_Init();

	MX_ADC2_Init();

	//MX_CAN1_Init();
	//MX_CAN2_Init();
    can_msgr_init();
	CAN_SetSpeed(CAN_SPD_100, &hcan1);
	CAN_SetSpeed(CAN_SPD_100, &hcan2);

	//HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, 1);

	MX_DAC_Init();

	MX_SPI1_Init();


	//  MX_SPI3_Init();
	MX_USART2_UART_Init();
	MX_USB_DEVICE_Init();

	MX_TIM6_Init();
	MX_TIM3_Init();
	MX_TIM2_Init();

	MX_FATFS_Init();

	// mainWatchDogInitAndStart();
	//HAL_Delay(2000);
	Battery_Serial = 0;
	modem_init();
	SD_Card_data_init();
	//jumpToBootLoader();// here it works
  /* 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
	modCommandsInit(&packState,generalConfig);

	modUARTInit();																	  						// Will act on UART message requests
	modPowerElectronicsInit(&packState,generalConfig);
	UpdateGSMParamsFromConfig();
	Battery_Serial = generalConfig->serialNumber;

	HAL_TIM_Base_Start_IT(&htim6);
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_TIM_Base_Start_IT(&htim2);

	SimStatus_Struct.Status_flag[__STATUS_CHARGING_DISCONNECT]=1;
	SimStatus_Struct.Status_flag[__STATUS_TAKE_BRUSH]=1;
	SimStatus_Struct.Active_State = __GLSTATUS_IDLE;
	SimStatus_Struct.Previous_Active_State = __GLSTATUS_IDLE;

  /* USER CODE BEGIN WHILE */


	//jumpToBootLoader();// here it doesn't work

  while (1)
  {

	//  mainWatchDogReset();
	//  modUARTTask();
	//HAL_GPIO_WritePin(GSM_RST_GPIO_Port, GSM_RST_Pin, GPIO_PIN_RESET);

	// Sim processing function
	// all service operations for sim is here
	SIM800_Processing(&SIM800_Struct, &UART_Buffer);

	// SD processing function
	// all service operations for SD is here
	SD_Card_Processing(&SD_Global_Struct);

	SD_Global_Struct.SD_CARD_ChipDetect = !HAL_GPIO_ReadPin(SD_CD_GPIO_Port, SD_CD_Pin);
	SD_Global_Struct.Battery_Serial = Battery_Serial;

	if (SD_Global_Struct.Mount_Flag) HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_SET);
	else HAL_GPIO_WritePin(HL4_GPIO_Port, HL4_Pin, GPIO_PIN_RESET);

	if (SD_Global_Struct.SD_CARD_ChipDetect && SIM800_Struct.Sim_Main_States.GPRS_Established){
		LED_Blink_Delay = __BLINK_GSM_AND_SD_OK;
	}
	else if (!SD_Global_Struct.SD_CARD_ChipDetect && SIM800_Struct.Sim_Main_States.GPRS_Established){
		LED_Blink_Delay = __BLINK_GSM_OK_NO_SD;
	}
	else if (SD_Global_Struct.SD_CARD_ChipDetect && !SIM800_Struct.Sim_Main_States.GPRS_Established){
		LED_Blink_Delay = __BLINK_SD_OK_NO_GSM;
	}
	else LED_Blink_Delay = __BLINK_INIT;


	if (SD_Global_Struct.SD_CARD_ChipDetect){
//		if (!SD_Global_Struct.Mount_Flag){
//			SD_Global_Struct.Mount_Flag = SD_Mount();
//			SD_Ready2Send_Flag=0;
//		}
//		else if (SD_Global_Struct.Mount_Flag) {
			SD_Ready2Send_Flag=1;
			SD_Event_and_Param_Processing();
//		}
	}
	else {
		SD_Global_Struct.Mount_Flag=0;
	}

	//Global_Reset_Timer(__GRT_PERIOD);



//	Pinstate = HAL_GPIO_ReadPin(SD_CD_GPIO_Port, SD_CD_Pin);

	if (TIM_Clock>__DELAY_FOR_SIM || SS_Ready2Send_Flag){ //it is better to get time via sim

		if (SD_Ready2Send_Flag){

			if (DPC_TO_Check(TO_SD_Filename)==TO_OUT_TOOK){
				SD_Global_Struct.Filename_Check_Done=0;
				DPC_TO_Set(TO_SD_Filename, __FILENAME_UPDATE_TIMEOUT);
			}

			if (!SD_Global_Struct.Filename_Check_Done){
				SD_Update_Filename(&SD_Global_Struct);
				SD_Update_Path(&SD_Global_Struct);
				//SD_Set_Command(&SD_Global_Struct, SD_OP_DELETEOLD, 30000);
			}

			SD_Event_and_Param_Processing();

		}

		if (!SimStatus_Struct.Load_Params_After_Reboot){
			Restore_shutdown_data();
			memcpy(&SD_CARD_Struct.Shutdown_time,&SimStatus_Struct.Shutdown_time, sizeof(SimStatus_Struct.Shutdown_time));

			if (SimStatus_Struct.Active_State!=0){
			  Status_Save(__STATUS_POWER_OFF);
			  SD_Status_Save(__STATUS_POWER_OFF);
			  Parameters_Send_to_Buf(SimStatus_Struct.Active_State);
			  SD_Params_Send_to_Buf(SimStatus_Struct.Active_State);
			  Set_Shutdown_Data();
			  Parameters_Send_to_Buf(__GLSTATUS_SHUTDOWN);
			  SD_Params_Send_to_Buf(__GLSTATUS_SHUTDOWN);
			}
			else {
			  Set_Shutdown_Data();
			  //Parameters_Send_to_Buf(__GLSTATUS_SHUTDOWN);
			}
			SimStatus_Struct.Active_State = __GLSTATUS_IDLE;
			Parameters_Save();
			RTC_Get_Values(&SimStatus_Struct.Started_at_time);
			SimStatus_Struct.Battery_Level_At_Start = (uint16_t) packState.SoC;
			SimStatus_Struct.Battery_Voltage_At_Start =  packState.packVoltage;
			Status_Save(__STATUS_POWER_ON);
			SD_Status_Save(__STATUS_POWER_ON);
			SimStatus_Struct.Load_Params_After_Reboot=1;
		}
	}



	if(SIM800_Struct.Sim_Main_States.GPRS_Established == 1) {
	  HAL_GPIO_WritePin(HL4_GPIO_Port, HL3_Pin, GPIO_PIN_SET);
	  SS_Sync_GPS();
	  if (SS_Ready2Send_Flag){
		  SS_Event_and_Param_Processing();
	  }
	  else {
		  if( SS_Sync_Time() ){
			  SS_Ready2Send_Flag = 1;
		  }
	  }
	}
	else HAL_GPIO_WritePin(HL4_GPIO_Port, HL3_Pin, GPIO_PIN_RESET);

	//  HAL_Delay(100);
	heart_beat();

	USB_Check_Timeout();

	updateLimitsFromMem();

	// indicator control
	Display_Control();

	Check_Status();

	//TODO: REMOVE BEFORE FLIGHT
	//Test_Output(__TO_TIME_ON, __TO_TIME_OFF);

	if (SimStatus_Struct.Load_Params_After_Reboot) Check_Events_and_Parameters();

	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
		 (Deep_Discharge_Status == 1)) {   				// No Deep discharge


		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
			   (Deep_Discharge_Status == 1)) {        	// No Deep discharge

		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
		if (packState.serial_number!=0){
			Battery_Serial = packState.serial_number;
		}
		modStateOfChargeProcess();
	}
	// If there is new data handle SoC estimation
	//	mainWatchDogReset();

	transmitCan1Packet();
	transmitCan2Packet();

	outputControl();

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

static 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_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

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

  /* USER CODE END TIM3_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 */

}

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 = 20;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_15TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = ENABLE;
  hcan1.Init.AutoRetransmission = ENABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_CAN_Start(&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 = ENABLE;
  hcan2.Init.ReceiveFifoLocked = DISABLE;
  hcan2.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan2) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_CAN_Start(&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_32;
  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****/
