/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : UARTCallback.c
  * @brief          : Header for remote.c file.
  *                   This file contains the common defines of the application.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 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 */
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "FreeRTOS.h"
#include "cmsis_os.h"
#include "task.h"
#include "queue.h"
#include "main.h"
#include "Callback.h"
#include "Modbussimple.h"
#include "FLASH.h"
#include "DRV8837D.h"
/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
BootParams params;

int32_t freq;  // 定时器1频率
extern uint8_t dataReceive485[BUFFER_SIZE485];	// 485
extern osMessageQueueId_t uart485rxqueueHandle;
extern uint16_t uartIRQ_rx_len;	// 485串口接收数据长度
uint16_t pwmdata = 0;
extern float Motor_spe;		//  电机转速

/*
	* @ 电控API阀参数信息
*/

//uint32_t Firmware_Version[4] = {1, 0, 0, 20250610};	//	固件版本号 [主版本][子版本][定制版本][打包日期]
//uint16_t Hardware_Version = 0x0100;									//	硬件版本号 [主版本][次版本]
//uint32_t Device_SN = 0x19060A01;								//	设备编号 [年份][月份][日期][序号]
//uint16_t Device_type = 0x0101;											//	设备类型 [主型号][子型号]
//uint16_t SlaveDevice_addr = 0x0022; 								//	从机设备地址
//uint16_t Serial_baud_rate = 0x0006;									//	串口波特率01 - 08对应4800 - 256000bps



uint16_t Running_time = 0;			//	运行时长
uint16_t Valve_status = 0;			//	阀状态0000关0001开
uint16_t Motor_status = 0;			//	电机状态0000缩回0001伸出 0002停止
uint32_t Motor_current = 0;			//	电机电流
uint32_t Motor_speed = 0;				//	电机转速
uint32_t Magnetic_angle = 0;		//	磁角度
uint32_t hall_data[4] = {0,0,0,0};	//	霍尔1到4的数据


/* USER CODE END ET */

/* Exported functions prototypes ---------------------------------------------*/

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // UART 接收完成回调
{
	Uart485Rx_msg uart485_msg;

	if (huart->Instance == USART1) 
	{
			BaseType_t xHigherPriorityTaskWoken = pdFALSE;
			memcpy(uart485_msg.data, dataReceive485, MAX_FRAME_SIZE);
			if (xQueueSendToBackFromISR(uart485rxqueueHandle, &uart485_msg, &xHigherPriorityTaskWoken) != pdPASS) 
			{
					uint8_t discard_buffer[MAX_FRAME_SIZE];
					xQueueReceiveFromISR(uart485rxqueueHandle, &discard_buffer, &xHigherPriorityTaskWoken);
					xQueueSendToBackFromISR(uart485rxqueueHandle, &uart485_msg, &xHigherPriorityTaskWoken);
			}
	}
}

void Process_Uart485callback(void)
{   
		uint8_t rxBuffer[MAX_FRAME_SIZE];   
		memset(rxBuffer, 0, MAX_FRAME_SIZE); 
		
    if (xQueueReceive(uart485rxqueueHandle, rxBuffer,  (TickType_t)0) == pdPASS) // portMAX_DELAY   (TickType_t)0
		{
			
//			DEBUG_PRINTF("485rxBuffer: ");
//			for (int i = 0; i < uartIRQ_rx_len; i++) {
//					DEBUG_PRINTF("%02X ", rxBuffer[i]);
//			}
//			DEBUG_PRINTF("\n");

			if (is_modbus_03_response(rxBuffer)) { // 处理03读指令
					process_modbus_03(rxBuffer);
					return;
			}
			if (is_modbus_06_response(rxBuffer)) { // 处理06写单指令
					process_modbus_06(rxBuffer);
					return;
			}
			if (is_modbus_42_response(rxBuffer)) { // 处理42升级指令
					process_modbus_42(rxBuffer);
					return;
			}
    }
}

bool is_modbus_03_response(uint8_t *data)  
{
    // 检查前三个字节是否符合要求
    if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) || data[0] == 0xFF) && 
          data[1] == 0x03 && 
          (data[2] == 0x40 || data[2] == 0x00)))    
    return false; // 不匹配，直接返回 false   
    uint16_t crc_received = (data[7] << 8) | data[6];		
    uint16_t crc_calculated = modbus_crc16(data, 6);
    return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0;
}

