/* ========================================================================= */ /* 1. Includes */ /* ========================================================================= */ #include "main.h" /* ========================================================================= */ /* 2. Local Macros & Constants (내부 전용 매크로 및 상수) */ /* ========================================================================= */ #define ALARM_UNDER_CHECK (0U) #define ALARM_OVER_CHECK (1U) #define LONG_KEY_TIME (500UL) #define KEY_POWER_MASK (0x0001UL) // 0x0001 - LOCAL POWER #define KEY_START_MASK (0x01A0UL) // 0x0100 - REMOTE STOP, 0x0080 - REMOTE START, 0x0020 - LOCAL START/STOP /* ========================================================================= */ /* 3. Local Typedefs & Structures (내부 전용 사용자 정의 자료형) */ /* ========================================================================= */ static CAlarmOperValue AlarmOperValue[(Uint16)IDX_FAULT_DCU_MAX]; /* ========================================================================= */ /* 4. Internal Linkage Function Declarations (내부 동작용 Static 함수 선언) */ /* ========================================================================= */ static void CInitAlarmOperValue(void); static void CKeyMainPowerProcess(void); static void CProcessArrowUpFocusChange(void); static void CProcessArrowUpPageChange(void); static void CKeyArrowUpProcess(void); static void CKeyArrowDownProcess(void); static void CProcessArrowDownPageChange(void); static void CProcessArrowDownFocusChange(void); static void CProcessEnterMenu1(void); static void CProcessEnterMenu2(void); static void CProcessEnterPassword(void); static void CProcessEnterMaintenance(void); static void CKeyEnterProcess(void); static void CKeyMenuProcess(void); static void CKeyEngineStartStopProcess(void); static void CKeyRemoteEngineStartProcess(void); static void CKeyRemoteEngineStopProcess(void); static void CKeyEmergencyProcess(void); static void CKeyBattleModeProcess(void); static void CInitAdcStructure(void); static Uint16 CAlarmCheck(E_IDX_DCU_FAULT Idx, float32 fValue, Uint16 uiCheckDetectTime, Uint16 uiCheckType); static void CApuSystemAlarmCheck(void); static Uint32 CGetKey(void); static void CKeyCheck(Uint32 ulChangeKey, Uint32 ulKeyRead); static void CMoveFocusLine(Uint16 maxLines, Uint16 direction); static void CChangePasswordDigit(Uint16 direction); static inline void CCalcAdcSum(CAdcCalcValue *AdcBuff); /* ========================================================================= */ /* 5. Global Variables & Structure Initialization (전역 변수 및 구조체 초기화) */ /* ========================================================================= */ CAdcCalcValue Adc_EngineHeater_V; CAdcCalcValue Adc_GlowPlug_V; CAdcCalcValue Adc_Solenoid_V; CAdcCalcValue Adc_FuelPump_V; CAdcCalcValue Adc_CoolantPump_V; CAdcCalcValue Adc_Fan1_V; CAdcCalcValue Adc_Fan2_V; CAdcCalcValue Adc_EngineHeater_I; CAdcCalcValue Adc_GlowPlug_I; CAdcCalcValue Adc_Solenoid_I; CAdcCalcValue Adc_FuelPump_I; CAdcCalcValue Adc_CoolantPump_I; CAdcCalcValue Adc_Fan1_I; CAdcCalcValue Adc_Fan2_I; CAdcOperValue AdcOperValue; CKeyOperValue KeyOperValue; Uint32 ulDcuTotalAlarm = 0UL; Uint32 ulGcuTotalAlarm = 0UL; Uint32 ulEcuTotalAlarm = 0UL; /* ========================================================================= */ /* Function Definitions */ /* ========================================================================= */ interrupt void CAdcInterrupt(void) { Uint16 uiTemp[(Uint16)IDX_ADC_MAX]; Uint16 i; const volatile Uint16 *pAdcAddress = &AdcRegs.ADCRESULT0; for (i = 0U; i < (Uint16)IDX_ADC_MAX; i++) { uiTemp[i] = (*(pAdcAddress++) >> 4); } Adc_EngineHeater_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_ENGINE_HEATER_V]; Adc_GlowPlug_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_GLOW_PLUG_V]; Adc_Solenoid_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_SOLENOID_V]; Adc_FuelPump_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_FUEL_PUMP_V]; Adc_CoolantPump_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_COOLANT_PUMP_V]; Adc_Fan1_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_FAN1_V]; Adc_Fan2_V.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_FAN2_V]; Adc_EngineHeater_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_ENGINE_HEATER_I]; Adc_GlowPlug_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_GLOW_PLUG_I]; Adc_Solenoid_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_SOLENOID_I]; Adc_FuelPump_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_FUEL_PUMP_I]; Adc_CoolantPump_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_COOLANT_PUMP_I]; Adc_Fan1_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_FAN1_I]; Adc_Fan2_I.iAdcValue = (int16) uiTemp[(Uint16)IDX_ADC_FAN2_I]; if (AdcOperValue.uiOffsetAdjustStart == 1U) // ADC Calibration { Adc_EngineHeater_I.fTempAdcOffset += Adc_EngineHeater_I.fSampledValue; Adc_GlowPlug_I.fTempAdcOffset += Adc_GlowPlug_I.fSampledValue; Adc_Solenoid_I.fTempAdcOffset += Adc_Solenoid_I.fSampledValue; Adc_FuelPump_I.fTempAdcOffset += Adc_FuelPump_I.fSampledValue; Adc_CoolantPump_I.fTempAdcOffset += Adc_CoolantPump_I.fSampledValue; Adc_Fan1_I.fTempAdcOffset += Adc_Fan1_I.fSampledValue; Adc_Fan2_I.fTempAdcOffset += Adc_Fan2_I.fSampledValue; AdcOperValue.uiAdcOffsetIndex--; if (AdcOperValue.uiAdcOffsetIndex == 0U) { Adc_EngineHeater_I.fOffset -= (Adc_EngineHeater_I.fTempAdcOffset / 10000.0F); Adc_GlowPlug_I.fOffset -= (Adc_GlowPlug_I.fTempAdcOffset / 10000.0F); Adc_Solenoid_I.fOffset -= (Adc_Solenoid_I.fTempAdcOffset / 10000.0F); Adc_FuelPump_I.fOffset -= (Adc_FuelPump_I.fTempAdcOffset / 10000.0F); Adc_CoolantPump_I.fOffset -= (Adc_CoolantPump_I.fTempAdcOffset / 10000.0F); Adc_Fan1_I.fOffset -= (Adc_Fan1_I.fTempAdcOffset / 10000.0F); Adc_Fan2_I.fOffset -= (Adc_Fan2_I.fTempAdcOffset / 10000.0F); AdcOperValue.uiOffsetAdjustStart = 0U; } } else { CCalcAdcSum(&Adc_EngineHeater_V); CCalcAdcSum(&Adc_GlowPlug_V); CCalcAdcSum(&Adc_Solenoid_V); CCalcAdcSum(&Adc_FuelPump_V); CCalcAdcSum(&Adc_CoolantPump_V); CCalcAdcSum(&Adc_Fan1_V); CCalcAdcSum(&Adc_Fan2_V); CCalcAdcSum(&Adc_EngineHeater_I); CCalcAdcSum(&Adc_GlowPlug_I); CCalcAdcSum(&Adc_Solenoid_I); CCalcAdcSum(&Adc_FuelPump_I); CCalcAdcSum(&Adc_CoolantPump_I); CCalcAdcSum(&Adc_Fan1_I); CCalcAdcSum(&Adc_Fan2_I); } // Reinitialize for next ADC sequence AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1U; // Reset SEQ1 AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1U; // Clear INT SEQ1 bit PieCtrlRegs.PIEACK.all |= PIEACK_GROUP1; // Acknowledge interrupt to PIE } void CDisplayAlarmPopup(void) { static Uint64 PrevFaultValue = 0U; static Uint32 PrevWarningValue = 0U; // FaultValue는 랫치상태 Uint64 FaultValue = ((Uint64)ulDcuTotalAlarm & MASK_26BIT) | (((Uint64)ulGcuTotalAlarm & MASK_WORD) << 26UL) | (((Uint64)ulEcuTotalAlarm & MASK_6BIT) << 42UL); // WarningValue는 경고가 사라질수 있기 때문에 랫치 하지 않음 Uint32 WarningValue = (((Uint32)Rx210.GcuWarning & (Uint32)MASK_LOW_NIBBLE) | (((Uint32)Rx310.EcuWarning & 0xFDU) << 4U)); // 0 → 1로 바뀐 비트만 추출 Uint64 NewFault = FaultValue & (~PrevFaultValue); Uint32 NewWarning = WarningValue & (~PrevWarningValue); // 현재 값 저장 PrevFaultValue = FaultValue; PrevWarningValue = WarningValue; Uint16 i; Uint16 UpdatePage = 0U; // 0: 유지, 1: Fault 이동, 2: Warning 이동 Uint64 TargetFault = 0U; // 검색할 대상 변수 (Fault) Uint32 TargetWarning = 0U; // 검색할 대상 변수 (Warning) if (NewFault > 0ULL) { TargetFault = NewFault; // 새로 뜬 Fault만 검색 대상 UpdatePage = 1U; } else { if (NewWarning > 0U) { TargetWarning = NewWarning; // 새로 뜬 Warning만 검색 대상 UpdatePage = 2U; } } // [페이지 이동 로직] if (UpdatePage > 0U) { /* Fault 처리 */ if (UpdatePage == 1U) { for (i = 0U; i < 64U; i++) { /* 비트 추출 시 Essential Type 일치를 위해 1ULL(또는 명시적 캐스팅) 사용 */ if (((TargetFault >> i) & 1ULL) == 1ULL) { if (i < (Uint16)IDX_FAULT_DCU_MAX) { Uint16 uiCalcPage = (Uint16)((i / 8U) + (Uint16)IDX_OLED_PAGE_FAULT1); OledOperValue.uiPageNum = (uiCalcPage <= (Uint16)IDX_OLED_PAGE_FAULT4) ? uiCalcPage : (Uint16)IDX_OLED_PAGE_FAULT4; } else { Uint16 uiCalcPage = (Uint16)((Uint16)IDX_OLED_PAGE_FAULT5 + ((i - (Uint16)IDX_FAULT_DCU_MAX) / 8U)); OledOperValue.uiPageNum = (uiCalcPage <= (Uint16)IDX_OLED_PAGE_FAULT7) ? uiCalcPage : (Uint16)IDX_OLED_PAGE_FAULT7; } break; /* 가장 낮은 비트(새로 발생한 것) 찾으면 즉시 이동 */ } } } else { /* 발전상태에서만 경고 처리, 고장 발생시 경고 페이지 이동 무시 */ if (GeneralOperValue.uiApuState == (Uint16)IDX_APU_OPER_GENERATING) { if ((NewWarning > 0U) && (FaultValue == 0U)) { for (i = 0U; i < 16U; i++) { if (((TargetWarning >> i) & 1U) == 1U) { Uint16 uiCalcPage = (Uint16)((i / 9U) + (Uint16)IDX_OLED_PAGE_WARNING1); OledOperValue.uiPageNum = (uiCalcPage <= (Uint16)IDX_OLED_PAGE_WARNING2) ? uiCalcPage : (Uint16)IDX_OLED_PAGE_WARNING2; break; } } } } } } } void CAlarmProcedure(void) { int16 iDiffRpm = 0; /* 통신 상태 업데이트 */ CommCheck.CarComputer = ((GeneralOperValue.Conection.CarComputer == 1U) && (CommCheck.CarComputer <= COMM_TIME_OUT_COUNT)) ? (CommCheck.CarComputer + 1U) : CommCheck.CarComputer; CommCheck.Gcu = ((GeneralOperValue.Conection.Gcu == 1U) && (CommCheck.Gcu <= COMM_TIME_OUT_COUNT)) ? (CommCheck.Gcu + 1U) : CommCheck.Gcu; CommCheck.Ecu = ((GeneralOperValue.Conection.Ecu == 1U) && (CommCheck.Ecu <= COMM_TIME_OUT_COUNT)) ? (CommCheck.Ecu + 1U) : CommCheck.Ecu; if (GeneralOperValue.uiApuState == (Uint16)IDX_APU_OPER_EMERGENCY) { /* Emergency 상태 시 처리 로직 (필요 시 작성) */ } else { if (GeneralOperValue.uiApuState > (Uint16)IDX_APU_OPER_EMERGENCY) { /* 통신 타임아웃 체크 및 비트 업데이트 */ CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_CAR_COMM, CAlarmCheck(IDX_FAULT_DCU_CAR_COMM, (float32)CommCheck.CarComputer, AlarmOperValue[(Uint16)IDX_FAULT_DCU_CAR_COMM].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_GCU_COMM, CAlarmCheck(IDX_FAULT_DCU_GCU_COMM, (float32)CommCheck.Gcu, AlarmOperValue[(Uint16)IDX_FAULT_DCU_GCU_COMM].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_ECU_COMM, CAlarmCheck(IDX_FAULT_DCU_ECU_COMM, (float32)CommCheck.Ecu, AlarmOperValue[(Uint16)IDX_FAULT_DCU_ECU_COMM].uiCheckTime, ALARM_OVER_CHECK)); /* 타임아웃 발생 시 연결 비트 클리어 */ GeneralOperValue.Conection.CarComputer = (CIsBitSet(ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_CAR_COMM) == 1U) ? 0U : GeneralOperValue.Conection.CarComputer; GeneralOperValue.Conection.Gcu = (CIsBitSet(ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_GCU_COMM) == 1U) ? 0U : GeneralOperValue.Conection.Gcu; GeneralOperValue.Conection.Ecu = (CIsBitSet(ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_ECU_COMM) == 1U) ? 0U : GeneralOperValue.Conection.Ecu; /* 과전류 알람 체크 */ CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OC, CAlarmCheck(IDX_FAULT_DCU_ENGINE_HEAT_OC, Adc_EngineHeater_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OC].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_GLOW_PLUG_OC, CAlarmCheck(IDX_FAULT_DCU_GLOW_PLUG_OC, Adc_GlowPlug_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OC].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_SOLENOID_OC, CAlarmCheck(IDX_FAULT_DCU_SOLENOID_OC, Adc_Solenoid_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OC].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FUEL_PUMP_OC, CAlarmCheck(IDX_FAULT_DCU_FUEL_PUMP_OC, Adc_FuelPump_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OC].uiCheckTime, ALARM_OVER_CHECK)); #if 0 // IDLE_SEQ_MOD CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OC, CAlarmCheck(IDX_FAULT_DCU_COOLANT_PUMP_OC, Adc_CoolantPump_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OC].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FAN1_OC, CAlarmCheck(IDX_FAULT_DCU_FAN1_OC, Adc_Fan1_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OC].uiCheckTime, ALARM_OVER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FAN2_OC, CAlarmCheck(IDX_FAULT_DCU_FAN2_OC, Adc_Fan2_I.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OC].uiCheckTime, ALARM_OVER_CHECK)); #endif /* 개별 전압 알람 체크 */ /* Engine Heater */ if (ENGINE_HEATER_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_ENGINE_HEAT_UV, CAlarmCheck(IDX_FAULT_DCU_ENGINE_HEAT_UV, Adc_EngineHeater_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OV, CAlarmCheck(IDX_FAULT_DCU_ENGINE_HEAT_OV, Adc_EngineHeater_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OV].uiCheckCount = 0U; } /* Glow Plug */ if (GLOW_PLUG_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_GLOW_PLUG_UV, CAlarmCheck(IDX_FAULT_DCU_GLOW_PLUG_UV, Adc_GlowPlug_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_GLOW_PLUG_OV, CAlarmCheck(IDX_FAULT_DCU_GLOW_PLUG_OV, Adc_GlowPlug_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OV].uiCheckCount = 0U; } /* Solenoid */ if (SOLENOID_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_SOLENOID_UV, CAlarmCheck(IDX_FAULT_DCU_SOLENOID_UV, Adc_Solenoid_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_SOLENOID_OV, CAlarmCheck(IDX_FAULT_DCU_SOLENOID_OV, Adc_Solenoid_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OV].uiCheckCount = 0U; } /* Fuel Pump */ if (FUEL_PUMP_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FUEL_PUMP_UV, CAlarmCheck(IDX_FAULT_DCU_FUEL_PUMP_UV, Adc_FuelPump_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FUEL_PUMP_OV, CAlarmCheck(IDX_FAULT_DCU_FUEL_PUMP_OV, Adc_FuelPump_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OV].uiCheckCount = 0U; } /* Coolant Pump */ if (COOLANT_PUMP_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_COOLANT_PUMP_UV, CAlarmCheck(IDX_FAULT_DCU_COOLANT_PUMP_UV, Adc_CoolantPump_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OV, CAlarmCheck(IDX_FAULT_DCU_COOLANT_PUMP_OV, Adc_CoolantPump_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OV].uiCheckCount = 0U; } /* Fan1 */ if (FAN1_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FAN1_UV, CAlarmCheck(IDX_FAULT_DCU_FAN1_UV, Adc_Fan1_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FAN1_OV, CAlarmCheck(IDX_FAULT_DCU_FAN1_OV, Adc_Fan1_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OV].uiCheckCount = 0U; } /* Fan2 */ if (FAN2_OUT() == 1U) { CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FAN2_UV, CAlarmCheck(IDX_FAULT_DCU_FAN2_UV, Adc_Fan2_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_UV].uiCheckTime, ALARM_UNDER_CHECK)); CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_FAN2_OV, CAlarmCheck(IDX_FAULT_DCU_FAN2_OV, Adc_Fan2_V.fLpfValue, AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OV].uiCheckTime, ALARM_OVER_CHECK)); } else { AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_UV].uiCheckCount = 0U; AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OV].uiCheckCount = 0U; } /* RPM Error 체크 */ if (GeneralOperValue.uiApuState == (Uint16)IDX_APU_OPER_GENERATING) { if ((GeneralOperValue.Conection.Gcu == 1U) && (GeneralOperValue.Conection.Ecu == 1U)) { iDiffRpm = (int16)CGetGeneratorRpm() - (int16)CGetEngineActualRpm(); iDiffRpm = (iDiffRpm < 0) ? -iDiffRpm : iDiffRpm; CUpdateFault(&ulDcuTotalAlarm, (Uint16)IDX_FAULT_DCU_RPM_ERR, CAlarmCheck(IDX_FAULT_DCU_RPM_ERR, (float32)iDiffRpm, AlarmOperValue[(Uint16)IDX_FAULT_DCU_RPM_ERR].uiCheckTime, ALARM_OVER_CHECK)); } } } } /* 알람 리셋 처리 */ if (GeneralOperValue.uiAlarmReset == 1U) { CInitAlarmOperValue(); ulDcuTotalAlarm = 0UL; /* 전체 비트 클리어 */ if (CSoftWaitCountProcedure(SOFTTIMER_WAIT_ALARM_RESET, TIME_1SEC) == (Uint16)TIME_OVER) { GeneralOperValue.uiAlarmReset = 0U; } } CApuSystemAlarmCheck(); } static Uint16 CAlarmCheck(E_IDX_DCU_FAULT Idx, float32 fValue, Uint16 uiCheckDetectTime, Uint16 uiCheckType) { Uint16 uiCheckStatus = 0; if (AlarmOperValue[Idx].uiCheck == 0U) { if (uiCheckType == ALARM_OVER_CHECK) { // Over Check ! if (fValue >= AlarmOperValue[Idx].fCheckLimit) { uiCheckStatus = 1U; } } else { // Under Check ! if (fValue <= AlarmOperValue[Idx].fCheckLimit) { uiCheckStatus = 1U; } } if (uiCheckStatus == 1U) { if (AlarmOperValue[Idx].uiCheckCount < uiCheckDetectTime) { AlarmOperValue[Idx].uiCheckCount++; } else { AlarmOperValue[Idx].uiCheck = 1U; AlarmOperValue[Idx].uiCheckCount = 0U; AlarmOperValue[Idx].fFaultValue = fValue; } } else { AlarmOperValue[Idx].uiCheckCount = 0U; } } return AlarmOperValue[Idx].uiCheck; } static void CApuSystemAlarmCheck(void) { Uint32 TotalFault = 0UL; Uint16 GcuCurrentFault; Uint16 EcuCurrentFault; /* 각 바이트를 Uint16으로 먼저 승격시킨 후 연산 수행 */ GcuCurrentFault = Rx210.GcuFault; EcuCurrentFault = Rx310.EcuFault; ulGcuTotalAlarm = ulGcuTotalAlarm | (Uint32)GcuCurrentFault; ulEcuTotalAlarm = ulEcuTotalAlarm | (Uint32)EcuCurrentFault; TotalFault = (Uint32)ulDcuTotalAlarm | (Uint32)ulGcuTotalAlarm | (Uint32)ulEcuTotalAlarm; if (TotalFault > 0U) { GeneralOperValue.uiFaultOccured = 1U; } else { GeneralOperValue.uiFaultOccured = 0U; } } static void CInitAlarmOperValue(void) { Uint16 i; for (i = 0U; i < (Uint16)IDX_FAULT_DCU_MAX; i++) { (void)memset((void*)&AlarmOperValue[i], 0, sizeof(CAlarmOperValue)); } (void)memset(&CommCheck, 0, sizeof(CCommCheck)); // 체계/GCU/ECU 통신 및 신호 단선은 다른 함수에서 처리 /* * Alarm Check Standard Value * Alarm Count per 1mS */ AlarmOperValue[(Uint16)IDX_FAULT_DCU_CAR_COMM].fCheckLimit = (float32)(COMM_TIME_OUT_COUNT); // 3 Seconds AlarmOperValue[(Uint16)IDX_FAULT_DCU_CAR_COMM].uiCheckTime = 1U; // 시간을 감지 하므로 즉시 검출 AlarmOperValue[(Uint16)IDX_FAULT_DCU_GCU_COMM].fCheckLimit = (float32)(COMM_TIME_OUT_COUNT); // 3 Seconds AlarmOperValue[(Uint16)IDX_FAULT_DCU_GCU_COMM].uiCheckTime = 1U; // 시간을 감지 하므로 즉시 검출 AlarmOperValue[(Uint16)IDX_FAULT_DCU_ECU_COMM].fCheckLimit = (float32)(COMM_TIME_OUT_COUNT); // 3 Seconds AlarmOperValue[(Uint16)IDX_FAULT_DCU_ECU_COMM].uiCheckTime = 1U; // 시간을 감지 하므로 즉시 검출 AlarmOperValue[(Uint16)IDX_FAULT_DCU_RPM_ERR].fCheckLimit = 300.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_RPM_ERR].uiCheckTime = 10U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OC].fCheckLimit = 30.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OC].fCheckLimit = 30.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OC].fCheckLimit = 10.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OC].fCheckLimit = 5.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OC].fCheckLimit = 7.5F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OC].fCheckLimit = 35.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OC].fCheckLimit = 35.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OC].uiCheckTime = 100U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_ENGINE_HEAT_OV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_GLOW_PLUG_OV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_SOLENOID_OV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FUEL_PUMP_OV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_COOLANT_PUMP_OV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN1_OV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_UV].fCheckLimit = 18.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_UV].uiCheckTime = 1000U; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OV].fCheckLimit = 31.0F; // Value AlarmOperValue[(Uint16)IDX_FAULT_DCU_FAN2_OV].uiCheckTime = 1000U; // Value } void CInitAdc(void) { InitAdc(); // ADC Initialize in DSP2833x_Adc.c AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x0; // No prescaler AdcRegs.ADCTRL1.bit.CPS = 0x1; // scaler 12.5Mhz AdcRegs.ADCTRL3.bit.SMODE_SEL = 0x0; // sequentail mode AdcRegs.ADCTRL1.bit.SEQ_OVRD = 0x0; // EOS AdcRegs.ADCTRL1.bit.SEQ_CASC = 0x1; // Cascade Sequence Mode AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Engine_Heater_V AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Glow_Plug_V AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2; // Solenoid_V AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3; // Fuel_Pump_V AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4; // Cooling_Pump_V AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5; // Fan1_V AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6; // Fan2_V AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x8; // Engine_Heater_I AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x9; // Glow_Plug_I AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0xA; // Solenoid_I AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xB; // Fuel_Pump_I AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0xC; // Cooling_Pump_I AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0xD; // Fan1_I AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0xE; // Fan2_I AdcRegs.ADCMAXCONV.all = ((Uint16)IDX_ADC_MAX - 1U); // Setup 16 channel conversion for cascade sequence mode AdcRegs.ADCREFSEL.bit.REF_SEL = 0x1; // external Reference 2.048[V], 'b01 - 2.048, b10 - 1.500[V], 'b11 - 1.024[v] AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0x0; AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1; // Enable SEQ1 interrupt (every EOS) AdcRegs.ADCTRL1.bit.ACQ_PS = 6; // Sample and hold duration(width) = (ACQ_PS + 1) CInitAdcStructure(); CInitAlarmOperValue(); } static void CInitAdcStructure(void) { (void)memset(&AdcOperValue, 0, sizeof(CAdcOperValue)); (void)memset(&Adc_EngineHeater_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_GlowPlug_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_Solenoid_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_FuelPump_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_CoolantPump_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_Fan1_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_Fan2_V, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_EngineHeater_I, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_GlowPlug_I, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_Solenoid_I, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_FuelPump_I, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_CoolantPump_I, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_Fan1_I, 0, sizeof(CAdcCalcValue)); (void)memset(&Adc_Fan2_I, 0, sizeof(CAdcCalcValue)); AdcOperValue.uiAdcOffsetIndex = 10000U; Adc_EngineHeater_V.fGain = 0.026726F; Adc_GlowPlug_V.fGain = 0.026726F; Adc_Solenoid_V.fGain = 0.026726F; Adc_FuelPump_V.fGain = 0.026726F; Adc_CoolantPump_V.fGain = 0.026726F; Adc_Fan1_V.fGain = 0.026726F; Adc_Fan2_V.fGain = 0.026726F; Adc_EngineHeater_V.fOffset = -71.157F; Adc_GlowPlug_V.fOffset = -71.157F; Adc_Solenoid_V.fOffset = -71.157F; Adc_FuelPump_V.fOffset = -71.157F; Adc_CoolantPump_V.fOffset = -71.157F; Adc_Fan1_V.fOffset = -71.157F; Adc_Fan2_V.fOffset = -71.157F; Adc_EngineHeater_I.fGain = 0.027778F; // 40A Limit Adc_GlowPlug_I.fGain = 0.027778F; // 40A Limit Adc_Solenoid_I.fGain = 0.027778F; // 20A Limit Adc_FuelPump_I.fGain = 0.027778F; // 20A Limit Adc_CoolantPump_I.fGain = 0.027778F; // 20A Limit Adc_Fan1_I.fGain = 0.027778F; // 40A Limit Adc_Fan2_I.fGain = 0.027778F; // 40A Limit Adc_EngineHeater_I.fOffset = -62.277778F; Adc_GlowPlug_I.fOffset = -62.277778F; Adc_Solenoid_I.fOffset = -62.277778F; Adc_FuelPump_I.fOffset = -62.277778F; Adc_CoolantPump_I.fOffset = -62.277778F; Adc_Fan1_I.fOffset = -62.277778F; Adc_Fan2_I.fOffset = -62.277778F; } static inline void CCalcAdcSum(CAdcCalcValue *AdcBuff) { AdcBuff->fSampledValue = ((float32) AdcBuff->iAdcValue * AdcBuff->fGain) + AdcBuff->fOffset; AdcBuff->fSampledSum += AdcBuff->fSampledValue; AdcBuff->uiSamplingCount++; if (AdcBuff->uiSamplingCount >= 20U) { AdcBuff->uiSamplingCount = 0U; AdcBuff->fSampledSum = AdcBuff->fSampledSum / 20.0F; AdcBuff->fLpfValue = (0.01884955F * AdcBuff->fSampledSum) + ((1.0F - 0.01884955F) * AdcBuff->fLpfValue); // 0.01884955f = (PI2 * ADC_LPF_COFF * (1.0F / ADC_FREQ)) AdcBuff->fLpfValue = (AdcBuff->fLpfValue < 0.0F) ? 0.0F : AdcBuff->fLpfValue; AdcBuff->fSampledSum = 0.0F; } } static Uint32 CGetKey(void) { const Uint16 uiKeyGpioList[(Uint16)IDX_KEY_MAX] = { 67U, 39U, 31U, 30U, 29U, 66U, 64U, 58U, 57U, 56U, 54U }; Uint16 i, ucDiv, ucMod; Uint32 ulGpioData = 0UL, ulKeyRead = 0UL; /* * ------GPIO Key List------ * * GPIO67 - POWER * GPIO39 - UP Arrow * GPIO31 - DOWN Arrow * GPIO30 - ENTER * GPIO29 - MENU * GPIO66 - START * GPIO64 - EMERGENCY * GPIO58 - REMOTE START * GPIO57 - REMOTE STOP * GPIO56 - REMOTE EMERGENCY * GPIO54 - REMOTE BATTLE MODE * ------------------------- */ for (i = 0U; i < (Uint16)IDX_KEY_MAX; i++) { ucDiv = (Uint16)((Uint16)uiKeyGpioList[i] / 32U); ucMod = (Uint16)((Uint16)uiKeyGpioList[i] % 32U); if (ucDiv == 0U) // GPIO-A { ulGpioData = GpioDataRegs.GPADAT.all; } else if (ucDiv == 1U) { ulGpioData = GpioDataRegs.GPBDAT.all; } else { ulGpioData = GpioDataRegs.GPCDAT.all; } if (((ulGpioData >> ucMod) & 0x01UL) == 0U) // Push Check { ulKeyRead |= (0x01UL << i); } } return ulKeyRead; } void CKeyCheckProcedure(void) { // [전원키용 변수] static Uint32 ulLongKeyCnt = 0UL; static Uint16 uiLongKeyProcessed = 1U; // 전원 켤 때 한번 무시 // [StartStop키용 변수 추가] static Uint32 ulStartKeyCnt = 0UL; // StartStop 롱키 카운트 static Uint16 uiStartKeyProcessed = 0U; // StartStop 롱키 처리 플래그 static Uint32 ulPrevKey = 0UL; Uint32 ulChangeKey; Uint32 ulReadKey = CGetKey(); // 전원키(KEY_POWER_MASK)와 StartStop키(KEY_START_MASK) 둘 다 일반 변화 감지에서 제외 ulChangeKey = (ulPrevKey ^ ulReadKey) & ~(KEY_POWER_MASK | KEY_START_MASK); if (ulChangeKey > 0UL) { if (KeyOperValue.uiKeyWait == 0U) // 채터링 무시 시작 { KeyOperValue.uiKeyWait = 1U; KeyOperValue.uiKeyWaitCount = 20; // 20ms } else { if ((KeyOperValue.uiKeyWaitCount == 0U) && (GeneralOperValue.uiApuState > (Uint16)IDX_APU_OPER_POST)) { // ulPrevKey 갱신 시, 롱키 처리되는 비트들(Power, StartStop)은 기존 상태를 유지하고 나머지만 갱신 ulPrevKey = (ulPrevKey & (KEY_POWER_MASK | KEY_START_MASK)) | (ulReadKey & ~(KEY_POWER_MASK | KEY_START_MASK)); CKeyCheck(ulChangeKey, ulReadKey); // 일반 키 동작 } } } else { // 변화가 없으면 채터링 대기 초기화 (일반 키용) if ((KeyOperValue.uiKeyWait != 0U) && (KeyOperValue.uiKeyWaitCount == 0U)) { KeyOperValue.uiKeyWait = 0U; } } // --------------------------------------------------------- // 전원키 (Power Key) 롱키 처리 (로컬 & 리모트 모두 포함) // --------------------------------------------------------- Uint32 ulPressedPowerKey = ulReadKey & KEY_POWER_MASK; if (ulPressedPowerKey != 0UL) { if (uiLongKeyProcessed == 0U) { ulLongKeyCnt++; // 롱키 시간 도달 시 동작 수행 if (ulLongKeyCnt >= LONG_KEY_TIME) { // KEY_POWER_MASK 전체가 아닌 '실제로 눌린 키(ulPressedPowerKey)'를 전달 CKeyCheck(ulPressedPowerKey, ulReadKey); uiLongKeyProcessed = 1U; // 처리 완료 플래그 ulLongKeyCnt = LONG_KEY_TIME; // 오버플로우 방지 } } } else { // 키를 뗐을 때 초기화 ulLongKeyCnt = 0UL; uiLongKeyProcessed = 0U; // ulPrevKey의 로컬 전원 키 비트를 모두 0으로 동기화 ulPrevKey &= ~KEY_POWER_MASK; } // --------------------------------------------------------- // 시동/정지 키 (StartStop) 롱키 처리 (로컬 & 리모트 모두 포함) // --------------------------------------------------------- Uint32 ulPressedStartKey = ulReadKey & KEY_START_MASK; if (ulPressedStartKey != 0UL) { if (uiStartKeyProcessed == 0U) { ulStartKeyCnt++; // 카운트 증가 // 0.5초(500ms) 도달 시 동작 수행 if (ulStartKeyCnt >= LONG_KEY_TIME) { // KEY_START_MASK가 아닌 '실제로 눌린 키(ulPressedStartKey)'를 전달 CKeyCheck(ulPressedStartKey, ulReadKey); uiStartKeyProcessed = 1U; // 처리 완료 플래그 ulStartKeyCnt = LONG_KEY_TIME; // 오버플로우 방지 } } } else { // 키를 뗐을 때 초기화 ulStartKeyCnt = 0UL; uiStartKeyProcessed = 0U; // ulPrevKey의 해당 비트(Bit 5, Bit 8) 모두 0으로 동기화 ulPrevKey &= ~KEY_START_MASK; } } void CKeyWaitCount(void) { if (KeyOperValue.uiKeyWait == 1U) { if (KeyOperValue.uiKeyWaitCount > 0U) { KeyOperValue.uiKeyWaitCount--; } else { KeyOperValue.uiKeyWait = 0U; } } } static void CKeyCheck(Uint32 ulChangeKey, Uint32 ulKeyRead) { static const CKeyHandler KeyTable[(Uint16)IDX_KEY_MAX] = { { IDX_KEY_MAIN_POWER, &CKeyMainPowerProcess }, { IDX_KEY_ARR_UP, &CKeyArrowUpProcess }, { IDX_KEY_ARR_DOWN, &CKeyArrowDownProcess }, { IDX_KEY_ENTER, &CKeyEnterProcess }, { IDX_KEY_MENU, &CKeyMenuProcess }, { IDX_KEY_ENG_START_STOP, &CKeyEngineStartStopProcess }, { IDX_KEY_EMERGENCY, &CKeyEmergencyProcess }, { IDX_KEY_REMOTE_START, &CKeyRemoteEngineStartProcess }, { IDX_KEY_REMOTE_STOP, &CKeyRemoteEngineStopProcess }, { IDX_KEY_REMOTE_EMERGENCY, &CKeyEmergencyProcess }, { IDX_KEY_BATTLE_MODE, &CKeyBattleModeProcess } }; Uint16 i; for (i = 0U; i < (Uint16)IDX_KEY_MAX; i++) { if ((ulChangeKey & (0x1UL << i)) > 0U) { if ((ulKeyRead & (0x1UL << i)) > 0U) { KeyTable[i].pAction(); } } } } static void CProcessArrowUpPageChange(void) { if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_APU2) { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_APU1; } else if ((OledOperValue.uiPageNum > (Uint16)IDX_OLED_PAGE_SENSOR1) && (OledOperValue.uiPageNum <= (Uint16)IDX_OLED_PAGE_SENSOR4)) { OledOperValue.uiPageNum = OledOperValue.uiPageNum - 1U; } else if ((OledOperValue.uiPageNum > (Uint16)IDX_OLED_PAGE_WARNING1) && (OledOperValue.uiPageNum <= (Uint16)IDX_OLED_PAGE_WARNING2)) { OledOperValue.uiPageNum = OledOperValue.uiPageNum - 1U; } else { if ((OledOperValue.uiPageNum > (Uint16)IDX_OLED_PAGE_FAULT1) && (OledOperValue.uiPageNum <= (Uint16)IDX_OLED_PAGE_FAULT7)) { OledOperValue.uiPageNum = OledOperValue.uiPageNum - 1U; } } } static void CProcessArrowUpFocusChange(void) { if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MENU1) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_1) { OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_1; } else { CMoveFocusLine(4U, DIR_UP); } } else if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MENU2) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_1) { // Go back to Menu 1 OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_4; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_MENU1; } else { CMoveFocusLine(4U, DIR_UP); } } else if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_PASSWORD) { CChangePasswordDigit(DIR_UP); } else if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_RESET_ALARM) { OledOperValue.uiResetAlarmAnswer = (OledOperValue.uiResetAlarmAnswer == 1U) ? 0U : 1U; } else { if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MAINTENANCE) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_1) { OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_1; } else { CMoveFocusLine(3U, DIR_UP); } } } } static void CKeyArrowUpProcess(void) { CProcessArrowUpPageChange(); CProcessArrowUpFocusChange(); } static void CProcessArrowDownPageChange(void) { if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_APU1) { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_APU2; } else if ((OledOperValue.uiPageNum >= (Uint16)IDX_OLED_PAGE_SENSOR1) && (OledOperValue.uiPageNum < (Uint16)IDX_OLED_PAGE_SENSOR4)) { OledOperValue.uiPageNum = OledOperValue.uiPageNum + 1U; } else if ((OledOperValue.uiPageNum >= (Uint16)IDX_OLED_PAGE_WARNING1) && (OledOperValue.uiPageNum < (Uint16)IDX_OLED_PAGE_WARNING2)) { OledOperValue.uiPageNum = OledOperValue.uiPageNum + 1U; } else { if ((OledOperValue.uiPageNum >= (Uint16)IDX_OLED_PAGE_FAULT1) && (OledOperValue.uiPageNum < (Uint16)IDX_OLED_PAGE_FAULT7)) { OledOperValue.uiPageNum = OledOperValue.uiPageNum + 1U; } } } static void CProcessArrowDownFocusChange(void) { if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MENU1) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_4) { OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_1; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_MENU2; } else { CMoveFocusLine(4U, DIR_DOWN); } } else if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MENU2) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_4) { OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_4; } else { CMoveFocusLine(4U, DIR_DOWN); } } else if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_PASSWORD) { CChangePasswordDigit(DIR_DOWN); } else if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_RESET_ALARM) { OledOperValue.uiResetAlarmAnswer = (OledOperValue.uiResetAlarmAnswer == 1U) ? 0U : 1U; } else { if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MAINTENANCE) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_3) { OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_3; } else { CMoveFocusLine(3U, DIR_DOWN); } } } } static void CKeyArrowDownProcess(void) { CProcessArrowDownPageChange(); CProcessArrowDownFocusChange(); } static void CChangePasswordDigit(Uint16 direction) { if (OledOperValue.uiFocusDigit <= (Uint16)IDX_OLED_PASS_DIGIT_4) { Uint16 *pDigit = &GeneralOperValue.uiPassword[OledOperValue.uiFocusDigit]; if (direction == DIR_UP) { *pDigit = (*pDigit + 1U) % 10U; } else // DIR_DOWN { if (*pDigit == 0U) { *pDigit = 9U; } else { *pDigit = (*pDigit - 1U) % 10U; } } } } static void CMoveFocusLine(Uint16 maxLines, Uint16 direction) { if (maxLines > 0U) { if (direction == DIR_UP) { OledOperValue.uiFocusLine = (Uint16)((OledOperValue.uiFocusLine + (Uint16)(maxLines - 1U)) % maxLines); } else /* DIR_DOWN */ { OledOperValue.uiFocusLine = (Uint16)((OledOperValue.uiFocusLine + 1U) % maxLines); } } } static void CProcessEnterMenu1(void) { switch (OledOperValue.uiFocusLine) { case (Uint16)IDX_OLED_MENU_APU: { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_APU1; break; } case (Uint16)IDX_OLED_MENU_TEMP: { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_TEMP; break; } case (Uint16)IDX_OLED_MENU_SENSOR: { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_SENSOR1; break; } default: { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_MENU_WARNING) { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_WARNING1; } break; } } } static void CProcessEnterMenu2(void) { switch (OledOperValue.uiFocusLine) { case (Uint16)IDX_OLED_LINE_FOCUS_1: // Fault { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_FAULT1; break; } case (Uint16)IDX_OLED_LINE_FOCUS_2: // Reset { OledOperValue.uiPrevFocusLine = OledOperValue.uiFocusLine; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_RESET_ALARM; break; } case (Uint16)IDX_OLED_LINE_FOCUS_3: // Maintenance { OledOperValue.uiPrevFocusLine = OledOperValue.uiFocusLine; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_PASSWORD; OledOperValue.uiFocusDigit = (Uint16)IDX_OLED_PASS_DIGIT_1; break; } case (Uint16)IDX_OLED_LINE_FOCUS_4: // Version { OledOperValue.uiPrevFocusLine = OledOperValue.uiFocusLine; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_VERSION; break; } default: { break; } } } static void CProcessEnterPassword(void) { if (OledOperValue.uiFocusDigit < (Uint16)IDX_OLED_PASS_DIGIT_4) { OledOperValue.uiFocusDigit = (OledOperValue.uiFocusDigit + 1U) % 4U; } else { const Uint16 uiPassword[4] = MAINTENECE_PASSKEY; Uint16 i; Uint16 uiIsMatch = 1U; // 1U: 일치함, 0U: 불일치함 for (i = 0U; i < (Uint16)(sizeof(uiPassword) / sizeof(uiPassword[0])); i++) { if (GeneralOperValue.uiPassword[i] != uiPassword[i]) { uiIsMatch = 0U; // 하나라도 다르면 불일치 break; } } if (uiIsMatch == 1U) { GeneralOperValue.uiMaintenance = 1U; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_MAINTENANCE; OledOperValue.uiFocusLine = (Uint16)IDX_OLED_LINE_FOCUS_1; } else { OledOperValue.uiFocusDigit = (Uint16)IDX_OLED_PASS_DIGIT_1; } } } static void CProcessEnterMaintenance(void) { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_1) { GeneralOperValue.Maintenance.ManualCranking = (GeneralOperValue.Maintenance.ManualCranking == 1U) ? 0U : 1U; } else if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_2) { GeneralOperValue.Maintenance.LampTest = (GeneralOperValue.Maintenance.LampTest == 1U) ? 0U : 1U; } else { if (OledOperValue.uiFocusLine == (Uint16)IDX_OLED_LINE_FOCUS_3) { GeneralOperValue.Maintenance.KeyTest = (GeneralOperValue.Maintenance.KeyTest == 1U) ? 0U : 1U; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_KEY_TEST; } } } static void CKeyEnterProcess(void) { switch (OledOperValue.uiPageNum) { case (Uint16)IDX_OLED_PAGE_MENU1: { CProcessEnterMenu1(); break; } case (Uint16)IDX_OLED_PAGE_MENU2: { CProcessEnterMenu2(); break; } case (Uint16)IDX_OLED_PAGE_PASSWORD: { CProcessEnterPassword(); break; } case (Uint16)IDX_OLED_PAGE_MAINTENANCE: { CProcessEnterMaintenance(); break; } case (Uint16)IDX_OLED_PAGE_RESET_ALARM: { if (OledOperValue.uiResetAlarmAnswer == 1U) { GeneralOperValue.uiAlarmReset = 1U; } OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_MENU2; break; } default: { // Fault/Warning page return to main page if ((OledOperValue.uiPageNum >= (Uint16)IDX_OLED_PAGE_WARNING1) && (OledOperValue.uiPageNum <= (Uint16)IDX_OLED_PAGE_FAULT7)) { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_APU1; } break; } } } static void CKeyMenuProcess(void) { // Return to main menus from sub-pages if ((OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MENU1) || (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MENU2)) { OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_APU1; OledOperValue.uiFocusLine = 0U; } else { if ((OledOperValue.uiPageNum >= (Uint16)IDX_OLED_PAGE_FAULT1) && (OledOperValue.uiPageNum <= (Uint16)IDX_OLED_PAGE_VERSION)) { // Return to Menu 2 from Faults or Debug if (OledOperValue.uiPageNum == (Uint16)IDX_OLED_PAGE_MAINTENANCE) { GeneralOperValue.uiMaintenance = 0U; OledOperValue.uiFocusLine = OledOperValue.uiPrevFocusLine; } OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_MENU2; } else { // Return to Menu 1 from others (APU, Temp, Sensor, Warning) OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_MENU1; } } } static void CKeyMainPowerProcess(void) { if (GeneralOperValue.uiApuState <= (Uint16)IDX_APU_OPER_STANDBY) { // APU가 정지 상태에서만 전원 스위치 입력 가능 KeyOperValue.KeyList.MainPower = 1U; OledOperValue.uiPageNum = (Uint16)IDX_OLED_PAGE_SHUTDOWN; } } static void CKeyEngineStartStopProcess(void) { if (GeneralOperValue.uiApuState == (Uint16)IDX_APU_OPER_STANDBY) { // 스탠바이 상태에서만 시동 시작 스위치 입력 받는다. KeyOperValue.KeyList.EngineStartStop = 1U; } else { KeyOperValue.KeyList.EngineStartStop = 0U; } } static void CKeyRemoteEngineStartProcess(void) { if (GeneralOperValue.uiApuState == (Uint16)IDX_APU_OPER_STANDBY) { // 스탠바이 상태에서만 시동 시작 스위치 입력 받는다. KeyOperValue.KeyList.EngineStartStop = 1U; } } static void CKeyRemoteEngineStopProcess(void) { KeyOperValue.KeyList.EngineStartStop = 0U; } static void CKeyEmergencyProcess(void) { KeyOperValue.KeyList.Emergency = KeyOperValue.KeyList.Emergency ^ 1U; } static void CKeyBattleModeProcess(void) { KeyOperValue.KeyList.BattleMode = KeyOperValue.KeyList.BattleMode ^ 1U; }