/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "fatfs.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
//	#include "math.h"
	#include "File_Handling.h"
	#include <string.h>
/* USER CODE END Includes */

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

/* 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 hadc1;
ADC_HandleTypeDef hadc3;

SD_HandleTypeDef hsd1;

TIM_HandleTypeDef htim4;
TIM_HandleTypeDef htim8;
TIM_HandleTypeDef htim10;
TIM_HandleTypeDef htim11;

UART_HandleTypeDef huart8;

/* USER CODE BEGIN PV */
uint32_t TO6, TO6_before, TO6_stop, TO6_uart, SD_SEEK, SD_SLIDE, temp32, TO7, TO7_before, TO7_PID, TO10, TO10_counter, TIM10_period;//timer 6 ticks & SD FILE COUNTER
uint8_t uart_buf, CPU_state, CPU_state_old, UART_transmission_request, State_Data[2], UART_DATA[DL_8], flg_tmt, u_tx_flg, u_rx_flg, TIM10_coflag;
uint16_t UART_rec_incr, UART_header, CS_result, temp16, Long_Data[DL_16], COMMAND[CL_16];//, SD_matr[SD_Length][DL_16];
FRESULT fresult;  // result
int test;
unsigned long fgoto, sizeoffile;//file pointer of the file object & size of file FPGA_RECEIVE_DATA_SIZE_32*FPGA_RECEIVE_WORD_SIZE_8+4+2

LDx_SetupTypeDef LD1_curr_setup, LD2_curr_setup, LD1_def_setup, LD2_def_setup;
Work_SetupTypeDef Curr_setup, Def_setup;
LDx_ParamTypeDef LD1_param, LD2_param;

LD_Blinker_StateTypeDef LD_blinker;

task_t task;



/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI4_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM5_Init(void);
static void MX_ADC1_Init(void);
static void MX_ADC3_Init(void);
static void MX_SPI2_Init(void);
static void MX_SPI5_Init(void);
static void MX_SPI6_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_SDMMC1_SD_Init(void);
static void MX_TIM7_Init(void);
static void MX_TIM6_Init(void);
static void MX_TIM10_Init(void);
static void MX_UART8_Init(void);
static void MX_TIM8_Init(void);
static void MX_TIM11_Init(void);
static void MX_TIM4_Init(void);
/* USER CODE BEGIN PFP */
static void Init_params(void);
static void Decode_uart(uint16_t *Command, LDx_SetupTypeDef *LD1_curr_setup, LDx_SetupTypeDef *LD2_curr_setup, Work_SetupTypeDef *Curr_setup);
static void Decode_task(uint16_t *Command, LDx_SetupTypeDef *LD1_curr_setup, LDx_SetupTypeDef *LD2_curr_setup, Work_SetupTypeDef *Curr_setup);
void Set_LTEC(uint8_t num, uint16_t DATA);
static uint16_t MPhD_T(uint8_t num);
static uint16_t Get_ADC(uint8_t num);
static uint16_t PID_Controller_Temp(LDx_SetupTypeDef * LDx_curr_setup, LDx_ParamTypeDef * LDx_results, uint8_t num);
uint8_t CheckChecksum(uint16_t *pbuff);
uint16_t CalculateChecksum(uint16_t *pbuff, uint16_t len);
//int SD_Init(void);
int SD_SAVE(uint16_t *pbuff);
//uint32_t Get_Length(void);
int SD_READ(uint16_t *pbuff);
int SD_REMOVE(void);
void USART_TX (uint8_t* dt, uint16_t sz);
void USART_TX_DMA (uint16_t sz);
static void Stop_TIM10();
static void OUT_trigger(uint8_t);
/* USER CODE END PFP */

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

/* USER CODE END 0 */

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

  /* USER CODE BEGIN 1 */
	HAL_StatusTypeDef st;
  /* USER CODE END 1 */

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

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
	/*I hope you don't forget that first - MX_DMA_Init(); and than - MX_USART1_UART_Init();*/
  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */
	
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI4_Init();
  MX_FATFS_Init();
  MX_TIM2_Init();
  MX_TIM5_Init();
  MX_ADC1_Init();
  MX_ADC3_Init();
  MX_SPI2_Init();
  MX_SPI5_Init();
  MX_SPI6_Init();
  MX_USART1_UART_Init();
  MX_SDMMC1_SD_Init();
  MX_TIM7_Init();
  MX_TIM6_Init();
  MX_TIM10_Init();
  MX_UART8_Init();
  MX_TIM8_Init();
  MX_TIM11_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
	Init_params();
	//HAL_TIM_Base_Start(&htim11);
	//HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); //start modulating by Mach-Zander modulator


    //TIM4,11 clocks = 92 MHz

	//ADC clock
	//TIM4 -> ARR = 60; // for 1.5 MHz
	//TIM4 -> ARR = 91; // for 1 MHz
	//TIM4 -> ARR = 45; // for 2 MHz
//	TIM4 -> ARR = 53; // for 1.735 MHz. It`s the highest frequency for correct ADC work. At higher freq artifacts (voltage peaks) appears.
	//TIM4 -> ARR = 100; // for 1.735 MHz. It`s the highest frequency for correct ADC work. At higher freq artifacts (voltage peaks) appears.

	TIM4 -> ARR = 37; //for 2.42 MHz. Highest freq for stm_ADC based on stm32G431-- 2.8 MHz

	TIM4 -> CCR3 = (TIM4 -> ARR +1)/2 - 1;


	//for E502_ADC

	//Mach-Zander clock (should be half of ADC clock freq)
	//TIM11 -> ARR = (TIM4 -> ARR +1)*2 - 1;
	//TIM11 -> CCR1 = (TIM11 -> ARR +1)/2 - 1;


	// for stm_ADC

	//Mach-Zander clock equal to ADC clock (adc triggers on rising and falling edges)
	TIM11 -> ARR = TIM4 -> ARR;
	TIM11 -> CCR1 = (TIM11 -> ARR +1)/2 - 1; //duty 50%



	/*
  if (HAL_GPIO_ReadPin(INP_0_GPIO_Port, INP_0_Pin) == 0){

	  CPU_state = DECODE_ENABLE;
  }
  */
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if ((HAL_GPIO_ReadPin(USB_FLAG_GPIO_Port, USB_FLAG_Pin)==GPIO_PIN_SET)&&(u_rx_flg == 0))
		{
			//NVIC_DisableIRQ(USART1_IRQn);
			LL_USART_EnableIT_PE(USART1);
			LL_USART_EnableIT_RXNE(USART1);
			LL_USART_EnableIT_ERROR(USART1);
			NVIC_SetPriority(USART1_IRQn, 0);
			NVIC_EnableIRQ(USART1_IRQn);//In other case you have FE error flag...
			u_rx_flg = 1;
		}
//		else
//		{
//			//NVIC_DisableIRQ(USART1_IRQn);
//			u_rx_flg = 0;
//		}
			switch (CPU_state)
			{
				case HALT://0 - Default state
					CPU_state_old = HALT;//Save main current cycle
					task.current_param = task.min_param;
					Stop_TIM10();
				break;
				case DECODE_ENABLE://1 - Decode rec. message
					CS_result = CalculateChecksum(COMMAND, CL_16-2);
					if (CheckChecksum(COMMAND))
					{
						LL_SPI_Enable(SPI2);//Enable SPI for Laser1 DAC & TEC1
						LL_SPI_Enable(SPI6);//Enable SPI for Laser2 DAC & TEC2
						Decode_uart(COMMAND, &LD1_curr_setup, &LD2_curr_setup, &Curr_setup);
						TO6_before = TO6;
						//LD1_param.LD_TEMP_Before = LD1_param.LD_TEMP;
						//LD2_param.LD_TEMP_Before = LD2_param.LD_TEMP;
						CPU_state = WORK_ENABLE;
						CPU_state_old = WORK_ENABLE;//Save main current cycle
					}
					else
					{
						State_Data[0] |= UART_DECODE_ERR;
						CPU_state = DEFAULT_ENABLE;
						CPU_state_old = HALT;//Save main current cycle
					}
					UART_transmission_request = MESS_01;
				break;
				case DEFAULT_ENABLE://2 - Go to HALT
					//Set current setup to default
					task.current_param = task.min_param;
					Stop_TIM10();
					Init_params();
					LL_SPI_Disable(SPI2);//Disable SPI for Laser1 DAC & TEC1
					LL_SPI_Disable(SPI6);//Disable SPI for Laser2 DAC & TEC2
					CPU_state = HALT;
					CPU_state_old = HALT;//Save main current cycle
					UART_transmission_request = MESS_01;
				break;
				case TRANS_S_ENABLE://3 - Transmith saved packet Before this operation must to be defaulting!
					temp16 = SD_READ(&Long_Data[0]);
					State_Data[0]|=temp16&0xff;
					if (temp16==0)
					{	
						UART_transmission_request = MESS_03;
					}
					else
					{
						UART_transmission_request = MESS_01;
					}
					CPU_state_old = HALT;
					CPU_state = CPU_state_old;//Return to main current cycle
				break;
				case TRANS_ENABLE://4 - Transmith current packet
					UART_transmission_request = MESS_02;
					CPU_state = CPU_state_old;//Return to main current cycle
				break;
				case REMOVE_FILE://5 - Remove file from SD
					State_Data[0]|=SD_REMOVE()&0xff;
					UART_transmission_request = MESS_01;
					CPU_state = CPU_state_old;
				break;
				case STATE://6 - Transmith state message
					UART_transmission_request = MESS_01;
					CPU_state = CPU_state_old;//Return to main current cycle
				break;
				case WORK_ENABLE://7 - Main work cycle
					task.current_param = task.min_param;
					Stop_TIM10();
					if (TO7>TO7_before)//Main work cycle go with the timer 7 (1000 us or 1 kHz)
					{
						TO7_before = TO7;
						LD1_param.POWER = MPhD_T(1);//Get Data from monitor photodiode of LD1
						LD1_param.POWER = MPhD_T(1);//Get Data from monitor photodiode of LD1
						LD2_param.POWER = MPhD_T(2);//Get Data from monitor photodiode of LD2
						LD2_param.POWER = MPhD_T(2);//Get Data from monitor photodiode of LD2
						
						//Correct temperature in all pulses
						(void) MPhD_T(3);
						LD1_param.LD_CURR_TEMP = MPhD_T(3);
						(void) MPhD_T(4);
						LD2_param.LD_CURR_TEMP = MPhD_T(4);
						temp16=PID_Controller_Temp(&LD1_curr_setup, &LD1_param, 1);
						Set_LTEC(3, temp16);//Drive Laser TEC 1
						temp16=PID_Controller_Temp(&LD2_curr_setup, &LD2_param, 2);
						Set_LTEC(4, temp16);//Drive Laser TEC 2
						
						Long_Data[1] = LD1_param.POWER;//Translate Data from monitor photodiode of LD1 to Long_Data
						Long_Data[2] = LD2_param.POWER;//Translate Data from monitor photodiode of LD2 to Long_Data

						Set_LTEC(1,LD1_curr_setup.CURRENT);//Drive Laser diode 1
						Set_LTEC(2,LD2_curr_setup.CURRENT);//Drive Laser diode 2

						//Prepare DATA of internals ADCs
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(0);
						temp16 = Get_ADC(1);
						Long_Data[7] = temp16; // PA2 -- 3V_monitor // PB1 -- U_Rt1_ext_Gain
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[8] = temp16; // PB0 -- U_Rt2_ext_Gain // PB0 -- U_Rt2_ext_Gain
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[9] = temp16; // PB1 -- U_Rt1_ext_Gain // PA2 -- 3V_monitor
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[10] = temp16; // PC0 -- 5V1_monitor // PC0 -- 5V1_monitor
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[11] = temp16; // PC1 -- 5V2_monitor // PC1 -- 5V2_monitor
						temp16 = Get_ADC(2);
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(3);
						temp16 = Get_ADC(4);
						Long_Data[12] = temp16;
						temp16 = Get_ADC(5);
													
						//Put the timer tick to Long_Data:
						TO6_stop = TO6;
						Long_Data[3] = (TO6_stop)&0xffff;
						Long_Data[4] = (TO6_stop>>16)&0xffff;
						
						//Put the average temperature of LD1 to Long_Data:
						Long_Data[5] = LD1_param.LD_CURR_TEMP;
						
						//Put the average temperature of LD2 to Long_Data:
						Long_Data[6] = LD2_param.LD_CURR_TEMP;

						if (Curr_setup.SD_EN==1)
						{
							CS_result = CalculateChecksum(&Long_Data[1], DL_16-2);
							Long_Data[DL_16-1] = CS_result;
							temp16 = SD_SAVE(&Long_Data[0]);
							State_Data[0]|=temp16&0xff;
						}
						CPU_state_old = WORK_ENABLE;//Save main current cycle
					}
				break;
				case DECODE_TASK:
					if (CheckChecksum(COMMAND))
					{
						Decode_task(COMMAND, &LD1_curr_setup, &LD2_curr_setup, &Curr_setup);
						TO6_before = TO6;
						CPU_state = RUN_TASK;
						CPU_state_old = RUN_TASK;//Save main current cycle
					}
					else
					{
						State_Data[0] |= UART_DECODE_ERR;
						CPU_state = DEFAULT_ENABLE;
						CPU_state_old = HALT;//Save main current cycle
					}
					UART_transmission_request = MESS_01;
				break;
				case RUN_TASK:
					switch (task.task_type)
					{
					case TT_CHANGE_CURR_1:


						//calculating timer periods for ADC clock and Mach-Zander modulator
						//ADC clock
						//TIM4 -> ARR = 60; // for 1.5 MHz
						//TIM4 -> ARR = 91; // for 1 MHz
						//TIM4 -> ARR = 45; // for 2 MHz

						//online calculation for debug purposes:
						//manually varying TIM4 -> ARR by debugger while running
						//TIM4 -> CCR3 = (TIM4 -> ARR +1)/2 - 1;


						//Mach-Zander clock (should be half of ADC clock freq)
						//TIM11 -> ARR = (TIM4 -> ARR +1)*2 - 1;
						//TIM11 -> CCR1 = (TIM11 -> ARR +1)/2 - 1;


						//for stm_ADC
						//TIM4 -- ADC clock. Rising edge -- for SYNC_DETector_ON
						//TIM4 -- ADC clock. Falling edge -- for SYNC_DETector_OFF

						//TIM4 freq is equal to TIM11
						//TIM4 phase should be adjustable to get correct sampling moment



						Set_LTEC(TT_CHANGE_CURR_2, task.curr);
						(void) MPhD_T(TT_CHANGE_TEMP_1);
						LD1_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_1);
						(void) MPhD_T(TT_CHANGE_TEMP_2);
						LD2_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_2);
						temp16=PID_Controller_Temp(&LD1_curr_setup, &LD1_param, 1);
						Set_LTEC(TT_CHANGE_TEMP_1, temp16);//Drive Laser TEC 1
						temp16=PID_Controller_Temp(&LD2_curr_setup, &LD2_param, 2);
						Set_LTEC(TT_CHANGE_TEMP_2, temp16);//Drive Laser TEC 2

						// Toggle pin for oscilloscope
						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET); //start of the whole frequency sweep procedure (start trigger pulse)
						//for (uint32_t i = 100000; i; --i){;}

		
						st = HAL_TIM_Base_Start_IT(&htim10);
						if (st != HAL_OK)
							while(1);

						uint16_t step_counter = 0;
						uint16_t trigger_counter = 0;
						uint16_t trigger_step = (uint8_t )((task.max_param - task.current_param)/task.delta_param * 10);
						uint16_t task_sheduler = 0;



						HAL_TIM_PWM_Stop(&htim11, TIM_CHANNEL_1); //start modulating by Mach-Zander modulator
						HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_3); //start ADC clock
						TIM11 -> CR1 &= ~(1 << 3); //disables one-pulse mode
						TIM4 -> CR1 &= ~(1 << 3); //disables one-pulse mode



						TIM11 -> CNT = 0;
						TIM4 -> CNT = 0;

						HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1); //start modulating by Mach-Zander modulator
						HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); //start ADC clock
						//TIM4 -> CNT = 0;

						TIM4 -> CNT = TIM4 -> ARR - 20; // not zero to make phase shift that will be robust to big delay in RF subsystem (up to ~400 ns)
						TIM11 -> CNT = 0;

						uint32_t curr_step_N = 0;
						uint32_t postAmpl_1_en_curr_step_N = ((task.max_param - task.current_param)/3.0 * 1.0) / task.delta_param;
						uint32_t postAmpl_2_en_curr_step_N = ((task.max_param - task.current_param)/3.0 * 2.0) / task.delta_param;


						while (task.current_param < task.max_param)
						{
							if (TIM10_coflag)
							{
								Set_LTEC(TT_CHANGE_CURR_1, task.current_param);
								HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_9); //toggle PG9. Change indicates that current step started.

								//TIM11 -> CNT = 0; // to link modulator phase
								//TIM4 -> CNT = 0; // to link ADC clock phase
								task.current_param += task.delta_param;
								TO10 = 0;
								TIM10_coflag = 0;
								
								if (curr_step_N == postAmpl_1_en_curr_step_N){
									HAL_GPIO_WritePin(OUT_6_GPIO_Port, OUT_6_Pin, GPIO_PIN_SET);
								}
								if (curr_step_N == postAmpl_2_en_curr_step_N){
									HAL_GPIO_WritePin(OUT_7_GPIO_Port, OUT_7_Pin, GPIO_PIN_SET);;
								}



								//HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9, GPIO_PIN_SET); // set the current step laser current trigger
								//HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9, GPIO_PIN_RESET);
//*
								if (step_counter % trigger_step == 0){ //trigger at every 60 step
									OUT_trigger(trigger_counter);
									++trigger_counter;
								}
								++step_counter;

								HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET); //stop trigger pulse
//*/
/*
								++task_sheduler;
								if (task_sheduler >= 10){
									task_sheduler = 0;
								}
								//maintain stable temperature of laser 2
								if (task_sheduler == 0){
									(void) MPhD_T(TT_CHANGE_TEMP_2);
									LD2_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_2);
									temp16=PID_Controller_Temp(&LD2_curr_setup, &LD2_param, 2);
									Set_LTEC(TT_CHANGE_TEMP_2, temp16);//Drive Laser TEC 2
								}
								//maintain stable temperature of laser 1
								//*
								if (task_sheduler == 5){
									(void) MPhD_T(TT_CHANGE_TEMP_1);
									LD1_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_1);
									temp16=PID_Controller_Temp(&LD1_curr_setup, &LD1_param, 1);
									Set_LTEC(TT_CHANGE_TEMP_1, temp16);//Drive Laser TEC 1
								}
//*/
							}
						}
						TIM11 -> DIER |= 1; //enable update interrupt. In this IRQ handler we will set both tims to one-pulse mode.
						//TIM11 -> CR1 |= 1 << 3; //sets timer to one-pulse mode. So it will turn off at the next UpdateEvent
						//TIM4 -> CR1 |= 1 << 3; //sets timer to one-pulse mode. So it will turn off at the next UpdateEvent
						//but one-pulse mode should be disabled

						//HAL_TIM_PWM_Stop(&htim11, TIM_CHANNEL_1); //start modulating by Mach-Zander modulator
						//HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_3); //start ADC clock



						Stop_TIM10();
						HAL_GPIO_WritePin(OUT_6_GPIO_Port, OUT_6_Pin, GPIO_PIN_RESET);
						HAL_GPIO_WritePin(OUT_7_GPIO_Port, OUT_7_Pin, GPIO_PIN_RESET);

						task.current_param = task.min_param;
						Set_LTEC(TT_CHANGE_CURR_1, task.current_param);
						if (task.tau > 3)
						{
							TIM10_period = htim10.Init.Period;
							htim10.Init.Period = 9999;
							TO10_counter = (task.tau - 1) * 100;
						}
						HAL_TIM_Base_Start_IT(&htim10);
					break;
					case TT_CHANGE_CURR_2:
						//Blink laser 2