void process_modbus_03(uint8_t *data) 
{		
		memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer));  // 清零缓存，防止旧数据影响
    uint8_t *tx_buf = (uint8_t *)g_modbusbuffer;  // 强制转成字节指针	

//		uint8_t dev_addr = data[0];	// 从机地址
    uint8_t func_code = data[1];	// 功能码
		uint16_t reg_addr  = (data[2] <<8) | data[3]; // 寄存器地址
		uint8_t reg_count  = data[5]; // 寄存器数量
	
		// 最多读取125个寄存器（Modbus限制）
    if (reg_count == 0 || reg_count > 125) return;
	
		// 填充应答头部
    tx_buf[0] = g_deviceParams.SlaveDevice_addr & 0xFF;
    tx_buf[1] = func_code;
    tx_buf[2] = reg_count * 2;

    uint16_t data_len = 0;
    bool found = read_modbus_registers(reg_addr, reg_count, &tx_buf[3], &data_len);
    if (!found) return; // 地址非法

    // 计算CRC
    uint16_t crc = modbus_crc16(tx_buf, 3 + data_len);
    tx_buf[3 + data_len] = crc & 0xFF;
    tx_buf[4 + data_len] = (crc >> 8) & 0xFF;

    // 发送帧长度
    uint16_t total_len = 5 + data_len;
		
    HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
    HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);

}
 
bool is_modbus_06_response(uint8_t *data)  
{
    // 检查前三个字节是否符合要求
    if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) || data[0] == 0xFF)&& 
					data[1] == 0x06 && (data[2] == 0x40 || data[2] == 0x00)))    
    return false; // 不匹配，直接返回 false   
    uint16_t crc_received = (data[7] << 8) | data[6];		
    uint16_t crc_calculated = modbus_crc16(data, 6);
    return memcmp(&crc_received, &crc_calculated, sizeof(crc_calculated)) == 0;
}

void process_modbus_06(uint8_t *data) 
{		
		memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer));  // 清零缓存，防止旧数据影响
    uint8_t *tx_buf = (uint8_t *)g_modbusbuffer;  // 强制转成字节指针	

//		uint8_t dev_addr = data[0];	//	从机地址
    uint8_t func_code = data[1];	// 功能码
		uint16_t reg_addr  = (data[2] <<8) | data[3]; // 寄存器地址
		uint16_t reg_data  = (data[4] <<8) |data[5]; // 写入数据
	
		switch(reg_addr)
		{
			 case 0x4010:  // 设置从机地址
            g_deviceParams.SlaveDevice_addr = reg_data;
						save_params_to_flash(); // 存入内部flash
            break;

        case 0x4011:  // 设置波特率
            if (reg_data >= 0x0001 && reg_data <= 0x0008)
						{
								g_deviceParams.Serial_baud_rate = reg_data;
								save_params_to_flash(); // 存入内部flash
								uint16_t data_len = 0;
								// 填充应答头部
								tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF;
								tx_buf[data_len++] = func_code;
								tx_buf[data_len++] = (reg_addr << 8) & 0xFF;
								tx_buf[data_len++] = reg_addr & 0xFF;
								tx_buf[data_len++] = (reg_data << 8) & 0xFF;
								tx_buf[data_len++] = reg_data & 0xFF;

								// 计算CRC
								uint16_t crc = modbus_crc16(tx_buf, data_len );
								tx_buf[data_len++] = crc & 0xFF;
								tx_buf[data_len++] = (crc >> 8) & 0xFF;
								
								HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
								HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len);
								osDelay (10);
								Set_485_Baudrate(g_deviceParams.Serial_baud_rate);  // 修改485串口1波特率
								const char* msg = "New baudrate applied\r\n";
								HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
								uart_enable();
								return;
						}
						// 电机角度	cur_angle_deg（0到360度）
						// 电机转速 Motor_spe 
						// 电机电流 Motor_cur （正常是0.0几，堵转最高是到0.3）
						// 目标速度 target_speed 
						
        case 0x0002:  // 控制电机
            Motor_status = reg_data;
						if(Motor_status == 0x0000)
						{
							use_pid_control = 0;
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
							
							Motormode = MOTOR_FORWARD; // 电机处于正转模式
//							Motor_Forward(pwmdata);	// 2号电机最低350才能动
							use_pid_control = 1;
							
						}else if(Motor_status == 0x0001)
						{
							use_pid_control = 0;
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
							
							Motormode = MOTOR_REVERSE; // 电机处于反转模式
//							Motor_Reverse(pwmdata);
							use_pid_control = 1;
							
						}else if(Motor_status == 0x0002)
						{
							Motormode = MOTOR_STOPPED; // 电机处于停止模式
							use_pid_control = 0;
							Motor_spe = 0;
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
							__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
						}
            break;
						
				case 0x0011:  // 控制电机目标转速
