/* 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 "dma.h"
#include "i2c.h"
#include "tim.h"
#include "queue.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
typedef StaticQueue_t osStaticMessageQDef_t;
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
typedef enum
{
	Close_output,
	Close_input,
	Open1_input,
	Open2_input,
	default_Hall
} hallADC;
hallADC Hallmode;

DeviceParams_t g_deviceParams;
/* USER CODE END PD */

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

//ADC变量定义
uint16_t AD_Value[5] = {0};
uint16_t AD1, AD2, AD3, AD4, AD5 = 0;
int i,adc;
float AD1_Vol,AD2_Vol,AD3_Vol,AD4_Vol,AD5_Vol,AD5_I;
extern uint16_t Valve_status;		//	阀状态0000关0001开
float pid_output = 0.0f;
extern uint16_t Running_time;			//	运行时长
extern uint32_t Motor_speed;			//  电机转速
extern uint32_t Motor_current;		//  电机电流
extern uint32_t Magnetic_angle;		//	磁角度
extern uint32_t hall_data[4];			//	霍尔1到4的数据
extern uint8_t dataReceive485[BUFFER_SIZE485];	// 485串口接收缓冲区
extern uint16_t uartIRQ_rx_len ;	// 485串口接收数据长度
float Motor_cur = 0.0f;		//  电机电流
float Motor_spe = 0.0f;		//  电机转速
extern float delta_time; 	//	读取角度间隔时间（毫秒）
extern int32_t freq; // 定时器1频率