//*
						Set_LTEC(TT_CHANGE_CURR_1, task.curr);
						(void) MPhD_T(TT_CHANGE_TEMP_1);
						LD1_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_1);
						(void) MPhD_T(TT_CHANGE_TEMP_2);
						LD2_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_2);
						temp16=PID_Controller_Temp(&LD1_curr_setup, &LD1_param, 1);
						Set_LTEC(TT_CHANGE_TEMP_1, temp16);//Drive Laser TEC 1
						temp16=PID_Controller_Temp(&LD2_curr_setup, &LD2_param, 2);
						Set_LTEC(TT_CHANGE_TEMP_2, temp16);//Drive Laser TEC 2

						LD_blinker.task_type = 2;
						LD_blinker.state = 0; // 0 -- disabled (do nothing); 1 -- update LD current; 2 -- blinking, LD ON now; 3 -- blinking, LD OFF now
						//LD_blinker.param = task.current_param;
						LD_blinker.param = 0;
						LD_blinker.param = 1000; // LD2 current (in unspecified units)
						LD_blinker.signal_port = OUT_9_GPIO_Port;
						LD_blinker.signal_pin = OUT_9_Pin;

						TIM8->ARR = 10000; //zero to LD_blinker.param change frequency (also in unspecified units).
											//When it is too low -- Desktop app crashes (there is not so much compute sources on MCU to anwser to desktop`s questions)
						st = HAL_TIM_Base_Start_IT(&htim8);
						if (st != HAL_OK)
							while(1);
//						*/

						// Toggle pin for oscilloscope
						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);
						uint32_t i = 10000; while (--i){}
						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
						LD_blinker.state = 2;

						st = HAL_TIM_Base_Start_IT(&htim10);
						if (st != HAL_OK)
							while(1);
						while (task.current_param < task.max_param)
						{
							if (TIM10_coflag)
							{
								//Set_LTEC(TT_CHANGE_CURR_2, task.current_param);
								//LD_blinker.param = task.current_param;
								//++LD_blinker.param;
								task.current_param += task.delta_param;
								TO10 = 0;
								TIM10_coflag = 0;


							}
						}
						HAL_TIM_Base_Stop(&htim10);
						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);

						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);

						HAL_TIM_Base_Stop_IT(&htim8);
						TIM8->CNT = 0;

						Stop_TIM10();
						task.current_param = task.min_param;
						Set_LTEC(TT_CHANGE_CURR_2, task.current_param);
						if (task.tau > 3)
						{
							TIM10_period = htim10.Init.Period;
							htim10.Init.Period = 9999;
							TO10_counter = (task.tau - 1) * 100;
						}
						HAL_TIM_Base_Start_IT(&htim10);


//*/

						/*  // Backup
						Set_LTEC(TT_CHANGE_CURR_1, task.curr);
						(void) MPhD_T(TT_CHANGE_TEMP_1);
						LD1_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_1);
						(void) MPhD_T(TT_CHANGE_TEMP_2);
						LD2_param.LD_CURR_TEMP = MPhD_T(TT_CHANGE_TEMP_2);
						temp16=PID_Controller_Temp(&LD1_curr_setup, &LD1_param, 1);
						Set_LTEC(TT_CHANGE_TEMP_1, temp16);//Drive Laser TEC 1
						temp16=PID_Controller_Temp(&LD2_curr_setup, &LD2_param, 2);
						Set_LTEC(TT_CHANGE_TEMP_2, temp16);//Drive Laser TEC 2

						// Toggle pin for oscilloscope
						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);
						HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);

						st = HAL_TIM_Base_Start_IT(&htim10);
						if (st != HAL_OK)
							while(1);
						while (task.current_param < task.max_param)
						{
							if (TIM10_coflag)
							{
								Set_LTEC(TT_CHANGE_CURR_2, task.current_param);
								task.current_param += task.delta_param;
								TO10 = 0;
								TIM10_coflag = 0;


							}
						}
						Stop_TIM10();
						task.current_param = task.min_param;
						Set_LTEC(TT_CHANGE_CURR_2, task.current_param);
						if (task.tau > 3)
						{
							TIM10_period = htim10.Init.Period;
							htim10.Init.Period = 9999;
							TO10_counter = (task.tau - 1) * 100;
						}
						HAL_TIM_Base_Start_IT(&htim10);
						*/


					break;
					case TT_CHANGE_TEMP_1:
						// isn't implemented
					break;
					case TT_CHANGE_TEMP_2:
						// isn't implemented
					break;
					}
	
					if (TO7>TO7_before)
					{
						TO7_before = TO7;
						
						LD1_param.POWER = MPhD_T(1);//Get Data from monitor photodiode of LD1
						LD1_param.POWER = MPhD_T(1);//Get Data from monitor photodiode of LD1
						LD2_param.POWER = MPhD_T(2);//Get Data from monitor photodiode of LD2
						LD2_param.POWER = MPhD_T(2);//Get Data from monitor photodiode of LD2
						
						Long_Data[1] = LD1_param.POWER;//Translate Data from monitor photodiode of LD1 to Long_Data
						Long_Data[2] = LD2_param.POWER;//Translate Data from monitor photodiode of LD2 to Long_Data
	
						//Prepare DATA of internals ADCs
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(0);
						temp16 = Get_ADC(1);
						Long_Data[7] = temp16;
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[8] = temp16;
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[9] = temp16;
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[10] = temp16;
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(1);
						Long_Data[11] = temp16;
						temp16 = Get_ADC(2);
						
						//Put the temperature of LD2 to Long_Data:
						temp16 = Get_ADC(3);
						temp16 = Get_ADC(4);
						Long_Data[12] = temp16;
						temp16 = Get_ADC(5);
													
						//Put the timer tick to Long_Data:
						TO6_stop = TO6;
						Long_Data[3] = (TO6_stop)&0xffff;
						Long_Data[4] = (TO6_stop>>16)&0xffff;
						
						//Put the average temperature of LD1 to Long_Data:
						Long_Data[5] = LD1_param.LD_CURR_TEMP;
						
						//Put the average temperature of LD2 to Long_Data:
						Long_Data[6] = LD2_param.LD_CURR_TEMP;
					}
					while (!TIM10_coflag);
					
					Stop_TIM10();
					
					if (task.tau > 3)
					{
						htim10.Init.Period = TIM10_period;
						TO10_counter = task.dt / 10;
					}
					
					CPU_state_old = RUN_TASK;
        break;
			}
			
		switch (UART_transmission_request)
		{
			case MESS_01://Default state
				USART_TX(State_Data,2);
				//HAL_UART_Transmit(&huart1, State_Data, 2, 10);
				State_Data[0]=0;
				State_Data[1]=0;//All OK!
				UART_transmission_request = NO_MESS;
			break;
			case MESS_02://Transmith packet
				
				//Find CS and put to Long_Data:
				CS_result = CalculateChecksum(&Long_Data[1], DL_16-2);
				Long_Data[DL_16-1] = CS_result;
				
				for (uint16_t i = 0; i < DL_16; i++)
				{
					UART_DATA[i*2] = (Long_Data[i])&0xff;
					UART_DATA[i*2+1] = (Long_Data[i]>>8)&0xff;
				}
				//HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);
				//HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
				//HAL_UART_Transmit_DMA(&huart1, UART_DATA, DL_8);
				//huart1.gState = HAL_UART_STATE_READY;
				//hdma_usart1_tx.State=HAL_DMA_STATE_BUSY;
				USART_TX_DMA (DL_8);//Send data by USART using DMA
				UART_transmission_request = NO_MESS;
			break;
			case MESS_03://Transmith saved packet
				for (uint16_t i = 0; i < DL_16; i++)
				{
					UART_DATA[i*2] = (Long_Data[i])&0xff;
					UART_DATA[i*2+1] = (Long_Data[i]>>8)&0xff;
				}
				//HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
				//HAL_UART_Transmit_DMA(&huart1, UART_DATA, DL_8);
				//huart1.gState = HAL_UART_STATE_READY;
				//hdma_usart1_tx.State=HAL_DMA_STATE_BUSY;
				USART_TX_DMA (DL_8);//Send data by USART using DMA
				UART_transmission_request = NO_MESS;
			break;			
		}
    if ((flg_tmt==1)&&((TO6-TO6_uart)>100))//Uart timeout handle. if timeout beetween zero byte of command and right now longer than 1 sec.:
		{
			UART_rec_incr = 0;//Reset uart command counter
			State_Data[0] |= UART_ERR;//timeout error!
			UART_transmission_request = MESS_01;//Send status
			flg_tmt = 0;//Reset timeout flag
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

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

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

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 368;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 8;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != 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_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

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

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 5;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_10;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_11;
  sConfig.Rank = ADC_REGULAR_RANK_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief ADC3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC3_Init(void)
{

  /* USER CODE BEGIN ADC3_Init 0 */

  /* USER CODE END ADC3_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC3_Init 1 */

  /* USER CODE END ADC3_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc3.Instance = ADC3;
  hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  hadc3.Init.Resolution = ADC_RESOLUTION_12B;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.ContinuousConvMode = DISABLE;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc3.Init.NbrOfConversion = 1;
  hadc3.Init.DMAContinuousRequests = DISABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_15;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC3_Init 2 */

  /* USER CODE END ADC3_Init 2 */

}

/**
  * @brief SDMMC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SDMMC1_SD_Init(void)
{

  /* USER CODE BEGIN SDMMC1_Init 0 */

  /* USER CODE END SDMMC1_Init 0 */

  /* USER CODE BEGIN SDMMC1_Init 1 */

  /* USER CODE END SDMMC1_Init 1 */
  hsd1.Instance = SDMMC1;
  hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
  hsd1.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
  hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;
  hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd1.Init.ClockDiv = 20;
  /* USER CODE BEGIN SDMMC1_Init 2 */

  /* USER CODE END SDMMC1_Init 2 */

}

