#include <string.h>
#include "DTC.h"
#include "UDS_Common.h"
#include "UDS_Service.h"
#include "bsp_eeprom.h"
//#include "api_event.h"
#include "common_include.h"

//every 500ms call:App_StoreDTC_handle()

extern uint8_t TestEolSCCResult;
extern uint8_t TestEolEPBResult;
extern uint8_t TestEolMDPSResult;
extern uint8_t TestEolESCResult;
extern uint8_t TestEolTPMSResult;
extern uint8_t TestEolLKA_LDWResult;
extern uint8_t TestEolAIR_BAGResult;
extern uint8_t TestEolATResult;

_DTC_StatusRecord DtcAndStatus[DtcListTotal];
_DTC DiagDtc[DtcListTotal];
_DiagnoCtl DiagnoCtl;
_SaveDtcInfo SaveDtcInfo;
uint8_t ReadDtcFromEepromN = 0;
uint8_t ReadDtcFromEepromMaxN = 0;

#define EEPROM_BLOCK_DTC_COUNTER1 0xA4
#define EEPROM_BLOCK_DTC_COUNTER2 0xA6
#define EEPROM_BLOCK_DTC_COUNTER3 0xA8

const _DTC_MAP_INFO dtc_map_info[DtcListTotal] =
{
    //DtcNum/DtcIndex/Exist/DtcAddr
    0x900051, EOLNotProgrammed,         1, EEPROM_BLOCK_DTC_COUNTER1, 0x00,
    0x900155, SCCPresentError,          1, EEPROM_BLOCK_DTC_COUNTER1, 0x10,
    0x900152, SCCMissingError,          1, EEPROM_BLOCK_DTC_COUNTER1, 0x20,
    0x900255, EPBPresentError,          1, EEPROM_BLOCK_DTC_COUNTER1, 0x30,
    0x900252, EPBMissingError,          1, EEPROM_BLOCK_DTC_COUNTER1, 0x40,
    0x900855, MDPSPresentError,         1, EEPROM_BLOCK_DTC_COUNTER1, 0x50,
    0x900852, MDPSMissingError,         1, EEPROM_BLOCK_DTC_COUNTER1, 0x60,
    0x901055, ESCPresentError,          1, EEPROM_BLOCK_DTC_COUNTER1, 0x70,
    0x901052, ESCMissingError,          1, EEPROM_BLOCK_DTC_COUNTER1, 0x80,
    0x902055, TPMSPresentError,         1, EEPROM_BLOCK_DTC_COUNTER1, 0x90,
    0x902052, TPMSMissingError,         1, EEPROM_BLOCK_DTC_COUNTER1, 0xA0,
    0x904055, LKA_LDWPresentError,      1, EEPROM_BLOCK_DTC_COUNTER1, 0xB0,
    0x904052, LKA_LDWMissingError,      1, EEPROM_BLOCK_DTC_COUNTER1, 0xC0,
    0x900555, AIRBIGPresentError,       1, EEPROM_BLOCK_DTC_COUNTER1, 0xD0,
    0x900552, AIRBIGMissingError,       1, EEPROM_BLOCK_DTC_COUNTER1, 0xE0,
    0x909055, TCUPresentError,          1, EEPROM_BLOCK_DTC_COUNTER2, 0x00,
    0x909052, TCUMissingError,          1, EEPROM_BLOCK_DTC_COUNTER2, 0x10,
    0xA80000, MMCanBusOff,              1, EEPROM_BLOCK_DTC_COUNTER2, 0x20,
    0xA80100, MMCanSingleLineError,     1, EEPROM_BLOCK_DTC_COUNTER2, 0x30,
};                                      

void CheckBusoffDTC(void)
{
    //if(1/*(CAN0RFLG_TSTAT == 0x03)||(CAN0RFLG_RSTAT == 0x03)*/)
    //{
    //    DiagDtc[CanBussOff].PassTimes = 0;
    //    if(g_canClock.BusOffTime == 0)
    //    {
    //        if(g_canClock.BusOffCn < 255)
    //        {
    //            g_canClock.BusOffCn ++;
    //        }
    //        if(g_canClock.BusOffCn >= 1)
    //        {
    //            g_canClock.BusOffTime = TDTC_200ms;
    //        }
    //        if(g_canClock.BusOffCn >= 2)
    //        {
    //            DiagDtc[CanBussOff].ErrorTimes = 10;
    //            App_DtcBit_handle(DiagDtc, FALSE, DiagSnap, CanBussOff);
    //        }
    //        g_canClock.CanDataTime = TDTC_96ms;
    //        g_canClock.CanKeepTime = TDTC_1s;
    //    }
    //    else
    //    {
    //        g_canClock.CanDataTime = 0;
    //        g_canClock.CanKeepTime = 0;
    //    }
    //    if(g_canClock.BusOffTime > 0)
    //    {
    //        g_canClock.BusOffTime--;
    //    }
    //}
}

