diff --git a/firmware/controllers/algo/accel_enrichment.cpp b/firmware/controllers/algo/accel_enrichment.cpp index e438fcefea..b8d0442897 100644 --- a/firmware/controllers/algo/accel_enrichment.cpp +++ b/firmware/controllers/algo/accel_enrichment.cpp @@ -97,7 +97,7 @@ float AccelEnrichmemnt::getMaxDelta(DECLARE_ENGINE_PARAMETER_F) { int index = getMaxDeltaIndex(PASS_ENGINE_PARAMETER_F); FuelSchedule *fs = engine->engineConfiguration2->injectionEvents; - return (cb.get(index) - (cb.get(index - 1))) * fs->eventsCount; + return (cb.get(index) - (cb.get(index - 1))) * CONFIG(specs.cylindersCount); } // todo: eliminate code duplication between these two methods! Some pointer magic would help. @@ -137,7 +137,7 @@ float AccelEnrichmemnt::getEngineLoadEnrichment(DECLARE_ENGINE_PARAMETER_F) { int index = getMaxDeltaIndex(PASS_ENGINE_PARAMETER_F); FuelSchedule *fs = engine->engineConfiguration2->injectionEvents; - float d = (cb.get(index) - (cb.get(index - 1))) * fs->eventsCount; + float d = (cb.get(index) - (cb.get(index - 1))) * CONFIG(specs.cylindersCount); float result = 0; int distance = 0; diff --git a/firmware/controllers/algo/engine.h b/firmware/controllers/algo/engine.h index b2de923b4f..1af7cd4327 100644 --- a/firmware/controllers/algo/engine.h +++ b/firmware/controllers/algo/engine.h @@ -48,15 +48,6 @@ public: InjectionEventList injectionEvents; - /** - * 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(); }; diff --git a/firmware/controllers/algo/event_registry.h b/firmware/controllers/algo/event_registry.h index 25777972e0..d83717deed 100644 --- a/firmware/controllers/algo/event_registry.h +++ b/firmware/controllers/algo/event_registry.h @@ -70,13 +70,15 @@ public: }; -/** - * two wire batch mode would generate twice the number of cylinders events, that's the max - */ -#define MAX_INJECTION_OUTPUT_COUNT 2 * INJECTION_PIN_COUNT +#define MAX_INJECTION_OUTPUT_COUNT INJECTION_PIN_COUNT #define MAX_IGNITION_EVENT_COUNT IGNITION_PIN_COUNT -typedef ArrayList InjectionEventList; +class InjectionEventList { +public: + InjectionEventList(); + InjectionEvent elements[MAX_INJECTION_OUTPUT_COUNT]; + bool isReady; +}; class IgnitionEventList { public: diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp index c8e5d0c235..0ccfc0deab 100644 --- a/firmware/controllers/math/engine_math.cpp +++ b/firmware/controllers/math/engine_math.cpp @@ -98,8 +98,6 @@ FuelSchedule::FuelSchedule() { } void FuelSchedule::clear() { - memset(hasEvents, 0, sizeof(hasEvents)); - eventsCount = 0; usedAtEngineCycle = 0; } @@ -159,11 +157,7 @@ void FuelSchedule::addFuelEventsForCylinder(int i, injection_mode_e mode DECLARE warning(CUSTOM_OBD_20, "no_pin_inj #%s", output->name); } - InjectionEvent *ev = injectionEvents.add(); - if (ev == NULL) { - // error already reported - return; - } + InjectionEvent *ev = &injectionEvents.elements[i]; fixAngle(angle); ev->isOverlapping = angle < 720 && (angle + injectionDuration) > 720; @@ -178,18 +172,10 @@ void FuelSchedule::addFuelEventsForCylinder(int i, injection_mode_e mode DECLARE #if EFI_UNIT_TEST printf("registerInjectionEvent angle=%f index=%d\r\n", angle, ev->injectionStart.eventIndex); #endif - - if (!hasEvents[ev->injectionStart.eventIndex]) { - hasEvents[ev->injectionStart.eventIndex] = true; - eventsCount++; - } } void FuelSchedule::addFuelEvents(injection_mode_e mode DECLARE_ENGINE_PARAMETER_S) { - clear(); // this method is relatively heavy -// sourceList->reset(); - - injectionEvents.reset(); + clear(); for (int i = 0; i < CONFIG(specs.cylindersCount); i++) { addFuelEventsForCylinder(i, mode PASS_ENGINE_PARAMETER); diff --git a/firmware/controllers/trigger/main_trigger_callback.cpp b/firmware/controllers/trigger/main_trigger_callback.cpp index 1d31d18694..7237e39007 100644 --- a/firmware/controllers/trigger/main_trigger_callback.cpp +++ b/firmware/controllers/trigger/main_trigger_callback.cpp @@ -363,7 +363,7 @@ static void handleFuelScheduleOverlap(InjectionEventList *injectionEvents DECLAR * see testFuelSchedulerBug299smallAndLarge unit test */ // - for (int injEventIndex = 0; injEventIndex < injectionEvents->size; injEventIndex++) { + for (int injEventIndex = 0; injEventIndex < CONFIG(specs.cylindersCount); injEventIndex++) { InjectionEvent *event = &injectionEvents->elements[injEventIndex]; if (!engine->engineConfiguration2->wasOverlapping[injEventIndex] && event->isOverlapping) { // we are here if new fuel schedule is crossing engine cycle boundary with this event @@ -413,11 +413,6 @@ static ALWAYS_INLINE void handleFuel(const bool limitedFuel, uint32_t trgEventIn handleFuelScheduleOverlap(injectionEvents PASS_ENGINE_PARAMETER); } - if (!fs->hasEvents[trgEventIndex]) { - // that's a performance optimization - return; - } - #if FUEL_MATH_EXTREME_LOGGING || defined(__DOXYGEN__) scheduleMsg(logger, "handleFuel ind=%d %d", trgEventIndex, getRevolutionCounter()); #endif /* FUEL_MATH_EXTREME_LOGGING */ @@ -427,7 +422,7 @@ static ALWAYS_INLINE void handleFuel(const bool limitedFuel, uint32_t trgEventIn ENGINE(fuelMs) = getInjectionDuration(rpm PASS_ENGINE_PARAMETER) * CONFIG(globalFuelCorrection); - for (int injEventIndex = 0; injEventIndex < injectionEvents->size; injEventIndex++) { + for (int injEventIndex = 0; injEventIndex < CONFIG(specs.cylindersCount); injEventIndex++) { InjectionEvent *event = &injectionEvents->elements[injEventIndex]; uint32_t eventIndex = event->injectionStart.eventIndex; // right after trigger change we are still using old & invalid fuel schedule. good news is we do not change trigger on the fly in real life diff --git a/firmware/controllers/trigger/spark_logic.cpp b/firmware/controllers/trigger/spark_logic.cpp index da20d5e695..11e2854cb4 100644 --- a/firmware/controllers/trigger/spark_logic.cpp +++ b/firmware/controllers/trigger/spark_logic.cpp @@ -21,6 +21,10 @@ IgnitionEventList::IgnitionEventList() { isReady = false; } +InjectionEventList::InjectionEventList() { + isReady = false; +} + int isInjectionEnabled(engine_configuration_s *engineConfiguration) { // todo: is this worth a method? should this be inlined? return engineConfiguration->isInjectionEnabled; diff --git a/unit_tests/test_accel_enrichment.cpp b/unit_tests/test_accel_enrichment.cpp index 3ccba6326c..1e471f2db6 100644 --- a/unit_tests/test_accel_enrichment.cpp +++ b/unit_tests/test_accel_enrichment.cpp @@ -21,8 +21,6 @@ void testAccelEnrichment(void) { engine->rpmCalculator.setRpmValue(600 PASS_ENGINE_PARAMETER); engine->periodicFastCallback(PASS_ENGINE_PARAMETER_F); - assertEqualsM("eventsCount", 4, engine->engineConfiguration2->injectionEvents->eventsCount); - engine->tpsAccelEnrichment.setLength(4); engine->tpsAccelEnrichment.onNewValue(0 PASS_ENGINE_PARAMETER); diff --git a/unit_tests/test_fuel_map.cpp b/unit_tests/test_fuel_map.cpp index 5ffe500069..1731daa659 100644 --- a/unit_tests/test_fuel_map.cpp +++ b/unit_tests/test_fuel_map.cpp @@ -182,40 +182,33 @@ void testAngleResolver(void) { assertEqualsM("shape size", 10, ts->getSize()); - ae.reset(); printf("*************************************************** testAngleResolver 0\r\n"); - findTriggerPosition(&ae.add()->injectionStart, -122 PASS_ENGINE_PARAMETER); - assertEqualsM("size", 1, ae.size); + findTriggerPosition(&ae.elements[0].injectionStart, -122 PASS_ENGINE_PARAMETER); assertEqualsM("eventIndex@0", 2, ae.elements[0].injectionStart.eventIndex); assertEquals(0.24, ae.elements[0].injectionStart.angleOffset); printf("*************************************************** testAngleResolver 0.1\r\n"); - ae.reset(); - findTriggerPosition(&ae.add()->injectionStart, -80 PASS_ENGINE_PARAMETER); + findTriggerPosition(&ae.elements[0].injectionStart, -80 PASS_ENGINE_PARAMETER); assertEqualsM("eventIndex@0", 2, ae.elements[0].injectionStart.eventIndex); assertEquals(42.24, ae.elements[0].injectionStart.angleOffset); printf("*************************************************** testAngleResolver 0.2\r\n"); - ae.reset(); - findTriggerPosition(&ae.add()->injectionStart, -54 PASS_ENGINE_PARAMETER); + findTriggerPosition(&ae.elements[0].injectionStart, -54 PASS_ENGINE_PARAMETER); assertEqualsM("eventIndex@0", 2, ae.elements[0].injectionStart.eventIndex); assertEquals(68.2400, ae.elements[0].injectionStart.angleOffset); printf("*************************************************** testAngleResolver 0.3\r\n"); - ae.reset(); - findTriggerPosition(&ae.add()->injectionStart, -53 PASS_ENGINE_PARAMETER); + findTriggerPosition(&ae.elements[0].injectionStart, -53 PASS_ENGINE_PARAMETER); assertEquals(2, ae.elements[0].injectionStart.eventIndex); assertEquals(69.24, ae.elements[0].injectionStart.angleOffset); printf("*************************************************** testAngleResolver 1\r\n"); - ae.reset(); - findTriggerPosition(&ae.add()->injectionStart, 0 PASS_ENGINE_PARAMETER); + findTriggerPosition(&ae.elements[0].injectionStart, 0 PASS_ENGINE_PARAMETER); assertEquals(2, ae.elements[0].injectionStart.eventIndex); assertEquals(122.24, ae.elements[0].injectionStart.angleOffset); printf("*************************************************** testAngleResolver 2\r\n"); - ae.reset(); - findTriggerPosition(&ae.add()->injectionStart, 56 PASS_ENGINE_PARAMETER); + findTriggerPosition(&ae.elements[0].injectionStart, 56 PASS_ENGINE_PARAMETER); assertEquals(2, ae.elements[0].injectionStart.eventIndex); assertEquals(178.24, ae.elements[0].injectionStart.angleOffset); diff --git a/unit_tests/test_trigger_decoder.cpp b/unit_tests/test_trigger_decoder.cpp index a31f6ee2be..4d1616d88c 100644 --- a/unit_tests/test_trigger_decoder.cpp +++ b/unit_tests/test_trigger_decoder.cpp @@ -393,8 +393,6 @@ void testRpmCalculator(void) { assertEquals(5, engine->triggerShape.triggerIndexByAngle[241]); timeNow += 5000; - assertEqualsM("Size 4.1", 6, engine->engineConfiguration2->injectionEvents->eventsCount); - assertFalseM("No squirts expected 4.1", engine->engineConfiguration2->injectionEvents->hasEvents[4]); eth.engine.triggerCentral.handleShaftSignal(SHAFT_PRIMARY_FALLING PASS_ENGINE_PARAMETER); assertEqualsM("queue size 4.1", 0, schedulingQueue.size()); @@ -666,7 +664,7 @@ static void setTestBug299(EngineTestHelper *eth) { assertEqualsM("exec#0", 0, schedulingQueue.executeAll(timeNow)); FuelSchedule * t = ENGINE(engineConfiguration2)->injectionEvents; - assertEqualsM("t.s#0", 4, t->injectionEvents.size); + assertInjectionEvent("#0", &t->injectionEvents.elements[0], 0, 1, 153, false); assertInjectionEvent("#1", &t->injectionEvents.elements[1], 1, 1, 333, false); assertInjectionEvent("#2", &t->injectionEvents.elements[2], 0, 0, 153, false); @@ -837,7 +835,7 @@ void testFuelSchedulerBug299smallAndMedium(void) { t = ENGINE(engineConfiguration2)->injectionEvents; - assertEqualsM("t.s", 4, t->injectionEvents.size); + assertInjectionEvent("#0", &t->injectionEvents.elements[0], 0, 0, 315, false); assertInjectionEvent("#1", &t->injectionEvents.elements[1], 1, 1, 135, false); assertInjectionEvent("#2", &t->injectionEvents.elements[2], 0, 1, 315, true); @@ -926,7 +924,7 @@ void testFuelSchedulerBug299smallAndMedium(void) { t = ENGINE(engineConfiguration2)->injectionEvents; - assertEqualsM("injectionEvents.size", 4, t->injectionEvents.size); + assertInjectionEvent("#0#", &t->injectionEvents.elements[0], 0, 0, 315, false); assertInjectionEvent("#1#", &t->injectionEvents.elements[1], 1, 1, 135, false); assertInjectionEvent("#2#", &t->injectionEvents.elements[2], 0, 1, 315, true); @@ -977,7 +975,7 @@ void testFuelSchedulerBug299smallAndMedium(void) { engine->periodicFastCallback(PASS_ENGINE_PARAMETER_F); t = ENGINE(engineConfiguration2)->injectionEvents; - assertEqualsM("t.s", 4, t->injectionEvents.size); + assertInjectionEvent("#00", &t->injectionEvents.elements[0], 0, 0, 225, false); // 87.5 duty cycle assertInjectionEvent("#10", &t->injectionEvents.elements[1], 1, 1, 45, false); assertInjectionEvent("#20", &t->injectionEvents.elements[2], 0, 1, 225, true);