/**
  * @brief SPI2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
  /**SPI2 GPIO Configuration
  PB13   ------> SPI2_SCK
  PB15   ------> SPI2_MOSI
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_13;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 7;
  LL_SPI_Init(SPI2, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_DisableNSSPulseMgt(SPI2);
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

/**
  * @brief SPI4 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI4_Init(void)
{

  /* USER CODE BEGIN SPI4_Init 0 */

  /* USER CODE END SPI4_Init 0 */

  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI4);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOE);
  /**SPI4 GPIO Configuration
  PE12   ------> SPI4_SCK
  PE13   ------> SPI4_MISO
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_12;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_13;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI4_Init 1 */

  /* USER CODE END SPI4_Init 1 */
  /* SPI4 parameter configuration*/
  SPI_InitStruct.TransferDirection = LL_SPI_SIMPLEX_RX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 7;
  LL_SPI_Init(SPI4, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI4, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_DisableNSSPulseMgt(SPI4);
  /* USER CODE BEGIN SPI4_Init 2 */

  /* USER CODE END SPI4_Init 2 */

}

/**
  * @brief SPI5 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI5_Init(void)
{

  /* USER CODE BEGIN SPI5_Init 0 */

  /* USER CODE END SPI5_Init 0 */

  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI5);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOF);
  /**SPI5 GPIO Configuration
  PF7   ------> SPI5_SCK
  PF8   ------> SPI5_MISO
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_8;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI5_Init 1 */

  /* USER CODE END SPI5_Init 1 */
  /* SPI5 parameter configuration*/
  SPI_InitStruct.TransferDirection = LL_SPI_SIMPLEX_RX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 7;
  LL_SPI_Init(SPI5, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI5, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_DisableNSSPulseMgt(SPI5);
  /* USER CODE BEGIN SPI5_Init 2 */

  /* USER CODE END SPI5_Init 2 */

}

/**
  * @brief SPI6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI6_Init(void)
{

  /* USER CODE BEGIN SPI6_Init 0 */

  /* USER CODE END SPI6_Init 0 */

  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI6);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
  /**SPI6 GPIO Configuration
  PA5   ------> SPI6_SCK
  PA7   ------> SPI6_MOSI
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_5;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI6_Init 1 */

  /* USER CODE END SPI6_Init 1 */
  /* SPI6 parameter configuration*/
  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 7;
  LL_SPI_Init(SPI6, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI6, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_DisableNSSPulseMgt(SPI6);
  /* USER CODE BEGIN SPI6_Init 2 */

  /* USER CODE END SPI6_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  LL_TIM_InitTypeDef TIM_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);

  /* TIM2 interrupt Init */
  NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM2_IRQn);

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  TIM_InitStruct.Prescaler = 1000;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 840000;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(TIM2, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM2);
  LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
  LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM2);
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

/**
  * @brief TIM4 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM4_Init(void)
{

  /* USER CODE BEGIN TIM4_Init 0 */

  /* USER CODE END TIM4_Init 0 */

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

  /* USER CODE BEGIN TIM4_Init 1 */

  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 45;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 22;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM4_Init 2 */

  /* USER CODE END TIM4_Init 2 */
  HAL_TIM_MspPostInit(&htim4);

}

/**
  * @brief TIM5 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM5_Init(void)
{

  /* USER CODE BEGIN TIM5_Init 0 */

  /* USER CODE END TIM5_Init 0 */

  LL_TIM_InitTypeDef TIM_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM5);

  /* TIM5 interrupt Init */
  NVIC_SetPriority(TIM5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM5_IRQn);

  /* USER CODE BEGIN TIM5_Init 1 */

  /* USER CODE END TIM5_Init 1 */
  TIM_InitStruct.Prescaler = 10000;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 560;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(TIM5, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM5);
  LL_TIM_SetClockSource(TIM5, LL_TIM_CLOCKSOURCE_INTERNAL);
  LL_TIM_SetTriggerOutput(TIM5, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM5);
  /* USER CODE BEGIN TIM5_Init 2 */

  /* USER CODE END TIM5_Init 2 */

}

/**
  * @brief TIM6 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM6_Init(void)
{

  /* USER CODE BEGIN TIM6_Init 0 */

  /* USER CODE END TIM6_Init 0 */

  LL_TIM_InitTypeDef TIM_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);

  /* TIM6 interrupt Init */
  NVIC_SetPriority(TIM6_DAC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM6_DAC_IRQn);

  /* USER CODE BEGIN TIM6_Init 1 */

  /* USER CODE END TIM6_Init 1 */
  TIM_InitStruct.Prescaler = 45999;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 19;
  LL_TIM_Init(TIM6, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM6);
  LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_ENABLE);
  LL_TIM_DisableMasterSlaveMode(TIM6);
  /* USER CODE BEGIN TIM6_Init 2 */

  /* USER CODE END TIM6_Init 2 */

}

/**
  * @brief TIM7 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM7_Init(void)
{

  /* USER CODE BEGIN TIM7_Init 0 */

  /* USER CODE END TIM7_Init 0 */

  LL_TIM_InitTypeDef TIM_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);

  /* TIM7 interrupt Init */
  NVIC_SetPriority(TIM7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM7_IRQn);

  /* USER CODE BEGIN TIM7_Init 1 */

  /* USER CODE END TIM7_Init 1 */
  TIM_InitStruct.Prescaler = 919;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 99;
  LL_TIM_Init(TIM7, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM7);
  LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_ENABLE);
  LL_TIM_DisableMasterSlaveMode(TIM7);
  /* USER CODE BEGIN TIM7_Init 2 */

  /* USER CODE END TIM7_Init 2 */

}

/**
  * @brief TIM8 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM8_Init(void)
{

  /* USER CODE BEGIN TIM8_Init 0 */

  /* USER CODE END TIM8_Init 0 */

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

  /* USER CODE BEGIN TIM8_Init 1 */

  /* USER CODE END TIM8_Init 1 */
  htim8.Instance = TIM8;
  htim8.Init.Prescaler = 0;
  htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim8.Init.Period = 91;
  htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim8.Init.RepetitionCounter = 0;
  htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM8_Init 2 */

  /* USER CODE END TIM8_Init 2 */

}

/**
  * @brief TIM10 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM10_Init(void)
{

  /* USER CODE BEGIN TIM10_Init 0 */

  /* USER CODE END TIM10_Init 0 */

  /* USER CODE BEGIN TIM10_Init 1 */

  /* USER CODE END TIM10_Init 1 */
  htim10.Instance = TIM10;
  htim10.Init.Prescaler = 183;
  htim10.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim10.Init.Period = 9;
  htim10.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim10.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim10) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM10_Init 2 */

  /* USER CODE END TIM10_Init 2 */

}

/**
  * @brief TIM11 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM11_Init(void)
{

  /* USER CODE BEGIN TIM11_Init 0 */

  /* USER CODE END TIM11_Init 0 */

  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM11_Init 1 */

  /* USER CODE END TIM11_Init 1 */
  htim11.Instance = TIM11;
  htim11.Init.Prescaler = 1;
  htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim11.Init.Period = 91;
  htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim11) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim11) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 91;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim11, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM11_Init 2 */

  /* USER CODE END TIM11_Init 2 */
  HAL_TIM_MspPostInit(&htim11);

}

/**
  * @brief UART8 Initialization Function
  * @param None
  * @retval None
  */
