GCC Code Coverage Report


Directory: ./
File: firmware/controllers/math/firing_order.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 33.1% 41 0 124
Functions: 75.0% 3 0 4
Branches: 31.2% 20 0 64
Decisions: 35.3% 24 - 68

Line Branch Decision Exec Source
1 #include "pch.h"
2
3 static const uint8_t order_1[] = {1};
4
5 static const uint8_t order_1_2[] = {1, 2};
6
7 static const uint8_t order_1_2_3[] = {1, 2, 3};
8 static const uint8_t order_1_3_2[] = {1, 3, 2};
9 // 4 cylinder
10
11 static const uint8_t order_1_THEN_3_THEN_4_THEN2[] = { 1, 3, 4, 2 };
12 static const uint8_t order_1_THEN_2_THEN_4_THEN3[] = { 1, 2, 4, 3 };
13 static const uint8_t order_1_THEN_3_THEN_2_THEN4[] = { 1, 3, 2, 4 };
14 static const uint8_t order_1_THEN_4_THEN_3_THEN2[] = { 1, 4, 3, 2 };
15
16 // 5 cylinder
17 static const uint8_t order_1_2_4_5_3[] = {1, 2, 4, 5, 3};
18
19 // 6 cylinder
20 static const uint8_t order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[] = { 1, 5, 3, 6, 2, 4 };
21 static const uint8_t order_1_THEN_4_THEN_2_THEN_5_THEN_3_THEN_6[] = { 1, 4, 2, 5, 3, 6 };
22 static const uint8_t order_1_THEN_2_THEN_3_THEN_4_THEN_5_THEN_6[] = { 1, 2, 3, 4, 5, 6 };
23 static const uint8_t order_1_6_3_2_5_4[] = {1, 6, 3, 2, 5, 4};
24 static const uint8_t order_1_4_3_6_2_5[] = {1, 4, 3, 6, 2, 5};
25 static const uint8_t order_1_6_2_4_3_5[] = {1, 6, 2, 4, 3, 5};
26 static const uint8_t order_1_6_5_4_3_2[] = {1, 6, 5, 4, 3, 2};
27 static const uint8_t order_1_4_5_2_3_6[] = {1, 4, 5, 2, 3, 6};
28
29 // 8 cylinder
30 static const uint8_t order_1_8_4_3_6_5_7_2[] = { 1, 8, 4, 3, 6, 5, 7, 2 };
31 static const uint8_t order_1_8_7_2_6_5_4_3[] = { 1, 8, 7, 2, 6, 5, 4, 3 };
32 static const uint8_t order_1_5_4_2_6_3_7_8[] = { 1, 5, 4, 2, 6, 3, 7, 8 };
33 static const uint8_t order_1_2_7_8_4_5_6_3[] = { 1, 2, 7, 8, 4, 5, 6, 3 };
34 static const uint8_t order_1_3_7_2_6_5_4_8[] = { 1, 3, 7, 2, 6, 5, 4, 8 };
35 static const uint8_t order_1_2_3_4_5_6_7_8[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
36 static const uint8_t order_1_5_4_8_6_3_7_2[] = { 1, 5, 4, 8, 6, 3, 7, 2 };
37 static const uint8_t order_1_8_7_3_6_5_4_2[] = { 1, 8, 7, 3, 6, 5, 4, 2 };
38 static const uint8_t order_1_5_4_8_3_7_2_6[] = { 1, 5, 4, 8, 3, 7, 2, 6 };
39 static const uint8_t order_1_8_6_2_7_3_4_5[] = { 1, 8, 6, 2, 7, 3, 4, 5 };
40
41 // 9 cylinder
42 static const uint8_t order_1_2_3_4_5_6_7_8_9[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
43
44 // 10 cylinder
45 static const uint8_t order_1_10_9_4_3_6_5_8_7_2[] = {1, 10, 9, 4, 3, 6, 5, 8, 7, 2};
46 static const uint8_t order_1_6_5_10_2_7_3_8_4_9[] = {1, 6, 5, 10, 2, 7, 3, 8, 4, 9};
47
48 // 12 cyliner
49 static const uint8_t order_1_7_5_11_3_9_6_12_2_8_4_10[] = {1, 7, 5, 11, 3, 9, 6, 12, 2, 8, 4, 10};
50 static const uint8_t order_1_7_4_10_2_8_6_12_3_9_5_11[] = {1, 7, 4, 10, 2, 8, 6, 12, 3, 9, 5, 11};
51 static const uint8_t order_1_12_5_8_3_10_6_7_2_11_4_9[] = {1, 12, 5, 8, 3, 10, 6, 7, 2, 11, 4, 9};
52 static const uint8_t order_1_2_3_4_5_6_7_8_9_10_11_12[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
53
54 // no comments
55 static const uint8_t order_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10[] = {1, 14, 9, 4, 7, 12, 15, 6, 13, 8, 3, 16, 11, 2, 5, 10};
56
57 13975 static size_t getFiringOrderLength() {
58
59
7/12
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12721 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 930 times.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 60 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
13975 switch (engineConfiguration->firingOrder) {
60
1/1
✓ Decision 'true' taken 16 times.
16 case FO_1:
61 16 return 1;
62 // 2 cylinder
63
1/1
✓ Decision 'true' taken 220 times.
220 case FO_1_2:
64 220 return 2;
65 // 3 cylinder
66
1/1
✓ Decision 'true' taken 12 times.
12 case FO_1_2_3:
67 case FO_1_3_2:
68
1/1
✓ Decision 'true' taken 12 times.
12 return 3;
69 // 4 cylinder
70
1/1
✓ Decision 'true' taken 12721 times.
12721 case FO_1_3_4_2:
71 case FO_1_2_4_3:
72 case FO_1_3_2_4:
73 case FO_1_4_3_2:
74
1/1
✓ Decision 'true' taken 12721 times.
12721 return 4;
75 // 5 cylinder
76 case FO_1_2_4_5_3:
77 return 5;
78
79 // 6 cylinder
80
1/1
✓ Decision 'true' taken 930 times.
930 case FO_1_5_3_6_2_4:
81 case FO_1_4_2_5_3_6:
82 case FO_1_2_3_4_5_6:
83 case FO_1_6_3_2_5_4:
84 case FO_1_4_3_6_2_5:
85 case FO_1_6_2_4_3_5:
86 case FO_1_6_5_4_3_2:
87 case FO_1_4_5_2_3_6:
88
1/1
✓ Decision 'true' taken 930 times.
930 return 6;
89
90 // 8 cylinder
91
1/1
✓ Decision 'true' taken 16 times.
16 case FO_1_8_4_3_6_5_7_2:
92 case FO_1_8_7_2_6_5_4_3:
93 case FO_1_5_4_2_6_3_7_8:
94 case FO_1_2_7_8_4_5_6_3:
95 case FO_1_3_7_2_6_5_4_8:
96 case FO_1_2_3_4_5_6_7_8:
97 case FO_1_5_4_8_6_3_7_2:
98 case FO_1_8_7_3_6_5_4_2:
99 case FO_1_5_4_8_3_7_2_6:
100 case FO_1_8_6_2_7_3_4_5:
101
1/1
✓ Decision 'true' taken 16 times.
16 return 8;
102
103 // 9 cylinder radial
104 case FO_1_2_3_4_5_6_7_8_9:
105 return 9;
106
107 // 10 cylinder
108 case FO_1_10_9_4_3_6_5_8_7_2:
109 case FO_1_6_5_10_2_7_3_8_4_9:
110 return 10;
111
112 // 12 cylinder
113
1/1
✓ Decision 'true' taken 60 times.
60 case FO_1_7_5_11_3_9_6_12_2_8_4_10:
114 case FO_1_7_4_10_2_8_6_12_3_9_5_11:
115 case FO_1_12_5_8_3_10_6_7_2_11_4_9:
116 case FO_1_2_3_4_5_6_7_8_9_10_11_12:
117
1/1
✓ Decision 'true' taken 60 times.
60 return 12;
118
119 case FO_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10:
120 return 16;
121
122 default:
123 firmwareError(ObdCode::CUSTOM_OBD_UNKNOWN_FIRING_ORDER, "Invalid firing order: %d", engineConfiguration->firingOrder);
124 }
125 return 1;
126 }
127
128 13975 static const uint8_t* getFiringOrderTable() {
129
8/36
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12721 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 820 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 110 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 16 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 30 taken 60 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
13975 switch (engineConfiguration->firingOrder) {
130
1/1
✓ Decision 'true' taken 16 times.
16 case FO_1:
131 16 return order_1;
132 // 2 cylinder
133
1/1
✓ Decision 'true' taken 220 times.
220 case FO_1_2:
134 220 return order_1_2;
135 // 3 cylinder
136
1/1
✓ Decision 'true' taken 12 times.
12 case FO_1_2_3:
137 12 return order_1_2_3;
138 case FO_1_3_2:
139 return order_1_3_2;
140 // 4 cylinder
141
1/1
✓ Decision 'true' taken 12721 times.
12721 case FO_1_3_4_2:
142 12721 return order_1_THEN_3_THEN_4_THEN2;
143 case FO_1_2_4_3:
144 return order_1_THEN_2_THEN_4_THEN3;
145 case FO_1_3_2_4:
146 return order_1_THEN_3_THEN_2_THEN4;
147 case FO_1_4_3_2:
148 return order_1_THEN_4_THEN_3_THEN2;
149 // 5 cylinder
150 case FO_1_2_4_5_3:
151 return order_1_2_4_5_3;
152
153 // 6 cylinder
154
1/1
✓ Decision 'true' taken 820 times.
820 case FO_1_5_3_6_2_4:
155 820 return order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4;
156 case FO_1_4_2_5_3_6:
157 return order_1_THEN_4_THEN_2_THEN_5_THEN_3_THEN_6;
158
1/1
✓ Decision 'true' taken 110 times.
110 case FO_1_2_3_4_5_6:
159 110 return order_1_THEN_2_THEN_3_THEN_4_THEN_5_THEN_6;
160 case FO_1_6_3_2_5_4:
161 return order_1_6_3_2_5_4;
162 case FO_1_4_3_6_2_5:
163 return order_1_4_3_6_2_5;
164 case FO_1_6_2_4_3_5:
165 return order_1_6_2_4_3_5;
166 case FO_1_6_5_4_3_2:
167 return order_1_6_5_4_3_2;
168 case FO_1_4_5_2_3_6:
169 return order_1_4_5_2_3_6;
170
171 // 8 cylinder
172
1/1
✓ Decision 'true' taken 16 times.
16 case FO_1_8_4_3_6_5_7_2:
173 16 return order_1_8_4_3_6_5_7_2;
174 case FO_1_8_7_2_6_5_4_3:
175 return order_1_8_7_2_6_5_4_3;
176 case FO_1_5_4_2_6_3_7_8:
177 return order_1_5_4_2_6_3_7_8;
178 case FO_1_2_7_8_4_5_6_3:
179 return order_1_2_7_8_4_5_6_3;
180 case FO_1_3_7_2_6_5_4_8:
181 return order_1_3_7_2_6_5_4_8;
182 case FO_1_2_3_4_5_6_7_8:
183 return order_1_2_3_4_5_6_7_8;
184 case FO_1_5_4_8_6_3_7_2:
185 return order_1_5_4_8_6_3_7_2;
186 case FO_1_8_7_3_6_5_4_2:
187 return order_1_8_7_3_6_5_4_2;
188 case FO_1_5_4_8_3_7_2_6:
189 return order_1_5_4_8_3_7_2_6;
190 case FO_1_8_6_2_7_3_4_5:
191 return order_1_5_4_8_3_7_2_6;
192
193 // 9 cylinder
194 case FO_1_2_3_4_5_6_7_8_9:
195 return order_1_2_3_4_5_6_7_8_9;
196
197
198 // 10 cylinder
199 case FO_1_10_9_4_3_6_5_8_7_2:
200 return order_1_10_9_4_3_6_5_8_7_2;
201 case FO_1_6_5_10_2_7_3_8_4_9:
202 return order_1_6_5_10_2_7_3_8_4_9;
203
204 // 12 cylinder
205
1/1
✓ Decision 'true' taken 60 times.
60 case FO_1_7_5_11_3_9_6_12_2_8_4_10:
206 60 return order_1_7_5_11_3_9_6_12_2_8_4_10;
207 case FO_1_7_4_10_2_8_6_12_3_9_5_11:
208 return order_1_7_4_10_2_8_6_12_3_9_5_11;
209 case FO_1_12_5_8_3_10_6_7_2_11_4_9:
210 return order_1_12_5_8_3_10_6_7_2_11_4_9;
211 case FO_1_2_3_4_5_6_7_8_9_10_11_12:
212 return order_1_2_3_4_5_6_7_8_9_10_11_12;
213
214 // do not ask
215 case FO_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10:
216 return order_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10;
217
218 default:
219 firmwareError(ObdCode::CUSTOM_OBD_UNKNOWN_FIRING_ORDER, "Invalid firing order: %d", engineConfiguration->firingOrder);
220 }
221
222 return NULL;
223 }
224
225 /**
226 * @param index from zero to cylindersCount - 1
227 * @return cylinderId from one to cylindersCount
228 */
229 13975 size_t getCylinderNumberAtIndex(size_t index) {
230 13975 const size_t firingOrderLength = getFiringOrderLength();
231
232
2/4
✓ Branch 0 taken 13975 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13975 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 13975 times.
13975 if (firingOrderLength < 1 || firingOrderLength > MAX_CYLINDER_COUNT) {
233 firmwareError(ObdCode::CUSTOM_FIRING_LENGTH, "fol %d", firingOrderLength);
234 return 0;
235 }
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13975 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 13975 times.
13975 if (engineConfiguration->cylindersCount != firingOrderLength) {
237 // May 2020 this somehow still happens with functional tests, maybe race condition?
238 firmwareError(ObdCode::CUSTOM_OBD_WRONG_FIRING_ORDER, "Wrong cyl count for firing order, expected %d cylinders, got %d", firingOrderLength, engineConfiguration->cylindersCount);
239 return 0;
240 }
241
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13975 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 13975 times.
13975 if (index >= firingOrderLength) {
243 // May 2020 this somehow still happens with functional tests, maybe race condition?
244 warning(ObdCode::CUSTOM_ERR_6686, "firing order index %d", index);
245 return 0;
246 }
247
248
1/2
✓ Branch 1 taken 13975 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 13975 times.
✗ Decision 'false' not taken.
13975 if (auto firingOrderTable = getFiringOrderTable()) {
249 13975 return firingOrderTable[index] - 1;
250 } else {
251 // error already reported
252 return 0;
253 }
254 }
255
256 /**
257 * @param prevCylinderId from one to cylindersCount
258 * @return cylinderId from one to cylindersCount
259 */
260 size_t getNextFiringCylinderId(size_t prevCylinderId) {
261 const size_t firingOrderLength = getFiringOrderLength();
262 auto firingOrderTable = getFiringOrderTable();
263
264 if (firingOrderTable) {
265 for (size_t i = 0; i < firingOrderLength; i++) {
266 if (firingOrderTable[i] == prevCylinderId) {
267 return firingOrderTable[(i + 1) % firingOrderLength];
268 }
269 }
270 }
271
272 return 1;
273 }
274