GCC Code Coverage Report


Directory: ./
File: firmware/controllers/sensors/impl/ego.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 30.2% 19 0 63
Functions: 50.0% 2 0 4
Branches: 7.7% 2 0 26
Decisions: 15.4% 2 - 13

Line Branch Decision Exec Source
1 /**
2 * @author Andrey Belomutskiy, (c) 2012-2020
3 *
4 * EGO Exhaust Gas Oxygen, also known as AFR Air/Fuel Ratio :) connectet over analog input
5 *
6 */
7 #include "pch.h"
8
9 StoredValueSensor smoothedLambda1Sensor(SensorType::SmoothedLambda1, MS2NT(500));
10 StoredValueSensor smoothedLambda2Sensor(SensorType::SmoothedLambda2, MS2NT(500));
11
12 ExpAverage expAverageLambda1;
13 ExpAverage expAverageLambda2;
14
15 #include "cyclic_buffer.h"
16
17 bool hasAfrSensor() {
18 if (engineConfiguration->enableAemXSeries) {
19 return true;
20 }
21
22 return isAdcChannelValid(engineConfiguration->afr.hwChannel);
23 }
24
25 float getAfr(SensorType type) {
26 afr_sensor_s * sensor = &engineConfiguration->afr;
27
28 if (!isAdcChannelValid(type == SensorType::Lambda1 ? engineConfiguration->afr.hwChannel : engineConfiguration->afr.hwChannel2)) {
29 return 0;
30 }
31
32 auto volts = adcGetScaledVoltage("ego", type == SensorType::Lambda1 ? sensor->hwChannel : sensor->hwChannel2);
33
34 float interpolatedAfr = interpolateMsg("AFR", sensor->v1, sensor->value1, sensor->v2, sensor->value2, volts.value_or(0));
35
36 switch (type) {
37 case SensorType::Lambda1: {
38 expAverageLambda1.setSmoothingFactor(engineConfiguration->afrExpAverageAlpha);
39 smoothedLambda1Sensor.setValidValue(expAverageLambda1.initOrAverage(interpolatedAfr), getTimeNowNt());
40 break;
41 }
42 case SensorType::Lambda2: {
43 expAverageLambda2.setSmoothingFactor(engineConfiguration->afrExpAverageAlpha);
44 smoothedLambda2Sensor.setValidValue(expAverageLambda2.initOrAverage(interpolatedAfr), getTimeNowNt());
45 break;
46 }
47 default:
48 break;
49 }
50
51 return interpolateMsg("AFR", sensor->v1, sensor->value1, sensor->v2, sensor->value2, volts.value_or(0))
52 + engineConfiguration->egoValueShift;
53 }
54
55 // this method is only used for canned tunes now! User-facing selection is defined in tunerstudio.template.ini using settingSelector
56 589 static void initEgoSensor(afr_sensor_s *sensor, ego_sensor_e type) {
57
58
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 586 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
589 switch (type) {
59 case ES_BPSX_D1:
60 /**
61 * This decodes BPSX D1 Wideband Controller analog signal
62 */
63 sensor->v1 = 0;
64 sensor->value1 = 9;
65 sensor->v2 = 5;
66 sensor->value2 = 19;
67 break;
68
69 case ES_Innovate_MTX_L:
70 sensor->v1 = 0;
71 sensor->value1 = 7.35;
72 sensor->v2 = 5;
73 sensor->value2 = 22.39;
74 break;
75
1/1
✓ Decision 'true' taken 586 times.
586 case ES_14Point7_Free:
76 586 sensor->v1 = 0;
77 586 sensor->value1 = 9.996;
78 586 sensor->v2 = 5;
79 586 sensor->value2 = 19.992;
80 586 break;
81 // technically 14Point7 and PLX use the same scale
82
1/1
✓ Decision 'true' taken 3 times.
3 case ES_PLX:
83 3 sensor->v1 = 0;
84 3 sensor->value1 = 10;
85 3 sensor->v2 = 5;
86 3 sensor->value2 = 20;
87 3 break;
88 case ES_AEM:
89 sensor->v1 = 0.5;
90 sensor->value1 = 8.5;
91 sensor->v2 = 4.5;
92 sensor->value2 = 18;
93 break;
94 default:
95 firmwareError(ObdCode::CUSTOM_EGO_TYPE, "Unexpected EGO %d", type);
96 break;
97 }
98 589 }
99
100 589 void setEgoSensor(ego_sensor_e type) {
101 589 engineConfiguration->afr_type = type;
102 589 initEgoSensor(&engineConfiguration->afr, type);
103 589 }
104