//            pwmdata = reg_data;		
						pidMotor1Speed.target_speed = reg_data; // 目标转速
            break;
						
        case 0x4040:  // 重启程序
						if(reg_data == 0x5599)
						{
							uint16_t data_len = 0;
							// 填充应答头部
							tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF;
							tx_buf[data_len++] = func_code;
							tx_buf[data_len++] = (reg_addr << 8) & 0xFF;
							tx_buf[data_len++] = reg_addr & 0xFF;
							tx_buf[data_len++] = (reg_data << 8) & 0xFF;
							tx_buf[data_len++] = reg_data & 0xFF;

							// 计算CRC
							uint16_t crc = modbus_crc16(tx_buf, data_len );
							tx_buf[data_len++] = crc & 0xFF;
							tx_buf[data_len++] = (crc >> 8) & 0xFF;
							
							HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
							HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len);
							osDelay (50);
							NVIC_SystemReset(); // 系统软件复位
						}
						if(reg_data == 0x55AA)
						{
							g_deviceParams.SlaveDevice_addr = 0x00FF; // 恢复出厂设置
							g_deviceParams.Serial_baud_rate = 0x0002;
							Motor_status = 0x0000;
							// 版本回退指令
														 // 电机缩回
							Set_485_Baudrate(g_deviceParams.Serial_baud_rate);  // 重设波特率
							Restart_UART1_DMA();
						}
						
            break;
				case 0xAABB:  // IAP-M42						

            break;
				
        default:
            
            break;
		
		}
		uint16_t data_len = 0;
		// 填充应答头部
    tx_buf[data_len++] = g_deviceParams.SlaveDevice_addr & 0xFF;
    tx_buf[data_len++] = func_code;
    tx_buf[data_len++] = (reg_addr << 8) & 0xFF;
		tx_buf[data_len++] = reg_addr & 0xFF;
    tx_buf[data_len++] = (reg_data << 8) & 0xFF;
		tx_buf[data_len++] = reg_data & 0xFF;

    // 计算CRC
    uint16_t crc = modbus_crc16(tx_buf, data_len );
    tx_buf[data_len++] = crc & 0xFF;
    tx_buf[data_len++] = (crc >> 8) & 0xFF;
		
    HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
    HAL_UART_Transmit_DMA(&huart1, tx_buf, data_len);

}

bool is_modbus_42_response(uint8_t *data)  
{
    // 检查前三个字节是否符合要求
    if (!((data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF) && data[0] == 0xFF)&& 
					data[1] == 0x42 && data[2] == 0xAA && data[3] == 0xBB))    
    return false; // 不匹配，直接返回 false 
	
    uint16_t crc_received = (data[uartIRQ_rx_len] << 8) | data[uartIRQ_rx_len - 1];		
    uint16_t crc_calculated = modbus_crc16(data, uartIRQ_rx_len - 1);
		if (crc_received != crc_calculated)
    {
        // CRC 错误，返回错误应答
        send_upgrade_response(0x42, 0xAABB, 0x05, 0x0000); // 0x05：CRC错误
        return false; // 返回false，不执行后续处理
    }

    return true;  // CRC正确
}

void process_modbus_42(uint8_t *data) 
{		
		memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer));  // 清零缓存，防止旧数据影响
		uint16_t iapDataCommandCode  = (data[4] <<8) |data[5]; // IAP数据的命令码 

		switch(iapDataCommandCode)
		{
			case 0x4000:  // 升级程序起始帧			
						handle_upgrade_start_frame(data); 					
            break;
					
				case 0x4001:  // 升级程序数据帧					
						handle_upgrade_data_frame(data);
            break;
				
				case 0x4002:  // 升级程序结束帧					
						handle_upgrade_end_frame();
            break;
				
        default:
            send_upgrade_response(0x42, 0xAABB, 0x07, 0x0000); // 命令码错误
            break;		
		}

}

