/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @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 "main.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "PLSR.h"	  
#include "includes.h"
#include "modbus.h"
#include "bitset.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t ArrFlag = 0; /* 加速度Flag */
float Acc;         /* 加速度 */
int32_t AllPulseCNT = 0;
int32_t BaseCNT = 0;
int32_t CNT_Only[10] = {0};

uint8_t EXT_Flag = 0;
uint8_t PulseStartFlag = 0;
uint8_t ArrTimes = 0;
uint8_t FixArrFlag = 0;

extern uint8_t Register_H[16384];      ///<寄存器的高字节
extern uint8_t Register_L[16384];      ///<寄存器的低字节
/* 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 PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

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

/* 任务优先级 */
#define TASK_Y1Direction    6
#define TASK_PulseStart     5
#define TASK_DirOutput      6
#define TASK_PulseGetCount  5
#define TASK_EXTSet         6

/* 任务堆栈大小 */
#define Task_Y1Direction_SIZE   256
#define Task_PulseStart_SIZE    512
#define Task_DirOutput_SIZE     256
#define Task_PulseGetCount_SIZE 256
#define Task_EXTSet_SIZE        256

/* 任务控制块 */
OS_TCB Y1Direction_Tsk;
OS_TCB PulseStart_Tsk; 
OS_TCB DirOutput_Tsk;
OS_TCB PulseGetCount_Tsk;
OS_TCB EXTSet_Tsk;
 
 /* 任务栈 */ 
CPU_STK Task_Y1Direction_STK[Task_Y1Direction_SIZE];
CPU_STK Task_PulseStart_STK[Task_PulseStart_SIZE];
CPU_STK Task_DirOutput_STK[Task_DirOutput_SIZE];
CPU_STK Task_PulseGetCount_STK[Task_PulseGetCount_SIZE];
CPU_STK Task_EXTSet_STK[Task_EXTSet_SIZE];

