Files
K2_DCU/Source/.staticdata/.previous/20260407_213608/K2DCU/fs/28df5e74bd8ddae9115a4fb8166fcf29
2026-04-14 00:56:31 +09:00

1296 lines
52 KiB
Plaintext

/* ========================================================================= */
/* 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));
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));
/* 개별 전압 알람 체크 */
/* 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;
}