//on uds service 0x19 call,refrence follow code
uint8_t App_Load_DTCAndStatus_Mask(uint8_t mask, uint8_t MaskValid)
{
    uint8_t  sn = 0;
    uint8_t  i;
    memset(DtcAndStatus, 0, sizeof (DtcAndStatus));
    for (i = 0; i < DtcListTotal; i++) {
        if (((App_CheckDtcStatus(i, mask, (_DTC*)&DiagDtc[i])) || (!MaskValid)) && (dtc_map_info[i].Exist)) {
            DtcAndStatus[sn].DTCHighByte = (uint8_t)(DiagDtc[i].DtcNum.Num >> 16);
            DtcAndStatus[sn].DTCMiddleByte = (uint8_t)(DiagDtc[i].DtcNum.Num >> 8);
            DtcAndStatus[sn].DTCLowByte = (uint8_t)DiagDtc[i].DtcNum.Num;
            DtcAndStatus[sn].statusOfDTC = DiagDtc[i].Status.Flag & DiagnoCtl.DTCByStatusMask;
            if (CurIgnSt != EVENT_IGN_ON) {
                DtcAndStatus[sn].statusOfDTC &= 0x08;
            }
            sn++;
        }
    }
    return sn;
}

void App_19_6Load(_19_6RetRecord *D19_6RetR, _DTC* DTC, _19_6ReqRecord* D19_6Req)
{
    D19_6RetR->NumAndStatus = DTC->DtcNum.Num;
    D19_6RetR->NumAndStatus = D19_6RetR->NumAndStatus << 8;
    D19_6RetR->NumAndStatus |= DTC->Status.Flag;
    switch (D19_6Req->DTCExtDataRecordNum) {
        case 1:  
            D19_6RetR->Data[0] = D19_6Req->DTCExtDataRecordNum;
            D19_6RetR->Data[1] = DTC->FaultOccurCount;
            D19_6RetR->dlc = 2;
        break;                        
        case 2:
            D19_6RetR->Data[0] = D19_6Req->DTCExtDataRecordNum;
            D19_6RetR->Data[1] = DTC->FaultPendCount;
            D19_6RetR->dlc = 2;
        break;
        case 3:
            D19_6RetR->Data[0] = D19_6Req->DTCExtDataRecordNum;
            D19_6RetR->Data[1] = DTC->DTCAgingCount;
            D19_6RetR->dlc = 2;
        break;
        case 4:
            D19_6RetR->Data[0] = D19_6Req->DTCExtDataRecordNum;
            D19_6RetR->Data[1] = DTC->DTCAgedCount;
            D19_6RetR->dlc = 2;
        break;
        case 0xFF:
            D19_6RetR->Data[0] = 1;
            D19_6RetR->Data[1] = DTC->FaultOccurCount;
            D19_6RetR->Data[2] = 2;
            D19_6RetR->Data[3] = DTC->FaultPendCount;
            D19_6RetR->Data[4] = 3;
            D19_6RetR->Data[5] = DTC->DTCAgingCount;
            D19_6RetR->Data[6] = 4;
            D19_6RetR->Data[7] = DTC->DTCAgedCount; 
            D19_6RetR->dlc = 8;
        break;                                    
    }
   
}

void ReadDtcFromEeprom(void)
{
    _DTC DtcRead;
    uint8_t check = 0;
    if (ReadDtcFromEepromN < ReadDtcFromEepromMaxN) {
        bsp_IIC_SequentialRead(dtc_map_info[ReadDtcFromEepromN].DtcBlock, dtc_map_info[ReadDtcFromEepromN].DtcAddr, (uint8_t*)&DtcRead, sizeof(_DTC));
        check = Api_CreateCRCCheckSum((uint8_t*)&DtcRead, sizeof (_DTC) - 2);
        if (check == DtcRead.bCheckSun) {
            if (DtcRead.DtcNum.Num == dtc_map_info[ReadDtcFromEepromN].DtcNum) {
                memcpy((uint8_t*)&DiagDtc[dtc_map_info[ReadDtcFromEepromN].DtcIndex], (uint8_t*)&DtcRead, sizeof(_DTC));
            }
        }
        ReadDtcFromEepromN++;
    }
}