/* 任务函数 */
void Y1Direction(void *p_arg);
void PulseStartTsk(void *p_arg);
void DirOutput(void *p_arg);
void PulseGetCount(void *p_arg);
void EXTSet(void *p_arg);

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  OS_ERR err;
  /* USER CODE END 1 */

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

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

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */
  
	HAL_PWR_EnableBkUpAccess();/* 使能备份域访问 */
	__HAL_RCC_BKPSRAM_CLK_ENABLE();/* 使能备份SRAM时钟 */
	HAL_PWREx_EnableBkUpReg();/* 使能备份SRAM */
	
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_TIM10_Init();
  MX_TIM2_Init();
  MX_TIM11_Init();
  MX_TIM13_Init();
  MX_TIM14_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  
  
  
  	BSP_Init();
	OSInit(&err); 
	
	CPU_SR_ALLOC();
	CPU_CRITICAL_ENTER();///进入临界区
	
	 /* 任务1 */
	 OSTaskCreate((OS_TCB  * )&Y1Direction_Tsk,                                    /* 任务控制块 */
                 (CPU_CHAR* )"Y1Direction",                                          /* 任务名字 */
                 (OS_TASK_PTR)Y1Direction,                                           /* 任务函数 */
                 (void  * )0,                                            /* 传递给任务函数的参数 */
                 (OS_PRIO   )TASK_Y1Direction,                                     /* 任务优先级 */
                 (CPU_STK * )&Task_Y1Direction_STK[0],                         /* 任务堆栈基地址 */
                 (CPU_STK_SIZE)Task_Y1Direction_SIZE/10,                     /* 任务堆栈深度限位 */
                 (CPU_STK_SIZE)Task_Y1Direction_SIZE,                            /* 任务堆栈大小 */
                 (OS_MSG_QTY)0,      /* 任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 */
                 (OS_TICK   )0,               /* 当使能时间片轮转时的时间片长度，为0时为默认长度 */
                 (void    * )0,                                              /* 用户补充的存储区 */
                 (OS_OPT    )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,                /* 任务选项 */
                 (OS_ERR  * )&err);                                  /* 存放该函数错误时的返回值 */
	 /* 任务2 */
	 OSTaskCreate((OS_TCB  * )&PulseStart_Tsk,                                    
                 (CPU_CHAR* )"PulseStartTsk",                                 
                 (OS_TASK_PTR)PulseStartTsk,                                 
                 (void  * )0,                                          
                 (OS_PRIO   )TASK_PulseStart,                                 
                 (CPU_STK * )&Task_PulseStart_STK[0],                    
                 (CPU_STK_SIZE)Task_PulseStart_SIZE/10,                
                 (CPU_STK_SIZE)Task_PulseStart_SIZE,                    
                 (OS_MSG_QTY)0,      
                 (OS_TICK   )0,            
                 (void    * )0,                                         
                 (OS_OPT    )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,          
                 (OS_ERR  * )&err);                              
     /* 任务3 */
	 OSTaskCreate((OS_TCB  * )&DirOutput_Tsk,                               
                 (CPU_CHAR* )"DirOutput_Tsk",                               
                 (OS_TASK_PTR)DirOutput,                                  
                 (void  * )0,                                       
                 (OS_PRIO   )TASK_DirOutput,                              
                 (CPU_STK * )&Task_DirOutput_STK[0],                         
                 (CPU_STK_SIZE)Task_DirOutput_SIZE/10,                   
                 (CPU_STK_SIZE)Task_DirOutput_SIZE,                        
                 (OS_MSG_QTY)0,     
                 (OS_TICK   )0,             
                 (void    * )0,                                           
                 (OS_OPT    )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,              
                 (OS_ERR  * )&err);          
	 /* 任务4 */
	 OSTaskCreate((OS_TCB  * )&PulseGetCount_Tsk,                               
                 (CPU_CHAR* )"PulseGetCount_Tsk",                               
                 (OS_TASK_PTR)PulseGetCount,                                  
                 (void  * )0,                                       
                 (OS_PRIO   )TASK_PulseGetCount,                              
                 (CPU_STK * )&Task_PulseGetCount_STK[0],                         
                 (CPU_STK_SIZE)Task_PulseGetCount_SIZE/10,                   
                 (CPU_STK_SIZE)Task_PulseGetCount_SIZE,                        
                 (OS_MSG_QTY)0,     
                 (OS_TICK   )0,             
                 (void    * )0,                                           
                 (OS_OPT    )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,              
                 (OS_ERR  * )&err);  	 
	 /* 任务5 */
	 OSTaskCreate((OS_TCB  * )&EXTSet_Tsk,                               
                 (CPU_CHAR* )"EXTSet_Tsk",                               
                 (OS_TASK_PTR)EXTSet,                                  
                 (void  * )0,                                       
                 (OS_PRIO   )TASK_EXTSet,                              
                 (CPU_STK * )&Task_EXTSet_STK[0],                         
                 (CPU_STK_SIZE)Task_EXTSet_SIZE/10,                   
                 (CPU_STK_SIZE)Task_EXTSet_SIZE,                        
                 (OS_MSG_QTY)0,     
                 (OS_TICK   )0,             
                 (void    * )0,                                           
                 (OS_OPT    )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,              
                 (OS_ERR  * )&err);  	
	 
	 /* 掉电数据读取 */
	 ModbusLoadSRAM();
	 PLSRPluseLoad(); //读取脉冲设置
	 PLSROptionLoad(); //读取脉冲基础设置
	 NowFrequency = PulseOutput[0].Frequency;
	 NowPulse = Options.StartPulse;
	 CPU_CRITICAL_EXIT() ;  ///退出临界区
	 OSStart(&err);
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* 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 = 6;
  RCC_OscInitStruct.PLL.PLLN = 72;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

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

/* USER CODE BEGIN 4 */

/**
* @brief 任务1， 脉冲加减速    
* @return 无
*/
void Y1Direction(void *p_arg)
{
	p_arg = p_arg;
	OS_ERR err;
	
	while(1)
	{
		if (NowFrequency != PulseOutput[NowPulse].Frequency)/* 如果现在寄存器内的频率与实际输出的频率不一致 */
		{
			FixArrFlag = 1; //使能频率修改脉冲加减速
			if (PulseOutput[NowPulse].Frequency > NowFrequency)
			{
				Acc = (PulseOutput[NowPulse].Frequency - NowFrequency ) / Options.AccUpTime;
			}
			else
			{
				Acc = (PulseOutput[NowPulse].Frequency - NowFrequency ) / Options.AccDownTime;
			}
			HAL_TIM_Base_Start_IT(&htim3);  /* 启动定时器3和中断 */
		}
		OSTimeDly(100, OS_OPT_TIME_DLY, &err); // 延时 100 个节拍
	}
}

/**
* @brief 任务2，脉冲开始,数据处理
* @return 无
*/
void PulseStartTsk(void *p_arg)
{
	p_arg = p_arg;
	OS_ERR err;
	uint8_t EN = 1;
	
	while(1)
	{
		PLSRPluseLoad(); //读取脉冲设置
	 	PLSROptionLoad(); //读取脉冲基础设置
		
		if (Register_L[0x3000] == 0x01 && EN == 1)
		{
			EN = 0;
			PulseStartFlag = 1;
			NowFrequency = PulseOutput[NowPulse].Frequency; /* 保存当前脉冲的频率 */
			PulseStart();
			HAL_TIM_Base_Start_IT(&htim3);  /* 启动定时器3和中断 */
		}
		else if (Register_L[0x3000] == 0x02 && EN == 0)
		{
			EN = 1;
		}

		ModbusSaveSRAM();	
		OSTimeDly(10, OS_OPT_TIME_DLY, &err); // 延时 10 个节拍
	}
}

