#include "MT6813CT.h"
#include "cmsis_os.h"
#include "i2c.h"
#include "uType.h"
#include "math.h"
#include "DRV8837D.h"

float diff_speed = 0.0f;
uint8_t no_mag_flag = 0;    // 磁铁状态标志位
uint16_t angle = 0;					// 读取到的磁角度寄存器数据
float cur_angle_deg = 0.0f; // 读取到的磁角度转成单位度deg

float prev_angle_deg = 0.0f;       // 上一次角度（单位：度）
uint32_t prev_time = 0;            // 上一次采样的时间（单位：ms）
extern float Motor_spe;		//  电机转速
float delta_time = 0.0f; 	//	读取角度间隔时间（毫秒）
static float last_angle_deg = 0;

extern uint32_t period_buffer[CAPTURE_DEPTH];    // PWM周期
extern uint32_t high_buffer[CAPTURE_DEPTH];      // PWM高电平时间

#define SPEED_NOISE_THRESHOLD 40.0f  // 速度突变阈值
static float speed_buffer[3] = {0}; // 三点速度缓存：前一帧、中间、后一帧
static int speed_index = 0;

void Scanning_I2C_ID(void)	
{	
    HAL_StatusTypeDef result;
    uint8_t found = 0;

    while (!found) // 直到发现 0x06 地址
    {
			result = HAL_I2C_IsDeviceReady(&hi2c2, 0x06 << 1, 2, 20);
			if (result == HAL_OK)
			{
					found = 1;
					break;					
			 }else{
					printf("I2C Slave ID incorrect\n");
			}
				osDelay(100);
				printf("HAL_I2C_IsDeviceReady fail\n");
				HAL_I2C_DeInit(&hi2c2);  // 停止并释放 I2C 硬件资源
				osDelay(100);
				MX_I2C2_Init();
        osDelay(100);
		}
}

void read_angle(void) 
{
    uint8_t angle_data[2];    

		Scanning_I2C_ID();
		HAL_I2C_Mem_Read(&hi2c2, 0xc, 0x03, I2C_MEMADD_SIZE_8BIT, angle_data, 1, 1000);
		osDelay(10);
		HAL_I2C_Mem_Read(&hi2c2, 0xc, 0x04, I2C_MEMADD_SIZE_8BIT, &angle_data[1], 1, 1000);

    angle = ((angle_data[0]&0xfe) << 5) | ((angle_data[1] & 0xFC) >> 2);
		no_mag_flag = (angle_data[1] & 0x02) >> 1;  // 提取磁铁状态标志位
    cur_angle_deg = (angle * 360.0f)*2 / 16384.0f;
		if(no_mag_flag == 1)
		{
			angle = 0;
			diff_speed = 0.0f;
			Motor_spe = 0.0f;
			return;
		}	
		// 转速计算部分
    uint32_t now_time = HAL_GetTick();  // 当前时间
    delta_time = now_time - prev_time;  // 毫秒

    float delta_angle = cur_angle_deg - prev_angle_deg;

    // 处理角度跳变（例如从359°跳到0°）
    if (delta_angle > 180.0f)
        delta_angle -= 360.0f;
    else if (delta_angle < -180.0f)
        delta_angle += 360.0f;

    if (delta_time > 0)
    {
        Motor_spe = (delta_angle / delta_time) * 1000.0f;  // 单位：度/秒
    }

    // 更新上一帧数据
    prev_angle_deg = cur_angle_deg;
    prev_time = now_time;
}
// 输入捕获+DMA
void Process_One_Capture(void)
{
    static uint32_t last_angle_tick = 0;
    uint32_t now_tick = HAL_GetTick();  // ms
		static float last_motor_spe = 0;
//	  static float last_delta_angle = 0;
	
    // 读取当前 DMA 写入位置
    uint16_t pos = (CAPTURE_DEPTH - __HAL_DMA_GET_COUNTER(htim1.hdma[TIM_DMA_ID_CC1])) % CAPTURE_DEPTH;

    uint32_t high = high_buffer[pos];
    uint32_t period = period_buffer[pos];
    if (period == 0) return;

    float duty = (float)high / period;
    float angle_now = duty * 360.0f;
		// 简单一阶滤波
		angle_now = 0.2f * angle_now + (1.0f - 0.2f) * last_angle_deg;
    cur_angle_deg = angle_now;

    // 计算速度（角度差 / 时间差）
    float dt = (now_tick - last_angle_tick) / 1000.0f; // 秒
    

    if (dt > 0.001f) // > 1ms
		{
				delta_time = dt;
				
				float delta_angle = angle_now - last_angle_deg; // 角度差
				if (delta_angle > 180.0f) delta_angle -= 360.0f;
				else if (delta_angle < -180.0f) delta_angle += 360.0f;

				delta_angle = roundf(delta_angle * 10.0f) / 10.0f; // 保留1位小数
				
				float new_speed = 0;
				if (fabsf(delta_angle) < 60.0f)  // 忽略大跳变
						new_speed = delta_angle / dt; // deg/s
				else
						new_speed = last_motor_spe; // 保持上一次值

				// 抑制突变（速度差大于 800）
				if (fabsf(new_speed - last_motor_spe) > 400.0f)
						new_speed = last_motor_spe;

				// 方向修正（防止正转/反转状态下出现反方向速度）
				static float last_valid_positive_speed = 0;
				static float last_valid_negative_speed = 0;

				if (Motormode == MOTOR_FORWARD) // 电机正转
				{
						if (new_speed < 0)
								new_speed = last_valid_positive_speed;  // 替换为上一次正向速度
						else
								last_valid_positive_speed = new_speed;  // 更新正向速度
				}
				else if (Motormode == MOTOR_REVERSE) // 电机反转
				{
						if (new_speed > 0)
								new_speed = last_valid_negative_speed;  // 替换为上一次负向速度
						else
								last_valid_negative_speed = new_speed;  // 更新反向速度
				}

				if((angle_now > 15.0f && angle_now < 55.0f)||
					 (angle_now > 350.0f && angle_now < 359.9f)) // 死区
				{
					new_speed = last_motor_spe;  // 替换为上一次速度
				}
				
				UpdateMotorSpeed(new_speed);

				// 一阶滤波
//				Motor_spe = 0.3f * new_speed + 0.7f * last_motor_spe;
				last_motor_spe = new_speed;
				
//				last_delta_angle  = delta_angle;
				last_angle_tick = now_tick;
				last_angle_deg = angle_now;
		}

}


