/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 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 "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "adc.h"
#include "usart.h"
#include "control.h"
#include "icd.h"
#include "MAX30003.h"
#include "parse.h"
#include "spi.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern adc_struct adc_str;//структура ацп
extern ctrl_struct Control; //FLASH    (rx)
extern icd_str ICD; //
extern max30003_str max30003_struct;
extern SPI_HandleTypeDef hspi1;
/* 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 ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
osThreadId defaultTaskHandle;
uint32_t defaultTaskBuffer[ 300 ];
osStaticThreadDef_t defaultTaskControlBlock;
osThreadId OprosTaskHandle;
uint32_t OprosTaskBuffer[ 300 ];
osStaticThreadDef_t OprosTaskControlBlock;
osThreadId ControlTaskHandle;
uint32_t ControlTaskBuffer[ 300 ];
osStaticThreadDef_t ControlTaskControlBlock;
osThreadId LowSpeedTaskHandle;
uint32_t LowSpeedTaskBuffer[ 300 ];
osStaticThreadDef_t LowSpeedTaskControlBlock;
osThreadId ButTaskHandle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void const * argument);
void StartOprosTask(void const * argument);
void StartControlTask(void const * argument);
void StartLowSpeedTask(void const * argument);
void StartButTask(void const * argument);

extern void MX_USB_DEVICE_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
	init_icd(&ICD);
	//плавный разряд включен
	HAL_GPIO_WritePin(HV_DIS_GPIO_Port, HV_DIS_Pin, GPIO_PIN_RESET);
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadStaticDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 300, defaultTaskBuffer, &defaultTaskControlBlock);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* definition and creation of OprosTask */
  osThreadStaticDef(OprosTask, StartOprosTask, osPriorityNormal, 0, 300, OprosTaskBuffer, &OprosTaskControlBlock);
  OprosTaskHandle = osThreadCreate(osThread(OprosTask), NULL);

  /* definition and creation of ControlTask */
  osThreadStaticDef(ControlTask, StartControlTask, osPriorityIdle, 0, 300, ControlTaskBuffer, &ControlTaskControlBlock);
  ControlTaskHandle = osThreadCreate(osThread(ControlTask), NULL);

  /* definition and creation of LowSpeedTask */
  osThreadStaticDef(LowSpeedTask, StartLowSpeedTask, osPriorityLow, 0, 300, LowSpeedTaskBuffer, &LowSpeedTaskControlBlock);
  LowSpeedTaskHandle = osThreadCreate(osThread(LowSpeedTask), NULL);

  /* definition and creation of ButTask */
  osThreadDef(ButTask, StartButTask, osPriorityIdle, 0, 300);
  ButTaskHandle = osThreadCreate(osThread(ButTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* init code for USB_DEVICE */
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN StartDefaultTask */
	max30003_struct.mode_set = true;
	osDelay(1000);
	/* Infinite loop */
	for(;;)
	{
	  max30003_Control(&max30003_struct);
	  osDelay(100);
	}
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_StartOprosTask */
/**
* @brief Function implementing the OprosTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartOprosTask */
void StartOprosTask(void const * argument)
{
  /* USER CODE BEGIN StartOprosTask */
	max30003_Init_hard();
	osDelay(50);

    // now combine the register address and the command into one byte:
    //uint8_t dataToSend = (WRITE_ADDRESS<<1) | WREG;
     // take the chip select low to select the device:

  /* Infinite loop */
	for (;;)
	{
		if (ICD.active_ch == 0)
		{
			if (max30003_struct.mode_now == true && max30003_struct.ready)
			{
				max30003_GET_ALL(&max30003_struct);
				get_data_max30003(&ICD,max30003_struct.ecg_raw);
				//обычный алгоритм поиска
				search_alg(&ICD);
				ble_HEX_new(&Control,&ICD, &adc_str,true);
			}
		}
		else
		{
			if(adc_str.drdy_trigger)
			{
				adc_str.drdy_trigger = false;//сбросили флаг
				if(ICD.active_ch == 1)
					get_data(&ICD,adc_str.ecg_1_raw);
				if(ICD.active_ch == 2)
					get_data(&ICD,adc_str.ecg_2_raw);
				if(ICD.active_ch == 3)
					get_data(&ICD,adc_str.ecg_3_raw);
				//обычный алгоритм поиска
				search_alg(&ICD);
				ble_HEX_new(&Control,&ICD, &adc_str,true);
			}
		}
		osDelay(1);
	}
  /* USER CODE END StartOprosTask */
}

/* USER CODE BEGIN Header_StartControlTask */
/**
* @brief Function implementing the ControlTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartControlTask */
void StartControlTask(void const * argument)
{
  /* USER CODE BEGIN StartControlTask */

  /* Infinite loop */
	for (;;)
	{
		terapy_algorithm(&ICD);
		osDelay(100);
	}
  /* USER CODE END StartControlTask */
}

/* USER CODE BEGIN Header_StartLowSpeedTask */
/**
* @brief Function implementing the LowSpeedTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartLowSpeedTask */
void StartLowSpeedTask(void const * argument)
{
  /* USER CODE BEGIN StartLowSpeedTask */
	static uint8_t buff[16];

	HAL_StatusTypeDef status;

	HAL_GPIO_WritePin(SPI1_PWR_GPIO_Port, SPI1_PWR_Pin, GPIO_PIN_SET);
	osDelay(100);
  /* Infinite loop */
	for (;;)
	{
		POT_cheek(&ICD.spi_pot_set, &ICD.spi_pot_now);
		status = HAL_UART_Receive_DMA(&huart1, (uint8_t*) buff, 7);
		osDelay(10);
		if (status == HAL_OK)
			parse_command(buff, &ICD);
	}
  /* USER CODE END StartLowSpeedTask */
}

/* USER CODE BEGIN Header_StartButTask */
/**
* @brief Function implementing the ButTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartButTask */
void StartButTask(void const * argument)
{
  /* USER CODE BEGIN StartButTask */
  /* Infinite loop */
	for (;;)
	{
		if (HAL_GPIO_ReadPin(BUT_1_GPIO_Port, BUT_1_Pin) == GPIO_PIN_SET)
		{
			Control.btn_1_state = true;
			Control.btn_1_cnt++;
			if (Control.btn_1_cnt > BUT_CNT)
			{
					Control.set_mode = Sleep;     //идем вверх по режимам
					osDelay(4000);
					lets_sleep();
			}
		}
		else
		{
			Control.btn_1_state = false;
			Control.btn_1_cnt = 0;
		}
	}
  /* USER CODE END StartButTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */
