2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file engine.h
|
|
|
|
*
|
|
|
|
* @date May 21, 2014
|
2015-12-31 13:02:30 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2016
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
#ifndef ENGINE_H_
|
|
|
|
#define ENGINE_H_
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "engine_configuration.h"
|
|
|
|
#include "rpm_calculator.h"
|
|
|
|
|
|
|
|
#include "global.h"
|
|
|
|
#include "engine_configuration.h"
|
|
|
|
#include "event_registry.h"
|
|
|
|
#include "trigger_structure.h"
|
|
|
|
#include "table_helper.h"
|
|
|
|
#include "listener_array.h"
|
|
|
|
#include "accel_enrichment.h"
|
2015-09-13 14:02:44 -07:00
|
|
|
#include "trigger_central.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-01-23 15:01:40 -08:00
|
|
|
#define MOCK_ADC_SIZE 16
|
|
|
|
|
|
|
|
class MockAdcState {
|
|
|
|
public:
|
|
|
|
MockAdcState();
|
|
|
|
bool hasMockAdc[MOCK_ADC_SIZE];
|
|
|
|
int fakeAdcValues[MOCK_ADC_SIZE];
|
|
|
|
|
|
|
|
void setMockVoltage(int hwChannel, float voltage);
|
|
|
|
int getMockAdcValue(int hwChannel);
|
|
|
|
};
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* This class knows about when to inject fuel
|
|
|
|
*/
|
|
|
|
class FuelSchedule {
|
|
|
|
public:
|
|
|
|
FuelSchedule();
|
|
|
|
/**
|
|
|
|
* this method schedules all fuel events for an engine cycle
|
|
|
|
*/
|
|
|
|
void addFuelEvents(injection_mode_e mode DECLARE_ENGINE_PARAMETER_S);
|
|
|
|
|
2016-01-24 22:02:55 -08:00
|
|
|
InjectionEventList injectionEvents;
|
2016-01-24 23:03:01 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* This is a performance optimization for https://sourceforge.net/p/rusefi/tickets/64/
|
|
|
|
* TODO: better data structure? better algorithm?
|
|
|
|
*/
|
|
|
|
uint8_t hasEvents[PWM_PHASE_MAX_COUNT];
|
|
|
|
/**
|
|
|
|
* How many trigger events have injection? This depends on fuel strategy & trigger shape
|
|
|
|
*/
|
|
|
|
int eventsCount;
|
|
|
|
private:
|
|
|
|
void clear();
|
2016-01-11 14:01:33 -08:00
|
|
|
void registerInjectionEvent(int injectorIndex, float angle, bool isSimultanious DECLARE_ENGINE_PARAMETER_S);
|
2015-07-10 06:01:56 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2015-12-21 17:02:32 -08:00
|
|
|
* This structure is still separate from Engine simply because this goes into CCM memory and Engine is in main memory
|
|
|
|
* todo: re-arrange global variables to put something else into CCM so that this can go into main
|
|
|
|
* so that this could be mergeed into Engine
|
|
|
|
* todo: move these fields into Engine class, eliminate this class
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
class engine_configuration2_s {
|
|
|
|
public:
|
|
|
|
engine_configuration2_s();
|
|
|
|
|
|
|
|
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
|
2016-01-25 00:02:33 -08:00
|
|
|
FuelSchedule injectionEvents0;
|
|
|
|
FuelSchedule injectionEvents1;
|
|
|
|
FuelSchedule *injectionEvents;
|
|
|
|
FuelSchedule *processing;
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif
|
|
|
|
|
2016-01-24 23:03:01 -08:00
|
|
|
OutputSignal fuelActuators[MAX_INJECTION_OUTPUT_COUNT];
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
float fsioLastValue[LE_COMMAND_COUNT];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* We are alternating two event lists in order to avoid a potential issue around revolution boundary
|
|
|
|
* when an event is scheduled within the next revolution.
|
|
|
|
*/
|
|
|
|
IgnitionEventList ignitionEvents[2];
|
|
|
|
};
|
|
|
|
|
|
|
|
class ThermistorMath {
|
|
|
|
public:
|
|
|
|
ThermistorMath();
|
|
|
|
thermistor_curve_s curve;
|
|
|
|
void init(thermistor_conf_s *config);
|
|
|
|
private:
|
|
|
|
thermistor_conf_s currentConfig;
|
|
|
|
};
|
|
|
|
|
|
|
|
class EngineState {
|
|
|
|
public:
|
|
|
|
EngineState();
|
2016-01-01 14:02:49 -08:00
|
|
|
void periodicFastCallback(DECLARE_ENGINE_PARAMETER_F);
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* WIP: accessing these values here would be a performance optimization since log() function needed for
|
|
|
|
* thermistor logic is relatively heavy
|
|
|
|
* Access to these two fields is not synchronized in any way - that should work since float read/write are atomic.
|
|
|
|
*/
|
|
|
|
float iat;
|
|
|
|
float clt;
|
|
|
|
|
2015-12-02 17:10:06 -08:00
|
|
|
float airMass;
|
|
|
|
|
2016-01-01 14:02:49 -08:00
|
|
|
float engineNoiseHipLevel;
|
|
|
|
|
2015-08-23 20:02:37 -07:00
|
|
|
/**
|
|
|
|
* that's fuel in tank - just a gauge
|
|
|
|
*/
|
2015-12-26 09:03:13 -08:00
|
|
|
percent_t fuelTankGauge;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
ThermistorMath iatCurve;
|
|
|
|
ThermistorMath cltCurve;
|
|
|
|
|
2015-09-06 18:02:46 -07:00
|
|
|
/**
|
|
|
|
* MAP averaging angle start, in relation to 'mapAveragingSchedulingAtIndex' trigger index index
|
|
|
|
*/
|
|
|
|
angle_t mapAveragingStart[INJECTION_PIN_COUNT];
|
2015-07-10 06:01:56 -07:00
|
|
|
angle_t mapAveragingDuration;
|
|
|
|
|
|
|
|
// spark-related
|
|
|
|
floatms_t sparkDwell;
|
|
|
|
angle_t timingAdvance;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ignition dwell duration as crankshaft angle
|
|
|
|
*/
|
|
|
|
angle_t dwellAngle;
|
|
|
|
|
|
|
|
// fuel-related;
|
|
|
|
float iatFuelCorrection;
|
|
|
|
float cltFuelCorrection;
|
|
|
|
float injectorLag;
|
|
|
|
|
|
|
|
float baroCorrection;
|
|
|
|
|
|
|
|
// speed density
|
|
|
|
float tChargeK;
|
|
|
|
float currentVE;
|
|
|
|
float targerAFR;
|
|
|
|
|
2015-12-02 17:10:06 -08:00
|
|
|
/**
|
|
|
|
* pre-calculated value from simple fuel lookup
|
|
|
|
*/
|
2016-01-02 22:01:37 -08:00
|
|
|
floatms_t baseTableFuel;
|
2015-12-02 17:10:06 -08:00
|
|
|
/**
|
2016-01-02 22:01:37 -08:00
|
|
|
* fuel injection duration regardless of fuel logic mode
|
2015-12-02 17:10:06 -08:00
|
|
|
*/
|
2016-01-02 22:01:37 -08:00
|
|
|
floatms_t baseFuel;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2015-12-26 09:03:13 -08:00
|
|
|
/**
|
2016-01-02 22:01:37 -08:00
|
|
|
* Fuel with CLT, IAT and TPS acceleration corrections, as squirt duration.
|
2015-12-26 09:03:13 -08:00
|
|
|
*/
|
2016-01-02 22:01:37 -08:00
|
|
|
floatms_t runningFuel;
|
2015-12-26 09:03:13 -08:00
|
|
|
|
2016-01-30 19:03:36 -08:00
|
|
|
/**
|
|
|
|
* TPS acceleration: extra fuel amount
|
|
|
|
*/
|
2016-01-02 22:01:37 -08:00
|
|
|
floatms_t tpsAccelEnrich;
|
2015-12-26 09:03:13 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
angle_t injectionOffset;
|
2016-01-23 15:01:40 -08:00
|
|
|
|
2016-01-26 17:02:45 -08:00
|
|
|
#if EFI_ENABLE_MOCK_ADC || defined(__DOXYGEN__)
|
2016-01-23 15:01:40 -08:00
|
|
|
MockAdcState mockAdcState;
|
2016-01-26 17:02:45 -08:00
|
|
|
#endif /* EFI_ENABLE_MOCK_ADC */
|
2015-07-10 06:01:56 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
class RpmCalculator;
|
|
|
|
|
|
|
|
#define MAF_DECODING_CACHE_SIZE 256
|
|
|
|
|
|
|
|
#define MAF_DECODING_CACHE_MULT (MAF_DECODING_CACHE_SIZE / 5.0)
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
uint32_t beforeMainTrigger;
|
|
|
|
uint32_t mainTriggerCallbackTime;
|
|
|
|
|
|
|
|
uint32_t beforeIgnitionMath;
|
|
|
|
uint32_t ignitionMathTime;
|
|
|
|
|
|
|
|
uint32_t beforeIgnitionSch;
|
|
|
|
uint32_t ignitionSchTime;
|
|
|
|
|
|
|
|
uint32_t beforeInjectonSch;
|
|
|
|
uint32_t injectonSchTime;
|
|
|
|
|
|
|
|
uint32_t beforeZeroTest;
|
|
|
|
uint32_t zeroTestTime;
|
|
|
|
|
|
|
|
uint32_t beforeAdvance;
|
|
|
|
uint32_t advanceLookupTime;
|
|
|
|
|
|
|
|
uint32_t beforeFuelCalc;
|
|
|
|
uint32_t fuelCalcTime;
|
|
|
|
|
|
|
|
uint32_t beforeMapAveragingCb;
|
|
|
|
uint32_t mapAveragingCbTime;
|
|
|
|
|
|
|
|
uint32_t beforeHipCb;
|
|
|
|
uint32_t hipCbTime;
|
|
|
|
|
|
|
|
uint32_t beforeRpmCb;
|
|
|
|
uint32_t rpmCbTime;
|
|
|
|
} monitoring_timestamps_s;
|
|
|
|
|
|
|
|
class Engine;
|
|
|
|
|
|
|
|
typedef void (*configuration_callback_t)(Engine*);
|
|
|
|
|
|
|
|
class Engine {
|
|
|
|
public:
|
|
|
|
Engine(persistent_config_s *config);
|
2016-01-24 23:03:01 -08:00
|
|
|
void init(persistent_config_s *config);
|
2016-01-25 09:01:30 -08:00
|
|
|
void prepareFuelSchedule(DECLARE_ENGINE_PARAMETER_F);
|
|
|
|
|
2016-01-26 20:01:44 -08:00
|
|
|
/**
|
|
|
|
* That's the list of pending spark firing events
|
|
|
|
*/
|
|
|
|
IgnitionEvent *iHead;
|
2016-01-30 19:03:36 -08:00
|
|
|
/**
|
|
|
|
* this is based on isEngineChartEnabled and engineSnifferRpmThreshold settings
|
|
|
|
*/
|
|
|
|
bool isEngineChartEnabled;
|
|
|
|
/**
|
|
|
|
* this is based on sensorChartMode and sensorSnifferRpmThreshold settings
|
|
|
|
*/
|
|
|
|
sensor_chart_e sensorChartMode;
|
2016-01-31 16:01:34 -08:00
|
|
|
/**
|
|
|
|
* based on current RPM and isAlternatorControlEnabled setting
|
|
|
|
*/
|
|
|
|
bool isAlternatorControlEnabled;
|
2016-01-26 20:01:44 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
RpmCalculator rpmCalculator;
|
|
|
|
persistent_config_s *config;
|
|
|
|
engine_configuration_s *engineConfiguration;
|
|
|
|
engine_configuration2_s *engineConfiguration2;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this is about 'stopengine' command
|
|
|
|
*/
|
|
|
|
efitick_t stopEngineRequestTimeNt;
|
|
|
|
|
2016-01-30 19:03:36 -08:00
|
|
|
/**
|
|
|
|
* always 360 or 720, never zero
|
|
|
|
*/
|
2016-01-14 21:01:42 -08:00
|
|
|
angle_t engineCycle;
|
|
|
|
|
2015-12-31 10:02:19 -08:00
|
|
|
AccelEnrichmemnt engineLoadAccelEnrichment;
|
2015-07-10 06:01:56 -07:00
|
|
|
AccelEnrichmemnt tpsAccelEnrichment;
|
|
|
|
|
2015-09-13 14:02:44 -07:00
|
|
|
TriggerCentral triggerCentral;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
2015-08-23 20:02:37 -07:00
|
|
|
* Fuel injection duration for current engine cycle, without wall wetting
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
floatms_t fuelMs;
|
2016-01-02 22:01:37 -08:00
|
|
|
/**
|
|
|
|
* fuel injection time correction to account for wall wetting effect, for current cycle
|
|
|
|
*/
|
2015-09-02 18:03:43 -07:00
|
|
|
floatms_t wallFuelCorrection;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2015-08-23 20:02:37 -07:00
|
|
|
/**
|
|
|
|
* This one with wall wetting accounted for, used for logging.
|
|
|
|
*/
|
|
|
|
floatms_t actualLastInjection;
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
void periodicFastCallback(DECLARE_ENGINE_PARAMETER_F);
|
2016-01-01 14:02:49 -08:00
|
|
|
void updateSlowSensors(DECLARE_ENGINE_PARAMETER_F);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-01-11 14:01:33 -08:00
|
|
|
bool clutchUpState;
|
|
|
|
bool clutchDownState;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isRunningPwmTest;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Are we experiencing knock right now?
|
|
|
|
*/
|
2016-01-11 14:01:33 -08:00
|
|
|
bool knockNow;
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* Have we experienced knock since engine was started?
|
|
|
|
*/
|
2016-01-11 14:01:33 -08:00
|
|
|
bool knockEver;
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* KnockCount is directly proportional to the degrees of ignition
|
|
|
|
* advance removed
|
|
|
|
*/
|
|
|
|
int knockCount;
|
|
|
|
|
2015-07-11 13:01:31 -07:00
|
|
|
float knockVolts;
|
|
|
|
|
2016-01-11 14:01:33 -08:00
|
|
|
bool knockDebug;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
efitimeus_t timeOfLastKnockEvent;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* are we running any kind of functional test? this affect
|
|
|
|
* some areas
|
|
|
|
*/
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isTestMode;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
TriggerShape triggerShape;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* pre-calculated offset for given sequence index within engine cycle
|
|
|
|
* (not cylinder ID)
|
|
|
|
* todo: better name?
|
|
|
|
*/
|
|
|
|
angle_t angleExtra[IGNITION_PIN_COUNT];
|
|
|
|
/**
|
|
|
|
* pre-calculated reference to which output pin should be used for
|
|
|
|
* given sequence index within engine cycle
|
2016-01-16 14:02:38 -08:00
|
|
|
* todo: update documentation
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2016-01-16 14:02:38 -08:00
|
|
|
int ignitionPin[IGNITION_PIN_COUNT];
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
void onTriggerEvent(efitick_t nowNt);
|
|
|
|
EngineState engineState;
|
|
|
|
efitick_t lastTriggerEventTimeNt;
|
|
|
|
|
|
|
|
/**
|
2016-01-22 16:01:28 -08:00
|
|
|
* Global injector lag + injectorLag(VBatt)
|
|
|
|
*
|
2015-07-10 06:01:56 -07:00
|
|
|
* this value depends on a slow-changing VBatt value, so
|
|
|
|
* we update it once in a while
|
|
|
|
*/
|
|
|
|
float injectorLagMs;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This coefficient translates ADC value directly into voltage adjusted according to
|
|
|
|
* voltage divider configuration. This is a future (?) performance optimization.
|
|
|
|
*/
|
|
|
|
float adcToVoltageInputDividerCoefficient;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This field is true if we are in 'cylinder cleanup' state right now
|
|
|
|
* see isCylinderCleanupEnabled
|
|
|
|
*/
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isCylinderCleanupMode;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* value of 'triggerShape.getLength()'
|
|
|
|
* pre-calculating this value is a performance optimization
|
|
|
|
*/
|
|
|
|
int engineCycleEventCount;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* fast spark dwell time interpolation helper
|
|
|
|
* todo: finish the implementation and
|
|
|
|
*/
|
|
|
|
Table2D<DWELL_CURVE_SIZE> sparkTable;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* fast kg/hour MAF decoding lookup table with ~0.2 volt step
|
|
|
|
* This table is build based on MAF decoding curve
|
|
|
|
*/
|
|
|
|
float mafDecodingLookup[MAF_DECODING_CACHE_SIZE];
|
|
|
|
|
|
|
|
void preCalculate();
|
|
|
|
void addConfigurationListener(configuration_callback_t callback);
|
|
|
|
|
|
|
|
void watchdog();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* here we have all the listeners which should be notified about a configuration
|
|
|
|
* change
|
|
|
|
*/
|
|
|
|
IntListenerArray configurationListeners;
|
|
|
|
|
|
|
|
monitoring_timestamps_s m;
|
|
|
|
|
|
|
|
void knockLogic(float knockVolts);
|
|
|
|
void printKnockState(void);
|
|
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* By the way:
|
|
|
|
* 'cranking' means engine is not stopped and the rpm are below crankingRpm
|
|
|
|
* 'running' means RPM are above crankingRpm
|
|
|
|
* 'spinning' means the engine is not stopped
|
|
|
|
*/
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isSpinning;
|
|
|
|
bool stopPins();
|
2015-07-10 06:01:56 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 6 crossing over 50% TPS means pressing and releasing three times
|
|
|
|
*/
|
|
|
|
#define PUMPS_TO_PRIME 6
|
|
|
|
|
|
|
|
class StartupFuelPumping {
|
|
|
|
public:
|
|
|
|
StartupFuelPumping();
|
|
|
|
void update(DECLARE_ENGINE_PARAMETER_F);
|
|
|
|
bool isTpsAbove50;
|
|
|
|
int pumpsCounter;
|
|
|
|
private:
|
|
|
|
void setPumpsCounter(engine_configuration_s *engineConfiguration, int newValue);
|
|
|
|
};
|
|
|
|
|
|
|
|
void prepareShapes(DECLARE_ENGINE_PARAMETER_F);
|
|
|
|
void resetConfigurationExt(Logging * logger, engine_type_e engineType DECLARE_ENGINE_PARAMETER_S);
|
|
|
|
void applyNonPersistentConfiguration(Logging * logger DECLARE_ENGINE_PARAMETER_S);
|
|
|
|
void prepareOutputSignals(DECLARE_ENGINE_PARAMETER_F);
|
|
|
|
|
|
|
|
#endif /* ENGINE_H_ */
|