| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | #include "pch.h" | |||
| 2 | ||||
| 3 | #include "init.h" | |||
| 4 | #include "adc_subscription.h" | |||
| 5 | #include "functional_sensor.h" | |||
| 6 | #include "table_func.h" | |||
| 7 | #include "func_chain.h" | |||
| 8 | ||||
| 9 | static FunctionalSensor maf (SensorType::Maf , /* timeout = */ MS2NT(50)); | |||
| 10 | static FunctionalSensor maf2(SensorType::Maf2, /* timeout = */ MS2NT(50)); | |||
| 11 | ||||
| 12 | // Just check min/max allowed voltage | |||
| 13 | struct MafVoltageCheck : public SensorConverter { | |||
| 14 | ✗ | SensorResult convert(float input) const override { | ||
| 15 | ✗ | if (input > 5) { | ||
| 16 | ✗ | return UnexpectedCode::High; | ||
| 17 | } | |||
| 18 | ||||
| 19 | ✗ | if (input < 0) { | ||
| 20 | ✗ | return UnexpectedCode::Low; | ||
| 21 | } | |||
| 22 | ||||
| 23 | ✗ | return input; | ||
| 24 | } | |||
| 25 | }; | |||
| 26 | ||||
| 27 | ||||
| 28 | // extract the type of the elements in the bin/value arrays | |||
| 29 | using BinType = std::remove_extent_t<decltype(config->mafDecodingBins)>; | |||
| 30 | using ValueType = std::remove_extent_t<decltype(config->mafDecoding)>; | |||
| 31 | ||||
| 32 | // This function converts volts -> kg/h | |||
| 33 | static TableFunc mafCurve(config->mafDecodingBins, config->mafDecoding); | |||
| 34 | ||||
| 35 | // grumble grumble func_chain doesn't do constructor parameters so we need an adapter | |||
| 36 | struct MafTable : public SensorConverter { | |||
| 37 | ✗ | SensorResult convert(float input) const override { | ||
| 38 | ✗ | return mafCurve.convert(input); | ||
| 39 | } | |||
| 40 | }; | |||
| 41 | ||||
| 42 | struct MafFilter final : public SensorConverter { | |||
| 43 | ✗ | SensorResult convert(float input) const override { | ||
| 44 | // engine->outputChannels.mafMeasured_preFilter = input; | |||
| 45 | ||||
| 46 | ✗ | float param = engineConfiguration->mafFilterParameter; | ||
| 47 | ✗ | if (param == 0) { | ||
| 48 | ✗ | return input; | ||
| 49 | } | |||
| 50 | ||||
| 51 | ✗ | float rpm = Sensor::getOrZero(SensorType::Rpm); | ||
| 52 | ||||
| 53 | ✗ | if (rpm == 0) { | ||
| 54 | ✗ | m_lastValue = input; | ||
| 55 | ✗ | return input; | ||
| 56 | } | |||
| 57 | ||||
| 58 | ✗ | float invTimeConstant = rpm / param; | ||
| 59 | ✗ | float alpha = (1e-3 * FAST_CALLBACK_PERIOD_MS) * invTimeConstant; | ||
| 60 | ||||
| 61 | ✗ | if (alpha < 0.001f) { | ||
| 62 | // Limit to 0.001 to avoid numerical issues | |||
| 63 | ✗ | alpha = 0.001f; | ||
| 64 | ✗ | } else if (alpha > 0.98f) { | ||
| 65 | // alpha > 0.98 (engine very fast and/or small manifold) | |||
| 66 | // -> disable filtering entirely | |||
| 67 | ✗ | m_lastValue = input; | ||
| 68 | ✗ | return input; | ||
| 69 | } | |||
| 70 | ||||
| 71 | ✗ | m_lastValue = alpha * input + (1 - alpha) * m_lastValue; | ||
| 72 | ||||
| 73 | ✗ | return m_lastValue; | ||
| 74 | } | |||
| 75 | ||||
| 76 | mutable float m_lastValue = 0; | |||
| 77 | }; | |||
| 78 | ||||
| 79 | static FuncChain<MafVoltageCheck, MafTable, MafFilter> mafFunction; | |||
| 80 | ||||
| 81 | 4 | static void initMaf(adc_channel_e channel, FunctionalSensor& m) { | ||
| 82 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
|
4 | if (!isAdcChannelValid(channel)) { |
| 83 | 2 | return; | ||
| 84 | } | |||
| 85 | ||||
| 86 | 2 | m.setFunction(mafFunction); | ||
| 87 | ||||
| 88 | 2 | AdcSubscription::SubscribeSensor(m, channel, /*lowpassCutoff =*/ 50); | ||
| 89 | 2 | m.Register(); | ||
| 90 | } | |||
| 91 | ||||
| 92 | 2 | void initMaf() { | ||
| 93 | 2 | initMaf(engineConfiguration->mafAdcChannel, maf); | ||
| 94 | 2 | initMaf(engineConfiguration->maf2AdcChannel, maf2); | ||
| 95 | 2 | } | ||
| 96 |