/**
* @brief 任务3，脉冲方向输出
* @return 无
*/
void DirOutput(void *p_arg)
{
	p_arg = p_arg;
	OS_ERR err;
	
	while(1)
	{
		/* 根据当前的方向和输出的方向的端口进行输出的配置 */
		if (Options.DirPost == 0)
		{
			if (Options.Dir == 1)
			{
				HAL_GPIO_WritePin(GPIOH, Y12_Pin, GPIO_PIN_SET);
			}
			else 
			{
				HAL_GPIO_WritePin(GPIOH, Y12_Pin, GPIO_PIN_RESET);
			}
		}
		if (Options.DirPost == 1)
		{
			if (Options.Dir == 1)
			{
				HAL_GPIO_WritePin(GPIOH, Y13_Pin, GPIO_PIN_SET);
			}
			else 
			{
				HAL_GPIO_WritePin(GPIOH, Y13_Pin, GPIO_PIN_RESET);
			}
		}
		if (Options.DirPost == 2)
		{
			if (Options.Dir == 1)
			{
				HAL_GPIO_WritePin(GPIOH, Y14_Pin, GPIO_PIN_SET);
			}
			else 
			{
				HAL_GPIO_WritePin(GPIOH, Y14_Pin, GPIO_PIN_RESET);
			}
		}
		if (Options.DirPost == 3)
		{
			if (Options.Dir == 1)
			{
				HAL_GPIO_WritePin(GPIOH, Y15_Pin, GPIO_PIN_SET);
			}
			else 
			{
				HAL_GPIO_WritePin(GPIOH, Y15_Pin, GPIO_PIN_RESET);
			}
		}
		/* 预留时间给其他任务 */
		OSTimeDly(100, OS_OPT_TIME_DLY, &err); // 延时 100 个节拍
	}
}

/**
* @brief 任务4，脉冲计数
* @return 无
*/
void PulseGetCount(void *p_arg)
{
	p_arg = p_arg;
	OS_ERR err;
	
	while(1)
	{
		/* 根据当前脉冲的方向设置输出的方向 */
		if(PulseOutput[NowPulse].PulseCount < 0)
		{
			Options.Dir = 1;
		}
		else
		{
			Options.Dir = 0;
		}
		if (TIM2->CNT != 0) CNT_Only[NowPulse] = TIM2->CNT;
		AllPulseCNT = CNT_Only[0] + CNT_Only[1] + CNT_Only[2] + CNT_Only[3] +
					  CNT_Only[4] + CNT_Only[5] + CNT_Only[6] + CNT_Only[7] +
					  CNT_Only[8] + CNT_Only[9];
		
		CountSave();
		OSTimeDly(10, OS_OPT_TIME_DLY, &err);
	}
}

/**
* @brief 任务5，EXT
* @return 无
*/
void EXTSet(void *p_arg)
{
	p_arg = p_arg;
	OS_ERR err;
	
	uint8_t X4_Sta, X5_Sta;
	while(1)
	{
		if(HAL_GPIO_ReadPin(GPIOB, X4_Pin) == GPIO_PIN_SET)
		{
			OSTimeDly(10, OS_OPT_TIME_DLY, &err);
			if(HAL_GPIO_ReadPin(GPIOB, X4_Pin) == GPIO_PIN_SET)
			{
				X4_Sta = 1;
				while(HAL_GPIO_ReadPin(GPIOB, X4_Pin) == GPIO_PIN_SET);
			}
		}
		if(HAL_GPIO_ReadPin(GPIOG, X5_Pin) == GPIO_PIN_SET)
		{
			OSTimeDly(10, OS_OPT_TIME_DLY, &err);
			if(HAL_GPIO_ReadPin(GPIOG, X5_Pin) == GPIO_PIN_SET)
			{
				X5_Sta = 1;
				while(HAL_GPIO_ReadPin(GPIOG, X5_Pin) == GPIO_PIN_SET);
			}
		}
		/* X4引脚的EXT信号 */
		if(X4_Sta == 1 && Options.EXT == 0 && PulseOutput[NowPulse].EXT == 1)
		{
			if (TIM2->CNT != 0) CNT_Only[NowPulse] = TIM2->CNT; /* 保存当前的脉冲计数 */
			TIM2->CNT = TIM2->ARR - 1;
			EXT_Flag = 1;
			X4_Sta = 0;
		}
		else
		{
			X4_Sta = 0;
		}
		
		/* X5引脚的EXT信号 */
		if(X5_Sta == 1 && Options.EXT == 1 && PulseOutput[NowPulse].EXT == 1)
		{
			if (TIM2->CNT != 0) CNT_Only[NowPulse] = TIM2->CNT; /* 保存当前的脉冲计数 */
			TIM2->CNT = TIM2->ARR - 1;			
			EXT_Flag = 1;
			X5_Sta = 0;
		}
		else
		{
			X5_Sta = 0;
		}
		
		if(EXT_Flag == 1)
		{
			EXT_Flag = 0;
			HAL_TIM_GenerateEvent(&htim2, TIM_EVENTSOURCE_UPDATE);
		}
		
		OSTimeDly(100, OS_OPT_TIME_DLY, &err);
	}
}

