/******************************************************************************
版权所有：
文件名称：	led.c
文件版本：	01.01
创建作者：	xxxxxx
创建日期：	2013-05-29
功能说明：	LED处理程序
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
 */
#include "head.h"
#include "ch423s.h"

/*------------------------------- 宏定义 --------------------------------------
 */

/*------------------------------ 类型结构 -------------------------------------
 */

/*------------------------------ 全局变量 -------------------------------------
 */

// 辅助板LED测试状态
u32 g_led_aux_test_st;
u32 g_led_kz_test_st;
int led_save_flag = 0;

// 基于公共、开关的灯状态，
// 数组第一维为公共、开关，0为公共，1~SWITCH_NUM_MAX为开关
// 数组第二维取公共、开关中灯个数的大值
// noted by sunxi: 20220701 加入(u16),以去除335x的编译告警
u8 g_led_stu[SWITCH_NUM_MAX + 1][(((u16)SW_LED_NUM > (u16)PUB_LED_NUM) ? SW_LED_NUM : PUB_LED_NUM)];
u8 g_led_stu_bk[SWITCH_NUM_MAX + 1][(((u16)SW_LED_NUM > (u16)PUB_LED_NUM) ? SW_LED_NUM : PUB_LED_NUM)];
u8 g_led_save[SWITCH_NUM_MAX + 1][(((u16)SW_LED_NUM > (u16)PUB_LED_NUM) ? SW_LED_NUM : PUB_LED_NUM)];
// 当前面板的LED配置
struct led_config *g_led_hmi;

#define LED_FILE_VERSION 0X01010101 // 文件版本
struct file *pf_ledsave = NULL;

#ifdef CPU_FUXI
/* 实际的led地址 */
/* 目前按照标准化的贴膜来配置地址
面膜灯
DB
电源 远方 合位 过流 跳闸 充电   重合闸动作 开关传动 异常    分布式 备用 备用
运行 通讯 分位 接地 告警 未储能 重合闸闭锁 合闸闭锁 常规保护 就地FA 集中FA 备用
DA
电源 通讯 告警     间隔1通讯 间隔3通讯 间隔5通讯 备用 网口1 串口1 串口3 备用 备用
运行 异常 级联异常 间隔2通讯 间隔4通讯 间隔6通讯 备用 网口2 串口2 串口4 备用 备用

*/
static uint8_t suca_led_hw_addr[LED_MAX_NUM] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
                                                12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
#endif

void _led_update_status(void);

static int _led_savefile(void)
{
    unsigned int addr, file_length;
    u16 crc;
    char *p;
    loff_t pos;
    struct file *pfile;
    struct cfg_file_head fileled_file;

    // 写文件头
    memset(&fileled_file, 0, sizeof(fileled_file));
    fileled_file.signature = SIG_LED_SAVE_FILE;
    fileled_file.version = LED_FILE_VERSION;

    addr = FILE_ADDR_ALGIN(sizeof(fileled_file));

    // 得到文件长度
    file_length = addr + sizeof(g_led_save);
    file_length = FILE_ADDR_ALGIN(file_length);

    // 分配并初始化空间
    p = rt_malloc(file_length + 2);
    if (!p)
    {
        return -1;
    }
    memset(p, 0, file_length + 2);

    // 写入文件头
    memcpy(p, (char *)&fileled_file, sizeof(fileled_file));

    // 写文件列表
    memcpy(p + addr, g_led_save, sizeof(g_led_save));

    // 计算CRC
    crc = CrcStr(p, file_length);
    memcpy(p + file_length, &crc, 2);

    // 创建数据文件
    if (pf_ledsave == NULL)
    {
        pfile = rt_file_open("/app/data/file_led.bin", O_CREAT | O_RDWR, 0);
        if (IS_ERR(pfile))
        {
            rt_free(p);
            rt_printf("\r\n create led save file fail");
            return -2;
        }
        pf_ledsave = pfile;
    }

    pos = 0;
    rt_file_write(pf_ledsave, p, file_length + 2, &pos);
    rt_free(p);
    return 0;
}

int _led_readfile(void)
{
    u32 len;
    u16 crc;
    u8 *buf;
    loff_t pos;
    struct file *pfile;
    struct cfg_file_head *brh;
    // 创建并打开文件
    pfile = rt_file_open("/app/data/file_led.bin", O_RDONLY, 0);
    if (IS_ERR(pfile))
    {
        return -1;
    }

    // 得到文件长度
    len = rt_file_getfile_size(pfile);
    if (len <= 0)
    {
        rt_file_close(pfile, 0);
        return -11;
    }

    // 分配内存
    buf = rt_malloc(len);
    if ((buf) == NULL)
    {
        rt_file_close(pfile, 0);
        return -2;
    }

    // 读出内容
    pos = 0;
    if (rt_file_read(pfile, buf, len, &pos) != len)
    {
        rt_file_close(pfile, 0);
        rt_free(buf);
        return -3;
    }

    // 关闭文件
    rt_file_close(pfile, 0);

    // 检查CRC
    crc = CrcStr(buf, len - 2);
    if (crc != *(u16 *)(buf + len - 2))
    {
        rt_free(buf);
        return -4;
    }

    // 检查文件签名
    brh = (struct cfg_file_head *)buf;
    if (brh->signature != SIG_LED_SAVE_FILE)
    {
        rt_free(buf);
        return -5;
    }

    // 校验一下文件长度，防止灯配置变化，文件读取正确，导致的灯状态异常
    {
        int filelenth;
        filelenth = FILE_ADDR_ALGIN(sizeof(struct cfg_file_head)) + sizeof(g_led_save);
        filelenth = FILE_ADDR_ALGIN(filelenth) + 2;
        if (filelenth != len)
        {
            rt_free(buf);
            return -6;
        }
    }
    memcpy(g_led_stu, buf + FILE_ADDR_ALGIN(sizeof(struct cfg_file_head)), sizeof(g_led_stu));
    // 根据保存的灯状态，预置动作标志
    {
        int sw, led;
        for (sw = 0; sw < SWITCH_NUM_MAX + 1; sw++)
        {
            if (sw == 0)
            {
                if (g_led_stu[sw][PUB_LED_DZ] == LED_ON)
                {
                    g_run_stu.pubdz = 1;
                }
                else if (g_led_stu[sw][PUB_LED_DZ] == LED_QUICK)
                {
                    g_run_stu.pubdz = 2;
                }
            }
            else
            {
                RUN_STU_SW *prun = &g_tRelay[sw - 1].run_stu;
                u8 *pstatus;
                u8 val = 0;
                for (led = 0; led < SW_LED_NUM; led++)
                {
                    pstatus = NULL;
                    val = 0;
                    if (led == SW_LED_GL)
                        pstatus = &prun->gl;
                    if (led == SW_LED_JD)
                        pstatus = &prun->jd;
                    if (led == SW_LED_CHZ)
                        pstatus = &prun->chzdz;
                    if (led == SW_LED_DZ)
                        pstatus = &prun->dz;
                    if (g_led_stu[sw][led] == LED_ON)
                    {
                        val = 1;
                    }
                    else if (g_led_stu[sw][led] == LED_QUICK)
                    {
                        val = 2;
                    }
                    if (pstatus != NULL)
                        *pstatus = val;
                }
            }
        }
    }
    _led_update_status();
    memcpy(g_led_save, g_led_stu, sizeof(g_led_stu));
    rt_free(buf);
    return 0;
}

int _led_status_save(void)
{
    int sw, led;
    static uint32_t led_save_us0;
    if (led_save_flag == 0)
    {
        for (sw = 0; sw < SWITCH_NUM_MAX + 1; sw++)
        {
            if (sw == 0)
            {
                for (led = 0; led < PUB_LED_NUM; led++)
                {
                    if (led == PUB_LED_DZ)
                    {
                        if (g_led_stu[sw][led] != g_led_save[sw][led])
                        {
                            led_save_flag = 1;
                            led_save_us0 = ustimer_get_origin();
                            break;
                        }
                    }
                }
            }
            else
            {
                for (led = 0; led < SW_LED_NUM; led++)
                {
                    if (led == SW_LED_GL || led == SW_LED_JD || led == SW_LED_CHZ || led == SW_LED_DZ)
                    {
                        if (g_led_stu[sw][led] != g_led_save[sw][led])
                        {
                            led_save_flag = 1;
                            led_save_us0 = ustimer_get_origin();
                            break;
                        }
                    }
                }
            }
        }
    }
    if (led_save_flag)
    {
        if (ustimer_get_duration(led_save_us0) > USTIMER_SEC * 5) // led灯变化10秒后保存灯状态
        {
            memcpy(g_led_save, g_led_stu, sizeof(g_led_stu));
            rt_printf("\r\n led save len=%d", sizeof(g_led_stu));
            _led_savefile();
            led_save_flag = 0;
        }
    }
    return 0;
}

int led_exit(void)
{
    if (pf_ledsave != 0)
    {
        rt_file_close(pf_ledsave, 0);
    }
    ch423sio_exit_dev();
    return 0;
}

/******************************************************************************
函数名称：	led_init
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-04-16
函数说明：	开出类型LED初始化，找到对应的灯配置索引的GPIO
参数说明：	无
返回值：  	成功返回0.
修改记录：
*/
int led_init(void)
{
    memset(g_led_stu, 0, sizeof(g_led_stu));
    memset(g_led_save, 0, sizeof(g_led_stu));
#ifdef STORE_PILOTELAMP
    _led_readfile();
#endif
    return ch423sio_init_dev();
}

/******************************************************************************
函数名称：	led_init_hmi
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-04-16
函数说明：	LED配置初始化
参数说明：	无
返回值：  	成功返回0.
修改记录：
*/
int led_init_hmi(void)
{
    u32 slot;
    g_led_hmi = 0;
    // 检查状态板是否配置
    slot = equ_get_slot_by_type(BOARD_TYPE_FUXI_24LED);
    // 检查状态板是否配置
    if (slot > 0)
    {
        g_led_hmi = &g_led_slot[slot];
    }
    return 0;
}

