From 761efd862cf061ecffb8c685e9eab4bd1df19ec5 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 29 Aug 2024 22:38:30 -0700 Subject: [PATCH] MAP avg uses engine module callbacks (#475) * use engine module callbacks * happy tests * happy small-can-board * interact with map avg via module * simplify map avg init * tweaks * omit module to disable it instead! * unnecessary guard * minor cleanups * unnecessary branch - lookups for these tables are fine at 0 rpm * oop --- .../boards/hellen/small-can-board/board.mk | 3 +- firmware/config/stm32f4ems/efifeatures.h | 4 - firmware/controllers/algo/engine.cpp | 4 - firmware/controllers/engine_controller.cpp | 8 +- .../engine_cycle/main_trigger_callback.cpp | 8 +- .../modules/map_averaging/map_averaging.cpp | 82 +++++++++---------- .../modules/map_averaging/map_averaging.h | 24 +++--- .../modules/map_averaging/map_averaging.mk | 2 +- firmware/controllers/modules/modules.mk | 5 +- firmware/controllers/sensors/impl/map.cpp | 4 +- .../sensors/sensor_info_printing.cpp | 5 -- firmware/hw_layer/hardware.cpp | 8 +- firmware/init/sensor/init_map.cpp | 6 ++ simulator/simulator/efifeatures.h | 1 - simulator/simulator/rusEfiFunctionalTest.cpp | 1 - unit_tests/efifeatures.h | 2 - unit_tests/engine_test_helper.cpp | 1 + 17 files changed, 76 insertions(+), 92 deletions(-) diff --git a/firmware/config/boards/hellen/small-can-board/board.mk b/firmware/config/boards/hellen/small-can-board/board.mk index d74665879a..67e84b1e30 100644 --- a/firmware/config/boards/hellen/small-can-board/board.mk +++ b/firmware/config/boards/hellen/small-can-board/board.mk @@ -17,11 +17,12 @@ DDEFS += -DEFI_SHAFT_POSITION_INPUT=FALSE DDEFS += -DEFI_ALTERNATOR_CONTROL=FALSE DDEFS += -DEFI_VVT_PID=FALSE DDEFS += -DEFI_EMULATE_POSITION_SENSORS=FALSE -DDEFS += -DEFI_MAP_AVERAGING=FALSE DDEFS += -DEFI_HPFP=FALSE DDEFS += -DEFI_TOOTH_LOGGER=FALSE DDEFS += -DRAM_UNUSED_SIZE=100 +NO_MAP_AVERAGING = yes + DDEFS += -DHW_SMALL_CAN_BOARD=1 #Mass Storage diff --git a/firmware/config/stm32f4ems/efifeatures.h b/firmware/config/stm32f4ems/efifeatures.h index 243b6ac985..421b684b94 100644 --- a/firmware/config/stm32f4ems/efifeatures.h +++ b/firmware/config/stm32f4ems/efifeatures.h @@ -302,10 +302,6 @@ //#define EFI_MALFUNCTION_INDICATOR FALSE #endif -#ifndef EFI_MAP_AVERAGING -#define EFI_MAP_AVERAGING TRUE -#endif - // todo: most of this should become configurable // todo: switch to continuous ADC conversion for fast ADC? diff --git a/firmware/controllers/algo/engine.cpp b/firmware/controllers/algo/engine.cpp index 6f76460f3e..4cfaa00a0a 100644 --- a/firmware/controllers/algo/engine.cpp +++ b/firmware/controllers/algo/engine.cpp @@ -466,10 +466,6 @@ injection_mode_e getCurrentInjectionMode() { void Engine::periodicFastCallback() { ScopePerf pc(PE::EnginePeriodicFastCallback); -#if EFI_MAP_AVERAGING - refreshMapAveragingPreCalc(); -#endif - engineState.periodicFastCallback(); tachUpdate(); diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp index abf9d29b52..068ad14386 100644 --- a/firmware/controllers/engine_controller.cpp +++ b/firmware/controllers/engine_controller.cpp @@ -513,11 +513,9 @@ void commonInitEngineController() { initElectronicThrottle(); #endif /* EFI_ELECTRONIC_THROTTLE_BODY */ -#if EFI_MAP_AVERAGING - if (engineConfiguration->isMapAveragingEnabled) { - initMapAveraging(); - } -#endif /* EFI_MAP_AVERAGING */ +#ifdef MODULE_MAP_AVERAGING + initMapAveraging(); +#endif /* MODULE_MAP_AVERAGING */ #if EFI_BOOST_CONTROL initBoostCtrl(); diff --git a/firmware/controllers/engine_cycle/main_trigger_callback.cpp b/firmware/controllers/engine_cycle/main_trigger_callback.cpp index d6657c4837..92902e971f 100644 --- a/firmware/controllers/engine_cycle/main_trigger_callback.cpp +++ b/firmware/controllers/engine_cycle/main_trigger_callback.cpp @@ -82,7 +82,7 @@ void mainTriggerCallback(uint32_t trgEventIndex, efitick_t edgeTimestamp, angle_ // todo: check for 'trigger->is_synchnonized?' return; } - if (rpm == NOISY_RPM) { + if (rpm == NOISY_RPM || rpm > UNREALISTIC_RPM) { warning(ObdCode::OBD_Crankshaft_Position_Sensor_A_Circuit_Malfunction, "noisy trigger"); return; } @@ -113,12 +113,6 @@ void mainTriggerCallback(uint32_t trgEventIndex, efitick_t edgeTimestamp, angle_ * For spark we schedule both start of coil charge and actual spark based on trigger angle */ onTriggerEventSparkLogic(rpm, edgeTimestamp, currentPhase, nextPhase); - -#if !EFI_UNIT_TEST -#if EFI_MAP_AVERAGING - mapAveragingTriggerCallback(edgeTimestamp, currentPhase, nextPhase); -#endif /* EFI_MAP_AVERAGING */ -#endif /* EFI_UNIT_TEST */ } #endif /* EFI_ENGINE_CONTROL */ diff --git a/firmware/controllers/modules/map_averaging/map_averaging.cpp b/firmware/controllers/modules/map_averaging/map_averaging.cpp index c1ba420e35..9a9f6ba19c 100644 --- a/firmware/controllers/modules/map_averaging/map_averaging.cpp +++ b/firmware/controllers/modules/map_averaging/map_averaging.cpp @@ -23,8 +23,6 @@ #include "pch.h" -#if EFI_MAP_AVERAGING - #include "trigger_central.h" #if EFI_SENSOR_CHART @@ -78,6 +76,11 @@ static void startAveraging(sampler* s) { { endAveraging, &averager }); } +void MapAverager::showInfo(const char* sensorName) const { + const auto value = get(); + efiPrintf("Sensor \"%s\" is MAP averager: valid: %s value: %.2f averaged sample count: %d", sensorName, boolToString(value.Valid), value.Value, m_lastCounter); +} + void MapAverager::start(uint8_t cylinderIndex) { chibios_rt::CriticalSectionLocker csl; @@ -133,24 +136,21 @@ void MapAverager::stop() { } } -#if HAL_USE_ADC - /** * This method is invoked from ADC callback. * @note This method is invoked OFTEN, this method is a potential bottleneck - the implementation should be * as fast as possible */ -void mapAveragingAdcCallback(float instantVoltage) { +void MapAveragingModule::submitSample(float volts) { efiAssertVoid(ObdCode::CUSTOM_ERR_6650, getCurrentRemainingStack() > 128, "lowstck#9a"); - SensorResult mapResult = getMapAvg(currentMapAverager).submit(instantVoltage); + SensorResult mapResult = getMapAvg(currentMapAverager).submit(volts); float instantMap = mapResult.value_or(0); #if EFI_TUNER_STUDIO engine->outputChannels.instantMAPValue = instantMap; #endif // EFI_TUNER_STUDIO } -#endif static void endAveraging(MapAverager* arg) { arg->stop(); @@ -169,50 +169,39 @@ static void applyMapMinBufferLength() { } } -void refreshMapAveragingPreCalc() { - int rpm = Sensor::getOrZero(SensorType::Rpm); - if (isValidRpm(rpm)) { - MAP_sensor_config_s * c = &engineConfiguration->map; - angle_t start = interpolate2d(rpm, c->samplingAngleBins, c->samplingAngle); - angle_t duration = interpolate2d(rpm, c->samplingWindowBins, c->samplingWindow); - efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_START_ASSERT, !std::isnan(start), "start"); - assertAngleRange(duration, "samplingDuration", ObdCode::CUSTOM_ERR_6563); - - // Clamp the duration to slightly less than one cylinder period - float cylinderPeriod = engine->engineState.engineCycle / engineConfiguration->cylindersCount; - duration = clampF(10, duration, cylinderPeriod - 10); - - for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) { - float cylinderStart = start + getCylinderAngle(i, ID2INDEX(getCylinderId(i)));; - wrapAngle(cylinderStart, "cylinderStart", ObdCode::CUSTOM_ERR_6562); - engine->engineState.mapAveragingStart[i] = cylinderStart; - } +void MapAveragingModule::onFastCallback() { + float rpm = Sensor::getOrZero(SensorType::Rpm); - engine->engineState.mapAveragingDuration = duration; - } else { - for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) { - engine->engineState.mapAveragingStart[i] = 0; - } + MAP_sensor_config_s * c = &engineConfiguration->map; + + angle_t start = interpolate2d(rpm, c->samplingAngleBins, c->samplingAngle); + efiAssertVoid(ObdCode::CUSTOM_ERR_MAP_START_ASSERT, !std::isnan(start), "start"); - engine->engineState.mapAveragingDuration = 0; + for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) { + float cylinderStart = start + getCylinderAngle(i, ID2INDEX(getCylinderId(i)));; + wrapAngle(cylinderStart, "cylinderStart", ObdCode::CUSTOM_ERR_6562); + engine->engineState.mapAveragingStart[i] = cylinderStart; } + angle_t duration = interpolate2d(rpm, c->samplingWindowBins, c->samplingWindow); + assertAngleRange(duration, "samplingDuration", ObdCode::CUSTOM_ERR_6563); + + // Clamp the duration to slightly less than one cylinder period + float cylinderPeriod = engine->engineState.engineCycle / engineConfiguration->cylindersCount; + engine->engineState.mapAveragingDuration = clampF(10, duration, cylinderPeriod - 10); } // Callback to schedule the start of map averaging for each cylinder -void mapAveragingTriggerCallback(efitick_t edgeTimestamp, angle_t currentPhase, angle_t nextPhase) { -#if EFI_ENGINE_CONTROL - int rpm = Sensor::getOrZero(SensorType::Rpm); - if (!isValidRpm(rpm)) { +void MapAveragingModule::onEnginePhase(float rpm, + efitick_t edgeTimestamp, + float currentPhase, + float nextPhase) { + if (!engineConfiguration->isMapAveragingEnabled) { return; } ScopePerf perf(PE::MapAveragingTriggerCallback); - if (engineConfiguration->mapMinBufferLength != mapMinBufferLength) { - applyMapMinBufferLength(); - } - int samplingCount = engineConfiguration->measureMapOnlyInOneCylinder ? 1 : engineConfiguration->cylindersCount; for (int i = 0; i < samplingCount; i++) { @@ -228,15 +217,20 @@ void mapAveragingTriggerCallback(efitick_t edgeTimestamp, angle_t currentPhase, } auto& s = samplers[i]; - s.cylinderIndex = i; - scheduleByAngle(&s.timer, edgeTimestamp, angleOffset, { startAveraging, &s }); } -#endif +} + +void MapAveragingModule::onConfigurationChange(engine_configuration_s const * previousConfig) { + if (!previousConfig || engineConfiguration->mapMinBufferLength != previousConfig->mapMinBufferLength) { + applyMapMinBufferLength(); + } } void initMapAveraging() { + for (size_t i = 0; i < efi::size(samplers); i++) { + samplers[i].cylinderIndex = i; + } + applyMapMinBufferLength(); } - -#endif /* EFI_MAP_AVERAGING */ diff --git a/firmware/controllers/modules/map_averaging/map_averaging.h b/firmware/controllers/modules/map_averaging/map_averaging.h index d399b56933..862bf5108c 100644 --- a/firmware/controllers/modules/map_averaging/map_averaging.h +++ b/firmware/controllers/modules/map_averaging/map_averaging.h @@ -9,22 +9,11 @@ #include "sensor_converter_func.h" -#if EFI_MAP_AVERAGING - -#if HAL_USE_ADC -void mapAveragingAdcCallback(float instantVoltage); -#endif - void initMapAveraging(); -void refreshMapAveragingPreCalc(); - -void mapAveragingTriggerCallback(efitick_t edgeTimestamp, angle_t currentPhase, angle_t nextPhase); // allow smoothing up to number of cylinders #define MAX_MAP_BUFFER_LENGTH (MAX_CYLINDER_COUNT) -#endif /* EFI_MAP_AVERAGING */ - class MapAverager : public StoredValueSensor { public: MapAverager(SensorType type, efidur_t timeout) @@ -54,3 +43,16 @@ class MapAverager : public StoredValueSensor { }; MapAverager& getMapAvg(size_t idx); + +class MapAveragingModule : public EngineModule { +public: + void onConfigurationChange(engine_configuration_s const * previousConfig); + + void onFastCallback() override; + void onEnginePhase(float rpm, + efitick_t edgeTimestamp, + float currentPhase, + float nextPhase) override; + + void submitSample(float volts); +}; diff --git a/firmware/controllers/modules/map_averaging/map_averaging.mk b/firmware/controllers/modules/map_averaging/map_averaging.mk index 75663c8291..3eeef0e618 100644 --- a/firmware/controllers/modules/map_averaging/map_averaging.mk +++ b/firmware/controllers/modules/map_averaging/map_averaging.mk @@ -1,6 +1,6 @@ MODULES_INC += $(PROJECT_DIR)/controllers/modules/map_averaging MODULES_CPPSRC += $(PROJECT_DIR)/controllers/modules/map_averaging/map_averaging.cpp MODULES_INCLUDE += \#include "map_averaging.h"\n -# MODULES_LIST += MapSampler, +MODULES_LIST += MapAveragingModule, DDEFS += -DMODULE_MAP_AVERAGING diff --git a/firmware/controllers/modules/modules.mk b/firmware/controllers/modules/modules.mk index c149ca5d9f..e9097266c6 100644 --- a/firmware/controllers/modules/modules.mk +++ b/firmware/controllers/modules/modules.mk @@ -1,5 +1,8 @@ include $(PROJECT_DIR)/controllers/modules/fan/fan.mk include $(PROJECT_DIR)/controllers/modules/fuel_pump/fuel_pump.mk include $(PROJECT_DIR)/controllers/modules/gear_detector/gear_detector.mk -include $(PROJECT_DIR)/controllers/modules/map_averaging/map_averaging.mk include $(PROJECT_DIR)/controllers/modules/trip_odometer/trip_odometer.mk + +ifeq ($(NO_MAP_AVERAGING),) + include $(PROJECT_DIR)/controllers/modules/map_averaging/map_averaging.mk +endif diff --git a/firmware/controllers/sensors/impl/map.cpp b/firmware/controllers/sensors/impl/map.cpp index 91369f2999..3c28bfe25a 100644 --- a/firmware/controllers/sensors/impl/map.cpp +++ b/firmware/controllers/sensors/impl/map.cpp @@ -31,12 +31,12 @@ static void printMAPInfo() { #if EFI_ANALOG_SENSORS efiPrintf("instant value=%.2fkPa", Sensor::getOrZero(SensorType::Map)); -#if EFI_MAP_AVERAGING +#ifdef MODULE_MAP_AVERAGING efiPrintf("map type=%d/%s MAP=%.2fkPa mapMinBufferLength=%d", engineConfiguration->map.sensor.type, getAir_pressure_sensor_type_e(engineConfiguration->map.sensor.type), Sensor::getOrZero(SensorType::Map), mapMinBufferLength); -#endif // EFI_MAP_AVERAGING +#endif // MODULE_MAP_AVERAGING adc_channel_e mapAdc = engineConfiguration->map.sensor.hwChannel; char pinNameBuffer[16]; diff --git a/firmware/controllers/sensors/sensor_info_printing.cpp b/firmware/controllers/sensors/sensor_info_printing.cpp index 4fe617d5a4..fdd3cbb3ab 100644 --- a/firmware/controllers/sensors/sensor_info_printing.cpp +++ b/firmware/controllers/sensors/sensor_info_printing.cpp @@ -68,11 +68,6 @@ void Lps25Sensor::showInfo(const char* sensorName) const { efiPrintf("%s: LPS25 baro %.2f kPa", sensorName, get().Value); } -void MapAverager::showInfo(const char* sensorName) const { - const auto value = get(); - efiPrintf("Sensor \"%s\" is MAP averager: valid: %s value: %.2f averaged sample count: %d", sensorName, boolToString(value.Valid), value.Value, m_lastCounter); -} - void LinearFunc::showInfo(float testRawValue) const { efiPrintf(" Linear function slope: %.2f offset: %.2f min: %.1f max: %.1f", m_a, m_b, m_minOutput, m_maxOutput); const auto value = convert(testRawValue); diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp index f8726a37ee..e661d0bd7a 100644 --- a/firmware/hw_layer/hardware.cpp +++ b/firmware/hw_layer/hardware.cpp @@ -148,9 +148,11 @@ void onFastAdcComplete(adcsample_t*) { // this callback is executed 10 000 times a second, it needs to be as fast as possible! ScopePerf perf(PE::AdcCallbackFast); -#if EFI_MAP_AVERAGING - mapAveragingAdcCallback(adcToVoltsDivided(getFastAdc(fastMapSampleIndex), engineConfiguration->map.sensor.hwChannel)); -#endif /* EFI_MAP_AVERAGING */ +#ifdef MODULE_MAP_AVERAGING + engine->module()->submitSample( + adcToVoltsDivided(getFastAdc(fastMapSampleIndex), engineConfiguration->map.sensor.hwChannel) + ); +#endif // MODULE_MAP_AVERAGING #if EFI_SENSOR_CHART && EFI_SHAFT_POSITION_INPUT if (getEngineState()->sensorChartMode == SC_AUX_FAST1) { diff --git a/firmware/init/sensor/init_map.cpp b/firmware/init/sensor/init_map.cpp index f41fe5ea2f..5cf5070457 100644 --- a/firmware/init/sensor/init_map.cpp +++ b/firmware/init/sensor/init_map.cpp @@ -16,6 +16,7 @@ static FunctionalSensor slowMapSensor2(SensorType::MapSlow2, MS2NT(50)); static FunctionalSensor compressorDischargePress(SensorType::CompressorDischargePressure, MS2NT(50)); static FunctionalSensor throttleInletPress(SensorType::ThrottleInletPressure, MS2NT(50)); +#ifdef MODULE_MAP_AVERAGING // lowest reasonable idle is maybe 600 rpm // one sample per cycle (1 cylinder, or "sample one cyl" mode) gives a period of 100ms // add some margin -> 200ms timeout for fast MAP sampling @@ -25,6 +26,7 @@ MapAverager fastMapSensor2(SensorType::MapFast2, MS2NT(200)); MapAverager& getMapAvg(size_t idx) { return idx == 0 ? fastMapSensor : fastMapSensor2; } +#endif // MODULE_MAP_AVERAGING // Combine MAP sensors: prefer fast sensor, but use slow if fast is unavailable. static FallbackSensor mapCombiner(SensorType::Map, SensorType::MapFast, SensorType::MapSlow); @@ -102,8 +104,10 @@ void initMap() { slowMapSensor.setFunction(mapConverter); slowMapSensor2.setFunction(mapConverter); +#ifdef MODULE_MAP_AVERAGING fastMapSensor.setFunction(mapConverter); fastMapSensor2.setFunction(mapConverter); +#endif // MODULE_MAP_AVERAGING compressorDischargePress.setFunction(mapConverter); throttleInletPress.setFunction(mapConverter); @@ -111,8 +115,10 @@ void initMap() { if (isAdcChannelValid(mapChannel)) { slowMapSensor.Register(); slowMapSensor2.Register(); +#ifdef MODULE_MAP_AVERAGING fastMapSensor.Register(); fastMapSensor2.Register(); +#endif // MODULE_MAP_AVERAGING mapCombiner.Register(); mapCombiner2.Register(); diff --git a/simulator/simulator/efifeatures.h b/simulator/simulator/efifeatures.h index a1dcdbf34b..2842419837 100644 --- a/simulator/simulator/efifeatures.h +++ b/simulator/simulator/efifeatures.h @@ -67,7 +67,6 @@ #define EFI_USE_UART_DMA FALSE -#define EFI_MAP_AVERAGING TRUE #define EFI_ALTERNATOR_CONTROL TRUE #define EFI_ENGINE_AUDI_AAN FALSE diff --git a/simulator/simulator/rusEfiFunctionalTest.cpp b/simulator/simulator/rusEfiFunctionalTest.cpp index 4d6ae5f809..ee673bd25b 100644 --- a/simulator/simulator/rusEfiFunctionalTest.cpp +++ b/simulator/simulator/rusEfiFunctionalTest.cpp @@ -20,7 +20,6 @@ #include "sensor_chart.h" #include "bench_test.h" #include "tunerstudio.h" -#include "map_averaging.h" #include "mmc_card.h" #include "memstreams.h" #include diff --git a/unit_tests/efifeatures.h b/unit_tests/efifeatures.h index c4fd5a0442..7637dbf147 100644 --- a/unit_tests/efifeatures.h +++ b/unit_tests/efifeatures.h @@ -68,8 +68,6 @@ #define EFI_BOARD_TEST FALSE -#define EFI_MAP_AVERAGING TRUE - #define EFI_LUA TRUE #define EFI_HPFP TRUE diff --git a/unit_tests/engine_test_helper.cpp b/unit_tests/engine_test_helper.cpp index 25ac6cf947..b1ab3b5c8b 100644 --- a/unit_tests/engine_test_helper.cpp +++ b/unit_tests/engine_test_helper.cpp @@ -104,6 +104,7 @@ EngineTestHelper::EngineTestHelper(engine_type_e engineType, configuration_callb initDataStructures(); resetConfigurationExt(configurationCallback, engineType); + engineConfiguration->isMapAveragingEnabled = false; validateConfig();