/**************************************************************
 * blade_control.c — 公共实现：脉冲发生器 / 映射表 / RS485 / 角度函数
 **************************************************************/
#include "blade_control.h"

/* ---- 叶轴角映射表：α=0.0 ~ 15.0°，步长 0.5°，共 31 点（细分1600、螺距4mm） ---- */
const unsigned long code AXIS_MAP[31] = {
        0UL,
     2185UL,
     4376UL,
     6573UL,
     8776UL,
    10985UL,
    13199UL,
    15419UL,
    17644UL,
    19874UL,
    22108UL,
    24347UL,
    26590UL,
    28838UL,
    31089UL,
    33343UL,
    35601UL,
    37862UL,
    40126UL,
    42392UL,
    44661UL,
    46932UL,
    49204UL,
    51478UL,
    53753UL,
    56030UL,
    58306UL,
    60583UL,
    62860UL,
    65137UL,
    67413UL
};

ctrl_t g_ctrl = { 1, 90.0f, 0.0f, ST_INIT };

/* ---- 脉冲状态 ---- */
static unsigned long steps_face = 0, steps_axis = 0;
static unsigned int  reload_face = T0_RELOAD_SLOW, reload_axis = T0_RELOAD_SLOW;
static bit busy_face = 0, busy_axis = 0;

/* ---- CRC8 (poly 0x07) ---- */
unsigned char crc8(const unsigned char *buf, unsigned char len)
{
    unsigned char c = 0, i;
    while (len--) {
        c ^= *buf++;
        for (i = 0; i < 8; i++)
            c = (c & 0x80) ? (unsigned char)((c << 1) ^ 0x07) : (unsigned char)(c << 1);
    }
    return c;
}

/* ---- 定时器：T0/T1 均 16 位自动重装（模式2 用于 T1 波特率）---- */
void timer_init(void)
{
    TMOD = 0x11;            /* T0 模式1（16位），T1 模式1 */
    TH0 = (unsigned char)(T0_RELOAD_SLOW >> 8);
    TL0 = (unsigned char)(T0_RELOAD_SLOW & 0xFF);
    TH1 = (unsigned char)(T0_RELOAD_SLOW >> 8);
    TL1 = (unsigned char)(T0_RELOAD_SLOW & 0xFF);
    ET0 = 1; ET1 = 1; EA = 1;
}

/* ---- T0 中断：叶面角脉冲 ---- */
void isr_t0(void) interrupt 1
{
    if (steps_face == 0) { busy_face = 0; TR0 = 0; return; }
    STEP_FACE = ~STEP_FACE;          /* 上升沿/下降沿各计一次，驱动器取上升沿 */
    if (STEP_FACE) steps_face--;
    TH0 = (unsigned char)(reload_face >> 8);
    TL0 = (unsigned char)(reload_face & 0xFF);
}

/* ---- T1 中断：叶轴角脉冲 ---- */
void isr_t1(void) interrupt 3
{
    if (steps_axis == 0) { busy_axis = 0; TR1 = 0; return; }
    STEP_AXIS = ~STEP_AXIS;
    if (STEP_AXIS) steps_axis--;
    TH1 = (unsigned char)(reload_axis >> 8);
    TL1 = (unsigned char)(reload_axis & 0xFF);
}

/* ---- 设置目标：叶面角（度）---- */
void set_face_target(float deg)
{
    long p; unsigned long n;
    if (deg < FACE_MIN_DEG) deg = FACE_MIN_DEG;
    if (deg > FACE_MAX_DEG) deg = FACE_MAX_DEG;
    p = (long)(deg / DEG_PER_PULSE_FACE + (deg >= 0 ? 0.5f : -0.5f));
    DIR_FACE = (p >= 0) ? 1 : 0;
    n = (p >= 0) ? (unsigned long)p : (unsigned long)(-p);
    steps_face = n * 2UL;             /* 半周期翻转 → 脉冲数 ×2 */
    reload_face = T0_RELOAD_SLOW;     /* 起步后再升速 */
    busy_face = 1; TR0 = 1;
}

/* ---- 设置目标：叶轴角（度）---- */
unsigned long axis_deg_to_pulses(float deg)
{
    unsigned char i; float f, n0, n1;
    if (deg <= 0.0f) return 0;
    if (deg >= 15.0f) return AXIS_MAP[30];
    i = (unsigned char)(deg * 2.0f);
    f = deg * 2.0f - (float)i;
    n0 = (float)AXIS_MAP[i]; n1 = (float)AXIS_MAP[i + 1];
    return (unsigned long)(n0 + (n1 - n0) * f + 0.5f);
}

void set_axis_target(float deg)
{
    unsigned long n = axis_deg_to_pulses(deg);
    DIR_AXIS = 1;                     /* 正角度 = 螺母向 +Z */
    steps_axis = n * 2UL;             /* ⚠ 此处为绝对步数，实际须做增量比较 */
    reload_axis = T0_RELOAD_SLOW;
    busy_axis = 1; TR1 = 1;
}

/* ---- 叶面角计算（按控制方法 2.1 节）---- */
float calc_leaf_surface_angle(float wind_angle, float slider_angle)
{
    float a = slider_angle;
    if (a < 0) a += 360.0f;
    if (a >= 0 && a < 45)    return 45.0f - a;
    if (a >= 45 && a < 135)  return 0.0f;
    if (a >= 135 && a < 225) return 135.0f - a;
    if (a >= 225 && a < 270) return -90.0f;
    if (a >= 270 && a < 315) return a - 360.0f;
    return 45.0f - a;
}

/* ---- 叶轴角计算（同上，分段）---- */
float calc_leaf_axis_angle(float slider_angle)
{
    float a = slider_angle;
    if (a < 0) a += 360.0f;
    if (a < 270) return 15.0f;
    return (315.0f - a) / 3.0f;
}

/* ---- RS485 发送（9 字节）---- */
void rs485_send_frame(unsigned char id, float face, float axis, unsigned char mode)
{
    unsigned char f[FRM_LEN], i;
    short fi, ai;
    fi = (short)(face * 10.0f);        /* 0.1° 分辨率 */
    ai = (short)(axis * 10.0f);
    f[0] = FRM_HEAD; f[1] = id;
    f[2] = (unsigned char)(fi >> 8); f[3] = (unsigned char)(fi & 0xFF);
    f[4] = (unsigned char)(ai >> 8); f[5] = (unsigned char)(ai & 0xFF);
    f[6] = mode;
    f[7] = crc8(f, 7);
    f[8] = FRM_TAIL;
    RS485_DE = 1;
    for (i = 0; i < FRM_LEN; i++) { SBUF = f[i]; while (!TI); TI = 0; }
    RS485_DE = 0;
}

/* ---- 速度斜坡：每 1ms 调用一次，逐步提高脉冲频率 ---- */
void pulse_service(void)
{
    static unsigned char up = 0;
    if (busy_face) {
        if (reload_face > T0_RELOAD_FAST) reload_face--;
        up = 1;
    }
    if (busy_axis) {
        if (reload_axis > T0_RELOAD_FAST) reload_axis--;
        up = 1;
    }
    if (!up) up = 0;
}

void lcd_show(unsigned char line, const char *s) { (void)line; (void)s; }  /* 略：接 LCD1602 */
