/******************************************************************************/ /* Copyright (c) 2016 MD Automotive Controls. Original Work. */ /* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher */ /******************************************************************************/ /* CONTEXT:USER_APP */ /* PACKAGE TITLE: Fuelling */ /* DESCRIPTION: This code module initialises the required */ /* resources and functions for fuelling calculations */ /* measurement */ /* FILE NAME: FUEL.c */ /* REVISION HISTORY: 28-03-2016 | 1.0 | Initial revision */ /* */ /******************************************************************************/ #define _FUEL_C /******************************************************************************/ /* HEADER FILES */ /******************************************************************************/ #include "build.h" #ifdef BUILD_USER #include "FUEL.h" #ifdef BUILD_FME #include "FME.h" #endif /* LOCAL VARIABLE DEFINITIONS (STATIC) ****************************************/ TEPMAPI_tstTimedKernelEvent FUEL_astTimedHoldKernelEvents[2]; TEPMAPI_tstTimedKernelEvent FUEL_astTimedFuelPumpEvents[100]; SPREADAPI_ttSpreadIDX FUEL_tSpreadAfmTFIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadTAFRxIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadTAFRyIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadFuelFlowIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadTFuelPressurexIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadTFuelPressureyIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadCrankingAirflowIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadInjResponseIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadInjShortOpeningIDX; SPREADAPI_ttSpreadIDX FUEL_tSpreadFuelCutsIDX; TABLEAPI_ttTableIDX FUEL_tTableCrankingAirflowIDX; TABLEAPI_ttTableIDX FUEL_tTableAfmTFIDX; TABLEAPI_ttTableIDX FUEL_tTableInjResponseIDX; TABLEAPI_ttTableIDX FUEL_tTableInjShortOpeningIDX; TABLEAPI_ttTableIDX FUEL_tTableFuelFlowIDX; TABLEAPI_ttTableIDX FUEL_tTableFuelCutsIDX; MAPSAPI_ttMapIDX FUEL_tMapTAFRIDX; MAPSAPI_ttMapIDX FUEL_tMapTFuelPressureIDX; uint16 FUEL_u16InjResponse; uint16 FUEL_u16TFuelPressure; uint16 FUEL_u16CrankingAirflow; uint32 FUEL_u32SensorStateBank2; bool FUEL_boCalculatePending; bool FUEL_bo720Injection; uint32 u32SequenceIDX; uint32 FUEL_u32ADCRaw; uint32 FUEL_u32ADCFiltered; bool FUEL_boNewSample; uint16 FUEL_u16FuelFlowRate; uint32 FUEL_u32FuelChannelsMask; uint32 FUEL_u32FuelChannelsCount; /* LOCAL FUNCTION PROTOTYPES (STATIC) *****************************************/ static void FUEL_vTEPMCallBack(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_ttEventTime tEventTime); static void FUEL_vCyclicCalculate(void); static void FUEL_vADCCallBack(IOAPI_tenEHIOResource, uint32); static void FUEL_vCalcFuelChannels(void); /* GLOBAL FUNCTION DEFINITIONS ************************************************/ void FUEL_vStart(puint32 const pu32Arg) { IOAPI_tenEHIOResource enEHIOResource; IOAPI_tenEHIOType enEHIOType; TEPMAPI_tstTEPMChannelCB stTEPMChannelCB; IOAPI_tenDriveStrength enDriveStrength; uint32 u32EventCount; ADCAPI_tstADCCB stADCCB; FUEL_u32ADCRaw = 0; FUEL_boNewSample = false; FUEL_u32FuelChannelsMask = 0; if (EH_IO_Invalid != USERCAL_stRAMCAL.u16FRSADResource) { enEHIOResource = USERCAL_stRAMCAL.u16FRSADResource; enEHIOType = IOAPI_enADSE; stADCCB.enSamplesAv = ADCAPI_en32Samples; stADCCB.pfResultCB = &FUEL_vADCCallBack; stADCCB.enTrigger = ADCAPI_enTrigger4; USER_vSVC(SYSAPI_enRequestIOResource, (void*)&enEHIOResource, (void*)NULL, (void*)NULL); if (SYSAPI_enOK == pstSVCDataStruct->enSVCResult) { USER_vSVC(SYSAPI_enInitialiseIOResource, (void*)&enEHIOResource, (void*)&enEHIOType, (void*)&stADCCB); if (SYSAPI_enOK != pstSVCDataStruct->enSVCResult) { *pu32Arg |= (uint32)SYSAPI_enResourceRequestFailed;/*CR1_13*/ } } else { *pu32Arg |= (uint32)SYSAPI_enResourceInitFailed;/*CR1_13*/ } } /* Setup fuel pump relay */ if (EH_IO_Invalid != USERCAL_stRAMCAL.enFuelPumpRelay) { enEHIOResource = USERCAL_stRAMCAL.enFuelPumpRelay; enEHIOType = IOAPI_enDIOOutput; enDriveStrength = IOAPI_enWeak; SETUP_vSetupDigitalIO(enEHIOResource, enEHIOType, enDriveStrength, pu32Arg); SETUP_vSetDigitalIOHigh(enEHIOResource); } /* Both peak and hold have a switch on and switch off event per cycle */ TEPMAPI_ttEventCount tEventCount = 2; /* Initialise the GDI fuel pump control parameters */ FUEL_tStartFPSolenoidDelay = 100; FUEL_tStartFPSolenoidPeak = 15000; FUEL_tStartFPSolenoidDutyHigh = 180;//160; FUEL_tStartFPSolenoidDutyLow = 100;//140; FUEL_tFPAccumulate = 9000; FUEL_u16TFuelPressure = 12000; /* Set injection time to Xms */ FUEL_tTimeHoldUs[0] = 1000; FUEL_tTimeHoldUs[1] = 1000; FUEL_tTimeHoldUs[2] = 1000; FUEL_tTimeHoldUs[3] = 1000; FUEL_tTimeHoldUs[4] = 1000; FUEL_tTimeHoldUs[5] = 1000; FUEL_tTimeHoldUs[6] = 1000; FUEL_tTimeHoldUs[7] = 1000; FUEL_tTimeHold[0] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[0]); FUEL_tTimeHold[1] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[1]); FUEL_tTimeHold[2] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[2]); FUEL_tTimeHold[3] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[3]); FUEL_tTimeHold[4] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[4]); FUEL_tTimeHold[5] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[5]); FUEL_tTimeHold[6] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[6]); FUEL_tTimeHold[7] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[7]); /* Set injection phase to 360 degrees */ FUEL_tStartHoldFraction[0] = (0x10000 * 2) / 720; FUEL_tStartHoldFraction[1] = (0x10000 * 2) / 720; FUEL_tStartHoldFraction[2] = (0x10000 * 2) / 720; FUEL_tStartHoldFraction[3] = (0x10000 * 2) / 720; FUEL_tStartHoldFraction[4] = (0x10000 * 2) / 720; FUEL_tStartHoldFraction[5] = (0x10000 * 5) / 720; FUEL_tStartHoldFraction[6] = (0x10000 * 5) / 720; FUEL_tStartHoldFraction[7] = (0x10000 * 5) / 720; /* Request and initialise Fuel Injector group A */ if ((0xffff > USERCAL_stRAMCAL.au32InjectionSequence[0]) && (EH_IO_Invalid > USERCAL_stRAMCAL.aFuelIOResource[0])) { enEHIOResource = USERCAL_stRAMCAL.aFuelIOResource[0]; //FUEL_nInj1Output; enEHIOType = IOAPI_enCaptureCompare; USER_vSVC(SYSAPI_enRequestIOResource, (void*)&enEHIOResource, (void*)NULL, (void*)NULL); /* Initialise the TEPM channel Fuel Injector group A */ if (SYSAPI_enOK == pstSVCDataStruct->enSVCResult) { stTEPMChannelCB.enAction = TEPMAPI_enSetLow; stTEPMChannelCB.boInterruptEnable = TRUE; stTEPMChannelCB.boAsyncRequestEnable = TRUE; stTEPMChannelCB.u32Sequence = USERCAL_stRAMCAL.au32InjectionSequence[0]; USER_vSVC(SYSAPI_enInitialiseIOResource, (void*)&enEHIOResource, (void*)&enEHIOType, (void*)&stTEPMChannelCB); } /* Switch injector on at a fraction of global time */ FUEL_astTimedHoldKernelEvents[0].enAction = TEPMAPI_enSetHigh; FUEL_astTimedHoldKernelEvents[0].enMethod = TEPMAPI_enGlobalLinkedFraction; FUEL_astTimedHoldKernelEvents[0].ptEventTime = &FUEL_tStartHoldFraction[0]; FUEL_astTimedHoldKernelEvents[0].enEHIOBitMirrorResource = EH_IO_Invalid; /* Switch injector off at timer ms */ FUEL_astTimedHoldKernelEvents[1].enAction = TEPMAPI_enSetLow; FUEL_astTimedHoldKernelEvents[1].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedHoldKernelEvents[1].ptEventTime = &FUEL_tTimeHold[0]; FUEL_astTimedHoldKernelEvents[1].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedHoldKernelEvents[1].enEHIOBitMirrorResource = EH_IO_Invalid; USER_vSVC(SYSAPI_enConfigureKernelTEPMOutput, (void*)&enEHIOResource, (void*)&FUEL_astTimedHoldKernelEvents[0], (void*)&tEventCount); if ((EH_IO_TMR1 <= USERCAL_stRAMCAL.aFuelIOResource[0]) && (EH_IO_TMR16 >= USERCAL_stRAMCAL.aFuelIOResource[0])) { FUEL_u32FuelChannelsMask |= (1 << (USERCAL_stRAMCAL.aFuelIOResource[0] - EH_IO_TMR1)); } } /* Request and initialise Fuel Injector group B */ if ((0xffff > USERCAL_stRAMCAL.au32InjectionSequence[1]) && (EH_IO_Invalid > USERCAL_stRAMCAL.aFuelIOResource[1])) { enEHIOResource = USERCAL_stRAMCAL.aFuelIOResource[1]; //FUEL_nInj2Output; enEHIOType = IOAPI_enCaptureCompare; USER_vSVC(SYSAPI_enRequestIOResource, (void*)&enEHIOResource, (void*)NULL, (void*)NULL); /* Initialise the TEPM channel Fuel Injector group B */ if (SYSAPI_enOK == pstSVCDataStruct->enSVCResult) { stTEPMChannelCB.enAction = TEPMAPI_enSetLow; stTEPMChannelCB.boInterruptEnable = TRUE; stTEPMChannelCB.boAsyncRequestEnable = TRUE; stTEPMChannelCB.u32Sequence = USERCAL_stRAMCAL.au32InjectionSequence[1]; USER_vSVC(SYSAPI_enInitialiseIOResource, (void*)&enEHIOResource, (void*)&enEHIOType, (void*)&stTEPMChannelCB); } /* Switch injector on at a fraction of global time */ FUEL_astTimedHoldKernelEvents[0].enAction = TEPMAPI_enSetHigh; FUEL_astTimedHoldKernelEvents[0].enMethod = TEPMAPI_enGlobalLinkedFraction; FUEL_astTimedHoldKernelEvents[0].ptEventTime = &FUEL_tStartHoldFraction[1]; FUEL_astTimedHoldKernelEvents[0].enEHIOBitMirrorResource = EH_IO_Invalid; /* Switch injector off at timer ms */ FUEL_astTimedHoldKernelEvents[1].enAction = TEPMAPI_enSetLow; FUEL_astTimedHoldKernelEvents[1].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedHoldKernelEvents[1].ptEventTime = &FUEL_tTimeHold[1]; FUEL_astTimedHoldKernelEvents[1].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedHoldKernelEvents[1].enEHIOBitMirrorResource = EH_IO_Invalid; USER_vSVC(SYSAPI_enConfigureKernelTEPMOutput, (void*)&enEHIOResource, (void*)&FUEL_astTimedHoldKernelEvents[0], (void*)&tEventCount); if ((EH_IO_TMR1 <= USERCAL_stRAMCAL.aFuelIOResource[1]) && (EH_IO_TMR16 >= USERCAL_stRAMCAL.aFuelIOResource[1])) { FUEL_u32FuelChannelsMask |= (1 << (USERCAL_stRAMCAL.aFuelIOResource[1] - EH_IO_TMR1)); } } /* Request and initialise Fuel Injector group C */ if ((0xffff > USERCAL_stRAMCAL.au32InjectionSequence[2]) && (EH_IO_Invalid > USERCAL_stRAMCAL.aFuelIOResource[2])) { enEHIOResource = USERCAL_stRAMCAL.aFuelIOResource[2]; //FUEL_nInj3Output; enEHIOType = IOAPI_enCaptureCompare; USER_vSVC(SYSAPI_enRequestIOResource, (void*)&enEHIOResource, (void*)NULL, (void*)NULL); /* Initialise the TEPM channel Fuel Injector group C */ if (SYSAPI_enOK == pstSVCDataStruct->enSVCResult) { stTEPMChannelCB.enAction = TEPMAPI_enSetLow; stTEPMChannelCB.boInterruptEnable = TRUE; stTEPMChannelCB.boAsyncRequestEnable = TRUE; stTEPMChannelCB.u32Sequence = USERCAL_stRAMCAL.au32InjectionSequence[2]; USER_vSVC(SYSAPI_enInitialiseIOResource, (void*)&enEHIOResource, (void*)&enEHIOType, (void*)&stTEPMChannelCB); } /* Switch injector on at a fraction of global time */ FUEL_astTimedHoldKernelEvents[0].enAction = TEPMAPI_enSetHigh; FUEL_astTimedHoldKernelEvents[0].enMethod = TEPMAPI_enGlobalLinkedFraction; FUEL_astTimedHoldKernelEvents[0].ptEventTime = &FUEL_tStartHoldFraction[2]; FUEL_astTimedHoldKernelEvents[0].enEHIOBitMirrorResource = EH_IO_Invalid; /* Switch injector off at timer ms */ FUEL_astTimedHoldKernelEvents[1].enAction = TEPMAPI_enSetLow; FUEL_astTimedHoldKernelEvents[1].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedHoldKernelEvents[1].ptEventTime = &FUEL_tTimeHold[2]; FUEL_astTimedHoldKernelEvents[1].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedHoldKernelEvents[1].enEHIOBitMirrorResource = EH_IO_Invalid; USER_vSVC(SYSAPI_enConfigureKernelTEPMOutput, (void*)&enEHIOResource, (void*)&FUEL_astTimedHoldKernelEvents[0], (void*)&tEventCount); if ((EH_IO_TMR1 <= USERCAL_stRAMCAL.aFuelIOResource[2]) && (EH_IO_TMR16 >= USERCAL_stRAMCAL.aFuelIOResource[2])) { FUEL_u32FuelChannelsMask |= (1 << (USERCAL_stRAMCAL.aFuelIOResource[2] - EH_IO_TMR1)); } } /* Initialise the TEPM channel Fuel Injector group D */ if ((0xffff > USERCAL_stRAMCAL.au32InjectionSequence[3]) && (EH_IO_Invalid > USERCAL_stRAMCAL.aFuelIOResource[3])) { enEHIOResource = USERCAL_stRAMCAL.aFuelIOResource[3]; //FUEL_nInj4Output; enEHIOType = IOAPI_enCaptureCompare; USER_vSVC(SYSAPI_enRequestIOResource, (void*)&enEHIOResource, (void*)NULL, (void*)NULL); /* Initialise the TEPM channel Fuel Injector group D */ if (SYSAPI_enOK == pstSVCDataStruct->enSVCResult) { stTEPMChannelCB.enAction = TEPMAPI_enSetLow; stTEPMChannelCB.boInterruptEnable = TRUE; stTEPMChannelCB.boAsyncRequestEnable = TRUE; stTEPMChannelCB.u32Sequence = USERCAL_stRAMCAL.au32InjectionSequence[3]; USER_vSVC(SYSAPI_enInitialiseIOResource, (void*)&enEHIOResource, (void*)&enEHIOType, (void*)&stTEPMChannelCB); } /* Switch injector on at a fraction of global time */ FUEL_astTimedHoldKernelEvents[0].enAction = TEPMAPI_enSetHigh; FUEL_astTimedHoldKernelEvents[0].enMethod = TEPMAPI_enGlobalLinkedFraction; FUEL_astTimedHoldKernelEvents[0].ptEventTime = &FUEL_tStartHoldFraction[3]; FUEL_astTimedHoldKernelEvents[0].enEHIOBitMirrorResource = EH_IO_Invalid; /* Switch injector off at timer ms */ FUEL_astTimedHoldKernelEvents[1].enAction = TEPMAPI_enSetLow; FUEL_astTimedHoldKernelEvents[1].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedHoldKernelEvents[1].ptEventTime = &FUEL_tTimeHold[3]; FUEL_astTimedHoldKernelEvents[1].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedHoldKernelEvents[1].enEHIOBitMirrorResource = EH_IO_Invalid; USER_vSVC(SYSAPI_enConfigureKernelTEPMOutput, (void*)&enEHIOResource, (void*)&FUEL_astTimedHoldKernelEvents[0], (void*)&tEventCount); if ((EH_IO_TMR1 <= USERCAL_stRAMCAL.aFuelIOResource[3]) && (EH_IO_TMR16 >= USERCAL_stRAMCAL.aFuelIOResource[3])) { FUEL_u32FuelChannelsMask |= (1 << (USERCAL_stRAMCAL.aFuelIOResource[3] - EH_IO_TMR1)); } } /* Initialise the Fuel Pressure Solenoid free-wheel enable*/ enEHIOResource = EH_IO_GP5; enEHIOType = IOAPI_enDIOOutput; enDriveStrength = IOAPI_enStrong; SETUP_vSetupDigitalIO(enEHIOResource, enEHIOType, enDriveStrength, pu32Arg); /* Initialise the TEPM channel Fuel Pressure Solenoid */ if (EH_IO_Invalid > USERCAL_stRAMCAL.u16FuelPressureSolenoidResource) { enEHIOResource = USERCAL_stRAMCAL.u16FuelPressureSolenoidResource; enEHIOType = IOAPI_enCaptureCompare; USER_vSVC(SYSAPI_enRequestIOResource, (void*)&enEHIOResource, (void*)NULL, (void*)NULL); /* Initialise the TEPM channel Fuel Pressure Solenoid */ if (SYSAPI_enOK == pstSVCDataStruct->enSVCResult) { stTEPMChannelCB.enAction = TEPMAPI_enSetLow; stTEPMChannelCB.boInterruptEnable = TRUE; stTEPMChannelCB.boAsyncRequestEnable = TRUE; stTEPMChannelCB.u32Sequence = 0x0000080; USER_vSVC(SYSAPI_enInitialiseIOResource, (void*)&enEHIOResource, (void*)&enEHIOType, (void*)&stTEPMChannelCB); } /* Switch injector on at a fraction of global time */ FUEL_astTimedFuelPumpEvents[0].enAction = TEPMAPI_enSetHigh; FUEL_astTimedFuelPumpEvents[0].enMethod = TEPMAPI_enGlobalLinkedTimeStep;//TEPMAPI_enGlobalLinkedFraction; FUEL_astTimedFuelPumpEvents[0].ptEventTime = &FUEL_tStartFPSolenoidDelay; FUEL_astTimedFuelPumpEvents[0].enEHIOBitMirrorResource = EH_IO_GP5; FUEL_astTimedFuelPumpEvents[1].enAction = TEPMAPI_enSetLow; FUEL_astTimedFuelPumpEvents[1].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedFuelPumpEvents[1].ptEventTime = &FUEL_tStartFPSolenoidPeak; FUEL_astTimedFuelPumpEvents[1].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedFuelPumpEvents[1].enEHIOBitMirrorResource = EH_IO_GP5; FUEL_astTimedFuelPumpEvents[1].ptAccumulate = &FUEL_tFPAccumulate; for (u32EventCount = 1; u32EventCount <= 48; u32EventCount++) { FUEL_astTimedFuelPumpEvents[2 * u32EventCount].enAction = TEPMAPI_enSetHigh; FUEL_astTimedFuelPumpEvents[2 * u32EventCount].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedFuelPumpEvents[2 * u32EventCount].ptEventTime = &FUEL_tStartFPSolenoidDutyLow; FUEL_astTimedFuelPumpEvents[2 * u32EventCount].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedFuelPumpEvents[2 * u32EventCount].enEHIOBitMirrorResource = EH_IO_GP5; FUEL_astTimedFuelPumpEvents[2 * u32EventCount].ptAccumulate = &FUEL_tFPAccumulate; FUEL_astTimedFuelPumpEvents[2 * u32EventCount + 1].enAction = TEPMAPI_enSetLow; FUEL_astTimedFuelPumpEvents[2 * u32EventCount + 1].enMethod = TEPMAPI_enHardLinkedTimeStep; FUEL_astTimedFuelPumpEvents[2 * u32EventCount + 1].ptEventTime = &FUEL_tStartFPSolenoidDutyHigh; FUEL_astTimedFuelPumpEvents[2 * u32EventCount + 1].pfEventCB = FUEL_vTEPMCallBack; FUEL_astTimedFuelPumpEvents[2 * u32EventCount + 1].enEHIOBitMirrorResource = EH_IO_GP5; FUEL_astTimedFuelPumpEvents[2 * u32EventCount + 1].ptAccumulate = &FUEL_tFPAccumulate; } tEventCount = 98; USER_vSVC(SYSAPI_enConfigureKernelTEPMOutput, (void*)&enEHIOResource, (void*)&FUEL_astTimedFuelPumpEvents[0], (void*)&tEventCount); } /* Request and initialise required Kernel managed spread for AfmTF */ FUEL_tSpreadAfmTFIDX = SETUP_tSetupSpread((void*)&FUEL_nXAFMAxisRef, (void*)&USERCAL_stRAMCAL.aUserCURVEAfmTFSpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed table for AfmTF */ FUEL_tTableAfmTFIDX = SETUP_tSetupTable((void*)&USERCAL_stRAMCAL.aUserCURVEAfmTFTable, (void*)&AFM_tAirFlowAFMRawUg, TYPE_enUInt32, 17, FUEL_tSpreadAfmTFIDX, NULL); /* Request and initialise required Kernel managed spread for Fuel Flow */ FUEL_tSpreadFuelFlowIDX = SETUP_tSetupSpread((void*)&FUEL_tKiloPaFiltered, (void*)&USERCAL_stRAMCAL.aUserFuelFlowRateSpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed table for Fuel Flow */ FUEL_tTableFuelFlowIDX = SETUP_tSetupTable((void*)&USERCAL_stRAMCAL.aUserFuelFlowRateTable, (void*)&FUEL_u16FuelFlowRate, TYPE_enUInt16, 17, FUEL_tSpreadFuelFlowIDX, NULL); /* Request and initialise required Kernel managed spread for TAFRx */ FUEL_tSpreadTAFRxIDX = SETUP_tSetupSpread((void*)&CAM_u32RPMFiltered, (void*)&USERCAL_stRAMCAL.aUserTAFRxSpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed spread for TAFRy */ FUEL_tSpreadTAFRyIDX = SETUP_tSetupSpread((void*)&MAP_tKiloPaFiltered, (void*)&USERCAL_stRAMCAL.aUserTAFRySpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed map for TAFR */ FUEL_tMapTAFRIDX = SETUP_tSetupMap((void*)&USERCAL_stRAMCAL.aUserMAPTAFR, (void*)&FUEL_u16TAFR, TYPE_enUInt16, 17, 17, FUEL_tSpreadTAFRxIDX, FUEL_tSpreadTAFRyIDX, NULL); /* Request and initialise required Kernel managed spread for injector response */ FUEL_tSpreadInjResponseIDX = SETUP_tSetupSpread((void*)&BVM_tBattVolts, (void*)&USERCAL_stRAMCAL.aUserInjResponseSpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed table for injector response */ FUEL_tTableInjResponseIDX = SETUP_tSetupTable((void*)&USERCAL_stRAMCAL.aUserInjResponseTable, (void*)&FUEL_u16InjResponse, TYPE_enUInt16, 17, FUEL_tSpreadInjResponseIDX, NULL); /* Request and initialise required Kernel managed spread for cranking airflow */ FUEL_tSpreadCrankingAirflowIDX = SETUP_tSetupSpread((void*)&CAM_u32RPMRaw, (void*)&USERCAL_stRAMCAL.aUserCrankingAirflowSpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed table for cranking airflow */ FUEL_tTableCrankingAirflowIDX = SETUP_tSetupTable((void*)&USERCAL_stRAMCAL.aUserCrankingAirflowTable, (void*)&FUEL_u16CrankingAirflow, TYPE_enUInt16, 17, FUEL_tSpreadCrankingAirflowIDX, NULL); /* Request and initialise required Kernel managed spread for injector short opening */ FUEL_tSpreadInjShortOpeningIDX = SETUP_tSetupSpread((void*)&FUEL_tTimePredictedUsInput, (void*)&USERCAL_stRAMCAL.aUserInjShortOpeningSpread, TYPE_enUInt32, 11, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed table for injector short opening */ FUEL_tTableInjShortOpeningIDX = SETUP_tSetupTable((void*)&USERCAL_stRAMCAL.aUserInjShortOpeningTable, (void*)&FUEL_tTimePredictedShortOpeningUs, TYPE_enUInt32, 11, FUEL_tSpreadInjShortOpeningIDX, NULL); /* Request and initialise required Kernel managed spread for launch and flat shift fuel cuts */ FUEL_tSpreadFuelCutsIDX = SETUP_tSetupSpread((void*)&CAM_u32RPMRaw, (void*)&USERCAL_stRAMCAL.aUserFuelCutsSpread, TYPE_enUInt32, 17, SPREADAPI_enSpread4ms, NULL); /* Request and initialise required Kernel managed table for launch and flat shift fuel cuts */ FUEL_tTableFuelCutsIDX = SETUP_tSetupTable((void*)&USERCAL_stRAMCAL.aUserFuelCutsTable, (void*)&FUEL_u16FuelCutsPercent, TYPE_enUInt16, 17, FUEL_tSpreadFuelCutsIDX, NULL); FUEL_bo720Injection = FALSE; for (u32SequenceIDX = 0; u32SequenceIDX < FUEL_nFuelSequenceCount; u32SequenceIDX++) { if (((USERCAL_stRAMCAL.au32InjectionSequence[u32SequenceIDX] & 0xff) == 0xff) || ((USERCAL_stRAMCAL.au32InjectionSequence[u32SequenceIDX] & 0xff00) == 0xff00)) { FUEL_bo720Injection = TRUE; } } CLO2_vInit(); FUEL_vCalcFuelChannels(); } void FUEL_vRun(puint32 const pu32Arg) { static uint32 u32FuelRunCount = 0; static sint32 s32FuelPressureErrorSum; static uint32 u32SampleCount = 0; uint16 u16WDTVal; IOAPI_tenTriState enTriState; IOAPI_tenEHIOResource enEHIOResource; RELAY_tenBit enBit; uint32 u32Temp; sint32 s32Temp; static bool boFuelCutsActivePrev = FALSE; bool boFuelCutsActive; static bool boAirflowFMEEnable; uint32 u32FuelCutPercent = 40; CLO2_vFilterSensors(); if (0 == u32FuelRunCount % FUEL_nInjRespCalcRate) { /* Calculate the current spread for injector response */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadInjResponseIDX, NULL, NULL); /* Lookup the current value for injector response */ USER_vSVC(SYSAPI_enCalculateTable, (void*)&FUEL_tTableInjResponseIDX, NULL, NULL); /* Calculate the current spread for TAFRx */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadTAFRxIDX, NULL, NULL); /* Calculate the current spread for TAFRy */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadTAFRyIDX, NULL, NULL); /* Lookup the current value for TAFR */ USER_vSVC(SYSAPI_enCalculateMap, (void*)&FUEL_tMapTAFRIDX, NULL, NULL); /* Reset the WDT */ USER_vSVC(SYSAPI_enResetWatchdog, &u16WDTVal, NULL, NULL); } if ((TRUE == FUEL_boCalculatePending) || (FALSE == FUEL_boFuelPrimed)) { FUEL_vCyclicCalculate(); if (EH_IO_Invalid > USERCAL_stRAMCAL.u16FuelPressureSolenoidResource) { if (USERCAL_stRAMCAL.u32GDIMAPMin > MAP_tKiloPaFiltered) { FUEL_u16TFuelPressure = USERCAL_stRAMCAL.u16GDIPressureMin; } else if (USERCAL_stRAMCAL.u32GDIMAPMax < MAP_tKiloPaFiltered) { FUEL_u16TFuelPressure = USERCAL_stRAMCAL.u16GDIPressureMax; } else { FUEL_u16TFuelPressure = USERCAL_stRAMCAL.u16GDIPressureMin + (((MAP_tKiloPaFiltered - USERCAL_stRAMCAL.u32GDIMAPMin) * (USERCAL_stRAMCAL.u16GDIPressureMax - USERCAL_stRAMCAL.u16GDIPressureMin)) / (USERCAL_stRAMCAL.u32GDIMAPMax - USERCAL_stRAMCAL.u32GDIMAPMin)); } s32Temp = FUEL_tKiloPaFiltered - FUEL_u16TFuelPressure; if (0 > s32Temp) { /* accumulate the feedback error */ s32FuelPressureErrorSum += ((s32Temp * 500) / (sint32)CAM_u32RPMRaw); s32FuelPressureErrorSum = 20000 < s32FuelPressureErrorSum ? 20000 : s32FuelPressureErrorSum; s32FuelPressureErrorSum = -20000 > s32FuelPressureErrorSum ? -20000 : s32FuelPressureErrorSum; /* pressure too low */ s32Temp *= USERCAL_stRAMCAL.u16FuelPressurePGain; s32Temp += (s32FuelPressureErrorSum * USERCAL_stRAMCAL.u16FuelPressureIGain / 4); s32Temp += 10000000; } else if (2000 < s32Temp) { /* pressure more than 2000 kPa too high */ s32Temp -= 2000; /* accumulate the feedback error */ s32FuelPressureErrorSum += ((s32Temp * 500) / (sint32)CAM_u32RPMRaw); s32FuelPressureErrorSum = 20000 < s32FuelPressureErrorSum ? 20000 : s32FuelPressureErrorSum; s32FuelPressureErrorSum = -20000 > s32FuelPressureErrorSum ? -20000 : s32FuelPressureErrorSum; s32Temp *= USERCAL_stRAMCAL.u16FuelPressurePGain; s32Temp += (s32FuelPressureErrorSum * USERCAL_stRAMCAL.u16FuelPressureIGain / 4); s32Temp /= 2; s32Temp += 10000000; } else { s32Temp = 10000000; s32Temp += (s32FuelPressureErrorSum * USERCAL_stRAMCAL.u16FuelPressureIGain / 4); } /* add feedforward guesstimate */ s32Temp -= (USERCAL_stRAMCAL.u16GDIValveFF * ((CAM_u32RPMRaw * MAP_tKiloPaFiltered) / 1000000)); s32Temp += 10000 * USERCAL_stRAMCAL.u16FuelPressureControlOffset; s32Temp = (1000 * (sint32)USERCAL_stRAMCAL.u16GDIValveMin) < s32Temp ? s32Temp : (1000 * (sint32)USERCAL_stRAMCAL.u16GDIValveMin); s32Temp = (1000 * (sint32)USERCAL_stRAMCAL.u16GDIValveMax) > s32Temp ? s32Temp : (1000 * (sint32)USERCAL_stRAMCAL.u16GDIValveMax); FUEL_tFPAccumulate = s32Temp / CAM_u32RPMRaw; FUEL_tFPAccumulate -= (CAM_u32RPMRaw / 16); FUEL_tStartFPSolenoidDelay = (7000000 - 500 * CAM_u32RPMRaw) / CAM_u32RPMRaw; } } if ((TRUE == CTS_boCTSReady) && (FALSE == FUEL_boFuelPrimed)) { if ((0 == CAM_u32RPMRaw) && (TRUE == USERCAL_stRAMCAL.u8FuelPrimeEnable)) { /* Prime the injectors */ USER_vSVC(SYSAPI_enTEPMAsyncRequest, NULL, NULL, NULL); FUEL_boFuelPrimed = TRUE; } else { FUEL_boFuelPrimed = TRUE; } } else if ((2000 == u32FuelRunCount) && (FALSE == FUEL_boFuelPrimed)) { /* Finish prime */ FUEL_boFuelPrimed = TRUE; } u32FuelRunCount++; if (EH_IO_Invalid != USERCAL_stRAMCAL.enFuelPumpRelay) { if (TRUE == FUEL_boFuelPumpOn) { enEHIOResource = USERCAL_stRAMCAL.enFuelPumpRelay; enTriState = IOAPI_enHigh; if (EH_IO_IIC1_SDA > enEHIOResource) { USER_vSVC(SYSAPI_enAssertDIOResource, (void*)&enEHIOResource, (void*)&enTriState, (void*)NULL); } else { enBit = 1 << (enEHIOResource - EH_IO_IIC1_SDA); RELAYS_vOutputBit(enBit, IOAPI_enHigh == enTriState); } } else { enEHIOResource = USERCAL_stRAMCAL.enFuelPumpRelay; enTriState = IOAPI_enLow; if (EH_IO_IIC1_SDA > enEHIOResource) { USER_vSVC(SYSAPI_enAssertDIOResource, (void*)&enEHIOResource, (void*)&enTriState, (void*)NULL); } else { enBit = 1 << (enEHIOResource - EH_IO_IIC1_SDA); RELAYS_vOutputBit(enBit, IOAPI_enHigh == enTriState); } } } if (FUEL_boNewSample == TRUE) { FUEL_u32ADSamples[u32SampleCount] = FUEL_u32ADCRaw; u32SampleCount = u32SampleCount % FUEL_nSampleCount; if (0 == u32SampleCount) { FUEL_u32ADCFiltered = USERMATH_u32DiscardAndAverage32(FUEL_u32ADSamples, FUEL_nSampleCount, 2);/*CR1_1*/ FUEL_u32ADCFiltered *= 0x100; } u32Temp = ((FUEL_u32ADCFiltered / 100U) * USERCAL_stRAMCAL.s32FuelPressureSensorGain) / 10000u; if (0 <= USERCAL_stRAMCAL.s32FuelPressureSensorOffset) { FUEL_tKiloPaFiltered = u32Temp + USERCAL_stRAMCAL.s32FuelPressureSensorOffset; } else { if (u32Temp >= -USERCAL_stRAMCAL.s32FuelPressureSensorOffset) { FUEL_tKiloPaFiltered = u32Temp + USERCAL_stRAMCAL.s32FuelPressureSensorOffset; } else { FUEL_tKiloPaFiltered = 0; } } FUEL_boNewSample = FALSE; u32SampleCount++; } boFuelCutsActive = SENSORS_boGetAuxActive(SENSORS_enAUX_LAUNCH_LOW); boFuelCutsActive |= SENSORS_boGetAuxActive(SENSORS_enAUX_LAUNCH_HIGH); boFuelCutsActive |= (0x100 != TORQUE_u32FuelTorqueModifier); if (TRUE == boFuelCutsActive) { if (EST_nIgnitionReqPrimary == EST_enIgnitionTimingRequest) { /* Calculate the current spread for fuel cuts */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadFuelCutsIDX, NULL, NULL); /* Lookup the current value for fuel cuts */ USER_vSVC(SYSAPI_enCalculateTable, (void*)&FUEL_tTableFuelCutsIDX, NULL, NULL); u32FuelCutPercent = (uint32)FUEL_u16FuelCutsPercent; } else { if (EST_nIgnitionReqDSGCutsStage3 == EST_enIgnitionTimingRequest) { if (2000 < CAM_u32RPMFiltered) { if (100000 < MAP_tKiloPaFiltered) { u32FuelCutPercent = (MAP_tKiloPaFiltered - 100000) / 1000; u32FuelCutPercent = USERCAL_stRAMCAL.u16TorqueReductionMaxFuelCut > u32FuelCutPercent ? u32FuelCutPercent : USERCAL_stRAMCAL.u16TorqueReductionMaxFuelCut; } else { u32FuelCutPercent = 0; } } else { u32FuelCutPercent = 0; } } else { /* No fuel cut pre-shift */ u32FuelCutPercent = 0; } } /* Set the fuel cuts */ USER_vSVC(SYSAPI_enSetFuelCuts, &u32FuelCutPercent, &FUEL_u32FuelChannelsMask, &FUEL_u32FuelChannelsCount); } else { u32FuelCutPercent = 0; if (boFuelCutsActivePrev != boFuelCutsActive) { USER_vSVC(SYSAPI_enSetFuelCuts, &u32FuelCutPercent, &FUEL_u32FuelChannelsMask, &FUEL_u32FuelChannelsCount); } } boFuelCutsActivePrev = boFuelCutsActive; /* FME fuel cuts */ #ifdef BUILD_FME if (0 != USERCAL_stRAMCAL.u8DBSlaveConfig) { boAirflowFMEEnable = AFM_tAirFlowAFMUg < USERCAL_stRAMCAL.u32AirflowFMELimitLow ? FALSE : boAirflowFMEEnable; boAirflowFMEEnable = AFM_tAirFlowAFMUg > USERCAL_stRAMCAL.u32AirflowFMELimitHigh ? TRUE : boAirflowFMEEnable; /* Override safety airflow limit set too high > 15g/s */ if (15000000u < USERCAL_stRAMCAL.u32AirflowFMELimitHigh) boAirflowFMEEnable = TRUE; u32Temp = (u32FuelRunCount >> 4) & 0x7; boFuelCutsActive = FALSE; if (TRUE == boAirflowFMEEnable) { boFuelCutsActive |= (FME_enFaultActive == FME_enGetDiagState(FME_enPPSPair)); boFuelCutsActive |= (FME_enFaultActive == FME_enGetDiagState(FME_enPedalTransfer)); boFuelCutsActive |= (FME_enFaultActive == FME_enGetDiagState(FME_enTPSMSingle)); boFuelCutsActive |= (FME_enFaultActive == FME_enGetDiagState(FME_enPPSMSingle)); boFuelCutsActive |= (FME_enFaultActive == FME_enGetDiagState(FME_enPPSSSingle)); } if (TRUE == boFuelCutsActive) { FUEL_aboFMECutFlag[u32Temp] = TRUE; } else { FUEL_aboFMECutFlag[u32Temp] = FALSE; } } #endif //BUILD_FME } void FUEL_vCalculateFuellingValues() { FUEL_boCalculatePending = TRUE; } static void FUEL_vCyclicCalculate(void) { static bool boAFMTransientControl; static bool boFuelAFRCutoff; static uint32 u32OverrunCutCount; uint32 u32SeqIDX; uint8 u8SeqFuelBit; uint32 u32FuelCycleTimeUs; uint32 u32Temp = 0; static bool boSequentialMode; static bool boHighDuty; static uint32 u32SequentialModeCount; uint32 u32MaxFuel; uint32 u32ReturnlessPressureKpa; uint16 u16FuelFlowRate; if ((FALSE == FUEL_boFuelPrimed) && (400 > CAM_u32RPMRaw) && (TRUE == USERCAL_stRAMCAL.u8FuelPrimeEnable)) { FUEL_tTimePredictedUs[0] = CTS_u32Primer; FUEL_tTimePredictedUs[1] = CTS_u32Primer; } else { uint32 u32Temp1; uint32 u32Temp2; sint32 s32Temp; /* Calculate the current spread for AfmTF */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadAfmTFIDX, NULL, NULL); /* Lookup the current AfmTF value for AfmTF */ USER_vSVC(SYSAPI_enCalculateTable, (void*)&FUEL_tTableAfmTFIDX, NULL, NULL); /* Max delta ramp airflow */ if (AFM_tAirFlowAFMRawUg >= AFM_tAirFlowAFMUg) { u32Temp = USERCAL_stRAMCAL.u16AFMMaxCycleDeltaUgPos * 1000; if (u32Temp < (AFM_tAirFlowAFMRawUg - AFM_tAirFlowAFMUg)) { AFM_tAirFlowAFMUg += u32Temp; } else { AFM_tAirFlowAFMUg = AFM_tAirFlowAFMRawUg; } } else { u32Temp = USERCAL_stRAMCAL.u16AFMMaxCycleDeltaUgNeg * 1000; if (u32Temp < (AFM_tAirFlowAFMUg - AFM_tAirFlowAFMRawUg)) { if (AFM_tAirFlowAFMUg > u32Temp) { AFM_tAirFlowAFMUg -= u32Temp; } else { AFM_tAirFlowAFMUg = 0; } } else { AFM_tAirFlowAFMUg = AFM_tAirFlowAFMRawUg; } } if (0 != USERCAL_stRAMCAL.u8VariableFuelPressureEnable) { /* Calculate the current spread for Fuel Flow */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadFuelFlowIDX, NULL, NULL); /* Lookup the current fuel flow rate */ USER_vSVC(SYSAPI_enCalculateTable, (void*)&FUEL_tTableFuelFlowIDX, NULL, NULL); } boAFMTransientControl = USERCAL_stRAMCAL.u32AFMTransientControlRPMLimit > CAM_u32RPMRaw ? TRUE : boAFMTransientControl; boAFMTransientControl = (USERCAL_stRAMCAL.u32AFMTransientControlRPMLimit + 100) < CAM_u32RPMRaw ? FALSE : boAFMTransientControl; if ((USERCAL_stRAMCAL.u16RPMRunThreshold < CAM_u32RPMRaw) || (USERCAL_stRAMCAL.u8CrankingAirflowEnable == FALSE)) { if ((TRUE == USERCAL_stRAMCAL.u8EnableBackupAirflowTransients) && (TRUE == boAFMTransientControl)) { if (AFM_tAirFlowAFMUg > AFM_tAirFlowBackupUg) { u32Temp1 = (AFM_tAirFlowBackupUg * 9) / 8; FUEL_tPredictedAirFlowUg = u32Temp > AFM_tAirFlowAFMUg ? AFM_tAirFlowAFMUg : u32Temp; } else { u32Temp1 = (AFM_tAirFlowBackupUg * 7) / 8; FUEL_tPredictedAirFlowUg = u32Temp > AFM_tAirFlowAFMUg ? u32Temp : AFM_tAirFlowAFMUg; } } else { if (USERCAL_stRAMCAL.u32SpeedDensityAFMTPSLim > TPS_tThetaFiltered) /* At small throttle angles */ { if (TRUE == USERCAL_stRAMCAL.u8EnableAFMPrimaryInputClosed) { FUEL_tPredictedAirFlowUg = AFM_tAirFlowAFMUg; } else if ((FALSE == USERCAL_stRAMCAL.u8EnableAFMPrimaryInputClosed) && (TRUE == USERCAL_stRAMCAL.u8EnableAFMPrimaryInputOpen)) { u32Temp1 = TPS_tThetaFiltered * (AFM_tAirFlowAFMUg / USERCAL_stRAMCAL.u32SpeedDensityAFMTPSLim); u32Temp2 = (USERCAL_stRAMCAL.u32SpeedDensityAFMTPSLim - TPS_tThetaFiltered) * (AFM_tAirFlowVEUg / USERCAL_stRAMCAL.u32SpeedDensityAFMTPSLim); FUEL_tPredictedAirFlowUg = u32Temp1 + u32Temp2; } else { FUEL_tPredictedAirFlowUg = AFM_tAirFlowVEUg; } } else { if (TRUE == USERCAL_stRAMCAL.u8EnableAFMPrimaryInputOpen) { FUEL_tPredictedAirFlowUg = AFM_tAirFlowAFMUg; } else { FUEL_tPredictedAirFlowUg = AFM_tAirFlowVEUg; } } } } else { /* Calculate the current spread for cranking airflow */ USER_vSVC(SYSAPI_enCalculateSpread, (void*)&FUEL_tSpreadCrankingAirflowIDX, NULL, NULL); /* Lookup the current value for cranking airflow */ USER_vSVC(SYSAPI_enCalculateTable, (void*)&FUEL_tTableCrankingAirflowIDX, NULL, NULL); FUEL_tPredictedAirFlowUg = 1000 * FUEL_u16CrankingAirflow; } if (TRUE == FUEL_boFuelPrimed) { CLO2_vRun(); IAC_vCallBack(NULL); } /* Add manifold capacitance transitory airflow */ if (500000 < MAP_s32ManDeltaChargeMassPerSUg) { FUEL_tPredictedAirFlowUg += (uint32)MAP_s32ManDeltaChargeMassPerSUg; } else if ((-500000 > MAP_s32ManDeltaChargeMassPerSUg) && (FUEL_tPredictedAirFlowUg > -MAP_s32ManDeltaChargeMassPerSUg)) { FUEL_tPredictedAirFlowUg += (uint32)MAP_s32ManDeltaChargeMassPerSUg; } FUEL_tPredictedFuelFlowUg = (10u * FUEL_tPredictedAirFlowUg) / FUEL_u16TAFR; /* Add CTS and ATS correction */ FUEL_tPredictedFuelFlowUg = ((FUEL_tPredictedFuelFlowUg / 10UL) * (CTS_u32FuelMultiplier + ATS_u32FuelMultiplier - 1000)) / 100UL; /* Add TPS moving enrichment */ FUEL_tPredictedFuelFlowUg = ((FUEL_tPredictedFuelFlowUg / 10UL) * (TPS_u32MovingTPSEnrichment)) / 100UL; /* Add TPS tip in enrichment */ FUEL_tPredictedFuelFlowUg = ((FUEL_tPredictedFuelFlowUg / 10UL) * (TPS_u32TipInEnrichment)) / 100UL; s32Temp = (sint32)FUEL_tPredictedFuelFlowUg + FILM_s32FilmLoadUgDeltaApplied; if (0 <= s32Temp) { FUEL_tPredictedFuelFlowUg = (uint32)s32Temp; } else { FUEL_tPredictedFuelFlowUg = 0; } /* Add STT trim */ FUEL_tPredictedFuelFlowPerInjectionNg[0] = (12 / USERCAL_stRAMCAL.u8InjDivide) * (100 * FUEL_tPredictedFuelFlowUg / CAM_u32RPMRaw);//was filtered!! FUEL_tPredictedFuelFlowPerInjectionNg[0] *= CLO2_u32STT[0]; FUEL_tPredictedFuelFlowPerInjectionNg[1] = (12 / USERCAL_stRAMCAL.u8InjDivide) * (100 * FUEL_tPredictedFuelFlowUg / CAM_u32RPMRaw);//was filtered!! FUEL_tPredictedFuelFlowPerInjectionNg[1] *= CLO2_u32STT[1]; /* Add fuel pressure trim */ if ((USERCAL_stRAMCAL.u8ReturnlessEnable == TRUE) && (FALSE == USERCAL_stRAMCAL.u8VariableFuelPressureEnable)) { u32ReturnlessPressureKpa = 1000 * USERCAL_stRAMCAL.u16ReturnlessPressureKPa; u32Temp = MAP_tKiloPaFiltered + u32ReturnlessPressureKpa; u32Temp /= (101 + (u32ReturnlessPressureKpa / 1000)); u32Temp = 1000 > u32Temp ? u32Temp : 999; u32Temp = USERMATH_u32GetSquareRoot(u32Temp); FUEL_tPredictedFuelFlowPerInjectionNg[0] /= 1000; FUEL_tPredictedFuelFlowPerInjectionNg[0] *= u32Temp; FUEL_tPredictedFuelFlowPerInjectionNg[1] /= 1000; FUEL_tPredictedFuelFlowPerInjectionNg[1] *= u32Temp; } if (FALSE == USERCAL_stRAMCAL.u8VariableFuelPressureEnable) { u16FuelFlowRate = (uint32)USERCAL_stRAMCAL.u16InjFlowRate; } else { u16FuelFlowRate = FUEL_u16FuelFlowRate; } u32Temp = (uint32)USERCAL_stRAMCAL.u8CylCount * u16FuelFlowRate; FUEL_tTimePredictedUs[0] = FUEL_tPredictedFuelFlowPerInjectionNg[0] / u32Temp; FUEL_tTimePredictedUs[1] = FUEL_tPredictedFuelFlowPerInjectionNg[1] / u32Temp; /* Trim short pulse */ if (USERCAL_stRAMCAL.u16MinLinearFuelPulse > FUEL_tTimePredictedUs[0]) { FUEL_tTimePredictedUsInput = FUEL_tTimePredictedUs[0]; (void)BOOSTED_boIndexAndCalculateTable(FUEL_tSpreadInjShortOpeningIDX, FUEL_tTableInjShortOpeningIDX); /* Pragmatic workaround - predicted event < 1.6 ms */ if (USERCAL_stRAMCAL.aUserInjShortOpeningTable[10] > FUEL_tTimePredictedUs[0]) { u32Temp = USERCAL_stRAMCAL.aUserInjShortOpeningTable[10] - FUEL_tTimePredictedShortOpeningUs; u32Temp *= (BVM_tBattVolts - 4000); u32Temp /= 11000; FUEL_tTimePredictedShortOpeningUs = USERCAL_stRAMCAL.aUserInjShortOpeningTable[10] - u32Temp; } FUEL_tTimePredictedUs[0] = FUEL_tTimePredictedShortOpeningUs; } if (USERCAL_stRAMCAL.u16MinLinearFuelPulse > FUEL_tTimePredictedUs[1]) { FUEL_tTimePredictedUsInput = FUEL_tTimePredictedUs[1]; (void)BOOSTED_boIndexAndCalculateTable(FUEL_tSpreadInjShortOpeningIDX, FUEL_tTableInjShortOpeningIDX); /* Pragmatic workaround - predicted event < 1.6 ms */ if (USERCAL_stRAMCAL.aUserInjShortOpeningTable[10] > FUEL_tTimePredictedUs[1]) { u32Temp = USERCAL_stRAMCAL.aUserInjShortOpeningTable[10] - FUEL_tTimePredictedShortOpeningUs; u32Temp *= (BVM_tBattVolts - 4000); u32Temp /= 11000; FUEL_tTimePredictedShortOpeningUs = USERCAL_stRAMCAL.aUserInjShortOpeningTable[10] - u32Temp; } FUEL_tTimePredictedUs[1] = FUEL_tTimePredictedShortOpeningUs; } boFuelAFRCutoff = (FUEL_u16TAFR < USERCAL_stRAMCAL.u16AFRReinstate) ? FALSE : boFuelAFRCutoff; boFuelAFRCutoff = (FUEL_u16TAFR > USERCAL_stRAMCAL.u16AFRCutoff) ? TRUE : boFuelAFRCutoff; } FUEL_tTimePredictedUs[0] = TRUE == boFuelAFRCutoff ? 0 : FUEL_tTimePredictedUs[0]; FUEL_tTimePredictedUs[1] = TRUE == boFuelAFRCutoff ? 0 : FUEL_tTimePredictedUs[1]; /* Apply DSG torque reduce trim */ if ((EST_nIgnitionReqDSGStage1 == EST_enIgnitionTimingRequest) || (EST_nIgnitionReqDSGStage2 == EST_enIgnitionTimingRequest) || (EST_nIgnitionReqDSGCutsStage3 == EST_enIgnitionTimingRequest)) { FUEL_tTimePredictedUs[0] = TORQUE_u32FuelTorqueModifier * FUEL_tTimePredictedUs[0] / 0x100; FUEL_tTimePredictedUs[1] = TORQUE_u32FuelTorqueModifier * FUEL_tTimePredictedUs[1] / 0x100; } /* Increment fuel consumed for BC */ FUEL_u32FuelConsumed += FUEL_tTimePredictedUs[0]; /* Manage overrun fuel cut */ #ifdef BUILD_BSP_VSS_CAN if ((TRUE == MAP_boHighVacuum) && (TRUE == TPS_boThrottleClosed) && (TRUE == IAC_boOverrunCutRPMEnable) && (0 != SENSORS_u16CANVSS) && (0xffff != SENSORS_u16CANVSS)) #else if ((TRUE == MAP_boHighVacuum) && (TRUE == TPS_boThrottleClosed) && (TRUE == IAC_boOverrunCutRPMEnable)) #endif { u32OverrunCutCount = 40 > u32OverrunCutCount ? u32OverrunCutCount + 1 : u32OverrunCutCount; for (u32SeqIDX = 0; u32SeqIDX < 8; u32SeqIDX++) { FUEL_aboSeqOverrunCutFlag[u32SeqIDX] = u32OverrunCutCount > (10 + (u32SeqIDX << 3)) ? TRUE : FALSE; } } else if (TRUE == IAC_boOverrunCutRPMEnable) { u32OverrunCutCount = 3 < u32OverrunCutCount ? u32OverrunCutCount - 4 : 0; for (u32SeqIDX = 0; u32SeqIDX < 8; u32SeqIDX++) { FUEL_aboSeqOverrunCutFlag[u32SeqIDX] = u32OverrunCutCount > (10 + (u32SeqIDX << 3)) ? TRUE : FALSE; } } else { u32OverrunCutCount = 0; for (u32SeqIDX = 0; u32SeqIDX < 8; u32SeqIDX++) { FUEL_aboSeqOverrunCutFlag[u32SeqIDX] = FALSE; } } u8SeqFuelBit = 1; /* Apply overrun and over-speed fuel cuts */ for (u32SeqIDX = 0; u32SeqIDX < 8; u32SeqIDX++) { if ((TRUE == FUEL_aboSeqRevCutFlag[u32SeqIDX]) || #ifdef BUILD_FME (TRUE == FUEL_aboFMECutFlag[u32SeqIDX]) || #endif //BUILD_FME (TRUE == FUEL_aboSeqOverrunCutFlag[u32SeqIDX])) { FUEL_tTimeHoldUs[u32SeqIDX] = 600; FUEL_tTimeHold[u32SeqIDX] = 400; } else { CPU_xEnterCritical(); if (0 == (u8SeqFuelBit & USERCAL_stRAMCAL.u8SeqFuelAssign)) { FUEL_tTimeHoldUs[u32SeqIDX] = FUEL_tTimePredictedUs[0] + (uint32)FUEL_u16InjResponse; FUEL_tTimeHoldUs[u32SeqIDX] = (uint32)((sint32)FUEL_tTimeHoldUs[u32SeqIDX] + USERCAL_stRAMCAL.s16SequenceFuelOffset[u32SeqIDX]); FUEL_tTimeHold[u32SeqIDX] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[u32SeqIDX]); } else { FUEL_tTimeHoldUs[u32SeqIDX] = FUEL_tTimePredictedUs[1] + (uint32)FUEL_u16InjResponse; FUEL_tTimeHoldUs[u32SeqIDX] = (uint32)((sint32)FUEL_tTimeHoldUs[u32SeqIDX] + USERCAL_stRAMCAL.s16SequenceFuelOffset[u32SeqIDX]); FUEL_tTimeHold[u32SeqIDX] = FUEL_xUsToSlowTicks(FUEL_tTimeHoldUs[u32SeqIDX]); } CPU_xExitCritical(); } u8SeqFuelBit *= 2; } FUEL_boCalculatePending = FALSE; u32MaxFuel = MAX(FUEL_tTimeHoldUs[0], FUEL_tTimeHoldUs[1]); u32MaxFuel = MAX(u32MaxFuel, FUEL_tTimeHoldUs[2]); u32MaxFuel = MAX(u32MaxFuel, FUEL_tTimeHoldUs[3]); u32FuelCycleTimeUs = 120000000 / (CAM_u32RPMRaw * USERCAL_stRAMCAL.u8InjDivide); u32Temp = (0x10000 * u32MaxFuel) / u32FuelCycleTimeUs; /* Condition the high duty flag */ boHighDuty = 40000 < u32Temp ? TRUE : boHighDuty; boHighDuty = 30000 > u32Temp ? FALSE : boHighDuty; /* Clear sequential counter */ if (250 > CAM_u32RPMFiltered) { u32SequentialModeCount = 0; } /* Check sequential mode */ if ((350 > CAM_u32RPMFiltered) || (true == boHighDuty) || (FALSE == FUEL_bo720Injection)) { u32SequentialModeCount = 0 < u32SequentialModeCount ? u32SequentialModeCount - 1 : 0; } else { u32SequentialModeCount = FUEL_nSeqModeCountLimit > u32SequentialModeCount ? u32SequentialModeCount + 1 : FUEL_nSeqModeCountLimit; } /* Condition the sequential flag */ boSequentialMode = FUEL_nSeqModeCountLimit <= u32SequentialModeCount ? TRUE : boSequentialMode; boSequentialMode = 0 == u32SequentialModeCount ? FALSE : boSequentialMode; if (TRUE == boSequentialMode) { if (49500 > u32Temp) { /* Assign the end of event angles */ FUEL_tStartHoldFraction[0] = 50000 - u32Temp; FUEL_tStartHoldFraction[1] = 50000 - u32Temp; FUEL_tStartHoldFraction[2] = 50000 - u32Temp; FUEL_tStartHoldFraction[3] = 50000 - u32Temp; } else { /* Assign the end of event angles */ FUEL_tStartHoldFraction[0] = 500; FUEL_tStartHoldFraction[1] = 500; FUEL_tStartHoldFraction[2] = 500; FUEL_tStartHoldFraction[3] = 500; } } else { /* Assign the start of event angles */ //FUEL_tStartHoldFraction[0] = 1500; //FUEL_tStartHoldFraction[1] = 1500; //FUEL_tStartHoldFraction[2] = 1500; //FUEL_tStartHoldFraction[3] = 1500; if (2000 > CAM_u32RPMRaw) { FUEL_tStartHoldFraction[0] = 2000 + ((2000 - CAM_u32RPMRaw) << 3); FUEL_tStartHoldFraction[1] = 2000 + ((2000 - CAM_u32RPMRaw) << 3); FUEL_tStartHoldFraction[2] = 2000 + ((2000 - CAM_u32RPMRaw) << 3); FUEL_tStartHoldFraction[3] = 2000 + ((2000 - CAM_u32RPMRaw) << 3); } else { FUEL_tStartHoldFraction[0] = 2000; FUEL_tStartHoldFraction[1] = 2000; FUEL_tStartHoldFraction[2] = 2000; FUEL_tStartHoldFraction[3] = 2000; } } } void FUEL_vTerminate(puint32 const pu32Arg) { } void FUEL_vCallBack(puint32 const pu32Arg) { } static void FUEL_vTEPMCallBack(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_ttEventTime tEventTime) { //FUEL_boFuelPrimed = TRUE; } static void FUEL_vADCCallBack(IOAPI_tenEHIOResource enEHIOResource, uint32 u32ADCResult) { FUEL_u32ADCRaw = MIN(u32ADCResult, SENSORS_nSENSORADMAX); FUEL_boNewSample = TRUE; } static void FUEL_vCalcFuelChannels(void) { uint32 u32IDX; uint32 u32Mask = 1; FUEL_u32FuelChannelsCount = 0; for (u32IDX = 0; u32IDX < 32; u32IDX++) { if (0 != (u32Mask & FUEL_u32FuelChannelsMask)) { FUEL_u32FuelChannelsCount++; } u32Mask *= 2; } } #endif //BUILD_USER