bool is_modbus_errorfunc_response(uint8_t *data)  
{
    // 检查从机地址是否符合要求（等于 g_deviceParams.SlaveDevice_addr 或 0xFF）
    bool is_valid_addr = (data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF)) || (data[0] == 0xFF);
    
    // 检查功能码是否不在允许的范围内（0x03, 0x06, 0x10, 0x42）
    bool is_invalid_func = (data[1] != 0x03) && 
                           (data[1] != 0x06) && 
                           (data[1] != 0x10) && 
                           (data[1] != 0x42);
    
    if (is_valid_addr && is_invalid_func)
    {
        uint16_t crc_received = (data[7] << 8) | data[6];        
        uint16_t crc_calculated = modbus_crc16(data, 6);
        return (memcmp(&crc_received, &crc_calculated, sizeof(crc_received)) == 0);
    }
    
    return false; // 不匹配，直接返回 false   
}

void process_modbus_errorfunc(uint8_t *data) 
{		
		memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer));  // 清零缓存，防止旧数据影响
    uint8_t *tx_buf = (uint8_t *)g_modbusbuffer;  // 强制转成字节指针
	
		uint8_t func_code = data[1];	// 功能码	
		uint8_t total_len = 0;
	
		total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x01, tx_buf); // 功能码错误
	
    HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
    HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);

}

bool is_modbus_error_regaddr_response(uint8_t *data)  
{
    // 检查从机地址是否符合要求（等于 g_deviceParams.SlaveDevice_addr 或 0xFF）
    bool is_valid_addr = (data[0] == (g_deviceParams.SlaveDevice_addr & 0xFF)) || (data[0] == 0xFF);
    
    // 检查功能码是否不在允许的范围内（0x03, 0x06, 0x10, 0x42）
    bool is_valid_func = (data[1] == 0x03) || 
                          (data[1] == 0x06) || 
                          (data[1] == 0x10) || 
                          (data[1] == 0x42);
		
		uint16_t reg_addr  = (data[2] <<8) | data[3]; // 寄存器地址
		
		// 检查寄存器地址是否不在允许的范围内（0x0000 到 0x001D 之间，0xAABB）
    bool is_invalid_regaddr = (reg_addr > 0x0021) && (reg_addr != 0xAABB);

    if (is_valid_addr && is_valid_func && is_invalid_regaddr)
    {
        uint16_t crc_received = (data[7] << 8) | data[6];        
        uint16_t crc_calculated = modbus_crc16(data, 6);
        return (memcmp(&crc_received, &crc_calculated, sizeof(crc_received)) == 0);
    }
    
    return false; // 不匹配，直接返回 false   
}

void process_modbus_error_regaddr(uint8_t *data) 
{		
		memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer));  // 清零缓存，防止旧数据影响
    uint8_t *tx_buf = (uint8_t *)g_modbusbuffer;  // 强制转成字节指针
	
		uint8_t func_code = data[1];	// 功能码	
		uint8_t total_len = 0;
	
		total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x02, tx_buf); // 功能码错误
	
    HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
    HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);

}

void process_modbus_error_data(uint8_t *data) 
{		
		memset(g_modbusbuffer, 0, sizeof(g_modbusbuffer));  // 清零缓存，防止旧数据影响
    uint8_t *tx_buf = (uint8_t *)g_modbusbuffer;  // 强制转成字节指针
	
		uint8_t func_code = data[1];	// 功能码	

		uint8_t total_len = modbus_error_response(g_deviceParams.SlaveDevice_addr & 0xFF, func_code, 0x03, tx_buf); // 功能码错误
	
    HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_SET);  	// 开启发送模式（RS485）
    HAL_UART_Transmit_DMA(&huart1, tx_buf, total_len);

}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)
      HAL_GPIO_WritePin(GPIOB, RS485_RE_Pin, GPIO_PIN_RESET);  // 发送完成后切回接收模式
}








/* USER CODE BEGIN EFP */