static void MX_UART8_Init(void)
{

  /* USER CODE BEGIN UART8_Init 0 */

  /* USER CODE END UART8_Init 0 */

  /* USER CODE BEGIN UART8_Init 1 */

  /* USER CODE END UART8_Init 1 */
  huart8.Instance = UART8;
  huart8.Init.BaudRate = 115200;
  huart8.Init.WordLength = UART_WORDLENGTH_8B;
  huart8.Init.StopBits = UART_STOPBITS_1;
  huart8.Init.Parity = UART_PARITY_NONE;
  huart8.Init.Mode = UART_MODE_TX_RX;
  huart8.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart8.Init.OverSampling = UART_OVERSAMPLING_16;
  huart8.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart8.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart8) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART8_Init 2 */

  /* USER CODE END UART8_Init 2 */

}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  LL_USART_InitTypeDef USART_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Initializes the peripherals clock
  */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
  /**USART1 GPIO Configuration
  PA9   ------> USART1_TX
  PA10   ------> USART1_RX
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USART1 DMA Init */

  /* USART1_TX Init */
  LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_7, LL_DMA_CHANNEL_4);

  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_7, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_7, LL_DMA_PRIORITY_VERYHIGH);

  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_7, LL_DMA_MODE_NORMAL);

  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_7, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_7, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_7, LL_DMA_PDATAALIGN_BYTE);

  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_7, LL_DMA_MDATAALIGN_BYTE);

  LL_DMA_DisableFifoMode(DMA2, LL_DMA_STREAM_7);

  /* USART1 interrupt Init */
  NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(USART1_IRQn);

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  USART_InitStruct.BaudRate = 115200;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
  USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
  LL_USART_Init(USART1, &USART_InitStruct);
  LL_USART_ConfigAsyncMode(USART1);
  LL_USART_Enable(USART1);
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);

  /* DMA interrupt init */
  /* DMA2_Stream7_IRQn interrupt configuration */
  NVIC_SetPriority(DMA2_Stream7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(DMA2_Stream7_IRQn);

}

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

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

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, ADC_MPD2_CS_Pin|SPI5_CNV_Pin|ADC_ThrLD2_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, EN_5V2_Pin|EN_5V1_Pin|LD2_EN_Pin|TEC2_PD_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, TECEN1_Pin|TECEN2_Pin|REF2_ON_Pin|DAC_LD2_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(DAC_TEC2_CS_GPIO_Port, DAC_TEC2_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOE, ADC_MPD1_CS_Pin|ADC_ThrLD1_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SPI4_CNV_GPIO_Port, SPI4_CNV_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, REF0_EN_Pin|TEC1_PD_Pin|DAC_LD1_CS_Pin|OUT_6_Pin
                          |OUT_7_Pin|OUT_8_Pin|OUT_9_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, LD1_EN_Pin|TEST_01_Pin|GPIO_PIN_7, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9|OUT_0_Pin|OUT_1_Pin|OUT_2_Pin
                          |OUT_3_Pin|OUT_4_Pin|OUT_5_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : INP_0_Pin INP_1_Pin */
  GPIO_InitStruct.Pin = INP_0_Pin|INP_1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pins : ADC_MPD2_CS_Pin SPI5_CNV_Pin ADC_ThrLD2_CS_Pin */
  GPIO_InitStruct.Pin = ADC_MPD2_CS_Pin|SPI5_CNV_Pin|ADC_ThrLD2_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pins : EN_5V2_Pin LD2_EN_Pin TEC2_PD_Pin */
  GPIO_InitStruct.Pin = EN_5V2_Pin|LD2_EN_Pin|TEC2_PD_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : EN_5V1_Pin */
  GPIO_InitStruct.Pin = EN_5V1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(EN_5V1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : TECEN1_Pin TECEN2_Pin REF2_ON_Pin DAC_TEC2_CS_Pin
                           DAC_LD2_CS_Pin */
  GPIO_InitStruct.Pin = TECEN1_Pin|TECEN2_Pin|REF2_ON_Pin|DAC_TEC2_CS_Pin
                          |DAC_LD2_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : TEC2_FLAG1_Pin TEC2_FLAG2_Pin TEC1_FLAG1_Pin TEC1_FLAG2_Pin */
  GPIO_InitStruct.Pin = TEC2_FLAG1_Pin|TEC2_FLAG2_Pin|TEC1_FLAG1_Pin|TEC1_FLAG2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pins : ADC_MPD1_CS_Pin ADC_ThrLD1_CS_Pin */
  GPIO_InitStruct.Pin = ADC_MPD1_CS_Pin|ADC_ThrLD1_CS_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 : SPI4_CNV_Pin */
  GPIO_InitStruct.Pin = SPI4_CNV_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(SPI4_CNV_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : REF0_EN_Pin TEC1_PD_Pin DAC_TEC1_CS_Pin DAC_LD1_CS_Pin
                           OUT_6_Pin OUT_7_Pin OUT_8_Pin OUT_9_Pin */
  GPIO_InitStruct.Pin = REF0_EN_Pin|TEC1_PD_Pin|DAC_TEC1_CS_Pin|DAC_LD1_CS_Pin
                          |OUT_6_Pin|OUT_7_Pin|OUT_8_Pin|OUT_9_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : LD1_EN_Pin TEST_01_Pin PD7 */
  GPIO_InitStruct.Pin = LD1_EN_Pin|TEST_01_Pin|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

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

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

  /*Configure GPIO pins : PG9 OUT_0_Pin OUT_1_Pin OUT_2_Pin
                           OUT_3_Pin OUT_4_Pin OUT_5_Pin */
  GPIO_InitStruct.Pin = GPIO_PIN_9|OUT_0_Pin|OUT_1_Pin|OUT_2_Pin
                          |OUT_3_Pin|OUT_4_Pin|OUT_5_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /* USER CODE BEGIN MX_GPIO_Init_2 */
  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

//void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {

//	UART_transmission_request = NO_MESS;

//}

static void Init_params(void)
{
	TO6 = 0;
	TO7 = 0;
	TO7_before = 0;
	TO6_before = 0;
	TO6_uart = 0;
	flg_tmt = 0;
	UART_rec_incr = 0;
	fgoto = 0;
	sizeoffile = 0;
	u_tx_flg = 0;
	u_rx_flg = 0;
	//State_Data[0]=0;
	//State_Data[1]=0;//All OK!
	for (uint16_t i=0; i<DL_16; i++)
	{
		Long_Data[i] = 0x00;
	}
	Long_Data[0]=0x1111;
	
	//Set default parameters
	Def_setup.AVERAGES = 0;
	Def_setup.LD1_EN = 0;
	Def_setup.LD2_EN = 0;
	Def_setup.MES_ID = 0;
	Def_setup.PI1_RD = 0;
	Def_setup.PI2_RD = 0;
	Def_setup.REF1_EN = 0;
	Def_setup.REF2_EN = 0;
	Def_setup.SD_EN = 0;
	Def_setup.TEC1_EN = 0;
	Def_setup.TEC2_EN = 0;
	Def_setup.TS1_EN = 0;
	Def_setup.TS2_EN = 0;
	Def_setup.U5V1_EN = 0;
	Def_setup.U5V2_EN = 0;
	Def_setup.WORK_EN = 0;
	
	LD1_def_setup.LD_TEMP = 0;
	LD2_def_setup.LD_TEMP = 0;
	LD1_def_setup.P_coef_temp = 0;
	LD2_def_setup.P_coef_temp = 0;
	LD1_def_setup.I_coef_temp = 0;
	LD2_def_setup.I_coef_temp = 0;
	
	//Set current setup to default
	Curr_setup = Def_setup;
	LD1_curr_setup = LD1_def_setup;
	LD2_curr_setup = LD2_def_setup;
	
	
	
	//Start timers 6 & 7
	LL_TIM_EnableIT_UPDATE(TIM6);
	LL_TIM_EnableCounter(TIM6);
	LL_TIM_EnableIT_UPDATE(TIM7);
	LL_TIM_EnableCounter(TIM7);
	//HAL_TIM_Base_Start_IT(&htim6);
	//HAL_TIM_Base_Start_IT(&htim7);
	//Start listen usart port

	
	//Enable DMA
  LL_DMA_DisableStream(DMA2, LL_DMA_STREAM_7);
  LL_DMA_ClearFlag_TC7(DMA2);
  LL_DMA_ClearFlag_TE7(DMA2);
  LL_USART_EnableDMAReq_TX(USART1);
  LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_7);
  LL_DMA_EnableIT_TE(DMA2, LL_DMA_STREAM_7);
  LL_DMA_ClearFlag_TC7(DMA2);
  LL_DMA_ClearFlag_TE7(DMA2);
  LL_DMA_ConfigAddresses(DMA2, LL_DMA_STREAM_7, (uint32_t)&UART_DATA, LL_USART_DMA_GetRegAddr(USART1, LL_USART_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(DMA2, LL_DMA_STREAM_7));
	
	//HAL_UART_Receive_IT(&huart1, &uart_buf, 1);
	
	
	SD_SEEK = 0;
	SD_SLIDE = 0;
	//Reset all periphery
	HAL_GPIO_WritePin(EN_5V1_GPIO_Port, EN_5V1_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(EN_5V2_GPIO_Port, EN_5V2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(LD1_EN_GPIO_Port, LD1_EN_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(LD2_EN_GPIO_Port, LD2_EN_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(REF0_EN_GPIO_Port, REF0_EN_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(REF2_ON_GPIO_Port, REF2_ON_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(TECEN1_GPIO_Port, TECEN1_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(TECEN2_GPIO_Port, TECEN2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(TEC1_PD_GPIO_Port, TEC1_PD_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(TEC2_PD_GPIO_Port, TEC2_PD_Pin, GPIO_PIN_RESET);
//	for (uint16_t i = 0; i < SD_Length; i++)
//	{
//		for (uint16_t j = 0; j < DL_16; j++)
//		{
//			SD_matr[i][j] = 0;
//		}
//	}
	//LL_SPI_Enable(SPI4);//Enable SPI for MPhD1 ADC
	//LL_SPI_Enable(SPI5);//Enable SPI for MPhD2 ADC
	HAL_GPIO_WritePin(ADC_MPD1_CS_GPIO_Port, ADC_MPD1_CS_Pin, GPIO_PIN_SET);//Enable SPI for MPhD1 ADC
	HAL_GPIO_WritePin(ADC_MPD2_CS_GPIO_Port, ADC_MPD2_CS_Pin, GPIO_PIN_SET);//Enable SPI for MPhD2 ADC
	HAL_GPIO_WritePin(SPI4_CNV_GPIO_Port, SPI4_CNV_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(SPI5_CNV_GPIO_Port, SPI4_CNV_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(DAC_LD1_CS_GPIO_Port, DAC_LD1_CS_Pin, GPIO_PIN_SET);//End operation with LDAC1
	HAL_GPIO_WritePin(DAC_LD2_CS_GPIO_Port, DAC_LD2_CS_Pin, GPIO_PIN_SET);//End operation with LDAC2
	HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_SET);//End operation with TEC1 DAC
	HAL_GPIO_WritePin(DAC_TEC2_CS_GPIO_Port, DAC_TEC2_CS_Pin, GPIO_PIN_SET);//End operation with TEC2 DAC
	
	//------------------------------------------------------------------------------------------------------------------
	//test = 11;
	if (HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin)==GPIO_PIN_RESET)//if exist sd && disconnect usb read comand
	{
		//test = 14;
		if (HAL_GPIO_ReadPin(USB_FLAG_GPIO_Port, USB_FLAG_Pin)==GPIO_PIN_RESET)
		{
			//test = 15;
			test = Mount_SD("/");
			if (test == 0) //0 - suc
			{
				//Format_SD();
				test = Seek_Read_File ("COMMAND.TXT", (uint8_t *)COMMAND, DL_8, DL_8);//Read next DL_8 bytes
				test = Unmount_SD("/"); // 0 - succ
				UART_rec_incr = 0;
				flg_tmt = 0;//Reset the timeout flag
			}
//			else
//			{
//				test = 13;
//			}
			CPU_state = DECODE_ENABLE;//Decoding data with last saved settings
		}
//		else
//		{
//			test = 16;
//		}
	}
//	else
//	{
//		test = 12;
//	}
}
static void Decode_uart(uint16_t *Command, LDx_SetupTypeDef *LD1_curr_setup, LDx_SetupTypeDef *LD2_curr_setup, Work_SetupTypeDef *Curr_setup)
{
//	uint8_t *temp1;
	uint16_t *temp2;
	
	//---------------------------------------------------------------------------------------------------------------------------------------------------------------------
	

	test=0;
	if ((HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin) == GPIO_PIN_RESET)&&
		  (HAL_GPIO_ReadPin(USB_FLAG_GPIO_Port, USB_FLAG_Pin) == GPIO_PIN_SET))//if exist sd && connect usb write comand to c
	{
		test = Mount_SD("/");
		if (test == 0) //0 - suc
		{
			//Format_SD();
			test = Remove_File ("COMMAND.TXT");
			test = Create_File("COMMAND.TXT"); // 0 -succ
			test = Write_File_byte("COMMAND.TXT", (uint8_t *)Command, CL_8);
			test = Update_File_byte("COMMAND.TXT", (uint8_t *)Command, CL_8);
			test = Unmount_SD("/"); // 0 - succ
		}
	}
	
	temp2 = (uint16_t *)Command;
	Curr_setup->WORK_EN = ((uint8_t)((*temp2)>>0))&0x01;
	Curr_setup->U5V1_EN = ((uint8_t)((*temp2)>>1))&0x01;
	Curr_setup->U5V2_EN = ((uint8_t)((*temp2)>>2))&0x01;
	Curr_setup->LD1_EN = ((uint8_t)((*temp2)>>3))&0x01;
	Curr_setup->LD2_EN = ((uint8_t)((*temp2)>>4))&0x01;
	Curr_setup->REF1_EN = ((uint8_t)((*temp2)>>5))&0x01;
	Curr_setup->REF2_EN = ((uint8_t)((*temp2)>>6))&0x01;
	Curr_setup->TEC1_EN = ((uint8_t)((*temp2)>>7))&0x01;
	Curr_setup->TEC2_EN = ((uint8_t)((*temp2)>>8))&0x01;
	Curr_setup->TS1_EN = ((uint8_t)((*temp2)>>9))&0x01;
	Curr_setup->TS2_EN = ((uint8_t)((*temp2)>>10))&0x01;
	Curr_setup->SD_EN = ((uint8_t)((*temp2)>>11))&0x01;
	Curr_setup->PI1_RD = ((uint8_t)((*temp2)>>12))&0x01;
	Curr_setup->PI2_RD = ((uint8_t)((*temp2)>>13))&0x01;
	
	temp2++;
	LD1_curr_setup->LD_TEMP = (uint16_t)(*temp2);
	temp2++;
	LD2_curr_setup->LD_TEMP = (uint16_t)(*temp2);
	temp2++;
	temp2++;
	temp2++;
	Curr_setup->AVERAGES = (uint16_t)(*temp2);
	temp2++;
	LD1_curr_setup->P_coef_temp = (float)((uint16_t)(*temp2))/((float)(256));//(float)(1/(float)((uint16_t)(*temp2))*((float)(10)));
	temp2++;
	LD1_curr_setup->I_coef_temp = (float)((uint16_t)(*temp2))/((float)(256));//(float)(1/(float)((uint16_t)(*temp2))*((float)(10)));
	temp2++;
	LD2_curr_setup->P_coef_temp = (float)((uint16_t)(*temp2))/((float)(256));//(float)(1/(float)((uint16_t)(*temp2))*((float)(10)));
	temp2++;
	LD2_curr_setup->I_coef_temp = (float)((uint16_t)(*temp2))/((float)(256));//(float)(1/(float)((uint16_t)(*temp2))*((float)(10)));
	temp2++;
	Long_Data[13] = (uint16_t)(*temp2);//Message ID
	temp2++;
	LD1_curr_setup->CURRENT = (uint16_t)(*temp2);
	temp2++;
	LD2_curr_setup->CURRENT = (uint16_t)(*temp2);
	temp2++;
	
	if (Curr_setup->U5V1_EN)
	{
		HAL_GPIO_WritePin(EN_5V1_GPIO_Port, EN_5V1_Pin, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(EN_5V1_GPIO_Port, EN_5V1_Pin, GPIO_PIN_RESET);
	}
	
	if (Curr_setup->U5V2_EN)
	{
		HAL_GPIO_WritePin(EN_5V2_GPIO_Port, EN_5V2_Pin, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(EN_5V2_GPIO_Port, EN_5V2_Pin, GPIO_PIN_RESET);
	}
	
	if (Curr_setup->LD1_EN)
	{
		HAL_GPIO_WritePin(LD1_EN_GPIO_Port, LD1_EN_Pin, GPIO_PIN_SET);
		//LL_SPI_Enable(SPI2);//Enable SPI for Laser1 DAC
	}
	else
	{
		HAL_GPIO_WritePin(LD1_EN_GPIO_Port, LD1_EN_Pin, GPIO_PIN_RESET);
		//LL_SPI_Disable(SPI2);//Disable SPI for Laser1 DAC
	}
	
	if (Curr_setup->LD2_EN)
	{
		HAL_GPIO_WritePin(LD2_EN_GPIO_Port, LD2_EN_Pin, GPIO_PIN_SET);
		//LL_SPI_Enable(SPI6);//Enable SPI for Laser2 DAC
	}
	else
	{
		HAL_GPIO_WritePin(LD2_EN_GPIO_Port, LD2_EN_Pin, GPIO_PIN_RESET);
		//LL_SPI_Disable(SPI6);//Disable SPI for Laser2 DAC
	}
	
	if (Curr_setup->REF1_EN)
	{
		HAL_GPIO_WritePin(REF0_EN_GPIO_Port, REF0_EN_Pin, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(REF0_EN_GPIO_Port, REF0_EN_Pin, GPIO_PIN_RESET);
	}
	
	if (Curr_setup->REF2_EN)
	{
		HAL_GPIO_WritePin(REF2_ON_GPIO_Port, REF2_ON_Pin, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(REF2_ON_GPIO_Port, REF2_ON_Pin, GPIO_PIN_RESET);
	}
	
	if ((Curr_setup->TS1_EN)&&(Curr_setup->TEC1_EN))
	{
		Set_LTEC(3,32767);
		Set_LTEC(3,32767);
		HAL_GPIO_WritePin(TEC1_PD_GPIO_Port, TEC1_PD_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(TECEN1_GPIO_Port, TECEN1_Pin, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(TECEN1_GPIO_Port, TECEN1_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(TEC1_PD_GPIO_Port, TEC1_PD_Pin, GPIO_PIN_RESET);		
	}
	
	if ((Curr_setup->TS2_EN)&&(Curr_setup->TEC2_EN))
	{
		Set_LTEC(4,32767);
		Set_LTEC(4,32767);
		HAL_GPIO_WritePin(TEC2_PD_GPIO_Port, TEC2_PD_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(TECEN2_GPIO_Port, TECEN2_Pin, GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(TECEN2_GPIO_Port, TECEN2_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(TEC2_PD_GPIO_Port, TEC2_PD_Pin, GPIO_PIN_RESET);		
	}
	
	if (Curr_setup->PI1_RD==0)
	{
		LD1_curr_setup->P_coef_temp = 10;
		LD1_curr_setup->I_coef_temp = 0.01;
	}
	
	if (Curr_setup->PI2_RD==0)
	{
		LD2_curr_setup->P_coef_temp = 10;
		LD2_curr_setup->I_coef_temp = 0.01;
	}
}

static void Decode_task(uint16_t *Command, LDx_SetupTypeDef *LD1_curr_setup, LDx_SetupTypeDef *LD2_curr_setup, Work_SetupTypeDef *Curr_setup)
{
	uint16_t *temp2;

	temp2 = (uint16_t *)Command;
	Curr_setup->WORK_EN = ((uint8_t)((*temp2)>>0))&0x01;
	Curr_setup->U5V1_EN = ((uint8_t)((*temp2)>>1))&0x01;
	Curr_setup->U5V2_EN = ((uint8_t)((*temp2)>>2))&0x01;
	Curr_setup->LD1_EN = ((uint8_t)((*temp2)>>3))&0x01;
	Curr_setup->LD2_EN = ((uint8_t)((*temp2)>>4))&0x01;
	Curr_setup->REF1_EN = ((uint8_t)((*temp2)>>5))&0x01;
	Curr_setup->REF2_EN = ((uint8_t)((*temp2)>>6))&0x01;
	Curr_setup->TEC1_EN = ((uint8_t)((*temp2)>>7))&0x01;
	Curr_setup->TEC2_EN = ((uint8_t)((*temp2)>>8))&0x01;
	Curr_setup->TS1_EN = ((uint8_t)((*temp2)>>9))&0x01;
	Curr_setup->TS2_EN = ((uint8_t)((*temp2)>>10))&0x01;
	Curr_setup->SD_EN = ((uint8_t)((*temp2)>>11))&0x01;
	Curr_setup->PI1_RD = ((uint8_t)((*temp2)>>12))&0x01;
	Curr_setup->PI2_RD = ((uint8_t)((*temp2)>>13))&0x01;

	temp2++;
	task.task_type   = (uint8_t)(*temp2); temp2++;
	task.min_param   = (float)(*temp2); temp2++;
	task.max_param   = (float)(*temp2); temp2++;
	task.delta_param = (float)(*temp2); temp2++;
	task.dt          = (float)(*temp2) / 100.0; temp2++;
	task.sec_param   = (float)(*temp2); temp2++;
	task.curr        = (float)(*temp2); temp2++;
	task.temp        = (float)(*temp2); temp2++;
	task.tau         = (float)(*temp2); temp2++;
	task.p_coef_1    = (float)(*temp2) * 256.0; temp2++;
	task.i_coef_1    = (float)(*temp2) * 256.0; temp2++;
	task.p_coef_2    = (float)(*temp2) * 256.0; temp2++;
	task.i_coef_2    = (float)(*temp2) * 256.0; temp2++;
	
	TO10_counter = task.dt / 10;
}

void OUT_trigger(uint8_t out_n)
{
	switch (out_n)
	{
	case 0:
		HAL_GPIO_WritePin(OUT_0_GPIO_Port, OUT_0_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_0_GPIO_Port, OUT_0_Pin, GPIO_PIN_RESET);
	break;

	case 1:
		HAL_GPIO_WritePin(OUT_1_GPIO_Port, OUT_1_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_1_GPIO_Port, OUT_1_Pin, GPIO_PIN_RESET);
	break;

	case 2:
		HAL_GPIO_WritePin(OUT_2_GPIO_Port, OUT_2_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_2_GPIO_Port, OUT_2_Pin, GPIO_PIN_RESET);
	break;

	case 3:
		HAL_GPIO_WritePin(OUT_3_GPIO_Port, OUT_3_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_3_GPIO_Port, OUT_3_Pin, GPIO_PIN_RESET);
	break;

	case 4:
		HAL_GPIO_WritePin(OUT_4_GPIO_Port, OUT_4_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_4_GPIO_Port, OUT_4_Pin, GPIO_PIN_RESET);
	break;

	case 5:
		HAL_GPIO_WritePin(OUT_5_GPIO_Port, OUT_5_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_5_GPIO_Port, OUT_5_Pin, GPIO_PIN_RESET);
	break;

	case 6:
		HAL_GPIO_WritePin(OUT_6_GPIO_Port, OUT_6_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_6_GPIO_Port, OUT_6_Pin, GPIO_PIN_RESET);
	break;

	case 7:
		HAL_GPIO_WritePin(OUT_7_GPIO_Port, OUT_7_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_7_GPIO_Port, OUT_7_Pin, GPIO_PIN_RESET);
	break;

	case 8:
		HAL_GPIO_WritePin(OUT_8_GPIO_Port, OUT_8_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_8_GPIO_Port, OUT_8_Pin, GPIO_PIN_RESET);
	break;

	case 9:
		HAL_GPIO_WritePin(OUT_9_GPIO_Port, OUT_9_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(OUT_9_GPIO_Port, OUT_9_Pin, GPIO_PIN_RESET);
	break;
	}
}

void Set_LTEC(uint8_t num, uint16_t DATA)
{
	uint32_t tmp32;

	switch (num)
	{
		case 1:
			HAL_GPIO_WritePin(DAC_LD1_CS_GPIO_Port, DAC_LD1_CS_Pin, GPIO_PIN_RESET);//Start operation with LDAC1
			//tmp32=0;
			//while(tmp32<500){tmp32++;}
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_TXE(SPI2))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			LL_SPI_TransmitData16(SPI2, DATA);//Transmit word to Laser1 DAC
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_RXNE(SPI2))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			(void) SPI2->DR;
		break;
		case 2:
			//HAL_GPIO_TogglePin(OUT_11_GPIO_Port, OUT_11_Pin); //for debug purposes
			HAL_GPIO_WritePin(DAC_LD2_CS_GPIO_Port, DAC_LD2_CS_Pin, GPIO_PIN_RESET);//Start operation with LDAC2
			//tmp32=0;
			//while(tmp32<500){tmp32++;}
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_TXE(SPI6))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			LL_SPI_TransmitData16(SPI6, DATA);//Transmit word to Laser1 DAC
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_RXNE(SPI6))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			(void) SPI6->DR;
		break;
		case 3:
			HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_RESET);//Start operation with TECDAC1
			//tmp32=0;
			//while(tmp32<500){tmp32++;}
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_TXE(SPI2))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			LL_SPI_TransmitData16(SPI2, DATA);//Transmit word to Laser1 DAC
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_RXNE(SPI2))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			(void) SPI2->DR;
		break;
		case 4:
			HAL_GPIO_WritePin(DAC_TEC2_CS_GPIO_Port, DAC_TEC2_CS_Pin, GPIO_PIN_RESET);//Start operation with TECDAC2
			//tmp32=0;
			//while(tmp32<500){tmp32++;}
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_TXE(SPI6))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			LL_SPI_TransmitData16(SPI6, DATA);//Transmit word to Laser1 DAC
			tmp32 = 0;
			while((!LL_SPI_IsActiveFlag_RXNE(SPI6))&&(tmp32<=500)) {tmp32++;}//When trans. last data cycle will be end.
			(void) SPI6->DR;
		break;
	}
	HAL_GPIO_WritePin(DAC_LD1_CS_GPIO_Port, DAC_LD1_CS_Pin, GPIO_PIN_SET);//End operation with LDAC1
	HAL_GPIO_WritePin(DAC_LD2_CS_GPIO_Port, DAC_LD2_CS_Pin, GPIO_PIN_SET);//End operation with LDAC2
	HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_SET);//End operation with TEC1
	HAL_GPIO_WritePin(DAC_TEC2_CS_GPIO_Port, DAC_TEC2_CS_Pin, GPIO_PIN_SET);//End operation with TEC2
}
static uint16_t MPhD_T(uint8_t num)
{
	uint16_t P;
	uint32_t tmp32;
	HAL_GPIO_WritePin(SPI4_CNV_GPIO_Port, SPI4_CNV_Pin, GPIO_PIN_RESET);//Prepare conversion
	HAL_GPIO_WritePin(SPI5_CNV_GPIO_Port, SPI5_CNV_Pin, GPIO_PIN_RESET);//Prepare conversion
	tmp32=0;
	while(tmp32<500){tmp32++;}
	HAL_GPIO_WritePin(SPI4_CNV_GPIO_Port, SPI4_CNV_Pin, GPIO_PIN_SET);//Stop acqusition & start conversion
	HAL_GPIO_WritePin(SPI5_CNV_GPIO_Port, SPI5_CNV_Pin, GPIO_PIN_SET);//Stop acqusition & start conversion
	tmp32=0;
	while(tmp32<500){tmp32++;}
	if (num==1)//MPD1
	{
		HAL_GPIO_WritePin(ADC_ThrLD1_CS_GPIO_Port, ADC_ThrLD1_CS_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(ADC_MPD1_CS_GPIO_Port, ADC_MPD1_CS_Pin, GPIO_PIN_RESET);
		tmp32=0;
		while(tmp32<500){tmp32++;}
		//LL_SPI_TransmitData16(SPI4, 0xFFFF);//We must to clock the CLK output for collect RX data. We can do that only by transmitting data... 
		LL_SPI_Enable(SPI4);//Enable SPI for MPhD1 ADC
		tmp32 = 0;
		while(((!LL_SPI_IsActiveFlag_RXNE(SPI4))&&(tmp32<=1000))) {tmp32++;}//When rec. last data cycle will be end.
		LL_SPI_Disable(SPI4);//Enable SPI for MPhD1 ADC
		while(tmp32<500){tmp32++;}
		//HAL_SPI_Receive(&hspi4, &P[0], 1, 100);
		HAL_GPIO_WritePin(ADC_MPD1_CS_GPIO_Port, ADC_MPD1_CS_Pin, GPIO_PIN_SET);
		P = LL_SPI_ReceiveData16(SPI4);
	}
	else if (num==2)//MPD2
	{
		HAL_GPIO_WritePin(ADC_ThrLD2_CS_GPIO_Port, ADC_ThrLD2_CS_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(ADC_MPD2_CS_GPIO_Port, ADC_MPD2_CS_Pin, GPIO_PIN_RESET);
		tmp32=0;
		while(tmp32<500){tmp32++;}
		//LL_SPI_TransmitData16(SPI5, 0xFFFF);//We must to clock the CLK output for collect RX data. We can do that only by transmitting data... 
		LL_SPI_Enable(SPI5);//Enable SPI for MPhD2 ADC
		tmp32 = 0;
		while(((!LL_SPI_IsActiveFlag_RXNE(SPI5))&&(tmp32<=1000))) {tmp32++;}//When rec. last data cycle will be end.
		LL_SPI_Disable(SPI5);//Enable SPI for MPhD2 ADC
		while(tmp32<500){tmp32++;}
		//HAL_SPI_Receive(&hspi4, &P[0], 1, 100);
		HAL_GPIO_WritePin(ADC_MPD2_CS_GPIO_Port, ADC_MPD2_CS_Pin, GPIO_PIN_SET);
		P = LL_SPI_ReceiveData16(SPI5);
	}
	else if (num==3)//ThrLD1
	{
		HAL_GPIO_WritePin(ADC_MPD1_CS_GPIO_Port, ADC_MPD1_CS_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(ADC_ThrLD1_CS_GPIO_Port, ADC_ThrLD1_CS_Pin, GPIO_PIN_RESET);
		tmp32=0;
		while(tmp32<500){tmp32++;}
		//LL_SPI_TransmitData16(SPI4, 0xFFFF);//We must to clock the CLK output for collect RX data. We can do that only by transmitting data... 
		LL_SPI_Enable(SPI4);//Enable SPI for ThrLD1 ADC
		tmp32 = 0;
		while(((!LL_SPI_IsActiveFlag_RXNE(SPI4))&&(tmp32<=1000))) {tmp32++;}//When rec. last data cycle will be end.
		LL_SPI_Disable(SPI4);//Enable SPI for ThrLD1 ADC
		while(tmp32<500){tmp32++;}
		//HAL_SPI_Receive(&hspi4, &P[0], 1, 100);
		HAL_GPIO_WritePin(ADC_ThrLD1_CS_GPIO_Port, ADC_ThrLD1_CS_Pin, GPIO_PIN_SET);
		P = LL_SPI_ReceiveData16(SPI4);
	}
	else if (num==4)//ThrLD2
	{
		HAL_GPIO_WritePin(ADC_MPD2_CS_GPIO_Port, ADC_MPD2_CS_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(ADC_ThrLD2_CS_GPIO_Port, ADC_ThrLD2_CS_Pin, GPIO_PIN_RESET);
		tmp32=0;
		while(tmp32<500){tmp32++;}
		//LL_SPI_TransmitData16(SPI5, 0xFFFF);//We must to clock the CLK output for collect RX data. We can do that only by transmitting data... 
		LL_SPI_Enable(SPI5);//Enable SPI for ThrLD2 ADC
		tmp32 = 0;
		while(((!LL_SPI_IsActiveFlag_RXNE(SPI5))&&(tmp32<=1000))) {tmp32++;}//When rec. last data cycle will be end.
		LL_SPI_Disable(SPI5);//Enable SPI for ThrLD2 ADC
		while(tmp32<500){tmp32++;}
		//HAL_SPI_Receive(&hspi4, &P[0], 1, 100);
		HAL_GPIO_WritePin(ADC_ThrLD2_CS_GPIO_Port, ADC_ThrLD2_CS_Pin, GPIO_PIN_SET);
		P = LL_SPI_ReceiveData16(SPI5);
	}
	/*float I_LD, Ith, I0m, T0m, Inorm, Tnorm1, Tnorm2, P, T_C, A, Pnorm;
	
	Inorm = (float) (65535) / (float) (100);
	Tnorm1 = (float) (65535) / (float) (50);
	Tnorm2 = 4;
	Pnorm = (float)(65535) / (float)(20);
	I0m = 8.1568;//@4 C - lowest temperature of system
	T0m = 48.6282;
	T_C = (float) (T_LD) / Tnorm1 + Tnorm2;
	
	Ith = I0m * expf(T_C/T0m);
	I_LD = (float) (C_LD) / Inorm;
	
	if (I_LD > Ith)
	{
		A = (float) (2.24276128270098e-07) * T_C * T_C * T_C  - (float) (4.73392579025590e-05) * T_C * T_C + (float) (0.00157250618257057) * T_C + (float) (0.228565407377466);
		P = A * (I_LD - Ith) * Pnorm;
	}
	else
	{
		P = 0;
	}	*/
	return P;
}
/*static uint16_t Temp_LD(uint16_t T_LD_before, uint16_t T_LD, uint32_t Timer_before, uint32_t Timer)
{
	uint16_t Result;
//	uint8_t randf;
	
	randf = 0;
	for (uint8_t i = 0; i < 32; i++)
	{
		randf = ((Timer>>i)&0x0001)^randf;
	}
	
	Result = ((float)(T_LD - T_LD_before))*((float)(1-expf(((float)(Timer_before)-(float)(Timer))/((float)(100))))) + T_LD_before + (float)(randf);
	
	return (uint16_t)(Result);
}*/
static uint16_t Get_ADC(uint8_t num)
{
	uint16_t OUT;
	switch (num)
		{
			case 0:
				HAL_ADC_Start(&hadc1); // Power on
			break;
			case 1:
				HAL_ADC_PollForConversion(&hadc1, 100); // Waiting for conversion
        OUT = HAL_ADC_GetValue(&hadc1); // Get value adc
			break;
			case 2:
				HAL_ADC_Stop(&hadc1); // Power off
			break;
			case 3:
				HAL_ADC_Start(&hadc3); // Power on
			break;
			case 4:
				HAL_ADC_PollForConversion(&hadc3, 100); // Waiting for conversion
        OUT = HAL_ADC_GetValue(&hadc3); // Get value adc
			break;
			case 5:
        HAL_ADC_Stop(&hadc3); // Power off
			break;
		}
	return OUT;
}

uint16_t Advanced_Controller_Temp(LDx_SetupTypeDef * LDx_curr_setup, LDx_ParamTypeDef * LDx_results, uint8_t num)
{
	// Main idea:
	// I is responsible to maintaining constant temperature difference between laser and room temperature.
	// As room temperature can be approximated as constant at current-varying time -- I should be kept constant too.
	// As current through laser diode heats it -- we can estimate excessive power on laser diode and trim peltier current according to it.
	// So, equation should be look like this:
	//   x_output = x_output_original + I(laser)*(a + (t - b)c)
	//     t -- cycle phase
	//     a,b,c -- constants
	//
	// How can we control laser diode temperature?
	//   -- We can set laser to fixed current at the time we need to measure.
	//   Then we should measure wavelength.
	// Calibration sequence:
	//   1) n



	int e_pid;
	float P_coef_current;//, I_coef_current;
	float e_integral;
	int x_output;

	e_pid =  (int) LDx_results->LD_CURR_TEMP - (int) LDx_curr_setup->LD_TEMP;

	e_integral = LDx_results->e_integral;

	if((e_pid < 3000) && (e_pid > - 3000)){
		e_integral += LDx_curr_setup->I_coef_temp * (float)(e_pid) * (float)(TO7 - TO7_PID) / (float) 100;//100 - timer is too fast
	}
	P_coef_current = LDx_curr_setup->P_coef_temp;

	if (e_integral > 32000){
			e_integral = 32000;
	}
	else if (e_integral < - 32000){
			e_integral = -32000;
	}
	LDx_results->e_integral = e_integral;

	x_output = 32768 + P_coef_current * e_pid + (int)e_integral;//32768 - P_coef_current * e_pid - (int)e_integral;//

	if(x_output < 1000){
		x_output = 8800;
	}
	else if(x_output > 56800){
		x_output = 56800;
	}

	if (num==2)
		TO7_PID = TO7;//Save current time only on 2nd laser

	return (uint16_t)x_output;
}


uint16_t PID_Controller_Temp(LDx_SetupTypeDef * LDx_curr_setup, LDx_ParamTypeDef * LDx_results, uint8_t num)
{			
	int e_pid;
	float P_coef_current;//, I_coef_current;
	float e_integral;
	int x_output;
	
	e_pid =  (int) LDx_results->LD_CURR_TEMP - (int) LDx_curr_setup->LD_TEMP;

	e_integral = LDx_results->e_integral;
	
	if((e_pid < 3000) && (e_pid > - 3000)){
		e_integral += LDx_curr_setup->I_coef_temp * (float)(e_pid) * (float)(TO7 - TO7_PID) / (float) 100;//100 - timer is too fast
	}
	P_coef_current = LDx_curr_setup->P_coef_temp;
	
	if (e_integral > 32000){
			e_integral = 32000;
	}
	else if (e_integral < - 32000){
			e_integral = -32000;
	}
	LDx_results->e_integral = e_integral;
	
	x_output = 32768 + P_coef_current * e_pid + (int)e_integral;//32768 - P_coef_current * e_pid - (int)e_integral;//
	
	if(x_output < 1000){
		x_output = 8800;
	}
	else if(x_output > 56800){
		x_output = 56800;
	}
	
	if (num==2)
		TO7_PID = TO7;//Save current time only on 2nd laser
	
	return (uint16_t)x_output;
}
uint8_t CheckChecksum(uint16_t *pbuff)
{
  uint16_t cl_ind;

  switch (UART_header)
  {
    case 0x7777:
      cl_ind = TSK_16 - 2;
    break;
    case 0x1111:
      cl_ind = CL_16 - 2;
    break;
    default:
      return 0;
    break;
  }

  CS_result = CalculateChecksum(pbuff, cl_ind);

  return ((CS_result == COMMAND[cl_ind]) ? 1 : 0);
}
uint16_t CalculateChecksum(uint16_t *pbuff, uint16_t len)
{
	short  i;
	uint16_t cs = *pbuff;
  
 	for(i = 1; i < len; i++)
	{
		cs ^= *(pbuff+i);
	}
	return cs;
}

/*int SD_Init(void)
{
	int test=0;
	if (HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin)==GPIO_PIN_RESET)
	{
		test = Mount_SD("/");
		if (test == 0) //0 - suc
		{
			//Format_SD();
			test = Create_File("FILE1.TXT"); // 0 -suc
			//Create_File("FILE2.TXT");
			Write_File ("FILE1.TXT", "____OSGG main borad information. Program made by Kazakov Viktor. Part ?01 (for DFB-1550-14BF lasers). Parameters of plate: Ilaser: 0...66.7 mA; Vlaser: 0...2 V; Itec: -1.27...1.27 A; Vtec: -2.56...2.56 V; IMphD: 0...519 uA; Tint: -1.2...+45.8 C; Text: -25.8...+43.4 C. Place for your advertising:..................................................................................................................................");
			test = Unmount_SD("/"); // 0 - succ
			return test;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		return 1;
	}
}*/

int SD_SAVE(uint16_t *pbuff)
{
	int test=0;
	if (HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin)==GPIO_PIN_RESET)
	{
		test = Mount_SD("/");
		if (test == 0) //0 - suc
		{
			//Format_SD();
			test = Update_File_byte("FILE1.TXT", (uint8_t *)pbuff, DL_8);
			test = Unmount_SD("/"); // 0 - succ
			return test;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		return 1;
	}
}



//uint32_t Get_Length(void)
//{
//	return SD_matr[0][0] + ((uint32_t) (SD_matr[0][1])<<16);
//}

int SD_READ(uint16_t *pbuff)
{
	int test=0;
	if (HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin)==GPIO_PIN_RESET)
	{
		test = Mount_SD("/");
		if (test == 0) //0 - suc
		{
			//Format_SD();
			test = Seek_Read_File ("FILE1.TXT", (uint8_t *)pbuff, DL_8, fgoto);//Read next 246 bytes
			fgoto+=DL_8;
			test = Unmount_SD("/"); // 0 - succ
			return test;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		return 1;
	}
	
/*	for (uint16_t j = 0; j < DL_16; j++)
	{
		*(pbuff+j) = SD_matr[SD_SLIDE][j];
	}
	if (SD_SLIDE<Get_Length())
	{
		SD_SLIDE++;
		return 0x0000;
	}
	else
	{
		return 0x0001;
	}*/
}

int SD_REMOVE(void)
{
	int test=0;
	if (HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin)==GPIO_PIN_RESET)
	{
		test = Mount_SD("/");
		if (test==FR_OK)
		{	
			test = Remove_File ("FILE1.TXT");
			test = Create_File("FILE1.TXT"); // 0 -suc
			//test = Write_File ("FILE1.TXT", "____OSGG main borad information. Program made by Kazakov Viktor. Part ?01 (for DFB-1550-14BF lasers). Parameters of plate: Ilaser: 0...66.7 mA; Vlaser: 0...2 V; Itec: -1.27...1.27 A; Vtec: -2.56...2.56 V; IMphD: 0...519 uA; Tint: -1.2...+45.8 C; Text: -25.8...+43.4 C. Place for your advertising:..................................................................................................................................");
			test = Unmount_SD("/"); // 0 - succ
			return test;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		return 1;
	}
}

//-------------------------------------------------------
void USART_TX (uint8_t* dt, uint16_t sz)
{
  uint16_t ind = 0;
  while (ind<sz)
  {
    while (!LL_USART_IsActiveFlag_TXE(USART1)) {}
    LL_USART_TransmitData8(USART1,*(uint8_t*)(dt+ind));
    ind++;
  }
}

void USART_TX_DMA (uint16_t sz)
{
	while (u_tx_flg) {}//Wait until previous transfer not complete. u_tx_flg is resetting in DMA interupt function.
	LL_DMA_DisableStream(DMA2, LL_DMA_STREAM_7);
  LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_7, sz);
  LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_7);
	u_tx_flg = 1;//indicate that transfer begin
}

static void Stop_TIM10(void)
{
	HAL_TIM_Base_Stop_IT(&htim10);
	TIM10_coflag = 0;
	TO10 = 0;
}
//-------------------------------------------------------
/* USER CODE END 4 */

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

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