GCC Code Coverage Report


Directory: ./
File: firmware/controllers/trigger/decoders/trigger_subaru.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 155 0 155
Functions: 100.0% 9 0 9
Branches: 66.7% 8 0 12
Decisions: 66.7% 8 - 12

Line Branch Decision Exec Source
1 /**
2 * @file trigger_subaru.cpp
3 *
4 * @date Sep 10, 2015
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8 #include "pch.h"
9
10 #include "trigger_subaru.h"
11
12 2 void initialize_one_of_36_2_2_2(TriggerWaveform *s, int firstCount, int secondCount) {
13 2 s->initialize(FOUR_STROKE_CRANK_SENSOR, SyncEdge::RiseOnly);
14
15 2 float narrow = 360 / 36;
16 2 float wide = narrow * 3;
17
18 2 float base = 0;
19
20
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 30 times.
✓ Decision 'false' taken 2 times.
32 for (int i = 0; i < firstCount; i++) {
21 30 s->addToothFallRise(base + narrow, narrow / 2);
22 30 base += narrow;
23 }
24
25 2 s->addToothFallRise(base + wide, wide / 2);
26 2 base += wide;
27
28
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 24 times.
✓ Decision 'false' taken 2 times.
26 for (int i = 0; i < secondCount; i++) {
29 24 s->addToothFallRise(base + narrow, narrow / 2);
30 24 base += narrow;
31 }
32
33 // depending on firstCount + secondCount we might have a gap here
34
35 2 s->addToothFallRise(360 - wide, narrow / 2);
36 2 s->addToothFallRise(360, narrow / 2);
37 2 }
38
39 /**
40 * This trigger is also used by Nissan and Mazda
41 * https://rusefi.com/forum/viewtopic.php?f=2&t=1932
42 */
43 1 void initialize36_2_2_2(TriggerWaveform *s) {
44 1 initialize_one_of_36_2_2_2(s, 12, 15);
45
46 #if EFI_UNIT_TEST
47 // usually used on crank but placed on 'cam' on '2-stroke' rotary
48 // this 'knownOperationMode' does not matter for trigger decoding only matters for .ini code generation and trigger images
49 1 s->knownOperationMode = false;
50 #endif // EFI_UNIT_TEST
51
52 // 36/2/2/2 data from https://rusefi.com/online/view.php?log=1287
53 // todo: probably should be unified with EZ30 below?
54 1 s->setTriggerSynchronizationGap3(/*gapIndex*/0, 0.25, 0.5);
55 1 s->setTriggerSynchronizationGap3(/*gapIndex*/1, 0.7, 1.7);
56 1 s->setTriggerSynchronizationGap3(/*gapIndex*/2, 2.25, 4.2);
57 1 }
58
59 1 void initializeSubaruEZ30(TriggerWaveform *s) {
60 1 initialize_one_of_36_2_2_2(s, 18, 9);
61
62 1 s->tdcPosition = 240;
63
64 1 s->setTriggerSynchronizationGap3(/*gapIndex*/0, 0.25, 0.5);
65 1 s->setTriggerSynchronizationGap3(/*gapIndex*/1, 0.7, 1.5);
66 1 s->setTriggerSynchronizationGap3(/*gapIndex*/2, 2, 4);
67 1 }
68
69 5 static void initializeSubaru7_6(TriggerWaveform *s, bool withCrankWheel) {
70 5 s->initialize(FOUR_STROKE_CAM_SENSOR, SyncEdge::RiseOnly);
71
72 /* To make trigger decoder happy last event should be exactly at 720
73 * This code generates two trigger patterns: crank+cam (7+6) and
74 * cam only (7-6).
75 * So last event should be CAM event
76 * Crank: --------||-|---||-|-----||-|---||-|
77 * Cam: -|-|-|------|------!-|------|------
78 * '!' pulse is selected as event at 720
79 * So next event is the first one on following description
80 * '!' pulse happens 20 degrees ATDC #2 (third in order)
81 * or 180 + 180 + 20. So we have */
82 5 s->tdcPosition = 160 + 360;
83
84 5 float width = 5;
85
86 /* 97 degrees BTDC, but we have 20 degrees shift:
87 * 180 - 97 - 20 = 63 */
88 #define SUBARU76_CRANK_PULSE0(cycle) \
89 s->addEvent720((180 * (cycle)) + 63 - width, TriggerValue::RISE, TriggerWheel::T_SECONDARY); \
90 s->addEvent720((180 * (cycle)) + 63, TriggerValue::FALL, TriggerWheel::T_SECONDARY)
91 /* 65 degrees BTDC, but we have 20 degrees shift:
92 * 180 - 65 - 20 = 95 */
93 #define SUBARU76_CRANK_PULSE1(cycle) \
94 s->addEvent720((180 * (cycle)) + 95 - width, TriggerValue::RISE, TriggerWheel::T_SECONDARY); \
95 s->addEvent720((180 * (cycle)) + 95, TriggerValue::FALL, TriggerWheel::T_SECONDARY)
96 /* 10 degrees BTDC, but we have 20 degrees shift:
97 * 180 - 10 - 20 = 150 */
98 #define SUBARU76_CRANK_PULSE2(cycle) \
99 s->addEvent720((180 * (cycle)) + 150 - width, TriggerValue::RISE, TriggerWheel::T_SECONDARY); \
100 s->addEvent720((180 * (cycle)) + 150, TriggerValue::FALL, TriggerWheel::T_SECONDARY)
101
102 #define SUBARU76_CAM_PULSE(cycle, offset) \
103 s->addEvent720((180 * (cycle)) + (offset) - width, TriggerValue::RISE, TriggerWheel::T_PRIMARY); \
104 s->addEvent720((180 * (cycle)) + (offset), TriggerValue::FALL, TriggerWheel::T_PRIMARY)
105
106 /* (TDC#2 + 20) + 15 */
107 5 SUBARU76_CAM_PULSE(0, +15);
108
109
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
5 if (withCrankWheel) {
110 5 SUBARU76_CRANK_PULSE0(0);
111 5 SUBARU76_CRANK_PULSE1(0);
112 5 SUBARU76_CRANK_PULSE2(0);
113 }
114
115 /* (TDC#4 + 20) */
116 5 SUBARU76_CAM_PULSE(1, 0);
117
118
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
5 if (withCrankWheel) {
119 5 SUBARU76_CRANK_PULSE0(1);
120 5 SUBARU76_CRANK_PULSE1(1);
121 5 SUBARU76_CRANK_PULSE2(1);
122 }
123
124 /* (TDC#1 + 20) - 15 */
125 5 SUBARU76_CAM_PULSE(2, -15);
126
127 /* (TDC#1 + 20) */
128 5 SUBARU76_CAM_PULSE(2, 0);
129
130 /* (TDC#1 + 20) + 15 */
131 5 SUBARU76_CAM_PULSE(2, +15);
132
133
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
5 if (withCrankWheel) {
134 5 SUBARU76_CRANK_PULSE0(2);
135 5 SUBARU76_CRANK_PULSE1(2);
136 5 SUBARU76_CRANK_PULSE2(2);
137 }
138
139 /* (TDC#3 + 20) */
140 5 SUBARU76_CAM_PULSE(3, 0);
141
142
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
5 if (withCrankWheel) {
143 5 SUBARU76_CRANK_PULSE0(3);
144 5 SUBARU76_CRANK_PULSE1(3);
145 5 SUBARU76_CRANK_PULSE2(3);
146 }
147
148 /* (TDC#2 + 20) */
149 5 SUBARU76_CAM_PULSE(4, 0);
150
151 // why is this trigger gap wider than average?
152 5 s->setTriggerSynchronizationGap3(/*index*/0, 6.53 * TRIGGER_GAP_DEVIATION_LOW, 15);
153 5 s->setTriggerSynchronizationGap3(/*index*/1, 0.3, 1 * TRIGGER_GAP_DEVIATION_HIGH);
154 5 s->setTriggerSynchronizationGap3(/*index*/2, 0.08, 0.3);
155
156 5 s->useOnlyPrimaryForSync = withCrankWheel;
157 5 }
158
159 5 void initializeSubaru7_6(TriggerWaveform *s) {
160 5 initializeSubaru7_6(s, true);
161 5 }
162
163 7 void initializeSubaru7_6_camOnly(TriggerWaveform *s) {
164 7 s->initialize(FOUR_STROKE_CAM_SENSOR, SyncEdge::RiseOnly);
165
166 7 const float width = 1;
167 7 const float offset = 720 - (3 * 180 + 20);
168
169 7 s->tdcPosition = 180 + offset;
170
171 #define SUBARU76_CAMONLY_PULSE(cyl, subtooth) \
172 s->addEventAngle(offset + (180 * (cyl)) + 20 + (15 * (subtooth)) - width, TriggerValue::RISE, TriggerWheel::T_PRIMARY); \
173 s->addEventAngle(offset + (180 * (cyl)) + 20 + (15 * (subtooth)), TriggerValue::FALL, TriggerWheel::T_PRIMARY)
174
175 // CYL1
176 // 5, 20, 35
177 7 SUBARU76_CAMONLY_PULSE(0, -1);
178 7 SUBARU76_CAMONLY_PULSE(0, 0);
179 7 SUBARU76_CAMONLY_PULSE(0, +1);
180
181 // CYL3
182 // 200
183 7 SUBARU76_CAMONLY_PULSE(1, 0);
184
185 // CYL2
186 // 380, 395
187 7 SUBARU76_CAMONLY_PULSE(2, 0);
188 7 SUBARU76_CAMONLY_PULSE(2, +1);
189
190 // CYL4
191 // 560
192 7 SUBARU76_CAMONLY_PULSE(3, 0);
193
194 // Tooths positions, deltas and gap ratios
195 // (5, 20, 35, 200, 380, 395, 560) 725...
196 // (15, 15, 165, 180, 15, 165, 165) 15...
197 // K: 0.09, 1, 11,1.09,0.08, 11, 1)0.09
198
199 // Gaps: 1, 0.09, 1, 11 at 560
200 //s->setTriggerSynchronizationGap3(0, 0.50, 1.50);
201 //s->setTriggerSynchronizationGap3(0, 0.04, 0.15);
202 //s->setTriggerSynchronizationGap3(1, 0.50, 1.50);
203 //s->setTriggerSynchronizationGap3(2, 7.00, 15.00);
204
205 7 s->setTriggerSynchronizationGap3(/*index*/0, 6.53 * TRIGGER_GAP_DEVIATION_LOW, 15);
206 7 s->setTriggerSynchronizationGap3(/*index*/1, 0.3, 1 * TRIGGER_GAP_DEVIATION_HIGH);
207 7 s->setTriggerSynchronizationGap3(/*index*/2, 0.08, 0.3);
208 7 }
209
210 7 void initializeSubaruOnly7(TriggerWaveform *s) {
211 //initializeSubaru7_6(s, false);
212 7 initializeSubaru7_6_camOnly(s);
213 7 }
214
215 5 void initializeSubaru7_6_crankOnly(TriggerWaveform *s) {
216 /**
217 * Note how we use 0..180 range while defining FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR trigger
218 * Note that only half of the physical wheel is defined here!
219 */
220 5 s->initialize(FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR, SyncEdge::RiseOnly);
221
222 5 const float width = 1;
223 5 const float offset = 10;
224
225 5 s->tdcPosition = 65;
226
227 // BTDC: 97, 65, 10
228 // Distances: 93, 32, 55
229 5 s->addEventAngle(180 + offset - 97 - width, TriggerValue::RISE, TriggerWheel::T_PRIMARY);
230 5 s->addEventAngle(180 + offset - 97, TriggerValue::FALL, TriggerWheel::T_PRIMARY);
231
232 5 s->addEventAngle(180 + offset - 65 - width, TriggerValue::RISE, TriggerWheel::T_PRIMARY);
233 5 s->addEventAngle(180 + offset - 65, TriggerValue::FALL, TriggerWheel::T_PRIMARY);
234
235 5 s->addEventAngle(180 + offset - 10 - width, TriggerValue::RISE, TriggerWheel::T_PRIMARY);
236 5 s->addEventAngle(180 + offset - 10, TriggerValue::FALL, TriggerWheel::T_PRIMARY);
237
238 // Nominal gaps:
239 // 55 / 32 = 1.7187
240 //s->setTriggerSynchronizationGap2(0.85f, 3.43f);
241 // 93 / 55 = 1.6909
242 //s->setTriggerSynchronizationGap2(0.84f, 3.38);
243 // 32 / 93 = 0.344
244 5 s->setTriggerSynchronizationGap2(0.172f, 0.688f);
245 5 }
246
247 /*
248 * Falling edges showed only:
249 * 6 3 2 5 4 1
250 * Cr #1 |-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
251 * Cr #2 ---|-|-|---|-|-----|-------|-|-|---|-|-----|-------
252 * Cam -|-------------------------------------------------
253 *
254 * Cr #1 last falling edge BTDC: 10
255 * Cr #2 single tooth's falling edge BTDC #1, #2: (55 + 1)
256 * There is no details about gap betweent Cr #2 tooths in 2 and 3 groups.
257 * Looking at timing diagram it is same as for Cr #1 = 30 degrees.
258 * So:
259 * Cr #2 two tooth group BTDC #3, #4: (55 + 1), (55 + 1 - 30)
260 * Cr #2 three tooth group BTDC #5, #6: (55 + 1), (55 + 1 - 30), (55 + 1 - 60) - last event actually after DTC
261 * Again there is no details about Cam tooth position, looking at
262 * diagrams it is about 30 degrees after #1 TDC
263 * Cam single tooth falling edge BTDC #6: (120 - 30) = 90
264 */
265
266 3 void initializeSubaru_SVX(TriggerWaveform *s) {
267 int n;
268 /* we should use only falling edges */
269 3 float width = 5.0;
270
271 3 float offset = 10.0; /* to make last event @ 720 */
272
273 /* T_CHANNEL_3 currently not supported, to keep trigger decode happy
274 * set cam second as primary, so logic will be able to sync
275 * Crank angle sensor #1 = TriggerWheel:: T_SECONDARY
276 * Crank andle sensor #2 = T_CHANNEL_3 - not supported yet
277 * Cam angle sensor = T_PRIMARY */
278 #define SVX_CRANK_1 TriggerWheel::T_SECONDARY
279 //#define SVX_CRANK_2 T_CHANNEL_3
280 #define SVX_CAM TriggerWheel::T_PRIMARY
281
282 #define CRANK_1_FALL(n) (20.0 + offset + 30.0 * (n))
283 #define CRANK_1_RISE(n) (CRANK_1_FALL(n) - width)
284
285 #define SUBARU_SVX_CRANK1_PULSE(n) \
286 s->addEventAngle(CRANK_1_RISE(n), TriggerValue::RISE, SVX_CRANK_1); \
287 s->addEventAngle(CRANK_1_FALL(n), TriggerValue::FALL, SVX_CRANK_1)
288
289 /* cam falling edge offset from preceding Cr #1 falling edge */
290 3 float cam_offset = (10.0 + 30.0 + 30.0 + 30.0) - 90.0;
291 #define SUBARU_SVX_CAM_PULSE(n) \
292 s->addEvent720(CRANK_1_RISE(n) + cam_offset, TriggerValue::RISE, SVX_CAM); \
293 s->addEvent720(CRANK_1_FALL(n) + cam_offset, TriggerValue::FALL, SVX_CAM)
294
295 #ifdef SVX_CRANK_2
296 /* Cr #2 signle tooth falling edge is (55 + 1) BTDC
297 * preceding Cr #1 falling edge is (10 + 30 + 30) BTDC */
298 float crank_2_offset = (10.0 + 30.0 + 30.0) - (55.0 + 1.0);
299
300 #define SUBARU_SVX_CRANK2_PULSE(n) \
301 s->addEvent720(CRANK_1_RISE(n) + crank_2_offset, TriggerValue::RISE, SVX_CRANK_2); \
302 s->addEvent720(CRANK_1_FALL(n) + crank_2_offset, TriggerValue::FALL, SVX_CRANK_2)
303 #else
304 #define SUBARU_SVX_CRANK2_PULSE(n) (void)(n)
305 #endif
306
307 /* we should use only falling edges */
308 // TODO: this trigger needs to be converted to SyncEdge::RiseOnly, so invert all rise/fall events!
309 // see https://github.com/rusefi/rusefi/issues/4624
310 3 s->initialize(FOUR_STROKE_CAM_SENSOR, SyncEdge::Fall);
311 3 s->isSynchronizationNeeded = false;
312 3 s->useOnlyPrimaryForSync = true;
313
314 /* counting Crank #1 tooths, should reach 23 at the end */
315 3 n = 0;
316 /****** 0 *****/
317 3 SUBARU_SVX_CRANK1_PULSE(n);
318 3 n++;
319 3 SUBARU_SVX_CRANK1_PULSE(n);
320 /* crank #2 - one 1/1 */
321 SUBARU_SVX_CRANK2_PULSE(n);
322 3 n++;
323 3 SUBARU_SVX_CRANK1_PULSE(n);
324 3 n++;
325 3 SUBARU_SVX_CRANK1_PULSE(n);
326 /* +10 - TDC #1 */
327 3 n++;
328 3 SUBARU_SVX_CRANK1_PULSE(n);
329 /* cam - one */
330 3 SUBARU_SVX_CAM_PULSE(n);
331 3 n++;
332 3 SUBARU_SVX_CRANK1_PULSE(n);
333 /* crank #2 - three - 1/3 */
334 SUBARU_SVX_CRANK2_PULSE(n);
335 3 n++;
336 3 SUBARU_SVX_CRANK1_PULSE(n);
337 /* crank #2 - three - 2/3 */
338 SUBARU_SVX_CRANK2_PULSE(n);
339 3 n++;
340 3 SUBARU_SVX_CRANK1_PULSE(n);
341 /* +10 - TDC #6 */
342 /* crank #2 - three - 3/3 */
343 SUBARU_SVX_CRANK2_PULSE(n);
344 3 n++;
345 3 SUBARU_SVX_CRANK1_PULSE(n);
346 3 n++;
347 3 SUBARU_SVX_CRANK1_PULSE(n);
348 /* crank #2 - two - 1/2 */
349 SUBARU_SVX_CRANK2_PULSE(n);
350 3 n++;
351 3 SUBARU_SVX_CRANK1_PULSE(n);
352 /* crank #2 - two - 2/2 */
353 SUBARU_SVX_CRANK2_PULSE(n);
354 3 n++;
355 3 SUBARU_SVX_CRANK1_PULSE(n);
356 /* +10 - TDC #3 */
357
358 /****** 360 *****/
359 3 n++;
360 3 SUBARU_SVX_CRANK1_PULSE(n);
361 3 n++;
362 3 SUBARU_SVX_CRANK1_PULSE(n);
363 /* crank #2 - one - 1/1 */
364 SUBARU_SVX_CRANK2_PULSE(n);
365 3 n++;
366 3 SUBARU_SVX_CRANK1_PULSE(n);
367 3 n++;
368 3 SUBARU_SVX_CRANK1_PULSE(n);
369 /* +10 - TDC #2 */
370 3 n++;
371 3 SUBARU_SVX_CRANK1_PULSE(n);
372 3 n++;
373 3 SUBARU_SVX_CRANK1_PULSE(n);
374 /* crank #2 - three - 1/3 */
375 SUBARU_SVX_CRANK2_PULSE(n);
376 3 n++;
377 3 SUBARU_SVX_CRANK1_PULSE(n);
378 /* crank #2 - three - 2/3 */
379 SUBARU_SVX_CRANK2_PULSE(n);
380 3 n++;
381 3 SUBARU_SVX_CRANK1_PULSE(n);
382 /* +10 - TDC #5 */
383 /* crank #2 - three - 3/3 */
384 SUBARU_SVX_CRANK2_PULSE(n);
385 3 n++;
386 3 SUBARU_SVX_CRANK1_PULSE(n);
387 3 n++;
388 3 SUBARU_SVX_CRANK1_PULSE(n);
389 /* crank #2 - two - 1/2 */
390 SUBARU_SVX_CRANK2_PULSE(n);
391 3 n++;
392 3 SUBARU_SVX_CRANK1_PULSE(n);
393 /* crank #2 - two - 2/2 */
394 SUBARU_SVX_CRANK2_PULSE(n);
395 3 n++;
396 3 SUBARU_SVX_CRANK1_PULSE(n);
397 /* +10 - TDC #4 */
398 /****** 720 *****/
399
400 /* from sichronization point, which is Cam falling */
401 3 s->tdcPosition = 720 - 30;
402
403 #undef SUBARU_SVX_CRANK1_PULSE
404 #undef SUBARU_SVX_CRANK2_PULSE
405 #undef SUBARU_SVX_CAM_PULSE
406 3 }
407