/******************************************************************************
函数名称：	led_polling_app
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-04-16
函数说明：	LED应用功能
参数说明：	无
返回值：  	成功返回0.
修改记录：
*/
void _led_update_status(void)
{
    int i, exerr;

    // 电源灯
    if (!g_run_stu.dcjlsd)
    {
        led_set_pub(PUB_LED_POWER, LED_ON);
    }
    else if (g_run_stu.dcjlsd && (!g_run_stu.dcqy))
    {
        led_set_pub(PUB_LED_POWER, LED_SLOW);
    }
    else if (g_run_stu.dcjlsd && g_run_stu.dcqy)
    {
        led_set_pub(PUB_LED_POWER, LED_QUICK);
    }
    // 运行灯
    if (rt_err_count())
    {
        led_set_pub(PUB_LED_RUN, LED_ON);
    }
    else
    {
        led_set_pub(PUB_LED_RUN, LED_SLOW);
    }

    // 异常灯,以内部异常优先级高
    exerr = 0;
    for (i = 0; i < g_sw_num; i++)
    {
        RUN_STU_SW *prun = &g_tRelay[i].run_stu;

        if (prun->exerr)
        {
            exerr = 1;
            break;
        }
    }
    if (rt_err_count())
    {
        led_set_pub(PUB_LED_ERR, LED_ON);
#if defined FUNC_DRIVE || defined FUNC_DRIVE_JY
        gb_drive.b_err = true;
#endif
    }
#ifdef defined GD_AREA_ZHONGSHAN_2020
    else if (exerr || soe_check(EV_GOOSE_CONFIG_ERR) == true) // 中山2020要求通信异常不允许亮异常灯
    {
        led_set_pub(PUB_LED_ERR, LED_ON);
    }
#else
    else if (exerr || (tFAg.commerr > 0)) // 中山要求，只有本机通信异常点告警灯，系统异常不点灯
    {
        led_set_pub(PUB_LED_ERR, LED_ON);
#if defined FUNC_DRIVE || defined FUNC_DRIVE_JY
        gb_drive.b_err = true;
#endif
    }
#endif
    else if (soe_check(EV_61850_ERR) == true)
    {
        led_set_pub(PUB_LED_ERR, LED_ON);
#if defined FUNC_DRIVE || defined FUNC_DRIVE_JY
        gb_drive.b_err = true;
#endif
    }
    else
    {
        led_set_pub(PUB_LED_ERR, LED_OFF);
#if defined FUNC_DRIVE || defined FUNC_DRIVE_JY
        gb_drive.b_err = false;
#endif
    }

#if defined GD_AREA_ECZD_2020
    for (i = 0; i < g_sw_num; i++)
    {
        RUN_STU_SW *prun = &g_tRelay[i].run_stu;

        if (prun->exerr || prun->qyd_bs || prun->qyd_bs || tPT.uPT1DX.bFlag.bPTYC || tPT.uPT2DX.bFlag.bPTYC)
        {
            exerr = 1;
            break;
        }
    }
    if (exerr || (tFAg.commerr > 0))
    {
        led_set_pub(PUB_LED_RUN_GJ, LED_ON);
#if defined FUNC_DRIVE || defined FUNC_DRIVE_JY
        gb_drive.b_warning = true;
#endif
    }
    else
    {
        led_set_pub(PUB_LED_RUN_GJ, LED_OFF);
#if defined FUNC_DRIVE || defined FUNC_DRIVE_JY
        gb_drive.b_warning = false;
#endif
    }
#endif
    if (g_run_stu.pubdz == 2) // ==2故障动作
    {
        led_set_pub(PUB_LED_DZ, LED_QUICK);
    }
    else
    {
        led_set_pub(PUB_LED_DZ, LED_OFF);
    }

    if (g_run_stu.yf)
    {
        led_set_pub(PUB_LED_YF, LED_ON);
    }
    else
    {
        led_set_pub(PUB_LED_YF, LED_OFF);
    }

#ifdef KZ_OUT_TT
    if (!g_run_stu.kz_out_tt)
    {
        led_set_pub(PUB_LED_KZ_OUT, LED_ON);
    }
    else
    {
        led_set_pub(PUB_LED_KZ_OUT, LED_OFF);
    }
#endif
    if (getIecLink101Status() || getCommStatus())
    {
        led_set_pub(PUB_LED_IEC_ERR, LED_ON);
    }
    else
    {
        led_set_pub(PUB_LED_IEC_ERR, LED_OFF);
    }
    if (g_bCommStatus)
        led_set_pub(PUB_LED_COMM_STATUS, LED_ON);
    else
        led_set_pub(PUB_LED_COMM_STATUS, LED_OFF);

    if (g_run_stu.jd)
    {
        led_set_pub(PUB_LED_JD, LED_ON);
    }
    else
    {
        led_set_pub(PUB_LED_JD, LED_OFF);
    }

    for (i = 0; i < g_sw_num; i++)
    {
        RUN_STU_SW *prun = &g_tRelay[i].run_stu;
#if !defined CPU_FUXI
        // 综合合位灯
        if (prun->sw == 0x2)
        {
            led_set_sw(i, SW_LED_ZHHW, LED_ON);
        }
        else if (prun->sw == 0x3)
        {
            led_set_sw(i, SW_LED_ZHHW, LED_SLOW);
        }
        else
        {
            led_set_sw(i, SW_LED_ZHHW, LED_OFF);
        }

        if (prun->sw == 0x1)
        {
            led_set_sw(i, SW_LED_ZHTW, LED_ON);
        }
        else if (prun->sw == 0x3)
        {
            led_set_sw(i, SW_LED_ZHTW, LED_SLOW);
        }
        else
        {
            led_set_sw(i, SW_LED_ZHTW, LED_OFF);
        }
#endif
        // 合位灯、跳位灯
        if (prun->hw)
        {
            sw_do(i, SW_DO_BHDZ, SW_DO_TYPE_OFF);
            led_set_sw(i, SW_LED_HW, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_HW, LED_OFF);
        }
        if (prun->tw)
        {
            led_set_sw(i, SW_LED_TW, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_TW, LED_OFF);
        }

        // 过流灯
        if (prun->gl == 1)
        {
            led_set_sw(i, SW_LED_GL, LED_ON);
        }
        else if (prun->gl == 2)
        {
            led_set_sw(i, SW_LED_GL, LED_QUICK);
        }

        // 接地灯
        if (prun->jd == 1)
        {
            led_set_sw(i, SW_LED_JD, LED_ON);
        }
        else if (prun->jd == 2)
        {
            led_set_sw(i, SW_LED_JD, LED_QUICK);
        }

        // 隔离刀闸灯
        if (prun->gldz)
        {
            led_set_sw(i, SW_LED_GLDZ, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_GLDZ, LED_OFF);
        }

        // 接地刀闸灯
        if (prun->jddz)
        {
            led_set_sw(i, SW_LED_JDDZ, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_JDDZ, LED_OFF);
        }

        if (prun->gj_led)
        {
            led_set_sw(i, SW_LED_FAULT_GJ, LED_ON);
        }

        // 重合闸灯
        if (prun->chzdz)
        {
            led_set_sw(i, SW_LED_CHZ, LED_ON);
        }

        // 重合闸充电灯
        if (prun->chzcd || prun->fa_ll_cd || prun->goose_qccd || prun->goose_glcd || prun->goose_ll_cd)
        {
            led_set_sw(i, SW_LED_CD, LED_ON);
            // led_set_sw(i,SW_LED_CHZBS, LED_OFF);//重合闸闭锁灯与充电灯功能相反
        }
        else
        {
            led_set_sw(i, SW_LED_CD, LED_OFF);
            // led_set_sw(i,SW_LED_CHZBS, LED_ON);//重合闸闭锁灯与充电灯功能相反
        }
        if (prun->chzcd)
            led_set_sw(i, SW_LED_CHZ_CD, LED_ON);
        else
            led_set_sw(i, SW_LED_CHZ_CD, LED_OFF);

// 重合闸闭锁灯跟FA闭锁灯合并
#if 0
		if(g_tRelay[i].run_stu.cgbhtt && !prun->chzcd)//保护与FA区分闭锁灯处理
			led_set_sw(i,SW_LED_CHZBS_LOCK, LED_ON);
		else if(g_tRelay[i].run_stu.fatt && prun->bs)
			led_set_sw(i,SW_LED_CHZBS_LOCK, LED_ON);
		else 
			led_set_sw(i,SW_LED_CHZBS_LOCK, LED_OFF);
#endif
        if (prun->bs || prun->chzbs)
        {
            led_set_sw(i, SW_LED_CHZBS_LOCK, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_CHZBS_LOCK, LED_OFF);
        }
        // 动作灯
        if (prun->dz == RY_DZ_XYBS) // xj 闭锁合闸长亮
        {
            led_set_sw(i, SW_LED_DZ, LED_ON);
            led_set_sw(i, SW_LED_TZ, LED_ON);
        }
        else if (prun->dz == RY_DZ_BHT) // xj 故障状态闪烁
        {
            led_set_sw(i, SW_LED_DZ, LED_QUICK);
            led_set_sw(i, SW_LED_TZ, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_DZ, LED_OFF);
        }

        if (BH_GOOSE_EN(i)) // 智能FA逻辑，联络开关自动查找
        {
            if (g_tRelay[i].tgoc.tllcd.sta.bFlag.bCD) // 本开关为联络开关
            {
                led_set_sw(i, SW_LED_LL, LED_ON);
                led_set_sw(i, SW_LED_FD, LED_OFF);
            }
            else
            {
                led_set_sw(i, SW_LED_LL, LED_OFF);
                led_set_sw(i, SW_LED_FD, LED_ON);
            }
        }
        else if (FA_ALL_EN(i))
        {
            if (prun->fa_ls) // 联络
            {
                led_set_sw(i, SW_LED_LL, LED_ON);
                led_set_sw(i, SW_LED_FD, LED_OFF);
            }
            else
            {
                led_set_sw(i, SW_LED_LL, LED_OFF);
                led_set_sw(i, SW_LED_FD, LED_ON);
            }
        }
        else
        {
            led_set_sw(i, SW_LED_FD, LED_OFF);
            led_set_sw(i, SW_LED_LL, LED_OFF);
        }

        // 运行模式压板灯
        if (BH_GOOSE_EN(i))
        {
#ifdef GD_AREA_ZHONGSHAN_2020 // 中山要求智能分布式充电完成，亮模式灯，分支亮保护灯
            if ((prun->goose_qccd || prun->goose_glcd || prun->goose_ll_cd) && !pRunSet->tSwSet[i].tGocSet.bsw_fz)
            {
                led_set_sw(i, SW_LED_MODE_GOOSE, LED_ON);
                led_set_sw(i, SW_LED_MODE_BH, LED_OFF);
                led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
            }
            else if (pRunSet->tSwSet[i].tGocSet.bsw_fz)
            {
                led_set_sw(i, SW_LED_MODE_GOOSE, LED_OFF);
                led_set_sw(i, SW_LED_MODE_BH, LED_ON);
                led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
            }
            else
            {
                led_set_sw(i, SW_LED_MODE_GOOSE, LED_OFF);
                led_set_sw(i, SW_LED_MODE_BH, LED_OFF);
                led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
            }
#else
            led_set_sw(i, SW_LED_MODE_GOOSE, LED_ON);
            led_set_sw(i, SW_LED_MODE_BH, LED_OFF);
            led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
#endif
        }
        else if (BH_GOOSE_COMMERR(i))
        {
            led_set_sw(i, SW_LED_MODE_GOOSE, LED_OFF);
            if (pRunSet->tSwSet[i].tGocSet.bsw_fz)
            {
                led_set_sw(i, SW_LED_MODE_BH, LED_ON);
                led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
            }
            else
            {
#ifdef GD_AREA_ZHONGSHAN_2020 // 中山2020要求联络自转电功能未投入不亮FA灯
                if (prun->fa_ls)
                {
                    if (soe_check(EV_FA_LL_EN + i * EV_SW_NUM) == true)
                        led_set_sw(i, SW_LED_MODE_FA, LED_ON);
                    else
                        led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
                }
                else
                {
                    led_set_sw(i, SW_LED_MODE_FA, LED_ON);
                }
                // 闭锁时灭fa模式灯
                if (prun->bs)
                {
                    led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
                }
#else
                led_set_sw(i, SW_LED_MODE_FA, LED_ON);
#endif

                led_set_sw(i, SW_LED_MODE_BH, LED_OFF);
            }
        }
        else
        {
            // BH
            if (BH_ALL_EN(i))
            {
                led_set_sw(i, SW_LED_MODE_BH, LED_ON);
            }
            else
            {
                led_set_sw(i, SW_LED_MODE_BH, LED_OFF);
            }
            // FA
            if (FA_ALL_EN(i))
            {
#ifdef GD_AREA_ZHONGSHAN_2020 // 中山2020要求联络自转电功能未投入不亮FA灯
                if (prun->fa_ls)
                {
                    if (soe_check(EV_FA_LL_EN + i * EV_SW_NUM) == true)
                        led_set_sw(i, SW_LED_MODE_FA, LED_ON);
                    else
                        led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
                }
                else
                {
                    led_set_sw(i, SW_LED_MODE_FA, LED_ON);
                }
                // 闭锁时灭fa模式灯
                if (prun->bs)
                {
                    led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
                }
#else
                led_set_sw(i, SW_LED_MODE_FA, LED_ON);
#endif
            }
            else
            {
                led_set_sw(i, SW_LED_MODE_FA, LED_OFF);
            }
            // Goose
            led_set_sw(i, SW_LED_MODE_GOOSE, LED_OFF);
        }
#ifdef GD_AREA_ZHONGSHAN_2020
        if (soe_check(EV_GOOSE_QC_OK + i * EV_SW_NUM) == true        // 切除OK
            || soe_check(EV_GOOSE_GL_OK + i * EV_SW_NUM) == true     // 隔离OK
            || soe_check(EV_GOOSE_EXT_TZ + i * EV_SW_NUM) == true    // 装置越级跳闸
            || soe_check(EV_GOOSE_SDLOST_TZ + i * EV_SW_NUM) == true // 首端失压分闸
            )                                                        // 故障动作后亮闭锁灯
        {
            g_tRelay[i].run_stu.fgbs = 1;
        }
#endif
        if (prun->bs || prun->fgbs)
        {
            led_set_sw(i, SW_LED_LOCK, LED_ON);
#ifdef GD_AREA_ZHONGSHAN_2020 // 中山2020要求分段的时候，双电源不亮闭锁灯
            if (!prun->fa_ls) // 分段
            {
                if (g_tRelay[i].tSDHZ.S_Status == S_BSDOUBLE)
                {
                    led_set_sw(i, SW_LED_LOCK, LED_OFF);
                    // led_set_sw(i,SW_LED_MODE_FA, LED_OFF);//关闭就地FA灯
                }
            }
#endif
        }
        else
        {
            led_set_sw(i, SW_LED_LOCK, LED_OFF);
#ifdef GD_AREA_ZHONGSHAN_2020
            if (!prun->fa_ls) // 分段
            {
                // if(g_tRelay[i].tSDHZ.S_Status == S_BSDOUBLE)
                // led_set_sw(i,SW_LED_MODE_FA, LED_OFF);//关闭就地FA灯
            }
#endif
        }
        // 储能/未储能灯需分合位合法(有对应遥信点)时才允许点亮
        if (prun->wcn && (prun->sw != 0) && (prun->sw != 3))
        {
            led_set_sw(i, SW_LED_WCN, LED_ON);
        }
        else if (!prun->wcn && (prun->sw != 0) && (prun->sw != 3))
        {
            led_set_sw(i, SW_LED_WCN, LED_OFF);
        }

#if !defined CPU_FUXI
        if (JL_ALL_EN(i))
        {
            led_set_sw(i, SW_LED_ZDJL, LED_ON);
            led_set_sw(i, SW_LED_TYZDJL, LED_OFF);
        }
        else
        {
            led_set_sw(i, SW_LED_ZDJL, LED_OFF);
            led_set_sw(i, SW_LED_TYZDJL, LED_ON);
        }

        if (!FUN_ALL_EN(i)) // 停用保护功能总
        {
            led_set_sw(i, SW_LED_TYBHTT, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_TYBHTT, LED_OFF);
        }
#endif
#ifdef FUNC_DRIVE
        if (pRunSet->tSwSet[0].btt_gnyb_btdcd)
        {
            led_set_sw(i, SW_LED_DRIVE, LED_ON);
        }
        else
        {
            led_set_sw(i, SW_LED_DRIVE, LED_OFF);
        }
#endif
    }
}