/*-------------------------------------------------------------------------
*   Function Name    : App_Load_DTC
*   Description      :
*   Input                    :
*   Output               : None
*   Return               : None
*   onther               :
--------------------------------------------------------------------------*/
void App_Load_DTC(void)
{
    ReadDtcFromEepromMaxN = sizeof(dtc_map_info) / sizeof(_DTC_MAP_INFO);
    ReadDtcFromEepromN = 0;
}

uint8_t MMCanBusOffCnts = 0;
uint8_t MMCanSingleLineErrorCnts = 0;
void CheckDtcCondition(void)
{
    if (CurIgnSt == EVENT_IGN_ON) {
        GET_CAN1_RX_IN_LEVEL;
        if (Can1Rx_IN == PortGpioLow) {
            if (MMCanSingleLineErrorCnts < 0xff) {
                MMCanSingleLineErrorCnts++;
            }
        } else {
            MMCanSingleLineErrorCnts = 0;
        }
    }
    if ((UdsEolStart == 0) && (UdsParameter.DtcSettingType == DTC_SETTING_TYPE_ON) && (CurIgnSt == EVENT_IGN_ON)) {
        if (GetCanFrameState(0x420) != CAN_FRAME_STATE_TIME_OUT) {
            TestEolSCCResult = 1;
        } else if (GetCanFrameState(0x420) == CAN_FRAME_STATE_TIME_OUT) {
            TestEolSCCResult = 2;
        } else {
            TestEolSCCResult = 3;
        }
        
        if (GetCanFrameState(0x490) != CAN_FRAME_STATE_TIME_OUT) {
            TestEolEPBResult = 1;
        } else if (GetCanFrameState(0x490) == CAN_FRAME_STATE_TIME_OUT) {
            TestEolEPBResult = 2;
        } else {
            TestEolEPBResult = 3;
        }
        
        if (                         (GetCanFrameState(0x381) != CAN_FRAME_STATE_TIME_OUT)) {
            TestEolMDPSResult = 1;
        } else if (                        ( GetCanFrameState(0x381) == CAN_FRAME_STATE_TIME_OUT)) {
            TestEolMDPSResult = 2;
        } else {
            TestEolMDPSResult = 3;
        }
        
        if ((                        GetCanFrameState(0x507) != CAN_FRAME_STATE_TIME_OUT)) {
            TestEolESCResult = 1;
        } else if (                        (GetCanFrameState(0x507) == CAN_FRAME_STATE_TIME_OUT)) {
            TestEolESCResult = 2;
        } else {
            TestEolESCResult = 3;
        }
        
        if (                         (GetCanFrameState(0x593) != CAN_FRAME_STATE_TIME_OUT)) {
            TestEolTPMSResult = 1;
        } else if (                       (  GetCanFrameState(0x593) == CAN_FRAME_STATE_TIME_OUT)) {
            TestEolTPMSResult = 2;
        } else {
            TestEolTPMSResult = 3;
        }
        
        if (                            (GetCanFrameState(0x340) != CAN_FRAME_STATE_TIME_OUT)) {
            TestEolLKA_LDWResult = 1;
        } else if (                            (GetCanFrameState(0x340) == CAN_FRAME_STATE_TIME_OUT)) {
            TestEolLKA_LDWResult = 2;
        } else {
            TestEolLKA_LDWResult = 3;
        }
        
        if ((                            GetCanFrameState(0x500) != CAN_FRAME_STATE_TIME_OUT)) {
            TestEolAIR_BAGResult = 1;
        } else if (                            (GetCanFrameState(0x500) == CAN_FRAME_STATE_TIME_OUT)) {
            TestEolAIR_BAGResult = 2;
        } else {
            TestEolAIR_BAGResult = 3;
        }
        
        if (                        (GetCanFrameState(0x368) != CAN_FRAME_STATE_TIME_OUT)) {
            TestEolATResult = 1;
        } else if (                        (GetCanFrameState(0x368) == CAN_FRAME_STATE_TIME_OUT)) {
            TestEolATResult = 2;
        } else {
            TestEolATResult = 3;
        }
    }
}

