/**************************************************************
 * MainSlave.c — 从滑块程序（STC89C52）
 * 功能：接收 RS485 广播 → 按本机 ID 计算叶面角/叶轴角
 *       驱动两台步进电机（T0 叶面角 / T1 叶轴角）
 *       显示状态；上报自身状态帧
 **************************************************************/
#include "blade_control.h"

#define SLAVE_ID   1        /* ⚠ 每台从机烧写不同 ID：1~24 */

static float g_wind_speed = 0.0f, g_wind_dir = 0.0f, g_master_angle = 0.0f;
static unsigned char g_mode = ST_INIT;
static unsigned int tick = 0;
static volatile unsigned char rx_buf[FRM_LEN], rx_idx = 0, rx_ok = 0;

/* ---- 串口接收中断：组帧 ---- */
void isr_uart(void) interrupt 4
{
    if (RI) {
        unsigned char b = SBUF; RI = 0;
        if (b == FRM_HEAD) { rx_idx = 0; rx_buf[rx_idx++] = b; }
        else if (rx_idx > 0 && rx_idx < FRM_LEN) {
            rx_buf[rx_idx++] = b;
            if (rx_idx == FRM_LEN) {
                if (rx_buf[8] == FRM_TAIL && crc8(rx_buf, 7) == rx_buf[7]) rx_ok = 1;
                rx_idx = 0;
            }
        } else rx_idx = 0;
    }
    if (TI) TI = 0;
}

void main(void)
{
    float slider_angle, face, axis;
    timer_init();
    uart_init(9);
    lcd_show(0, "SLAVE  INIT");

    set_face_target(90.0f);
    set_axis_target(0.0f);
    while (busy_face || busy_axis) pulse_service();

    while (1) {
        tick++;
        if (rx_ok) {
            rx_ok = 0;
            g_mode         = rx_buf[6];
            /* 公共量用 0.1° 定标：本机按 ID 计算自身方位角 */
            g_wind_dir     = (float)((short)((rx_buf[2] << 8) | rx_buf[3])) / 10.0f;
            g_master_angle = (float)((short)((rx_buf[4] << 8) | rx_buf[5])) / 10.0f;
            slider_angle   = calc_slave_angle(g_master_angle, SLAVE_ID, 25);
            face = calc_leaf_surface_angle(g_wind_dir, slider_angle);
            axis = calc_leaf_axis_angle(slider_angle);
        }

        switch (g_mode) {
            case ST_RUN:   set_face_target(face); set_axis_target(axis); lcd_show(0, "RUN"); break;
            case ST_MAINT: set_face_target(-90.0f); set_axis_target(15.0f); lcd_show(0, "MAINT"); break;
            case ST_STOP:  set_face_target(135.0f); set_axis_target(0.0f); lcd_show(0, "STOP"); break;
            case ST_PROT:  set_face_target(-90.0f); set_axis_target(15.0f); lcd_show(0, "PROTECT"); break;
            case ST_DANCE: dance_step(tick); break;
            default: break;
        }

        /* 1s 上报状态 */
        if (tick % 1000 == 0)
            rs485_send_frame(SLAVE_ID, cur_face_deg(), cur_axis_deg(), g_mode);

        pulse_service();
    }
}

/* 从机方位角：主机方位角 + ID × (360/25) */
float calc_slave_angle(float master_angle, unsigned char id, unsigned char total)
{
    float a = master_angle + (float)id * (360.0f / (float)total);
    while (a >= 360.0f) a -= 360.0f;
    return a;
}

/* 舞蹈动作（按编排序列，示例：波浪） */
void dance_step(unsigned int t)
{
    unsigned int ph = t % 8000;
    if (ph < 2000)      { set_face_target(90.0f);  set_axis_target(0.0f); }
    else if (ph < 4000) { set_face_target(90.0f);  set_axis_target(15.0f); }
    else if (ph < 6000) { set_face_target(45.0f);  set_axis_target(8.0f); }
    else                { set_face_target(135.0f); set_axis_target(0.0f); }
}