/**
* @brief 定时器中断回调函数，用来实现脉冲加减速（定时时间1ms）
* @return 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	OSIntEnter(); /* 进入中断 */
	
	if (htim == (&htim3))
	{
		/* 段切换的加减速 */
		if (ArrFlag == 1)
		{
			/* 脉冲加速 */
			if (Acc > 0)
			{
				if (ArrTimes <= Options.AccUpTime)
				{
					SetFrequency(Options.SentPost, PulseOutput[PrePulse].Frequency + ArrTimes * Acc);
					if(ArrTimes == 0) PulseStart(); /* 开始产生脉冲 */
					ArrTimes++;
				}
				else
				{
					SetFrequency(Options.SentPost, PulseOutput[NowPulse].Frequency);
					ArrTimes = 0;
					ArrFlag = 0;
					HAL_TIM_Base_Stop_IT(&htim3);  // 停止定时器并禁用中断
				}	
			}
			/* 脉冲减速 */
			else if (Acc <= 0)
			{
				if (ArrTimes <= Options.AccDownTime)
				{
					SetFrequency(Options.SentPost, PulseOutput[PrePulse].Frequency + ArrTimes * Acc);
					if (ArrTimes == 0) PulseStart(); /* 开始产生脉冲 */
					ArrTimes++;
				}
				else
				{
					SetFrequency(Options.SentPost, PulseOutput[NowPulse].Frequency);
					ArrTimes = 0;
					ArrFlag = 0;
					HAL_TIM_Base_Stop_IT(&htim3);  // 停止定时器并禁用中断
				}				
			}			
		}
		/* 实时修改频率的加减速 */
		if (FixArrFlag == 1)
		{
			/* 脉冲加速 */
			if (Acc > 0)
			{
				if (ArrTimes <= Options.AccUpTime)
				{
					SetFrequency(Options.SentPost, NowFrequency + ArrTimes * Acc);
					if(ArrTimes == 0) PulseStart(); /* 开始产生脉冲 */
					ArrTimes++;
				}
				else
				{
					SetFrequency(Options.SentPost, PulseOutput[NowPulse].Frequency);
					ArrTimes = 0;
					FixArrFlag = 0;
					HAL_TIM_Base_Stop_IT(&htim3);  // 停止定时器并禁用中断
				}	
			}
			/* 脉冲减速 */
			else if (Acc <= 0)
			{
				if (ArrTimes <= Options.AccDownTime)
				{
					SetFrequency(Options.SentPost, NowFrequency + ArrTimes * Acc);
					if (ArrTimes == 0) PulseStart(); /* 开始产生脉冲 */
					ArrTimes++;
				}
				else
				{
					SetFrequency(Options.SentPost, PulseOutput[NowPulse].Frequency);
					ArrTimes = 0;
					FixArrFlag = 0;
					HAL_TIM_Base_Stop_IT(&htim3);  // 停止定时器并禁用中断
				}				
			}			
		}
		
		/* 第一段脉冲的加速 */
		if (NowPulse == Options.StartPulse && PulseStartFlag == 1)
		{
			Acc = PulseOutput[NowPulse].Frequency / Options.AccUpTime;/* 计算加速度 */
			if(ArrTimes <= Options.AccUpTime)
			{
				ArrTimes++;
				SetFrequency(Options.SentPost, ArrTimes * Acc);
				if (ArrTimes == 1) PulseStart(); /* 开始产生脉冲 */
			}
			else
			{
				SetFrequency(Options.SentPost, PulseOutput[NowPulse].Frequency);
				HAL_TIM_Base_Stop_IT(&htim3);  // 停止定时器并禁用中断
				PulseStartFlag = 0;
				ArrTimes = 0;
			}
		}
		/* 最后一段脉冲的减速 */
		if(Options.AllPulse == PulseNum)
		{
			Acc = - PulseOutput[NowPulse].Frequency / Options.AccUpTime;/* 计算加速度 */
			/* 思路： 在中断内计算正常情况下减速时间对应多少脉冲，在给最后一段脉冲赋值时减去对应的值，同时使能减速标志位
				在此函数内实现最后一段脉冲的减速过程。 */
		}
	}
	
	OSIntExit(); /* 退出中断 */
}
/* 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 */