/*-------------------------------------------------------------------------
*   Function Name : Diag_DTC_Check_main
*   Description :
*   Input :
*   Output : None
*   Return : None
*   onther :
--------------------------------------------------------------------------*/
void Diag_DTC_Check_main(void)
{
    uint8_t i;
    uint8_t len;
    len = sizeof(dtc_map_info) / sizeof(_DTC_MAP_INFO);
    if (UdsParameter.DtcSettingType == DTC_SETTING_TYPE_ON) {                //check 30
        if ((UdsParameter.CommType == COMM_TYPE_EnRxEnTx_NormalAndNetworkMsg)/* && ((CurIgnVoltage >= 900) && (CurIgnVoltage < 1600))*/) { 
            if (                                1        ) {
                DiagDtc[EOLNotProgrammed].ErrorTimes = 10; 
                DiagDtc[EOLNotProgrammed].PassTimes = 0;
                DiagDtc[SCCPresentError].ErrorTimes = 0; 
                DiagDtc[SCCPresentError].PassTimes = 5; 
                DiagDtc[SCCMissingError].ErrorTimes = 0; 
                DiagDtc[SCCMissingError].PassTimes = 5;
                DiagDtc[EPBPresentError].ErrorTimes = 0; 
                DiagDtc[EPBPresentError].PassTimes = 5; 
                DiagDtc[EPBMissingError].ErrorTimes = 0; 
                DiagDtc[EPBMissingError].PassTimes = 5;
                DiagDtc[MDPSPresentError].ErrorTimes = 0; 
                DiagDtc[MDPSPresentError].PassTimes = 5; 
                DiagDtc[MDPSMissingError].ErrorTimes = 0; 
                DiagDtc[MDPSMissingError].PassTimes = 5;
                DiagDtc[ESCPresentError].ErrorTimes = 0; 
                DiagDtc[ESCPresentError].PassTimes = 5; 
                DiagDtc[ESCMissingError].ErrorTimes = 0; 
                DiagDtc[ESCMissingError].PassTimes = 5;
                DiagDtc[TPMSPresentError].ErrorTimes = 0; 
                DiagDtc[TPMSPresentError].PassTimes = 5; 
                DiagDtc[TPMSMissingError].ErrorTimes = 0; 
                DiagDtc[TPMSMissingError].PassTimes = 5;
                DiagDtc[LKA_LDWPresentError].ErrorTimes = 0; 
                DiagDtc[LKA_LDWPresentError].PassTimes = 5; 
                DiagDtc[LKA_LDWMissingError].ErrorTimes = 0; 
                DiagDtc[LKA_LDWMissingError].PassTimes = 5;
                DiagDtc[AIRBIGPresentError].ErrorTimes = 0; 
                DiagDtc[AIRBIGPresentError].PassTimes = 5; 
                DiagDtc[AIRBIGMissingError].ErrorTimes = 0; 
                DiagDtc[AIRBIGMissingError].PassTimes = 5;
                DiagDtc[TCUPresentError].ErrorTimes = 0; 
                DiagDtc[TCUPresentError].PassTimes = 5; 
                DiagDtc[TCUMissingError].ErrorTimes = 0; 
                DiagDtc[TCUMissingError].PassTimes = 5;                
            }  
            
            if (1) {
                if (TestEolSCCResult == 1) { 
                    DiagDtc[SCCPresentError].ErrorTimes = 10; DiagDtc[SCCPresentError].PassTimes = 0; DiagDtc[SCCMissingError].ErrorTimes = 0; DiagDtc[SCCMissingError].PassTimes = 5;
                } else if (TestEolSCCResult == 2) { 
                    DiagDtc[SCCPresentError].ErrorTimes = 0; DiagDtc[SCCPresentError].PassTimes = 5; DiagDtc[SCCMissingError].ErrorTimes = 10; DiagDtc[SCCMissingError].PassTimes = 0;
                } else if (TestEolSCCResult == 3) { 
                    DiagDtc[SCCPresentError].ErrorTimes = 0; DiagDtc[SCCPresentError].PassTimes = 5; DiagDtc[SCCMissingError].ErrorTimes = 0; DiagDtc[SCCMissingError].PassTimes = 5;
                }
                TestEolSCCResult = 0xff;
                
                if (TestEolEPBResult == 1) { 
                    DiagDtc[EPBPresentError].ErrorTimes = 10; DiagDtc[EPBPresentError].PassTimes = 0; DiagDtc[EPBMissingError].ErrorTimes = 0; DiagDtc[EPBMissingError].PassTimes = 5;
                } else if (TestEolEPBResult == 2) { 
                    DiagDtc[EPBPresentError].ErrorTimes = 0; DiagDtc[EPBPresentError].PassTimes = 5; DiagDtc[EPBMissingError].ErrorTimes = 10; DiagDtc[EPBMissingError].PassTimes = 0;
                } else if (TestEolEPBResult == 3) { 
                    DiagDtc[EPBPresentError].ErrorTimes = 0; DiagDtc[EPBPresentError].PassTimes = 5; DiagDtc[EPBMissingError].ErrorTimes = 0; DiagDtc[EPBMissingError].PassTimes = 5;
                }
                TestEolEPBResult = 0xff;
                
                if (TestEolMDPSResult == 1) { 
                    DiagDtc[MDPSPresentError].ErrorTimes = 10; DiagDtc[MDPSPresentError].PassTimes = 0; DiagDtc[MDPSMissingError].ErrorTimes = 0; DiagDtc[MDPSMissingError].PassTimes = 5;
                } else if (TestEolMDPSResult == 2) { 
                    DiagDtc[MDPSPresentError].ErrorTimes = 0; DiagDtc[MDPSPresentError].PassTimes = 5; DiagDtc[MDPSMissingError].ErrorTimes = 10; DiagDtc[MDPSMissingError].PassTimes = 0;
                } else if (TestEolMDPSResult == 3) { 
                    DiagDtc[MDPSPresentError].ErrorTimes = 0; DiagDtc[MDPSPresentError].PassTimes = 5; DiagDtc[MDPSMissingError].ErrorTimes = 0; DiagDtc[MDPSMissingError].PassTimes = 5;
                }
                TestEolMDPSResult = 0xff;
                
                if (TestEolESCResult == 1) { 
                    DiagDtc[ESCPresentError].ErrorTimes = 10; DiagDtc[ESCPresentError].PassTimes = 0; DiagDtc[ESCMissingError].ErrorTimes = 0; DiagDtc[ESCMissingError].PassTimes = 5;
                } else if (TestEolESCResult == 2) { 
                    DiagDtc[ESCPresentError].ErrorTimes = 0; DiagDtc[ESCPresentError].PassTimes = 5; DiagDtc[ESCMissingError].ErrorTimes = 10; DiagDtc[ESCMissingError].PassTimes = 0;
                } else if (TestEolESCResult == 3) { 
                    DiagDtc[ESCPresentError].ErrorTimes = 0; DiagDtc[ESCPresentError].PassTimes = 5; DiagDtc[ESCMissingError].ErrorTimes = 0; DiagDtc[ESCMissingError].PassTimes = 5;
                }
                TestEolESCResult = 0xff;
                
                if (TestEolTPMSResult == 1) { 
                    DiagDtc[TPMSPresentError].ErrorTimes = 10; DiagDtc[TPMSPresentError].PassTimes = 0; DiagDtc[TPMSMissingError].ErrorTimes = 0; DiagDtc[TPMSMissingError].PassTimes = 5;
                } else if (TestEolTPMSResult == 2) { 
                    DiagDtc[TPMSPresentError].ErrorTimes = 0; DiagDtc[TPMSPresentError].PassTimes = 5; DiagDtc[TPMSMissingError].ErrorTimes = 10; DiagDtc[TPMSMissingError].PassTimes = 0;
                } else if (TestEolTPMSResult == 3) { 
                    DiagDtc[TPMSPresentError].ErrorTimes = 0; DiagDtc[TPMSPresentError].PassTimes = 5; DiagDtc[TPMSMissingError].ErrorTimes = 0; DiagDtc[TPMSMissingError].PassTimes = 5;
                }
                TestEolTPMSResult = 0xff;
                
                if (TestEolLKA_LDWResult == 1) { 
                    DiagDtc[LKA_LDWPresentError].ErrorTimes = 10; DiagDtc[LKA_LDWPresentError].PassTimes = 0; DiagDtc[LKA_LDWMissingError].ErrorTimes = 0; DiagDtc[LKA_LDWMissingError].PassTimes = 5;
                } else if (TestEolLKA_LDWResult == 2) { 
                    DiagDtc[LKA_LDWPresentError].ErrorTimes = 0; DiagDtc[LKA_LDWPresentError].PassTimes = 5; DiagDtc[LKA_LDWMissingError].ErrorTimes = 10; DiagDtc[LKA_LDWMissingError].PassTimes = 0;
                } else if (TestEolLKA_LDWResult == 3) { 
                    DiagDtc[LKA_LDWPresentError].ErrorTimes = 0; DiagDtc[LKA_LDWPresentError].PassTimes = 5; DiagDtc[LKA_LDWMissingError].ErrorTimes = 0; DiagDtc[LKA_LDWMissingError].PassTimes = 5;
                }
                TestEolLKA_LDWResult = 0xff;
                
                if (TestEolAIR_BAGResult == 1) { 
                    DiagDtc[AIRBIGPresentError].ErrorTimes = 10; DiagDtc[AIRBIGPresentError].PassTimes = 0; DiagDtc[AIRBIGMissingError].ErrorTimes = 0; DiagDtc[AIRBIGMissingError].PassTimes = 5;
                } else if (TestEolAIR_BAGResult == 2) { 
                    DiagDtc[AIRBIGPresentError].ErrorTimes = 0; DiagDtc[AIRBIGPresentError].PassTimes = 5; DiagDtc[AIRBIGMissingError].ErrorTimes = 10; DiagDtc[AIRBIGMissingError].PassTimes = 0;
                } else if (TestEolAIR_BAGResult == 3) { 
                    DiagDtc[AIRBIGPresentError].ErrorTimes = 0; DiagDtc[AIRBIGPresentError].PassTimes = 5; DiagDtc[AIRBIGMissingError].ErrorTimes = 0; DiagDtc[AIRBIGMissingError].PassTimes = 5;
                }
                TestEolAIR_BAGResult = 0xff;
                
                if (TestEolATResult == 1) { 
                    DiagDtc[TCUPresentError].ErrorTimes = 10; DiagDtc[TCUPresentError].PassTimes = 0; DiagDtc[TCUMissingError].ErrorTimes = 0; DiagDtc[TCUMissingError].PassTimes = 5;
                } else if (TestEolATResult == 2) {
                    DiagDtc[TCUPresentError].ErrorTimes = 0; DiagDtc[TCUPresentError].PassTimes = 5; DiagDtc[TCUMissingError].ErrorTimes = 10; DiagDtc[TCUMissingError].PassTimes = 0;
                } else if (TestEolATResult == 3) {
                    DiagDtc[TCUPresentError].ErrorTimes = 0; DiagDtc[TCUPresentError].PassTimes = 5; DiagDtc[TCUMissingError].ErrorTimes = 0; DiagDtc[TCUMissingError].PassTimes = 5;
                }
                TestEolATResult = 0xff;
            }
            if (CurIgnSt == EVENT_IGN_ON) {
                if (MMCanBusOffCnts >= 2) {
                    DiagDtc[MMCanBusOff].ErrorTimes = 10; DiagDtc[MMCanBusOff].PassTimes = 0;
                } else {
                    DiagDtc[MMCanBusOff].ErrorTimes = 0; DiagDtc[MMCanBusOff].PassTimes = 5;
                }
                
                if (MMCanSingleLineErrorCnts >= 200) {
                    DiagDtc[MMCanSingleLineError].ErrorTimes = 10; DiagDtc[MMCanSingleLineError].PassTimes = 0;
                } else {
                    DiagDtc[MMCanSingleLineError].ErrorTimes = 0; DiagDtc[MMCanSingleLineError].PassTimes = 5;
                }
            }
            
            for (i = 0; i < len; i++) {
                if (dtc_map_info[i].Exist) {
                    App_DtcBit_handle(DiagDtc, FALSE, i);
                }
            }
        }
    }
}