void UpdateMotorSpeed(float new_speed)
{
    // 先把新速度放入缓存，循环覆盖三个点
    speed_buffer[speed_index] = new_speed;
    speed_index = (speed_index + 1) % 3;

    // 只有当缓冲满三点时才判断滤波
    if (speed_buffer[0] != 0 && speed_buffer[1] != 0 && speed_buffer[2] != 0)
    {
        // 中间点是当前速度，比较前后点
        float prev_speed = speed_buffer[(speed_index + 2) % 3];
        float curr_speed = speed_buffer[(speed_index + 1) % 3];
        float next_speed = speed_buffer[speed_index];

        // 识别中间值为低值但前后较高，视为噪点
        if ((curr_speed < 80) &&
            (prev_speed > 80) &&
            (next_speed > 80))
        {
            Motor_spe = (prev_speed + next_speed) / 2.0f;
        }
        // 普通速度噪点跳变抑制
        else if (fabsf(curr_speed - prev_speed) > SPEED_NOISE_THRESHOLD &&
                 fabsf(curr_speed - next_speed) > SPEED_NOISE_THRESHOLD)
        {
            Motor_spe = (prev_speed + next_speed) / 2.0f;
        }
        else
        {
            Motor_spe = curr_speed;
        }
    }
    else
    {
        Motor_spe = new_speed;  // 缓存没满时直接用新速度
    }
}

//		printf("\n");
//		printf("Angle(deg): %.2f \n", diff_speed);
//		printf("Raw: %d / 0x%04X \n", angle, angle);
//		printf("Magnet_Status: %s\n", no_mag_flag ? "NO" : "YES");

/*
void read_angle(void)
{    
  uint8_t temp[2];
  int16_t angle;
  float angle_f;    
  HAL_I2C_Mem_Read(&hi2c2, 0x06 << 1, 0x03, I2C_MEMADD_SIZE_8BIT, temp, 2, 50);    
  angle = ((temp[0]&0xfe) << 5) | ((temp[1] & 0xFC) >> 2);    
  angle_f = (float)angle * 360 / 16384;
  printf("angle = %d\tangle_f: %.03f\r\n", angle, angle_f);
}
*/
/*	SlaveAddress：0x6<<1 
 * IIC 方式读取角度信息
 * 返回数据为 0 ~ 360 之间的浮点数
 */
/*
void read_angle(void)
{
    uint32_t angle = 0;
    float fangle = 0.0f;
    uint8_t ReadBuffer1,ReadBuffer2;

    HAL_I2C_Mem_Read(&hi2c2,0xc,0x3,I2C_MEMADD_SIZE_8BIT,&ReadBuffer1,1,0XFF);
    angle = ReadBuffer1;
    angle <<= 8;
    HAL_I2C_Mem_Read(&hi2c2,0xc,0x4,I2C_MEMADD_SIZE_8BIT,&ReadBuffer2,1,0XFF);
    angle += ReadBuffer2;
    angle >>= 2;            //取数据高 14 位
		printf("\n");
		printf("ReadBuffer1: 0x%2x\n",ReadBuffer1);
		printf("ReadBuffer2: 0x%2x\n",ReadBuffer2);
    fangle = (float)(angle * 360.0f) / 16384.0f;
		printf("fangle(deg): %.2f\n",fangle);

}
*/