#ifdef CPU_FUXI
/**
 * @brief          处理led
 * @author         lch (lch_work@foxmail.com)
 * @version        1.0
 * @date           20251226
 * @return         * int
 * @retval         none
 *
 * @warning        none
 * @note           现在是1000ms运行一次
 */
static int led_updata_led(void)
{
    int i = 0;
    u8 uc_stu = 0, uc_idx = 0;
    u32 ul_time = 0;
    enum e_mode_ch423 e_mode = e_io_mode_off;

    // 没有配置，不执行
    if (g_led_hmi == 0)
    {
        return -1;
    }

    for (i = 0; i < g_led_hmi->num; i++)
    {
        // 未配置灯继续循环
        if (g_led_hmi->sn[i].no == LED_NULL)
        {
            continue;
        }

        // 硬件地址
        uc_idx = suca_led_hw_addr[i];
        // 取出灯状态
        uc_stu = g_led_stu[g_led_hmi->sn[i].sw][g_led_hmi->sn[i].no];

        // 按位置将灯状态置入dwled
        switch (uc_stu)
        {
        case LED_ON:
            e_mode = e_io_mode_on;
            break;

        case LED_SLOW:
        case LED_QUICK:
            e_mode = e_io_mode_shine;
            break;

        case LED_OFF:
            e_mode = e_io_mode_off;
            break;
        }
        if (uc_stu != g_led_stu_bk[g_led_hmi->sn[i].sw][g_led_hmi->sn[i].no])
        {
            ch423sio_control_state(uc_idx, e_mode, g_led_hmi->sn[i].time);
            g_led_stu_bk[g_led_hmi->sn[i].sw][g_led_hmi->sn[i].no] = uc_stu;
        }
    }

    return 0;
}
#endif