/*-------------------------------------------------------------------------
*   Function Name : App_DTCCount_handle
*   Description :
*   Input :
*   Output : None
*   Return : None
*   onther :
--------------------------------------------------------------------------*/
uint16_t App_DTCCount_handle(uint8_t mask)
{
    uint8_t count = 0;
    uint8_t i;
    uint8_t len;
    len = sizeof(dtc_map_info) / sizeof(_DTC_MAP_INFO);
    for(i = 0; i < len; i++) {
        if (dtc_map_info[i].Exist) {
            count += App_CheckDtcStatus(i, mask, (_DTC *)&DiagDtc[i]);
        }
    }
    return count;
}

/*-------------------------------------------------------------------------
*   Function Name : App_DtcBit_handle
*   Description :
*   Input :
*   Output : None
*   Return : None
*   onther :
--------------------------------------------------------------------------*/
void App_DtcBit_handle(_DTC DTC[], uint8_t SignalLed, uint8_t pos)
{
    if (CurIgnSt == EVENT_IGN_ON) {
        if (1/*DiagnoCtl.tDiagStart >= T_900ms*/) {
            if (DTC[pos].ErrorTimes >= 10) {
                if ((DTC[pos].Status.Bits.PendingDTC == 0) && (DTC[pos].FaultPendingCntStar == 0)) {
                    DTC[pos].FaultPendCount = 1;
                    DTC[pos].FaultPendingCntStar = 2;
                }
                DTC[pos].Status.Bits.TestFailedThisOprCyc   = 0;                //bit1
                DTC[pos].Status.Bits.PendingDTC             = 1;                //bit2
                DTC[pos].Status.Bits.ConfirmedDTC           = 1;                //bit3
                DTC[pos].Status.Bits.TestNotCompLastClr     = 0;                //bit4
                DTC[pos].Status.Bits.TestFailedLastClr      = 1;                //bit5
                DTC[pos].Status.Bits.TestNotCompThisCyc     = 0;                //bit6
                if (DTC[pos].Status.Bits.TestFailed == 0) {
                    if (DTC[pos].FaultOccurCount < 255) {
                        DTC[pos].FaultOccurCount++;
                    }
                    DTC[pos].Status.Bits.TestFailed = 1;                //bit0
                }
                DTC[pos].DTCAgingCount = 0;
                DTC[pos].DTCAgingCntStar = 0;
            }
            if (DTC[pos].PassTimes >= 5) {
                DTC[pos].Status.Bits.TestNotCompLastClr = 0;
                DTC[pos].Status.Bits.TestNotCompThisCyc = 0;
                DTC[pos].Status.Bits.TestFailed = 0;                //bit0
                DTC[pos].Status.Bits.ConfirmedDTC = 0;
            }
        } else {
            DTC[pos].PassTimes = 0;
            DTC[pos].ErrorTimes = 0;
            DTC[pos].Status.Bits.TestNotCompThisCyc = 1;
            DTC[pos].Status.Bits.TestFailed = 0;        //bit0
        }
        if (DTC[pos].Status.Bits.TestFailed) {
            DTC[pos].Status.Bits.WarnIndicatorReq = SignalLed;
        } else {
            DTC[pos].Status.Bits.WarnIndicatorReq = 0;
        }
    }
    
    if (CurIgnSt != EVENT_IGN_ON) {
        if (DTC[pos].Status.Bits.TestNotCompThisCyc == 0) {   //TEST COMPLETE
            DTC[pos].Status.Bits.TestNotCompThisCyc = 1;
            if (DTC[pos].Status.Bits.TestFailedThisOprCyc == 0) {   //this  opt cycle   test ok
                DTC[pos].Status.Bits.PendingDTC = 0;
                if (DTC[pos].FaultPendCount) {
                    DTC[pos].FaultPendCount = 0;
                    DTC[pos].FaultPendingCntStar = 0;
                    DTC[pos].DTCAgingCntStar = 1;
                }
                if (DTC[pos].DTCAgingCntStar == 1) {
                    DTC[pos].DTCAgingCount++;
                }
            } else {
                if (DTC[pos].FaultPendingCntStar == 1) {
                    if (DTC[pos].FaultPendCount < 255) {
                        DTC[pos].FaultPendCount ++;
                    }
                }
                if (DTC[pos].FaultPendingCntStar == 2) {
                    DTC[pos].FaultPendingCntStar = 1;
                }
            }
        }
    }
    if (DTC[pos].DTCAgingCount >= 40) {
        DTC[pos].DTCAgingCount = 0;
        DTC[pos].FaultOccurCount = 0;
        DTC[pos].FaultPendCount =   0;
        DTC[pos].DTCAgingCntStar = 0;
        DTC[pos].FaultPendingCntStar = 0;
        if (DTC[pos].Status.Bits.ConfirmedDTC) {
            DTC[pos].Status.Bits.ConfirmedDTC = 0;
            if (DTC[pos].DTCAgedCount < 255) {
                DTC[pos].DTCAgedCount++;
            }
        }
        App_CheckDtc_Store(&dtc_map_info[pos], (_DTC *)&DiagDtc[pos]);
    }
}