uint32_t period_buffer[CAPTURE_DEPTH];    // PWM周期
uint32_t high_buffer[CAPTURE_DEPTH];      // PWM高电平时间
sysmode Systemmode;
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for HighestTask */
osThreadId_t HighestTaskHandle;
const osThreadAttr_t HighestTask_attributes = {
  .name = "HighestTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityRealtime,
};
/* Definitions for ReadTask */
osThreadId_t ReadTaskHandle;
const osThreadAttr_t ReadTask_attributes = {
  .name = "ReadTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for DealTask */
osThreadId_t DealTaskHandle;
const osThreadAttr_t DealTask_attributes = {
  .name = "DealTask",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for CommonTask */
osThreadId_t CommonTaskHandle;
const osThreadAttr_t CommonTask_attributes = {
  .name = "CommonTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityBelowNormal,
};
/* Definitions for MotorTask */
osThreadId_t MotorTaskHandle;
const osThreadAttr_t MotorTask_attributes = {
  .name = "MotorTask",
  .stack_size = 256 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for uart485rxqueue */
osMessageQueueId_t uart485rxqueueHandle;
uint8_t uart485queueBuffer[ 16 * sizeof( Uart485Rx_msg ) ];
osStaticMessageQDef_t uart485queueControlBlock;
const osMessageQueueAttr_t uart485rxqueue_attributes = {
  .name = "uart485rxqueue",
  .cb_mem = &uart485queueControlBlock,
  .cb_size = sizeof(uart485queueControlBlock),
  .mq_mem = &uart485queueBuffer,
  .mq_size = sizeof(uart485queueBuffer)
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
//void uart_enable(void);
//void Restart_UART1_DMA(void);
float Read_MT6813_Angle(void);
void pack_hall_data(void) ;
void pack_Magnetic_angle(void);
void pack_Motor_current(void); //  电机电流
void pack_Motor_speed(void); //  电机转速
/* USER CODE END FunctionPrototypes */

void HighestLEDTask(void *argument);
void ReaddataTask(void *argument);
void DealcallbackTask(void *argument);
void CommonPrintTask(void *argument);
void MotorControlTask(void *argument);

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

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
	printf("API2_ELE 0612\r\n");
	Systemmode = Debugmode; // 调试模式
	
	load_params_from_flash(); // 从内部flash读取传感器参数
  Set_485_Baudrate(g_deviceParams.Serial_baud_rate);
	Restart_UART1_DMA();
	
  /* 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 */

  /* Create the queue(s) */
  /* creation of uart485rxqueue */
  uart485rxqueueHandle = osMessageQueueNew (16, sizeof(Uart485Rx_msg), &uart485rxqueue_attributes);

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

  /* Create the thread(s) */
  /* creation of HighestTask */
  HighestTaskHandle = osThreadNew(HighestLEDTask, NULL, &HighestTask_attributes);

  /* creation of ReadTask */
  ReadTaskHandle = osThreadNew(ReaddataTask, NULL, &ReadTask_attributes);

  /* creation of DealTask */
  DealTaskHandle = osThreadNew(DealcallbackTask, NULL, &DealTask_attributes);

  /* creation of CommonTask */
  CommonTaskHandle = osThreadNew(CommonPrintTask, NULL, &CommonTask_attributes);

  /* creation of MotorTask */
  MotorTaskHandle = osThreadNew(MotorControlTask, NULL, &MotorTask_attributes);

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

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_HighestLEDTask */
/**
  * @brief  Function implementing the HighestTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_HighestLEDTask */
void HighestLEDTask(void *argument)
{
  /* USER CODE BEGIN HighestLEDTask */
  /* Infinite loop */
	LEDStatus_t current_status;
	uint8_t last_status = 0;
	uint32_t runtimecount = 0;
  for(;;)
  {
		
    if(Hallmode == Close_output)
      current_status = LED_WARNING_1;
    else if(Hallmode == Close_input)
      current_status = LED_WARNING_2;
    else if(Hallmode == Open1_input)
      current_status = LED_WARNING_3;
    else if(Hallmode == Open2_input)
      current_status = LED_WARNING_4;			
    else
      current_status = LED_NORMAL;

		if(Motormode == MOTOR_OVERCURRENT)
      current_status = LED_WARNING_5;
		
		if(Systemmode == IAPbootloader)
      current_status = LED_IAP;
		
    // 只有当状态发生变化时才调用
    if (current_status != last_status)
    {
      last_status = current_status;
      UpdateLEDStatus(current_status);
    }

    LED_FlashHandler(&led_green);
    LED_FlashHandler(&led_red);
		if(runtimecount > 100)
		{
			runtimecount = 0;
			Running_time ++ ;
			if(Running_time > 65535)
				Running_time = 0;				
		}
		runtimecount++;
    osDelay(10);
  }
  /* USER CODE END HighestLEDTask */
}

/* USER CODE BEGIN Header_ReaddataTask */
/**
* @brief Function implementing the ReadTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_ReaddataTask */
void ReaddataTask(void *argument)
{
  /* USER CODE BEGIN ReaddataTask */
  /* Infinite loop */
	/*角度PWM输入捕获*/
//	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
//	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);		
//	HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
//	HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
	HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_1, period_buffer, CAPTURE_DEPTH);
	HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_2, high_buffer, CAPTURE_DEPTH);
	/*ADC多通道读取*/
	ADC_Enable (&hadc1);
	HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED); // 启动ADC校准（单端模式）消除ADC的偏移误差 ADC_DIFFERENTIAL_ENDED ADC_SINGLE_ENDED
	HAL_ADC_Start_DMA(&hadc1,(uint32_t *) AD_Value, 5); // 启动ADC并通过DMA搬运数据
	
  for(;;)
  {
//		Read_MT6813_Angle(); // PWM中断读取角度		
//		read_angle();	// 硬件iic读取角度		
		pack_Magnetic_angle(); // 组包到 Magnetic_angle 用于MODBUS发送
		pack_Motor_speed(); 	 // 组包到 Motor_speed 用于MODBUS发送
		
		AD1 = AD_Value[0];
		AD2 = AD_Value[1];
		AD3 = AD_Value[2];
		AD4 = AD_Value[3];
		AD5 = AD_Value[4];
		
		AD1_Vol = (float) AD1 / 4096 * (float) 3.3;
		AD2_Vol = (float) AD2 / 4096 * (float) 3.3;
		AD3_Vol = (float) AD3 / 4096 * (float) 3.3;
		AD4_Vol = (float) AD4 / 4096 * (float) 3.3;
		AD5_Vol = (float) AD5 / 4096 * (float) 3.3;
		
		if( AD5_Vol > 3.3f )
			AD5_Vol = 0.0f;
		AD5_I = AD5_Vol / 0.5f;
		Motor_cur = AD5_I;
		pack_hall_data(); 		// 组包到 hall_data 用于MODBUS发送
		pack_Motor_current(); // 组包到 Motor_current 用于MODBUS发送

		
		if(AD1_Vol > 1.6f && AD1_Vol < 2.0f && AD2_Vol > 2.5f && AD4_Vol > 1.1f && AD4_Vol < 1.5f)
		{
			// 拉杆关 电机伸出到位
			Hallmode = Close_output;
			Valve_status = 0;
		}
		else if(AD1_Vol > 1.6f && AD1_Vol < 2.0f && AD2_Vol > 2.5f && AD4_Vol > 1.5f && AD4_Vol < 2.0f)
		{
			// 拉杆关 电机缩回到位
			Hallmode = Close_input;
			Valve_status = 1;
		}
		else if(AD1_Vol < 1.0f && AD2_Vol > 1.0f && AD2_Vol < 1.4f  && AD4_Vol > 1.6f && AD4_Vol < 2.0f)
		{
			// 拉杆开 电机缩回到位
			Hallmode = Open1_input;
			Valve_status = 1;
		}
		else if(AD1_Vol > 1.2f && AD1_Vol < 1.6f && AD2_Vol > 0.9f && AD2_Vol < 1.3f && AD4_Vol > 1.6f && AD4_Vol < 2.0f)
		{
			// 拉杆开 电机缩回到位
			Hallmode = Open2_input;
			Valve_status = 1;
		}else{
			Hallmode = default_Hall;
			Valve_status = 1;
		}
		
    osDelay(5);
  }
  /* USER CODE END ReaddataTask */
}

/* USER CODE BEGIN Header_DealcallbackTask */
/**
* @brief Function implementing the DealTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_DealcallbackTask */
void DealcallbackTask(void *argument)
{
  /* USER CODE BEGIN DealcallbackTask */
  /* Infinite loop */
	
	
	
  for(;;)
  {
		Process_Uart485callback(); // 处理485指令应答
    osDelay(20);
  }
  /* USER CODE END DealcallbackTask */
}

/* USER CODE BEGIN Header_CommonPrintTask */
/**
* @brief Function implementing the CommonTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_CommonPrintTask */
void CommonPrintTask(void *argument)
{
  /* USER CODE BEGIN CommonPrintTask */
  /* Infinite loop */
  for(;;)
  {
		target_angle_deg = pidMotor1Speed.target_val;	
		diff_Angle = pidMotor1Speed.err;		
		
//		printf("target=[%.2f] cur=[%.2f] diff=[%.2f] pid_output=[%.2f] Magnet:[%s] Motor_spe[%.2f] delta_time[%.2f]\r\n", 
//						target_angle_deg, cur_angle_deg, diff_Angle ,pid_output ,no_mag_flag ? "NO" : "YES" ,Motor_spe ,delta_time);
		printf("cur_angle_deg=[%.2f] Motor_spe[%.2f] Motor_cur[%.3f]\r\n", cur_angle_deg,Motor_spe,Motor_cur);
		osDelay(200);
		
//		printf("AD1_Vol:[%.3f], AD2_Vol:[%.3f], AD3_Vol:[%.3f], AD4_Vol[%.3f], AD5_Vol[%.3f],  Motor_cur[%.3f]\r\n",
//						AD1_Vol, AD2_Vol, AD3_Vol, AD4_Vol, AD5_Vol, Motor_cur);
 

		if(Hallmode == Close_output)
		{
			printf("Close output \r\n"); // 拉杆关 电机伸出到位
		}
		if(Hallmode == Close_input)
		{
			printf("Close input \r\n"); // 拉杆关 电机收回到位
		}
		if(Hallmode == Open1_input)
		{
			printf("Open1 input \r\n"); // 拉杆开一档 电机收回到位
		}
		if(Hallmode == Open2_input)
		{
			printf("Open2 input \r\n"); // 拉杆开二挡 电机收回到位
		}
		if(Hallmode == default_Hall)
		{
			printf("default_Hall \r\n"); // 拉杆开 电机收回到位
		}

  }
  /* USER CODE END CommonPrintTask */
}

/* USER CODE BEGIN Header_MotorControlTask */
/**
* @brief Function implementing the MotorTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_MotorControlTask */
void MotorControlTask(void *argument)
{
  /* USER CODE BEGIN MotorControlTask */
  /* Infinite loop */
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);  // 启动电机 CH1 PWM（控制 IN1）
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);  // 启动电机 CH2 PWM（控制 IN2）
	uint16_t overcurrent_timer_ms = 0;       // 记录过流持续时间
	PID_init();
	
  for(;;)
  {
		// 电机角度	cur_angle_deg（0到360度）
		// 电机转速 Motor_spe （-400到+400）
		// 电机电流 Motor_cur （正常是0.01，堵转最高是到0.035）
		// 目标速度 target_speed 
		
//		Motor_Angle_Current_PID_Control();			
		if(use_pid_control)
		{	
			if (Motor_cur > 0.035f )
			{
					if (overcurrent_timer_ms < 1500)
					{
							overcurrent_timer_ms += 10;  // 每10ms调用一次
					}
					else
					{
							// 过流超时，停转
							Motormode = MOTOR_OVERCURRENT;
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
					}
			}
			else
			{
					// 电流恢复正常，清零计时器
					overcurrent_timer_ms = 0;
			}
//				Motor_PID_Control();
//			Motor_Angle_Current_PID_Control();
			int16_t pwm_output = PID_Incremental_Calc(&pidMotor1Speed, pidMotor1Speed.target_speed, Motor_spe);

			// 起动门槛限制
			if (abs(pwm_output) < 350 && pidMotor1Speed.target_speed != 0)
					pwm_output = (pwm_output > 0) ? 500 : -500;

			if (Motormode == MOTOR_FORWARD)
					Motor_Forward(pwm_output);
			if (Motormode == MOTOR_REVERSE)
					Motor_Reverse(pwm_output);
			if (Motormode == MOTOR_STOPPED)
			{
				__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
				__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
			}
			
		}
		
//			float pwm_Speed = PID_Incremental_Calc(&pidMotor1Speed,1000,Motor_spe);
//			__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, pwm_Speed); 	//电机正转
			
		if(Hallmode != Close_output)
			__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
		
		if(Hallmode != Open1_input && Hallmode != Open2_input && Hallmode != Close_input)
      __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0); 
    osDelay(10);
  }
  /* USER CODE END MotorControlTask */
}

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


