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 |