/*-------------------------------------------------------------------------
*   Function Name    : App_ErrorInfoInit
*   Description      :
*   Input                    :
*   Output               : None
*   Return               : None
*   onther               :
--------------------------------------------------------------------------*/
void App_DtcInfoInit(_DTC *DTC,uint32_t DtcNum)
{
    DTC->bFlag = 0x55;
    DTC->DtcNum.Num = DtcNum;
    DTC->Status.Bits.TestFailed = 0;            //bit0
    DTC->Status.Bits.TestFailedThisOprCyc = 0;  //bit1
    DTC->Status.Bits.PendingDTC = 0;            //bit2
    DTC->Status.Bits.ConfirmedDTC = 0;          //bit3
    DTC->Status.Bits.TestNotCompLastClr = 1;    //bit4
    DTC->Status.Bits.TestFailedLastClr = 0;     //bit5
    DTC->Status.Bits.TestNotCompThisCyc = 1;    //bit6
    DTC->Status.Bits.WarnIndicatorReq = 0;
    DTC->FaultOccurCount = 0;
    DTC->FaultPendCount = 0;
    DTC->DTCAgingCount = 0;
    DTC->DTCAgedCount = 0;
    DTC->FaultPendingCntStar = 0;
    DTC->DTCAgingCntStar = 0;
    DTC->PassTimes = 0;
    DTC->ErrorTimes = 0;
}

