mirror of https://github.com/FOME-Tech/fome-fw.git
extract injection refactoring from #215
This commit is contained in:
parent
537ed44b74
commit
e09ed790eb
|
@ -156,7 +156,7 @@ const trigger_state_primary_s* getLiveData(size_t) {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
const wall_fuel_state_s* getLiveData(size_t) {
|
const wall_fuel_state_s* getLiveData(size_t) {
|
||||||
return &engine->injectionEvents.elements[0].wallFuel;
|
return &engine->injectionEvents.elements[0].getWallFuel();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -541,7 +541,7 @@ static void updateFuelInfo() {
|
||||||
updateFuelCorrections();
|
updateFuelCorrections();
|
||||||
updateFuelResults();
|
updateFuelResults();
|
||||||
|
|
||||||
const auto& wallFuel = engine->injectionEvents.elements[0].wallFuel;
|
const auto& wallFuel = engine->injectionEvents.elements[0].getWallFuel();
|
||||||
engine->outputChannels.wallFuelAmount = wallFuel.getWallFuel() * 1000; // Convert grams to mg
|
engine->outputChannels.wallFuelAmount = wallFuel.getWallFuel() * 1000; // Convert grams to mg
|
||||||
engine->outputChannels.wallFuelCorrectionValue = wallFuel.wallFuelCorrection * 1000; // Convert grams to mg
|
engine->outputChannels.wallFuelCorrectionValue = wallFuel.wallFuelCorrection * 1000; // Convert grams to mg
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ static void resetAccel() {
|
||||||
|
|
||||||
for (size_t i = 0; i < efi::size(engine->injectionEvents.elements); i++)
|
for (size_t i = 0; i < efi::size(engine->injectionEvents.elements); i++)
|
||||||
{
|
{
|
||||||
engine->injectionEvents.elements[i].wallFuel.resetWF();
|
engine->injectionEvents.elements[i].getWallFuel().resetWF();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,14 @@ void turnInjectionPinHigh(InjectionEvent *event) {
|
||||||
|
|
||||||
FuelSchedule::FuelSchedule() {
|
FuelSchedule::FuelSchedule() {
|
||||||
for (int cylinderIndex = 0; cylinderIndex < MAX_CYLINDER_COUNT; cylinderIndex++) {
|
for (int cylinderIndex = 0; cylinderIndex < MAX_CYLINDER_COUNT; cylinderIndex++) {
|
||||||
elements[cylinderIndex].ownIndex = cylinderIndex;
|
elements[cylinderIndex].setIndex(cylinderIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WallFuel& InjectionEvent::getWallFuel() {
|
||||||
|
return wallFuel;
|
||||||
|
}
|
||||||
|
|
||||||
void FuelSchedule::invalidate() {
|
void FuelSchedule::invalidate() {
|
||||||
isReady = false;
|
isReady = false;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +68,7 @@ InjectionEvent::InjectionEvent() {
|
||||||
|
|
||||||
// Returns the start angle of this injector in engine coordinates (0-720 for a 4 stroke),
|
// Returns the start angle of this injector in engine coordinates (0-720 for a 4 stroke),
|
||||||
// or unexpected if unable to calculate the start angle due to missing information.
|
// or unexpected if unable to calculate the start angle due to missing information.
|
||||||
expected<float> InjectionEvent::computeInjectionAngle(int cylinderIndex) const {
|
expected<float> InjectionEvent::computeInjectionAngle() const {
|
||||||
floatus_t oneDegreeUs = getEngineRotationState()->getOneDegreeUs();
|
floatus_t oneDegreeUs = getEngineRotationState()->getOneDegreeUs();
|
||||||
if (cisnan(oneDegreeUs)) {
|
if (cisnan(oneDegreeUs)) {
|
||||||
// in order to have fuel schedule we need to have current RPM
|
// in order to have fuel schedule we need to have current RPM
|
||||||
|
@ -86,7 +90,7 @@ expected<float> InjectionEvent::computeInjectionAngle(int cylinderIndex) const {
|
||||||
assertAngleRange(openingAngle, "openingAngle_r", ObdCode::CUSTOM_ERR_6554);
|
assertAngleRange(openingAngle, "openingAngle_r", ObdCode::CUSTOM_ERR_6554);
|
||||||
|
|
||||||
// Convert from cylinder-relative to cylinder-1-relative
|
// Convert from cylinder-relative to cylinder-1-relative
|
||||||
openingAngle += getCylinderAngle(cylinderIndex, cylinderNumber);
|
openingAngle += getCylinderAngle(ownIndex, cylinderNumber);
|
||||||
|
|
||||||
efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !cisnan(openingAngle), "findAngle#3", false);
|
efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !cisnan(openingAngle), "findAngle#3", false);
|
||||||
assertAngleRange(openingAngle, "findAngle#a33", ObdCode::CUSTOM_ERR_6544);
|
assertAngleRange(openingAngle, "findAngle#a33", ObdCode::CUSTOM_ERR_6544);
|
||||||
|
@ -100,8 +104,8 @@ expected<float> InjectionEvent::computeInjectionAngle(int cylinderIndex) const {
|
||||||
return openingAngle;
|
return openingAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InjectionEvent::updateInjectionAngle(int cylinderIndex) {
|
bool InjectionEvent::updateInjectionAngle() {
|
||||||
auto result = computeInjectionAngle(cylinderIndex);
|
auto result = computeInjectionAngle();
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
// If injector duty cycle is high, lock injection SOI so that we
|
// If injector duty cycle is high, lock injection SOI so that we
|
||||||
|
@ -119,10 +123,8 @@ bool InjectionEvent::updateInjectionAngle(int cylinderIndex) {
|
||||||
/**
|
/**
|
||||||
* @returns false in case of error, true if success
|
* @returns false in case of error, true if success
|
||||||
*/
|
*/
|
||||||
bool FuelSchedule::addFuelEventsForCylinder(int i) {
|
bool InjectionEvent::update() {
|
||||||
InjectionEvent *ev = &elements[i];
|
bool updatedAngle = updateInjectionAngle();
|
||||||
|
|
||||||
bool updatedAngle = ev->updateInjectionAngle(i);
|
|
||||||
|
|
||||||
if (!updatedAngle) {
|
if (!updatedAngle) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -133,7 +135,7 @@ bool FuelSchedule::addFuelEventsForCylinder(int i) {
|
||||||
|
|
||||||
// Map order index -> cylinder index (firing order)
|
// Map order index -> cylinder index (firing order)
|
||||||
// Single point only uses injector 1 (index 0)
|
// Single point only uses injector 1 (index 0)
|
||||||
int injectorIndex = mode == IM_SINGLE_POINT ? 0 : ID2INDEX(getCylinderId(i));
|
int injectorIndex = mode == IM_SINGLE_POINT ? 0 : ID2INDEX(getCylinderId(ownIndex));
|
||||||
|
|
||||||
InjectorOutputPin *secondOutput = nullptr;
|
InjectorOutputPin *secondOutput = nullptr;
|
||||||
|
|
||||||
|
@ -144,23 +146,23 @@ bool FuelSchedule::addFuelEventsForCylinder(int i) {
|
||||||
// Compute the position of this cylinder's twin in the firing order
|
// Compute the position of this cylinder's twin in the firing order
|
||||||
// Each injector gets fired as a primary (the same as sequential), but also
|
// Each injector gets fired as a primary (the same as sequential), but also
|
||||||
// fires the injector 360 degrees later in the firing order.
|
// fires the injector 360 degrees later in the firing order.
|
||||||
int secondOrder = (i + (engineConfiguration->cylindersCount / 2)) % engineConfiguration->cylindersCount;
|
int secondOrder = (ownIndex + (engineConfiguration->cylindersCount / 2)) % engineConfiguration->cylindersCount;
|
||||||
int secondIndex = ID2INDEX(getCylinderId(secondOrder));
|
int secondIndex = ID2INDEX(getCylinderId(secondOrder));
|
||||||
secondOutput = &enginePins.injectors[secondIndex];
|
secondOutput = &enginePins.injectors[secondIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
ev->outputs[0] = &enginePins.injectors[injectorIndex];
|
outputs[0] = &enginePins.injectors[injectorIndex];
|
||||||
ev->outputs[1] = secondOutput;
|
outputs[1] = secondOutput;
|
||||||
ev->isSimultaneous = mode == IM_SIMULTANEOUS;
|
isSimultaneous = mode == IM_SIMULTANEOUS;
|
||||||
// Stash the cylinder number so we can select the correct fueling bank later
|
// Stash the cylinder number so we can select the correct fueling bank later
|
||||||
ev->cylinderNumber = injectorIndex;
|
cylinderNumber = injectorIndex;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuelSchedule::addFuelEvents() {
|
void FuelSchedule::addFuelEvents() {
|
||||||
for (size_t cylinderIndex = 0; cylinderIndex < engineConfiguration->cylindersCount; cylinderIndex++) {
|
for (size_t cylinderIndex = 0; cylinderIndex < engineConfiguration->cylindersCount; cylinderIndex++) {
|
||||||
bool result = addFuelEventsForCylinder(cylinderIndex);
|
bool result = elements[cylinderIndex].update();
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
|
@ -18,26 +18,33 @@ class InjectionEvent {
|
||||||
public:
|
public:
|
||||||
InjectionEvent();
|
InjectionEvent();
|
||||||
|
|
||||||
// Update the injection start angle
|
bool update();
|
||||||
bool updateInjectionAngle(int cylinderIndex);
|
|
||||||
|
|
||||||
// Compute the injection start angle, compensating for injection duration and injection phase settings.
|
|
||||||
expected<float> computeInjectionAngle(int cylinderIndex) const;
|
|
||||||
|
|
||||||
// Call this every decoded trigger tooth. It will schedule any relevant events for this injector.
|
// Call this every decoded trigger tooth. It will schedule any relevant events for this injector.
|
||||||
void onTriggerTooth(int rpm, efitick_t nowNt, float currentPhase, float nextPhase);
|
void onTriggerTooth(int rpm, efitick_t nowNt, float currentPhase, float nextPhase);
|
||||||
|
|
||||||
|
WallFuel& getWallFuel();
|
||||||
|
|
||||||
|
void setIndex(uint8_t index) {
|
||||||
|
ownIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Update the injection start angle
|
||||||
|
bool updateInjectionAngle();
|
||||||
|
|
||||||
|
// Compute the injection start angle, compensating for injection duration and injection phase settings.
|
||||||
|
expected<float> computeInjectionAngle() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a performance optimization for IM_SIMULTANEOUS fuel strategy.
|
* This is a performance optimization for IM_SIMULTANEOUS fuel strategy.
|
||||||
* It's more efficient to handle all injectors together if that's the case
|
* It's more efficient to handle all injectors together if that's the case
|
||||||
*/
|
*/
|
||||||
bool isSimultaneous = false;
|
bool isSimultaneous = false;
|
||||||
InjectorOutputPin *outputs[MAX_WIRES_COUNT];
|
|
||||||
uint8_t ownIndex = 0;
|
uint8_t ownIndex = 0;
|
||||||
uint8_t cylinderNumber = 0;
|
uint8_t cylinderNumber = 0;
|
||||||
|
|
||||||
float injectionStartAngle = 0;
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* we need atomic flag so that we do not schedule a new pair of up/down before previous down was executed.
|
* we need atomic flag so that we do not schedule a new pair of up/down before previous down was executed.
|
||||||
*
|
*
|
||||||
|
@ -47,7 +54,13 @@ public:
|
||||||
*/
|
*/
|
||||||
bool isScheduled = false;
|
bool isScheduled = false;
|
||||||
|
|
||||||
|
private:
|
||||||
WallFuel wallFuel;
|
WallFuel wallFuel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// TODO: this should be private
|
||||||
|
InjectorOutputPin *outputs[MAX_WIRES_COUNT];
|
||||||
|
float injectionStartAngle = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void turnInjectionPinHigh(InjectionEvent *event);
|
void turnInjectionPinHigh(InjectionEvent *event);
|
||||||
|
@ -66,11 +79,8 @@ public:
|
||||||
// Call this every trigger tooth. It will schedule all required injector events.
|
// Call this every trigger tooth. It will schedule all required injector events.
|
||||||
void onTriggerTooth(int rpm, efitick_t nowNt, float currentPhase, float nextPhase);
|
void onTriggerTooth(int rpm, efitick_t nowNt, float currentPhase, float nextPhase);
|
||||||
|
|
||||||
/**
|
// Calculate injector opening angle, pins, and mode for all injectors
|
||||||
* this method schedules all fuel events for an engine cycle
|
|
||||||
*/
|
|
||||||
void addFuelEvents();
|
void addFuelEvents();
|
||||||
bool addFuelEventsForCylinder(int cylinderIndex);
|
|
||||||
|
|
||||||
void resetOverlapping();
|
void resetOverlapping();
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
void endSimultaneousInjection(InjectionEvent *event) {
|
void endSimultaneousInjection(InjectionEvent *event) {
|
||||||
event->isScheduled = false;
|
event->isScheduled = false;
|
||||||
endSimultaneousInjectionOnlyTogglePins();
|
endSimultaneousInjectionOnlyTogglePins();
|
||||||
getFuelSchedule()->addFuelEventsForCylinder(event->ownIndex);
|
event->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void turnInjectionPinLow(InjectionEvent *event) {
|
void turnInjectionPinLow(InjectionEvent *event) {
|
||||||
|
@ -62,7 +62,7 @@ void turnInjectionPinLow(InjectionEvent *event) {
|
||||||
output->close(nowNt);
|
output->close(nowNt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getFuelSchedule()->addFuelEventsForCylinder(event->ownIndex);
|
event->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectionEvent::onTriggerTooth(int rpm, efitick_t nowNt, float currentPhase, float nextPhase) {
|
void InjectionEvent::onTriggerTooth(int rpm, efitick_t nowNt, float currentPhase, float nextPhase) {
|
||||||
|
|
|
@ -76,11 +76,11 @@ TEST(fuel, testWallWettingEnrichmentScheduling) {
|
||||||
int expectedInvocationCounter = 1;
|
int expectedInvocationCounter = 1;
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
ASSERT_EQ(expectedInvocationCounter, engine->injectionEvents.elements[i].wallFuel.invocationCounter);
|
ASSERT_EQ(expectedInvocationCounter, engine->injectionEvents.elements[i].getWallFuel().invocationCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cylinder 5 doesn't exist - shouldn't have been called!
|
// Cylinder 5 doesn't exist - shouldn't have been called!
|
||||||
ASSERT_EQ(0, engine->injectionEvents.elements[5].wallFuel.invocationCounter);
|
ASSERT_EQ(0, engine->injectionEvents.elements[5].getWallFuel().invocationCounter);
|
||||||
|
|
||||||
eth.engine.periodicFastCallback();
|
eth.engine.periodicFastCallback();
|
||||||
eth.engine.periodicFastCallback();
|
eth.engine.periodicFastCallback();
|
||||||
|
@ -88,9 +88,9 @@ TEST(fuel, testWallWettingEnrichmentScheduling) {
|
||||||
|
|
||||||
// still same 1 per cylinder - wall wetting is NOT invoked from 'periodicFastCallback'
|
// still same 1 per cylinder - wall wetting is NOT invoked from 'periodicFastCallback'
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
ASSERT_EQ(expectedInvocationCounter, engine->injectionEvents.elements[i].wallFuel.invocationCounter);
|
ASSERT_EQ(expectedInvocationCounter, engine->injectionEvents.elements[i].getWallFuel().invocationCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cylinder 5 doesn't exist - shouldn't have been called!
|
// Cylinder 5 doesn't exist - shouldn't have been called!
|
||||||
ASSERT_EQ(0, engine->injectionEvents.elements[5].wallFuel.invocationCounter);
|
ASSERT_EQ(0, engine->injectionEvents.elements[5].getWallFuel().invocationCounter);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue