#include "Int_TMC2209.h"

/* 
 * TIM2 CH1 使用 TOGGLE 模式输出 STEP：
 * 每次中断只翻转一次电平，两个中断才构成一个完整 STEP 脉冲。
 */

// 静态变量，记录分频状态
static uint8_t double_flag = 0;

void Int_TMC2209_init(void)
{
}

static void Int_TMC2209_set_steps(Stepper_t *stepper)
{
    /* 将目标运动参数换算为总步数和梯形/三角速度曲线参数 */
    // --- 参数单位定义 ---
    // stepper->distance  -> 代表目标距离 (mm)
    // stepper->speed   -> 代表目标速度 (mm/s)
    // stepper->acc     -> 代表加速度 (mm/s^2)
    // stepper->start_speed -> 代表启动速度 (mm/s)

    // 1. 计算总步数
    // 总步数 = 距离(mm) * 每毫米步数
    stepper->total_step = (uint32_t)(stepper->distance * STEPS_PER_MM);

    // 2. 物理运动学公式计算加速距离
    // 公式: x = (v^2 - v0^2) / 2a
    // 单位全部统一为 mm, mm/s, mm/s^2
    float v_target = stepper->speed;      // mm/s
    float v_start = stepper->start_speed; // mm/s
    float accel = stepper->acc;           // mm/s^2

    // 防止除0错误
    if (accel == 0 || v_target == 0)
        return;

    // 计算加速所需的距离 (mm)
    float acc_distance_mm = (v_target * v_target - v_start * v_start) / (2.0f * accel);

    // 将加速距离转换为加速步数
    stepper->acc_step = (uint32_t)(acc_distance_mm * STEPS_PER_MM);

    // 3. 规划梯形/三角形速度曲线
    if (stepper->total_step < stepper->acc_step * 2)
    {
        // 距离太短，跑不到目标速度 -> 三角形加减速
        stepper->acc_step = stepper->total_step / 2;
        stepper->constant_step = 0;
        debug_printf("Model: Triangle, AccStep: %d", stepper->acc_step);
    }
    else
    {
        // 距离足够 -> 梯形加减速
        stepper->constant_step = stepper->total_step - stepper->acc_step * 2;
        debug_printf("Model: Trapezoid, Acc: %d, Const: %d", stepper->acc_step, stepper->constant_step);
    }

    // 4. 计算每一步的速度增量 (mm/s per step)
    // 逻辑：(目标速度 - 启动速度) / 加速步数
    // 含义：每走一步，速度增加多少 mm/s
    if (stepper->acc_step > 0)
    {
        stepper->speed_inc = (float)(v_target - v_start) / stepper->acc_step;
    }
    else
    {
        stepper->speed_inc = 0;
    }

    // 5. 初始化状态
    stepper->step_count = 0;
    stepper->current_speed = stepper->start_speed;
    stepper->state = ACCELERATE;
}

void Int_stepper_run(void)
{
    /* 仅用于调试的固定步进函数，不参与正式运行逻辑 */
    // 此函数用于测试，硬编码了步数，建议根据新的 STEPS_PER_MM 修改这里
    // 例如走 10mm:
    // uint32_t steps = 10 * STEPS_PER_MM * 2; // *2 是因为 toggle
    HAL_GPIO_WritePin(STEPPER123_EN_GPIO_Port, STEPPER123_EN_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(STEPPER1_DIR_GPIO_Port, STEPPER1_DIR_Pin, GPIO_PIN_SET);

    // 这里的3200原来是转一圈，现在如果导程是8mm，3200次toggle (1600步) = 8mm
    for (uint16_t i = 0; i < 3200; i++)
    {
        HAL_GPIO_TogglePin(STEPPER_1_STEP_GPIO_Port, STEPPER_1_STEP_Pin);
        HAL_Delay(1);
    }
}

void Int_TMC2209_start(Stepper_t *stepper, Encoder_t *encoder)
{
    /* 启动流程：
     * 1) 清零编码器基准
     * 2) 使能驱动并配置方向
     * 3) 计算速度曲线参数
     * 4) 配置并启动 TIM2 输出中断
     */
    // 清零编码器值
    encoder->pulses = 0;
    encoder->overflow = 0;
    __HAL_TIM_SET_COUNTER(&htim1, 0);
    encoder->z = 0;
    HAL_GPIO_WritePin(ENCODER_MODE_GPIO_Port, ENCODER_MODE_Pin, GPIO_PIN_RESET);
    HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);

    // 使能驱动
    HAL_GPIO_WritePin(STEPPER123_EN_GPIO_Port, STEPPER123_EN_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(STEPPER1_DIR_GPIO_Port, STEPPER1_DIR_Pin, stepper->dir);

    // 复位分频标志位
    double_flag = 0;

    // 设置步数参数
    Int_TMC2209_set_steps(stepper);

    // [修改] 计算初始ARR (基于 mm/s)
    // 最小速度保护，防止ARR计算溢出
    if (stepper->start_speed < 0.1f)
        stepper->start_speed = 0.1f;

    // 这里传入的是 mm/s
    uint32_t arr = CALC_ARR(stepper->start_speed);

    debug_printf("Start Speed: %.2f mm/s, ARR: %d", stepper->start_speed, arr);

    __HAL_TIM_SET_COUNTER(&htim2, 0);
    __HAL_TIM_SET_AUTORELOAD(&htim2, arr);
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, arr / 2);

    HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1);
}

void Int_TMC2209_stop(void)
{
    /* 停止流程：停止STEP输出 -> 关闭驱动 -> 停止编码器计数 */
    HAL_TIM_OC_Stop_IT(&htim2, TIM_CHANNEL_1);
    HAL_GPIO_WritePin(STEPPER123_EN_GPIO_Port, STEPPER123_EN_Pin, GPIO_PIN_RESET);
    HAL_TIM_Encoder_Stop(&htim1, TIM_CHANNEL_ALL);
}

extern Stepper_t stepper_1;
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
    /* TIM2中断中完成步进脉冲计数、速度状态机更新和ARR重装载 */
    if (htim->Instance == TIM2)
    {
        Stepper_t *s = &stepper_1;

        double_flag++;

        // 必须满2次中断（1个完整脉冲）才进行计算
        if (double_flag < 2)
            return;

        s->step_count++;
        double_flag = 0;

        // --- 状态机管理 ---
        switch (s->state)
        {
        case ACCELERATE:
            s->current_speed += s->speed_inc; // 这里的 speed_inc 单位是 mm/s per step
            if (s->step_count >= s->acc_step || s->current_speed >= s->speed)
            {
                s->current_speed = s->speed;
                s->state = CONSTANT;
            }
            break;

        case CONSTANT:
            if (s->step_count >= (s->total_step - s->acc_step))
                s->state = DECELERATE;
            break;

        case DECELERATE:
            s->current_speed -= s->speed_inc;
            if (s->current_speed < s->start_speed)
                s->current_speed = s->start_speed;

            if (s->step_count >= s->total_step)
            {
                s->state = STOP;
                Int_TMC2209_stop(); // 内部会关闭中断，所以这里直接return即可
                return;
            }
            break;

        case STOP:
            Int_TMC2209_stop();
            return;
        }

        // --- 更新硬件 ---
        if (s->state != STOP)
        {
            // 传入 mm/s，计算新的 ARR
            uint32_t new_arr = CALC_ARR(s->current_speed);
            __HAL_TIM_SET_AUTORELOAD(&htim2, new_arr);
            __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, new_arr / 2);
        }
    }
}