void App_DTC_InitPara(void)
{
    uint8_t i;
    DiagnoCtl.DTCByStatusMask = 0x4B;
    for (i = 0; i < DtcListTotal; i++) {
        if (dtc_map_info[i].Exist) {
              DiagDtc[i].Status.Bits.TestFailedThisOprCyc = 0;        //bit1
        }
    }
}

/*-------------------------------------------------------------------------
*   Function Name    : App_DTC_EEpromInit
*   Description      :
*   Input                    :
*   Output               : None
*   Return               : None
*   onther               :
--------------------------------------------------------------------------*/
void App_DTC_EEpromInit(void)
{
    uint8_t i; 
    App_DTC_InitPara();
    for (i = 0; i < DtcListTotal; i++) {
        App_DtcInfoInit((_DTC *)&DiagDtc[i], dtc_map_info[i].DtcNum);
    }
    App_Load_DTC();
}

/*-------------------------------------------------------------------------
*   Function Name : App_CheckDtcStatus
*   Description :
*   Input :
*   Output : None
*   Return : None
*   onther :
--------------------------------------------------------------------------*/
uint8_t App_CheckDtcStatus(uint8_t i, uint8_t mask, _DTC *Dtc)
{
    if (CurIgnSt == EVENT_IGN_ON) {
        if (Dtc->Status.Flag & mask & DiagnoCtl.DTCByStatusMask) {
            return 1;
        } else {
            return 0;
        }
    } else {
        if (Dtc->Status.Flag & mask & DiagnoCtl.DTCByStatusMask & 0x8) {
            return 1;
        } else {
            return 0;
        }
    }
}