void led_polling_app(void)
{
    static uint32_t us0 = 0;
    uint32_t us;

    ch423sio_handle_mode();

    // 平时1秒处理一次，AUX板测试时0.5S一次
    us = (g_led_aux_test_st || g_led_kz_test_st) ? (USTIMER_SEC / 4) : USTIMER_SEC;
    if (ustimer_delay_origin2(&us0, us) != 1)
    {
        return;
    }

    // 更新灯状态
    _led_update_status();
#ifdef STORE_PILOTELAMP
    _led_status_save();
#endif
#ifdef CPU_FUXI
    led_updata_led();
#endif
}

/******************************************************************************
函数名称：	led_set_sw
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2014-12-16
函数说明：	设置开出类LED灯的状态
参数说明：	led: 灯的序号 LED_RUN,...,KC_LED_NUM
            status: 灯的状态 LED_ON, LED_SLOW, LED_QUICK, LED_OFF
返回值：  	无
修改记录：
*/
void led_set_pub(u8 no, u8 st)
{
    g_led_stu[0][no] = st;
}

void led_set_sw(u8 sw, u8 no, u8 st)
{
    g_led_stu[sw + 1][no] = st;
}

/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/

/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/

int led_info_printf(void)
{
    int slot, i;
    const char *name;
    struct equ_config_do *cdo;

    cdo = g_equ_config_do;
    rt_printf("\r\nslot\tindex\towner\tno\ttime\tvalue\tname\r\n");
    for (slot = 0; slot < EQU_SLOT_NUM_MAX; slot++)
    {
        rt_printf("slot%02d:num=%d.\r\n", slot, g_led_slot[slot].num);
        for (i = 0; i < g_led_slot[slot].num; i++)
        {
            if (g_led_slot[slot].sn[i].no == LED_NULL)
            {
                continue;
            }

            if (g_led_slot[slot].sn[i].sw == 0)
            {
                name = g_pub_led_name[g_led_slot[slot].sn[i].no];
            }
            else
            {
                name = g_sw_led_name[g_led_slot[slot].sn[i].no];
            }
            rt_printf("%02d\t%02d\t%02d\t%d\t%d\t%d\t%s\r\n",
                      slot,
                      i,
                      g_led_slot[slot].sn[i].sw,
                      g_led_slot[slot].sn[i].no,
                      g_led_slot[slot].sn[i].time,
                      g_led_stu[g_led_slot[slot].sn[i].sw][g_led_slot[slot].sn[i].no],
                      name);
        }
    }
    return 0;
}

/*------------------------------ 文件结束 -------------------------------------
 */
