#include "Popup_Scheduler.h"
#include "Sound_Scheduler.h"
#include "EOL_Para.h"

void UpdateClassMbFirst(void);
void UpdateClassMbLoop(void);
void UpdateCurrentPopup(void);


/*指向报警属性表,根据声音或报警的配置选择不同的属性 (和弦音/真人语音)*/
const PopupAttributeStruct *PopupAttributeTable;

/******************************************************************************
报警属性表
******************************************************************************/
const PopupAttributeStruct PopupAttributeTable_1[POPUP_NUMBER_TOTAL] =
{                   /* 910101-8*/ 
/*============================================================================================================================================================================================================================
|  报警序号                                  |优先级   |   报警类                      | 成员 | 数量| 播放模式              | 报警音                   | 声音模式:持续/单周期|	保持时间*100ms   |最小保持时间*100ms |
============================================================================================================================================================================================================================*/
/*  雷达长鸣                            */{  12u,         POPUP_Radar_Changming,         NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_RADAR_Changming,      POPUP_MODE_MULTI,          11u,              10u,         },
/*  雷达1hz                             */{  12u,         POPUP_Radar_1HZ,              NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_RADAR_1HZ,            POPUP_MODE_MULTI,          11u,              10u,         },
/*  雷达2hz                             */{  12u,         POPUP_Radar_2HZ,              NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_RADAR_2HZ,            POPUP_MODE_MULTI,         11u,              10u,         },
/*  雷达4hz                             */{  12u,         POPUP_Radar_4HZ,              NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_RADAR_4HZ,            POPUP_MODE_MULTI,          11u,              10u,         },
/*  倒车雷达系统故障                     */{  12u,         POPUP_RADAR_SYSTEM_FAILURE,    NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_RADAR_2S,             POPUP_MODE_SINGLE,         30u,              10u,         },
/*  倒车雷达传感器故障                   */{  12u,         POPUP_RADAR_SENSOR_FAILURE,    NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_RADAR_2S,             POPUP_MODE_SINGLE,         20u,              10u,         },
/*  雷达开关故障                         */{  0u,         POPUP_RADAR_SWITCH_FAILURE,    NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_RADAR_0S,             POPUP_MODE_SINGLE,         30u,              10u,         },
/*  雷达自检ok长鸣0.5s                   */{  12u,         POPUP_RADAR_CHECK_OK,         NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_RADAR_OK0S,             POPUP_MODE_MULTI,         5u,              5u,         },
/*  制动液位低                           */{  2u,         POPUP_EPB_Status,              NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_EPB_Status,           POPUP_MODE_SINGLE,         11u,              10u,         },
/*  安全带未系 1HZ                       */{  3u,         POPUP_SEATBELT_DR_1HZ,         NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_SEATBELT_DR_1HZ,      POPUP_MODE_MULTI,          0xFFFFu,              10u,         },
/*  安全带未系 2HZ                       */{  3u,         POPUP_SEATBELT_DR_2HZ,         NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_SEATBELT_DR_2HZ,      POPUP_MODE_MULTI,          0xFFFFu,              10u,         },
/*  车门开报警                           */{  4u,         POPUP_DoorOpen,                NULL, 1u,    POPUP_MODE_SHORT_HINT,    SND_DoorOpen,             POPUP_MODE_SINGLE,           11u,              10u,         },
/*  车门开报警 1HZ                       */{  4u,         POPUP_DoorOpen_1HZ,            NULL, 1u,    POPUP_MODE_LONG_HINT,    SND_DoorOpen_1HZ,         POPUP_MODE_MULTI,          0xFFFFu,              10u,         },
/*  EBD故障                              */{  6u,         POPUP_EBD_fault,               NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_EBD_fault,            POPUP_MODE_SINGLE,         11u,              10u,         },
/*  ABS故障                              */{  7u,         POPUP_ABS,                     NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_ABS,                  POPUP_MODE_SINGLE,         11u,              10u,         },
/*  EPS故障                              */{  8u,         POPUP_EPS,                     NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_EPS,                  POPUP_MODE_SINGLE,         11u,              10u,         },
/*  驻车制动                             */{  5u,         POPUP_Park_Brak,               NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_Park_Brak,             POPUP_MODE_SINGLE,         11u,              10u,         },
/*  电机故障                             */{  9u,         POPUP_MotorFault,              NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_MotorFault,           POPUP_MODE_SINGLE,         11u,              10u,         },
/*  动力电池报警                         */{  10u,         POPUP_SOC_Fault,               NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_SOC_Fault,            POPUP_MODE_SINGLE,         11u,              10u,         },
/*  高压绝缘故障                         */{  11u,         POPUP_InsulationFault,         NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_InsulationFault,      POPUP_MODE_SINGLE,         11u,              10u,         },
/*  电池热失控                           */{  1u,        POPUP_SOC_HT,                  NULL, 1u,    POPUP_MODE_LONG_HINT,   SND_SOC_HT,               POPUP_MODE_MULTI,            11u,              10u,         },
/*  单踏板功能激活                       */{  13u,        POPUP_Energy_Recovery,         NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_Energy_Recovery,      POPUP_MODE_SINGLE,         11u,              10u,         },
/*  单踏板功能激活 1HZ 3次  1.4变更新增  */{  13u,        POPUP_Energy_Recovery_1,       NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_Energy_Recovery_1,    POPUP_MODE_MULTI,          0xFFFFu,              10u,         },
/*  ECO状态激活                          */{  14u,        POPUP_ECO,                     NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_ECO,                  POPUP_MODE_SINGLE,         11u,              10u,         },
/*  READY状态激活                        */{  15u,        POPUP_READY,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_READY,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  限功率报警                           */{  16u,        POPUP_PowerLimit,              NULL, 1u,    POPUP_MODE_LONG_HINT,   SND_PowerLimit,           POPUP_MODE_SINGLE,         11u,              10u,         },
/*  蓄电池电量低                         */{  17u,        POPUP_SOC_LP,                  NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_SOC_LP,               POPUP_MODE_SINGLE,         11u,              10u,         },
/*  蓄电池充电故障                       */{  17u,        POPUP_SOC_CF,                  NULL, 1u,    POPUP_MODE_LONG_HINT,   SND_SOC_CF,               POPUP_MODE_MULTI,         11u,              10u,         },
/*  动力系统故障                         */{  18u,        POPUP_SystemFault,             NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_SystemFault,          POPUP_MODE_SINGLE,         11u,              10u,         },
/*  动力系统故障                         */{  18u,        POPUP_SystemFault1,             NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_SystemFault1,          POPUP_MODE_SINGLE,         11u,              10u,         },
/*  换挡错误                             */{  17u,        POPUP_GearFault,               NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_GearFault,            POPUP_MODE_SINGLE,         11u,              10u,         },
/*  高压报警                             */{  20u,        POPUP_WeightOverload,          NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_WeightOverload,       POPUP_MODE_SINGLE,         11u,              10u,         },
/*  高压报警                             */{  20u,        POPUP_WeightOverload2,          NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_WeightOverload2,       POPUP_MODE_SINGLE,        11u,              10u,         },
/*  远程锁车                             */{  21u,        POPUP_RemoteLocking,           NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_RemoteLocking,        POPUP_MODE_SINGLE,         11u,              10u,         },
/*  小灯未关                             */{  22u,        POPUP_PositionNotClosed,       NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_PositionNotClosed,    POPUP_MODE_SINGLE,          600u,              10u,         },
/*  驾驶员离车提醒                       */{  23u,        POPUP_DepartureReminder,       NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_DepartureReminder,     POPUP_MODE_SINGLE,          30u,              10u,         },
/*  OTA 报警0                            */{  22u,        POPUP_OTA_0,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_OTA_0,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  OTA 报警1                            */{  22u,        POPUP_OTA_1,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_OTA_1,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  OTA 报警2                            */{  22u,        POPUP_OTA_2,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_OTA_2,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  OTA 报警3                            */{  22u,        POPUP_OTA_3,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_OTA_3,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  OTA 报警4                            */{  22u,        POPUP_OTA_4,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_OTA_4,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  OTA 报警5                            */{  22u,        POPUP_OTA_5,                   NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_OTA_5,                POPUP_MODE_SINGLE,         11u,              10u,         },
/*  OTA 报警5                            */{  22u,        POPUP_ESC,                     NULL, 1u,    POPUP_MODE_SHORT_HINT,   SND_ESC,                  POPUP_MODE_SINGLE,         11u,              10u,         },
/*  超速报警                              */{  13u,       POPUP_Over_Speed,              NULL, 1u,    POPUP_MODE_SHORT_HINT,    SND_Over_Speed,           POPUP_MODE_SINGLE,          11u,             10u,         },
/*==========================================================================================================================================================================================================================================*/
};                                                                                                                                                                                    
                                                                                                                                                                                      
                                                                                                                                                                                      
/*** 弹出信息状态(链)表 ***/                                                                                                                                                          
#pragma location ="BACKUP_RAM_CONTENT"                                                                                                                                                
PopupStatusStruct         PopupStatus[POPUP_NUMBER_TOTAL];                                                                                                                            
/*=====================================================                                                                                                                               
                  弹出信息调度链表                                                                                                                                                    
-------------------------------------------------------                                                                                                                               
        序号        |            链表名称                                                                                                                                             
 (链表控制数组下标) |
-------------------------------------------------------
          0         | POPUP_LINK_LIST_NEW_WARNING
          1         | POPUP_LINK_LIST_WARNING
          2         | POPUP_LINK_LIST_MASKED_WARNING
=====================================================*/
#pragma location ="BACKUP_RAM_CONTENT"
PopupLinkListCtrlStruct   PopupLinkList[3u];

/*** 弹出信息调度管理 ***/
#pragma location ="BACKUP_RAM_CONTENT"
PopupSchedulingStruct     PopupScheduling;

/******************************************************************************
函数名:Popup_Scheduler_Init
功  能:初始化弹出信息调度器
参  数:无
返回值:无
******************************************************************************/
void Popup_Scheduler_Init(void)
{
    uint8_t i;
    
    PopupAttributeTable= PopupAttributeTable_1;


    for (i = 0u; i < (uint8_t)POPUP_NUMBER_TOTAL; i++)
    {
        PopupStatus[i].Status     = POPUP_STATUS_OFF;
        PopupStatus[i].LinkList   = POPUP_LINK_LIST_NONE;
        PopupStatus[i].Prev       = i;
        PopupStatus[i].Next       = i;
        PopupStatus[i].SndReqCode = 1u;
    }

    Popup_Link_List_Init(   POPUP_LINK_LIST_NEW_WARNING, POPUP_PRIORITY_NUMBER_WARNING);
    Popup_Link_List_Init(       POPUP_LINK_LIST_WARNING, POPUP_PRIORITY_NUMBER_WARNING);
    Popup_Link_List_Init(POPUP_LINK_LIST_MASKED_WARNING, POPUP_PRIORITY_NUMBER_WARNING);

    PopupScheduling.Timer         = 0u;
    PopupScheduling.Current       = POPUP_NONE;
    PopupScheduling.NewSnd        = 0u;
    PopupScheduling.WarningExist  = 0u;
    PopupScheduling.MaskReq       = 0u;
    PopupScheduling.LastMasked    = POPUP_NONE;
    PopupScheduling.MaskedPolling = 0u;
};

/******************************************************************************
函数名:Popup_Scheduling_Service
功  能:调度弹出信息,更新当前应播放的弹出信息与应播放的报警音
        可能导致播放的弹出信息发生切换的条件:    1.当前播放的弹出信息被删除
                                              或  2.当前播放的弹出信息被屏蔽
                                              或  3.有新弹出信息到来
                                              或  4.当前弹出信息播放时间到
参  数:无
返回值:无
*******************************************************************************
注  意:该服务函数必须每100ms被调用一次
******************************************************************************/
void Popup_Scheduling_Service(void)
{

  if (PopupScheduling.Timer < 0xFFFFu) /*910101-1*/
  {
    PopupScheduling.Timer++;
  }

  /*===========================================================================
  1.当前播放的弹出信息被删除
  ============================================================================*/
  if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
  {
    if (PopupStatus[PopupScheduling.Current].Status == POPUP_STATUS_DELETE)
    {

        if (PopupStatus[PopupScheduling.Current].LinkList == POPUP_LINK_LIST_NEW_WARNING)/*首次播放*/
        {
            if (((PopupScheduling.Timer >= POPUP_DISP_TIME_MIN ) && 
                 (PopupScheduling.Timer < POPUP_DISP_TIME_NORMAL) ) ||
                 (PopupScheduling.Timer==0xFFFFu )
                )/*超过最小播放时间,可以删除状态置为OFF*/
            {

                Popup_Link_List_Remove(PopupScheduling.Current);
                PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_OFF;

              if(PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cur != POPUP_NONE) /* 还有等待的报警需要播放*/
                {
                    UpdateCurrentPopup();
                }
              else /* 没有报警要播放了*/
                {
                    PopupScheduling.Current = POPUP_NONE;
                    PopupScheduling.Timer   = POPUP_DISP_TIME_NORMAL;
                }

            }

        }
        else/*循环播放可以直接删除*/
        {

            Popup_Link_List_Remove(PopupScheduling.Current);
            PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_OFF;
            if(PopupLinkList[POPUP_LINK_LIST_WARNING].Cur != POPUP_NONE)
            {
                PopupScheduling.Current = PopupLinkList[POPUP_LINK_LIST_WARNING].Cur;                
            }
            else
            {
                PopupScheduling.Current = POPUP_NONE;
                PopupScheduling.Timer   = POPUP_DISP_TIME_NORMAL ;
            }

        }

      }
      else if (PopupStatus[PopupScheduling.Current].Status == POPUP_STATUS_CLEAR)
      {

          Popup_Link_List_Remove(PopupScheduling.Current);
          PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_OFF;
          PopupScheduling.Current = POPUP_NONE;
          PopupScheduling.Timer   = POPUP_DISP_TIME_NORMAL ;
      }
      else
      {}

    }

    /*===========================================================================
    4.有新弹出信息到来
    ============================================================================*/

    /*** #4.3:处理新到来的报警信息 ***/
    if ((PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cur != POPUP_NONE) && \
        (PopupStatus[PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cur].Status == POPUP_STATUS_NEW))
    {
      if (PopupScheduling.Current != POPUP_NONE ) /*当前有报警在播放*/
      {
          if( PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)/*有效性检查*/
          {
            
            switch (PopupStatus[PopupScheduling.Current].LinkList)
            {

              case  POPUP_LINK_LIST_NEW_WARNING :   /*当前是报警信息在首次播放*/

                  /*报警信息可以打断报警信息,但被打断的报警信息必须至少播放达到或超过最小播放时间*/ 
                  if (((PopupScheduling.Timer >= POPUP_DISP_TIME_MIN ) && 
                      (PopupScheduling.Timer < POPUP_DISP_TIME_NORMAL) ) ||
                      (PopupScheduling.Timer==0xFFFFu)  /*持续类报警解除*/
                      )
                  {
                      if (PopupScheduling.Current != PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cur)  
                      {
                          if((PopupAttributeTable[PopupScheduling.Current].DispMode == POPUP_MODE_SHORT_HINT)) /*非持续播放的这类报警*/
                          {
                              /*Popup_Link_List_Remove(PopupScheduling.Current);从列表移除*/                      
                              /*PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_MASKED;.*/
                              /*************只报一次就屏蔽(不需要查询)的处理方式:改状态就行了*/ 
                              PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_NEW;/*改为新触发的报警,高优先级结束后重新报警*/
                              UpdateClassMbFirst();                                          /*报警类的成员状态更新为首次*/
                          }
                          else if(PopupAttributeTable[PopupScheduling.Current].DispMode ==POPUP_MODE_LONG_WARNING)/*被打断的是要循环播放的*/
                          { 
                            Popup_Link_List_Remove(PopupScheduling.Current);/*从列表移除*/ 
                            Popup_Link_List_Insert(POPUP_LINK_LIST_WARNING, PopupScheduling.Current);
                            PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_LOOP;            /*标记原信息进入循环播放*/
                            UpdateClassMbLoop();/*报警类的成员状态更新为循环*/
                          }
                          else
                          {}
                      }
                         
                      UpdateCurrentPopup();        /*更新当前报警 重置播放时间*/  
                  }
                  break; /*910101-7  910101-5 */

              case  POPUP_LINK_LIST_WARNING :     /*当前是报警信息在循环播放*/
              default :                           /*意外情况*/
                     UpdateCurrentPopup();         /*更新当前报警*/
                  break;
            }            
          }

        }
        else /*此信息到来时并无其他信息播放*/
        {
            UpdateCurrentPopup();/*更新当前报警*/
        }

    }

    /*===========================================================================
    6.当前弹出信息播放时间到
    ============================================================================*/
    /*只在播放时间到的那个时间点做处理,超出时间认为当前无弹出信息播放,持续得报警不处理 */
    if( (PopupScheduling.Timer == POPUP_DISP_TIME_NORMAL ) && (POPUP_DISP_TIME_NORMAL != 0xFFFFu) )/*910101-1*/
    {
        /*** #6.1:处理播放完的报警 ***/
        if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
        {
            switch (PopupStatus[PopupScheduling.Current].LinkList)
            {

            case POPUP_LINK_LIST_NEW_WARNING :/*首次报警链表*/

                Popup_Link_List_Remove(PopupScheduling.Current);   /*将当前报警移除报警列表*/

                if (PopupAttributeTable[PopupScheduling.Current].DispMode == POPUP_MODE_SHORT_HINT)
                { /*播放一次就隐藏且不要查询*/
                    PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_MASKED;  
                }
                else if(PopupAttributeTable[PopupScheduling.Current].DispMode == POPUP_MODE_LONG_WARNING)
                {
                  /*循环显示的处理根据需要添加*/
                  Popup_Link_List_Insert(POPUP_LINK_LIST_WARNING, PopupScheduling.Current); /*将原信息转移至循环报警列表中*/
                  PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_LOOP; /*标记原信息进入循环播放*/
                  UpdateClassMbLoop();/*报警类的成员状态更新为循环*/
                  PopupLinkList[POPUP_LINK_LIST_WARNING].Cur = PopupStatus[PopupScheduling.Current].Next;
                }
                else
                {
                  /*其他类型需求需*/
                }

                break;

            case POPUP_LINK_LIST_WARNING :/*循环报警链表*/

                PopupLinkList[POPUP_LINK_LIST_WARNING].Cur = PopupStatus[PopupScheduling.Current].Next;
                break;

            default :

                break;
            }
        }

        /*** #6.2:查找下一个播放的报警 ***/
       
        if (PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cnt)
        {                                       /*有未播放过的报警*/
          PopupScheduling.Current = PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cur;
        }                                       
        else if (PopupLinkList[POPUP_LINK_LIST_WARNING].Cnt)
        {                                       /*有循环播放的报警*/
          PopupScheduling.Current = PopupLinkList[POPUP_LINK_LIST_WARNING].Cur;
        }
        else                                    
        {                                       /*无报警需要播放*/
          PopupScheduling.Current = POPUP_NONE; 
        }

        if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
        {
            PopupScheduling.Timer = 0u;

            if (PopupStatus[PopupScheduling.Current].Status == POPUP_STATUS_NEW)
            {
                PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_FIRST;
                UpdateClassMbFirst();/*报警类的成员状态更新为首次*/
            }
            else
            {
              PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_LOOP;
            }

        }
    }


    /*===========================================================================
    7.更新报警存在状态
    ============================================================================*/
    if ((PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cnt != 0u) || \
            (PopupLinkList[POPUP_LINK_LIST_WARNING].Cnt != 0u) || \
            (PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cnt != 0u))
    {
      PopupScheduling.WarningExist = 1u;
    } 
    else
    {
      PopupScheduling.WarningExist = 0u;
    }

}

void UpdateClassMbFirst(void)
{
  uint8_t   i;
  uint8_t   PopupMbr;   
  if(PopupScheduling.Current<(uint8_t)POPUP_NUMBER_TOTAL)
  {
    if (PopupAttributeTable[PopupScheduling.Current].pMbrList != NULL)                  /*如果是一个报警类*/
    {
      for (i = 0u; i < PopupAttributeTable[PopupScheduling.Current].MbrCnt; i++)        /*更新该类下所有成员的状态*/
      {
          PopupMbr = PopupAttributeTable[PopupScheduling.Current].pMbrList[i];
          if (PopupStatus[PopupMbr].Status == POPUP_STATUS_NEW)
          {
            PopupStatus[PopupMbr].Status = POPUP_STATUS_FIRST;                          /*标记成员进入首次播放*/
          }
             
      }

      if (PopupStatus[PopupScheduling.Current].SndReqCode == 0xFFu)                     /*更新声音请求码*/
      {
        PopupStatus[PopupScheduling.Current].SndReqCode = 0x01u;
      }
      else
      {
        PopupStatus[PopupScheduling.Current].SndReqCode++;
      }
            
    } 
  }

}

void UpdateClassMbLoop(void)
{
  uint8_t   i;
  uint8_t   PopupMbr; 
  if(PopupScheduling.Current<(uint8_t)POPUP_NUMBER_TOTAL)
  {
    if (PopupAttributeTable[PopupScheduling.Current].pMbrList != NULL)            /*如果原信息是一个报警类*/
    {
      for (i = 0u; i < PopupAttributeTable[PopupScheduling.Current].MbrCnt; i++)  /*更新该类下所有成员的状态*/
      {
          PopupMbr = PopupAttributeTable[PopupScheduling.Current].pMbrList[i];
          if (PopupStatus[PopupMbr].Status == POPUP_STATUS_FIRST)
          {
            PopupStatus[PopupMbr].Status = POPUP_STATUS_LOOP;               	   /*标记成员进入循环播放*/
          }
      }
    }
  }
}	

void UpdateCurrentPopup(void)
{
    PopupScheduling.Current = PopupLinkList[POPUP_LINK_LIST_NEW_WARNING].Cur;      /*新到来的报警进入当前播放*/
    if(PopupScheduling.Current<(uint8_t)POPUP_NUMBER_TOTAL)                        /*合法性检擦*/
    {    
      PopupStatus[PopupScheduling.Current].Status = POPUP_STATUS_FIRST;            /*标记此信息进入首次播放*/
      PopupScheduling.Timer = 0u;                                                  /*重置播放时间*/ /*910101-4*/
      UpdateClassMbFirst();                                                        /*报警类的成员状态更新为首次*/  /*910101-6*/
    }
}
/******************************************************************************
函数名:Popup_Request
功  能:请求播放一个弹出信息
参  数:PopupID:请求播放的弹出信息
返回值:无
******************************************************************************/
void Popup_Request(uint8_t PopupID)
{
  if(PopupID<(uint8_t)POPUP_NUMBER_TOTAL) 
  {
    if (PopupStatus[PopupID].Status == POPUP_STATUS_OFF)
    {
        if (PopupAttributeTable[PopupID].MbrCnt == 0u)       /*申请的报警是某报警类的成员*/
        {
            PopupStatus[PopupID].Status = POPUP_STATUS_NEW;   /*置该弹出信息状态为新信息状态*/

            PopupID = PopupAttributeTable[PopupID].Class;     /*类成员不进入链表,获取该报警对应的报警类进行调度*/
            Popup_Link_List_Remove(PopupID);                  /*将该报警类移出原报警列表*/
        }
 
         PopupStatus[PopupID].Status = POPUP_STATUS_NEW;    
         Popup_Link_List_Insert(POPUP_LINK_LIST_NEW_WARNING, PopupID);   


    }
    else if (PopupStatus[PopupID].Status == POPUP_STATUS_DELETE)
    {
        /*有POPUP_STATUS_DELETE标志的一定是正在播放的信息
        直接根据所在链表恢复状态即可*/
        if(PopupStatus[PopupID].LinkList == POPUP_LINK_LIST_NEW_WARNING)
        {
            PopupStatus[PopupID].Status = POPUP_STATUS_FIRST;
        }
        else if (PopupStatus[PopupID].LinkList == POPUP_LINK_LIST_WARNING)
        {
            PopupStatus[PopupID].Status = POPUP_STATUS_LOOP;
        }
        else if (PopupStatus[PopupID].LinkList == POPUP_LINK_LIST_MASKED_WARNING)
        {
            PopupStatus[PopupID].Status = POPUP_STATUS_MASKED;        
        }
        else
        { }

    }
    else
    { }  
  }

}

/******************************************************************************
函数名:Popup_Delete
功  能:请求解除播放一个弹出信息
参  数:PopupID:请求解除播放的弹出信息
返回值:无
******************************************************************************/
void Popup_Delete(uint8_t PopupID)
{
    uint8_t i;
    uint8_t PopupCls;
    uint8_t PopupMbr;
    
    uint8_t dis=0u;
    if(PopupID<(uint8_t)POPUP_NUMBER_TOTAL) 
    {
      if (!((PopupStatus[PopupID].Status == POPUP_STATUS_OFF) || \
            (PopupStatus[PopupID].Status == POPUP_STATUS_DELETE) || \
            (PopupStatus[PopupID].Status == POPUP_STATUS_CLEAR)))
      {
        if (PopupAttributeTable[PopupID].MbrCnt == 0u)                 /*要删除的报警是某报警类的成员*/
        {
            Popup_Link_List_Remove(PopupID);
            PopupStatus[PopupID].Status = POPUP_STATUS_OFF;

            PopupCls = PopupAttributeTable[PopupID].Class;               /*获取该报警对应的报警类*/
            for (i = 0u; i < PopupAttributeTable[PopupCls].MbrCnt; i++)   /*检查该类报警下的成员*/
            {
                PopupMbr = PopupAttributeTable[PopupCls].pMbrList[i];

                if ((PopupStatus[PopupMbr].Status == POPUP_STATUS_NEW) || \
                        (PopupStatus[PopupMbr].Status == POPUP_STATUS_FIRST) || \
                        (PopupStatus[PopupMbr].Status == POPUP_STATUS_LOOP) || \
                        (PopupStatus[PopupMbr].Status == POPUP_STATUS_MASKED))
                {
                  dis =1u;
                }
                    
            }
            
            if(dis==0u)
            {
              PopupID = PopupCls;
            }
            
        }
        
        if(dis==0u)
        {
          if (PopupScheduling.Current == PopupID)         /*正在播放中的报警不能立即删除,置标志,由调度程序删除*/
          {
              PopupStatus[PopupID].Status = POPUP_STATUS_DELETE;
          }
          else
          {
            Popup_Link_List_Remove(PopupID);
            PopupStatus[PopupID].Status = POPUP_STATUS_OFF;      
          }
        
        }      
      }   
    }    
}

/******************************************************************************
函数名:Popup_Clear
功  能:请求立即清除播放一个弹出信息,无论该信息是否达到最小播放时间
        用于IGN OFF时,立即清除弹出信息播放
参  数:PopupID:请求解除播放的弹出信息
返回值:无
******************************************************************************/
void Popup_Clear(uint8_t PopupID)
{
    uint8_t i;
    uint8_t PopupCls;
    uint8_t PopupMbr;
    
    uint8_t dis=0u;
    if(PopupID<(uint8_t)POPUP_NUMBER_TOTAL)
    {
        if(!((PopupStatus[PopupID].Status == POPUP_STATUS_OFF) || \
             (PopupStatus[PopupID].Status == POPUP_STATUS_CLEAR)))
        {
          if (PopupAttributeTable[PopupID].MbrCnt == 0u)                 /*要删除的报警是某报警类的成员*/
          {
              Popup_Link_List_Remove(PopupID);
              PopupStatus[PopupID].Status = POPUP_STATUS_OFF;

              PopupCls = PopupAttributeTable[PopupID].Class;               /*获取该报警对应的报警类*/
              for (i = 0u; i < PopupAttributeTable[PopupCls].MbrCnt; i++)   /*检查该类报警下的成员*/
              {
                  PopupMbr = PopupAttributeTable[PopupCls].pMbrList[i];

                  if ((PopupStatus[PopupMbr].Status == POPUP_STATUS_NEW) || \
                          (PopupStatus[PopupMbr].Status == POPUP_STATUS_FIRST) || \
                          (PopupStatus[PopupMbr].Status == POPUP_STATUS_LOOP) || \
                          (PopupStatus[PopupMbr].Status == POPUP_STATUS_MASKED))
                  {
                    dis=1u;
                  }
                      
              }
             
              if(dis==0u)
              {
                PopupID = PopupCls;
              }
              
          }

          if(dis==0u)
          {
            if (PopupScheduling.Current == PopupID)         /*正在播放中的报警不能立即删除,置标志,由调度程序删除*/
            {
                PopupStatus[PopupID].Status = POPUP_STATUS_CLEAR;
            }
            else
            {
              Popup_Link_List_Remove(PopupID);
              PopupStatus[PopupID].Status = POPUP_STATUS_OFF;      
            }      
          }

       }     
    }

}





/******************************************************************************
函数名:Popup_Mask_Request
功  能:请求屏蔽报警信息
        可以在任意时刻发出屏蔽请求,只有满足屏蔽条件时,报警信息才会被屏蔽
参  数:无
返回值:无
******************************************************************************/
void Popup_Mask_Request(void)
{
    PopupScheduling.MaskReq = 1u;
}

/******************************************************************************
函数名:Popup_Mask_Request
功  能:请求屏蔽报警信息
        可以在任意时刻发出屏蔽请求,只有满足屏蔽条件时,报警信息才会被屏蔽
参  数:无
返回值:无
******************************************************************************/
void Popup_Hint_Mask_Request(uint8_t PopupID)
{
    if (PopupID < (uint8_t)POPUP_NUMBER_TOTAL)
    {

        if (PopupScheduling.Current == PopupID)         /*正在播放中的提示信息不能立即屏蔽,置标志,由调度程序屏蔽*/
        {
            PopupStatus[PopupID].Status = POPUP_STATUS_MASKED;
        }
        else
        {
          PopupStatus[PopupID].Status = POPUP_STATUS_LOOP;
          Popup_Link_List_Remove(PopupScheduling.Current);
        
        }
        
    }
}

/******************************************************************************
函数名:Popup_Get_Status
功  能:获取弹出信息的当前状态
参  数:PopupID:弹出信息名称
返回值:弹出信息的当前状态
******************************************************************************/
uint8_t Popup_Get_Status(uint8_t PopupID)
{
  uint8_t Status;
  if (PopupID < (uint8_t)POPUP_NUMBER_TOTAL) 
  {
    Status = PopupStatus[PopupID].Status;
  }
  else
  {
    Status = POPUP_STATUS_OFF;
  }
  return Status;
}


/******************************************************************************
函数名:Popup_Get_Current_Type
功  能:获取当前播放的弹出信息的类型
参  数:无
返回值:当前播放的弹出信息的类型
******************************************************************************/
uint8_t Popup_Get_Current_Type(void)
{
  uint8_t m8;
    if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
    {
      m8= PopupAttributeTable[PopupScheduling.Current].DispMode;
    } 
    else
    {
     m8= POPUP_NONE;
    }
   return m8;
     
}

/******************************************************************************
函数名:Popup_Get_Current_Message
功  能:获取当前应播放的弹出信息
参  数:无
返回值:当前应播放的弹出信息
******************************************************************************/
uint8_t Popup_Get_Current_Message(void)
{
   uint8_t m8;
   
    if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
    {
      m8= PopupAttributeTable[PopupScheduling.Current].Class;
    }
    else
    {
      m8= POPUP_NONE;
    }

    return m8;
}

/******************************************************************************
函数名:Popup_Get_Current_Sound
功  能:获取当前应播放的声音
参  数:无
返回值:当前应播放的声音
******************************************************************************/
uint8_t Popup_Get_Current_Sound(void)
{
  uint8_t m8;

    if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
    {
       m8= PopupAttributeTable[PopupScheduling.Current].Snd;
    } 
    else
    { 
      m8= SND_NONE;
    }
    return m8;
}
/******************************************************************************
函数名:Popup_Get_Current_Sound_Req_Code
功  能:获取当前应播放的声音的请求码
参  数:无
返回值:请求码
******************************************************************************/
uint8_t Popup_Get_Current_Sound_Req_Code(void)
{
  uint8_t m8;
    if (PopupScheduling.Current < (uint8_t)POPUP_NUMBER_TOTAL)
    {
      if (PopupAttributeTable[PopupScheduling.Current].SndMode == POPUP_MODE_MULTI)
      {
        m8 = PopupStatus[PopupScheduling.Current].SndReqCode;
      } 
      else 
      {
        if (PopupStatus[PopupScheduling.Current].Status == POPUP_STATUS_FIRST)
        {
          m8 = PopupStatus[PopupScheduling.Current].SndReqCode;
        }
        else
        {
          m8=0u;
        }      
      }
    }
    else
    {
      m8 =0u;
    }
    

    return m8;
}

/******************************************************************************
函数名:Popup_Get_Warning_Status
功  能:获取报警信息的状态,用于惊叹号标志的播放
参  数:无
返回值:0 - 当前没有报警信息
        1 - 当前有报警信息(新报警信息 或 循环播放报警信息 或 已屏蔽的报警信息)
******************************************************************************/
uint8_t Popup_Get_Warning_Status(void)
{
    return PopupScheduling.WarningExist;
}

/******************************************************************************
函数名:Popup_Get_First_Masked_Warning
功  能:获取屏蔽的报警信息中的第一个报警信息
        当前没有已屏蔽的报警信息时,返回 POPUP_NONE
参  数:无
返回值:已屏蔽的第一个报警信息
******************************************************************************/
uint8_t Popup_Get_First_Masked_Warning(void)
{
    uint8_t i,m8;
    uint8_t PopupID;
    
    m8 = POPUP_NONE;
    if (PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cnt)
    {
        i = 0u;
        while (i < PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].PrioNum)
        {
            PopupID = PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Prio[i].First;
            if (PopupID != POPUP_NONE)
            {
              m8= PopupID;
            }

            i++;
        }
    }
    else
    {
      m8 = POPUP_NONE;
    }

    return m8;
}

/******************************************************************************
函数名:Popup_Get_Last_Masked_Warning
功  能:获取屏蔽的报警信息中的最后一个报警信息
        当前没有已屏蔽的报警信息时,返回 POPUP_NONE
参  数:无
返回值:已屏蔽的最后一个报警信息
******************************************************************************/
uint8_t Popup_Get_Last_Masked_Warning(void)
{
    uint8_t i,m8;
    uint8_t j;
    uint8_t PopupID;
    m8 = POPUP_NONE;
    if (PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cnt)
    {
        i = 0u;
        while (i < PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].PrioNum)
        {
            i++;
            j = PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].PrioNum - i;

            PopupID = PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Prio[j].Last;
            if (PopupID != POPUP_NONE)
            {
               m8 =PopupID;
            } 
        }
    }
    else
    {
      m8 = POPUP_NONE;
    }

    return m8;
}

/******************************************************************************
函数名:Popup_Get_Masked_Warning_Msg
功  能:获取屏蔽的报警信息
        当前没有已屏蔽的报警信息时,返回 POPUP_NONE
参  数:无
返回值:已屏蔽的报警信息
******************************************************************************/
uint8_t Popup_Get_Masked_Warning_Msg(void)
{
    uint8_t PopupID ,m8;

    PopupID = PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur;

    if (PopupID < (uint8_t)POPUP_NUMBER_TOTAL)
    {
      m8 = PopupAttributeTable[PopupID].Class;
    }
    else
    {
      m8 = POPUP_NONE;
    }

    return m8;
}

/******************************************************************************
函数名:Popup_Masked_Warning_Polling_Reset
功  能:重置已屏蔽的报警查询起点
参  数:Mode:查询模式 POPUP_POLLING_FORWARD - 正向查找模式
                       POPUP_POLLING_REVERSE - 逆向查找模式
返回值:无
******************************************************************************/
void Popup_Masked_Warning_Polling_Reset(uint8_t Mode)
{
    uint8_t PopupID;

    if (Mode == POPUP_POLLING_FORWARD)
    {
      PopupID = Popup_Get_First_Masked_Warning();
    }
    else
    {
      PopupID = Popup_Get_Last_Masked_Warning();
    }
        

    PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur = PopupID;
}

/******************************************************************************
函数名:Popup_Masked_Warning_Polling
功  能:查询已屏蔽的报警

        每调用一次此函数,已屏蔽报警指针会按指定方向移动一位,当指针已移指定方向
        上的最后一个报警信息时,再次向同一方向查询,当前的已屏蔽报警信息会变为
        POPUP_NONE 表示报警查询已结束

        例如:当前有已屏蔽报警 A、B、C、D,调用Popup_Masked_Warning_Polling_Reset
        函数,设定方向为 POPUP_POLLING_FORWARD 时,已屏蔽报警指针会指向报警A,而后,
        调用该函数设定方向为 POPUP_POLLING_FORWARD 时已屏蔽报警指针即指向报警B.
        重复调用此函数且方向不变至已屏蔽报警指针指向报警D后,再以相同方向调用此函
        数则返回 POPUP_NONE,表示查询已结束

        通过调用Popup_Get_Masked_Warning可读出当前已屏蔽报警指针指向的报警

参  数:Mode:查询模式 POPUP_POLLING_FORWARD - 正向查找模式
                       POPUP_POLLING_REVERSE - 逆向查找模式
返回值:无
******************************************************************************/
void Popup_Masked_Warning_Polling(uint8_t Mode)
{
    uint8_t PopupEnd;
    uint8_t PopupID;

    PopupID  = PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur;

    if (PopupID != POPUP_NONE)
    {
        if (Mode == POPUP_POLLING_FORWARD)
        {
            PopupEnd = Popup_Get_Last_Masked_Warning();

            if (PopupEnd != POPUP_NONE)
            {
                if (PopupID == PopupEnd)
                {
                  PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur = POPUP_NONE;
                }
                else
                {
                  PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur = PopupStatus[PopupID].Next;
                }
                    
            }
        }
        else
        {
            PopupEnd = Popup_Get_First_Masked_Warning();

            if (PopupEnd != POPUP_NONE)
            {
                if (PopupID == PopupEnd)
                {
                   PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur = POPUP_NONE;
                }
                else
                {
                  PopupLinkList[POPUP_LINK_LIST_MASKED_WARNING].Cur = PopupStatus[PopupID].Prev;
                }
                    
            }
        }
    }
}

/******************************************************************************
函数名:Popup_Link_List_Init
功  能:初始化链表
参  数:LinkListID:链表名称
        PrioNum   :该链表下优先级数
返回值:无
******************************************************************************/
void Popup_Link_List_Init(uint8_t LinkListID, uint8_t PrioNum)
{
    uint8_t i;

    PopupLinkList[LinkListID].Cnt     = 0u;
    PopupLinkList[LinkListID].Cur     = POPUP_NONE;
    PopupLinkList[LinkListID].PrioNum = PrioNum;

    for (i = 0u; i < PrioNum; i++)
    {
        PopupLinkList[LinkListID].Prio[i].First = POPUP_NONE;
        PopupLinkList[LinkListID].Prio[i].Last  = POPUP_NONE;
    }
}

/******************************************************************************
函数名:Popup_Link_List_Insert
功  能:向链表中插入弹出信息
参  数:LinkListID:链表名称
        PopupID   :弹出信息名称
返回值:无  
******************************************************************************/
void Popup_Link_List_Insert(uint8_t LinkListID, uint8_t PopupID)  /*823008-8*/
{
    uint8_t   i;
    uint8_t   FoundID;
    uint8_t   Prio;
    uint8_t   InsResult;

    uint8_t   SemeType_Pirod;/*报警类型相同(PEPS,SHORT_HINT,LONG_HINT)*/

    SemeType_Pirod = 0u;
    if (PopupID < (uint8_t)POPUP_NUMBER_TOTAL) 
    {
      if (PopupStatus[PopupID].LinkList != LinkListID)    /*弹出信息已经不在前链表中*/
      {

        Prio = PopupAttributeTable[PopupID].Priority;     /*获取弹出信息优先级*/

        if (PopupLinkList[LinkListID].Cnt == 0u)          /*当前链表下没有任何弹出信息*/
        {
            PopupStatus[PopupID].Prev = PopupID;          /*因只有一个弹出信息,前后弹出信息均指向自己*/
            PopupStatus[PopupID].Next = PopupID;

            PopupLinkList[LinkListID].Cur = PopupID;      /*当前此链表指针指向该弹出信息*/

            PopupLinkList[LinkListID].Prio[Prio].First = PopupID;         /*优先级维护*/
            PopupLinkList[LinkListID].Prio[Prio].Last  = PopupID;
        }
        else                                              /*当前链表已有弹出信息*/
        {
            InsResult = 0u;                               /*清插入成功标示*/

            for (i = 0u; i <= Prio; i++)                  /*从当前优先级起前向查找新弹出信息的接入点*/
            {
                FoundID = PopupLinkList[LinkListID].Prio[Prio - i].Last;

                if (FoundID != POPUP_NONE)                /*找到插入点*/
                {
                    /*需要插入的报警ID的优先级==找到的插入点优先级 && 类型相同(SHORT_HINT,LONG_HINT)*/
                    if(  (PopupAttributeTable[PopupID].Priority == PopupAttributeTable[FoundID].Priority)
                            &&
                            ( 
                              ((PopupAttributeTable[PopupID].DispMode == POPUP_MODE_SHORT_HINT) &&
                               (PopupAttributeTable[FoundID].DispMode == POPUP_MODE_SHORT_HINT))  ||
                              ((PopupAttributeTable[PopupID].DispMode == POPUP_MODE_LONG_HINT) &&
                               (PopupAttributeTable[FoundID].DispMode == POPUP_MODE_LONG_HINT))
                            )
                      )
                    {
                        SemeType_Pirod = 1u;   /*符合相同优先级打断规则*/
                    }

                    if(SemeType_Pirod == 1u)
                    {
                        FoundID = PopupLinkList[LinkListID].Prio[Prio].First;

                        PopupStatus[PopupStatus[FoundID].Prev].Next = PopupID; /*链接前一个*/
                        PopupStatus[PopupID].Prev = PopupStatus[FoundID].Prev; /*插到此类型的最前面*/
                        PopupStatus[PopupID].Next = FoundID;
                        PopupStatus[FoundID].Prev = PopupID;
                        /* PopupStatus[FoundID].Next 保持不变*/
                        InsResult = 1u;                           /*插入成功*/
                       
                    }
                    else/*其他情况按照优先级排队规则插入*/
                    {
                        PopupStatus[PopupID].Prev = FoundID;      /*插入弹出信息,维护链表*/
                        PopupStatus[PopupID].Next = PopupStatus[FoundID].Next;
                        PopupStatus[PopupStatus[FoundID].Next].Prev = PopupID;
                        PopupStatus[FoundID].Next = PopupID;
                        InsResult = 1u;                           /*插入成功*/
                        
                    }
                    
                    break;
                   
                }
            }

            if (InsResult == 0u)                           /*前向查找时未能成功插入新弹出信息则转入后向查找*/
            {
                for (i = Prio + 1u; i < PopupLinkList[LinkListID].PrioNum; i++)
                {
                    FoundID = PopupLinkList[LinkListID].Prio[i].First;

                    if (FoundID != POPUP_NONE)                /*找到插入点*/
                    {
                        PopupStatus[PopupID].Next = FoundID;    /*插入弹出信息,维护链表*/
                        PopupStatus[PopupID].Prev = PopupStatus[FoundID].Prev;
                        PopupStatus[PopupStatus[FoundID].Prev].Next = PopupID;
                        PopupStatus[FoundID].Prev = PopupID;

                        break;
                    }
                }
            }

            if(Prio < PopupAttributeTable[PopupLinkList[LinkListID].Cur].Priority) /*910101-2  910101-3 */
            {
                PopupLinkList[LinkListID].Cur = PopupID; /*将当前此链表指针指向更高优先级弹出信息*/
            }

            if ( (Prio < PopupAttributeTable[PopupLinkList[LinkListID].Cur].Priority)        ||

                    ((PopupAttributeTable[PopupLinkList[LinkListID].Cur].DispMode == POPUP_MODE_SHORT_HINT)  && /*短时提示类相同优先级可以打断*/
                     (Prio <= PopupAttributeTable[PopupLinkList[LinkListID].Cur].Priority))      ||

                    ((PopupAttributeTable[PopupLinkList[LinkListID].Cur].DispMode == POPUP_MODE_LONG_HINT)   && /*长时提示类相同优先级可以打断*/
                     (Prio <= PopupAttributeTable[PopupLinkList[LinkListID].Cur].Priority))      /*此时没有报警触发的情况*/
               )
            {
                PopupLinkList[LinkListID].Cur = PopupID;    /*将当前此链表指针指向更高优先级弹出信息*/
            }


            if(PopupLinkList[LinkListID].Prio[Prio].First == POPUP_NONE)  /*当前优先级下尚无弹出信息*/
            {
                PopupLinkList[LinkListID].Prio[Prio].First = PopupID;       /*则当前优先级下的首末弹出信息均为此新弹出信息*/
                PopupLinkList[LinkListID].Prio[Prio].Last  = PopupID;
            }
            else                                                          /*当前优先级下有弹出信息*/
            {
                if(SemeType_Pirod == 1u)
                {
                   PopupLinkList[LinkListID].Prio[Prio].First  = PopupID;
                } 
                else
                {
                   PopupLinkList[LinkListID].Prio[Prio].Last  = PopupID;     /*依照插入规则,新弹出信息排列于此优先级下的末位*/
                }
                    
            }

        }

        PopupLinkList[LinkListID].Cnt++;
        PopupStatus[PopupID].LinkList = LinkListID;     /*标记弹出信息所在链表*/
      }    
    }

}

/******************************************************************************
函数名:Popup_Link_List_Remove
功  能:从弹出信息所在链表中移除弹出信息
参  数:PopupID   :弹出信息名称
返回值:无
******************************************************************************/
void Popup_Link_List_Remove(uint8_t PopupID)
{
    uint8_t   Prio;
    uint8_t   LinkListID;

    if (PopupID < (uint8_t)POPUP_NUMBER_TOTAL) 
    {
      LinkListID = PopupStatus[PopupID].LinkList;

      if (LinkListID!= POPUP_LINK_LIST_NONE)
      {
          if (PopupLinkList[LinkListID].Cnt)
          {
            PopupLinkList[LinkListID].Cnt--;
          }  

          Prio = PopupAttributeTable[PopupID].Priority;   /*获取弹出信息优先级*/

          if (PopupLinkList[LinkListID].Cnt == 0u)         /*删除后当前链表已下没有任何弹出信息*/
          {
              PopupLinkList[LinkListID].Prio[Prio].First = POPUP_NONE;         /*优先级维护*/
              PopupLinkList[LinkListID].Prio[Prio].Last  = POPUP_NONE;

              PopupLinkList[LinkListID].Cur = POPUP_NONE;   /*重置当前此链表指针*/
          }
          else
          {
              if (PopupID == PopupLinkList[LinkListID].Prio[Prio].First)/*lmj报警在当前队列中优先级第一*/
              {
                  if (PopupLinkList[LinkListID].Prio[Prio].First == PopupLinkList[LinkListID].Prio[Prio].Last)/*lmj如果当前就自己*/
                  {
                      PopupLinkList[LinkListID].Prio[Prio].First = POPUP_NONE; /*lmj当前优先级中没有报警了*/
                      PopupLinkList[LinkListID].Prio[Prio].Last  = POPUP_NONE; /*lmj当前优先级中没有报警了*/
                  }
                  else
                  {
                      PopupLinkList[LinkListID].Prio[Prio].First = PopupStatus[PopupID].Next;/*lmj下一个提升为最高优先级*/
                  }
                     
              }
              else if (PopupID == PopupLinkList[LinkListID].Prio[Prio].Last)
              {
                  PopupLinkList[LinkListID].Prio[Prio].Last = PopupStatus[PopupID].Prev;/*lmj倒数第二优先级改为最低优先级*/
              }
              else
              {}

              if (PopupLinkList[LinkListID].Cur == PopupID)
              {
                PopupLinkList[LinkListID].Cur = PopupStatus[PopupID].Next;/*下一个立刻变为当前*/
              }
                  
              PopupStatus[PopupStatus[PopupID].Prev].Next = PopupStatus[PopupID].Next; /*lmj 上下衔接*/
              PopupStatus[PopupStatus[PopupID].Next].Prev = PopupStatus[PopupID].Prev;
          }

          PopupStatus[PopupID].Prev = PopupID;                      /*弹出信息被删除,前后弹出信息均指向自己*/
          PopupStatus[PopupID].Next = PopupID;

          PopupStatus[PopupID].LinkList = POPUP_LINK_LIST_NONE;     /*弹出信息已不在任何链表中*/
      }    
    }


}

void PopupAndSound_Delete(uint8_t PopupID)
  {
    if(PopupID < (uint8_t)POPUP_NUMBER_TOTAL)
    {
      Popup_Delete(PopupID);
      Sound_Delete(PopupAttributeTable[PopupID].Snd);    
    }

  }