/*-------------------------------------------------------------------------
*   Function Name    : App_CheckDtc_Store
*   Description      :
*   Input                    :
*   Output               : None
*   Return               : None
*   onther               :
--------------------------------------------------------------------------*/
void App_CheckDtc_Store(const _DTC_MAP_INFO *mapInfo, _DTC *dtc)
{
    if (mapInfo->Exist) {
        dtc->bFlag = 0x55;
        dtc->bCheckSun = Api_CreateCRCCheckSum((uint8_t*)dtc, sizeof (_DTC) - 2);
      //  bsp_eeprom_write(mapInfo->DtcBlock, mapInfo->DtcAddr, (uint8_t*)dtc, sizeof (_DTC));
    }
}

/*-------------------------------------------------------------------------
*   Function Name    : App_StoreDTC_handle
*   Description :
*   Input :
*   Output : None
*   Return : None
*   onther :
--------------------------------------------------------------------------*/
void App_StoreDTC_handle(void)
{
    uint8_t wtemp[16] = {0};
    if (1) {    //condition "every 10ms"
        if (SaveDtcInfo.EE_WriteDtcSel == StoreDTC_EE) {
            App_CheckDtc_Store(&dtc_map_info[SaveDtcInfo.DtcStep], (_DTC*)&DiagDtc[SaveDtcInfo.DtcStep]);
            SaveDtcInfo.DtcStep++;
            if (SaveDtcInfo.DtcStep >= DtcListTotal) {
                SaveDtcInfo.EE_WriteDtcSel = NoneOpDTC_EE;
                SaveDtcInfo.DtcStep = 0;
            }
        } else if (SaveDtcInfo.EE_WriteDtcSel == ClearDTC_EE) {
         // bsp_eeprom_write(dtc_map_info[SaveDtcInfo.DtcStep].DtcBlock, dtc_map_info[SaveDtcInfo.DtcStep].DtcAddr, (uint8_t*)&wtemp, sizeof (_DTC));
            SaveDtcInfo.DtcStep++;
            if (SaveDtcInfo.DtcStep >= DtcListTotal) {
                SaveDtcInfo.EE_WriteDtcSel = NoneOpDTC_EE;
                SaveDtcInfo.DtcStep = 0;
            }
        }
    }
}