float Read_MT6813_Angle(void)
{
    uint32_t high_time = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2); // 高电平宽度
    uint32_t period = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1)+1;    // 周期

    if (period == 0) return 0.0f;

    float duty = (float)high_time / period;
    cur_angle_deg = duty * 360.0f;
		
    return angle;
}


void pack_hall_data(void)
{
    memcpy(&hall_data[0], &AD1_Vol, sizeof(float));  // float --> uint32_t（IEEE754位一致）
    memcpy(&hall_data[1], &AD2_Vol, sizeof(float));
    memcpy(&hall_data[2], &AD3_Vol, sizeof(float));
    memcpy(&hall_data[3], &AD4_Vol, sizeof(float));
}

void pack_Magnetic_angle(void)
{
    memcpy(&Magnetic_angle, &cur_angle_deg, sizeof(float));  // float --> uint32_t
}

void pack_Motor_speed(void) //  电机转速
{
    memcpy(&Motor_speed, &Motor_spe, sizeof(float));  // float --> uint32_t
}
void pack_Motor_current(void) //  电机电流
{
    memcpy(&Motor_current, &Motor_cur, sizeof(float));  // float --> uint32_t
}
	
void JumpToBootloader(void)
{
    uint32_t i;
    void (*SysMemBootJump)(void);
    uint32_t BootAddr = 0x1FFF0000;  // STM32L431 系统 Bootloader 起始地址

    /* 关闭全局中断 */
    __disable_irq();

    /* 关闭 SysTick */
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL  = 0;

    /* 复位 RCC 时钟设置 */
    HAL_RCC_DeInit();

    /* 禁用所有 NVIC 中断 */
    for (i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }

    /* 重新允许中断（尽管之后马上跳转） */
    __enable_irq();

    /* 重新映射系统内存到 0x00000000 */
    __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

    /* 设置 MSP（Main Stack Pointer） */
    __set_MSP(*((uint32_t *)BootAddr));

    /* 设置 CONTROL 寄存器，切换为特权级、使用 MSP */
    __set_CONTROL(0);

    /* 获取 Bootloader 的复位向量地址（入口地址） */
    SysMemBootJump = (void (*)(void)) (*((uint32_t *)(BootAddr + 4)));

    /* 跳转到系统 Bootloader */
    SysMemBootJump();

    /* 此处不应再返回 */
    while (1);
}

/* USER CODE END Application */

