Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /* | |||
2 | * @file trigger_universal.cpp | |||
3 | * | |||
4 | * @date Jan 3, 2017 | |||
5 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
6 | */ | |||
7 | ||||
8 | #include "pch.h" | |||
9 | ||||
10 | #include "trigger_universal.h" | |||
11 | ||||
12 | /** | |||
13 | * @see getCycleDuration | |||
14 | */ | |||
15 | 128350 | angle_t getEngineCycle(operation_mode_e operationMode) { | ||
16 |
2/2✓ Branch 0 taken 2826 times.
✓ Branch 1 taken 125524 times.
|
128350 | return operationMode == TWO_STROKE ? 360 : FOUR_STROKE_ENGINE_CYCLE; | |
17 | } | |||
18 | ||||
19 | /** | |||
20 | * last fall aligned at 720 and skipped area is right before 720 | |||
21 | */ | |||
22 | 277 | void addSkippedToothTriggerEvents(TriggerWheel wheel, TriggerWaveform *s, int totalTeethCount, int skippedCount, | ||
23 | float toothWidthPercentage, float offset, float engineCycle, float filterLeft, float filterRight) { | |||
24 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 277 times.
|
277 | criticalAssertVoid(totalTeethCount > 0, "total count"); | |
25 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 277 times.
|
277 | criticalAssertVoid(skippedCount >= 0, "skipped count"); | |
26 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 277 times.
|
277 | criticalAssertVoid(toothWidthPercentage < 1, "toothWidthPercentage"); | |
27 | ||||
28 | 277 | float oneTooth = engineCycle / totalTeethCount; | ||
29 | ||||
30 |
2/2✓ Branch 0 taken 4632 times.
✓ Branch 1 taken 277 times.
|
2/2✓ Decision 'true' taken 4632 times.
✓ Decision 'false' taken 277 times.
|
4909 | for (int i = 0; i < totalTeethCount - skippedCount - 1; i++) { |
31 | 4632 | float angleDown = oneTooth * (i + (1 - toothWidthPercentage)); | ||
32 | 4632 | float angleUp = oneTooth * (i + 1); | ||
33 | 4632 | s->addEventClamped(offset + angleDown, TriggerValue::RISE, wheel, filterLeft, filterRight); | ||
34 | 4632 | s->addEventClamped(offset + angleUp, TriggerValue::FALL, wheel, filterLeft, filterRight); | ||
35 | } | |||
36 | ||||
37 | 277 | float angleDown = oneTooth * (totalTeethCount - skippedCount - 1 + (1 - toothWidthPercentage)); | ||
38 | 277 | s->addEventClamped(offset + angleDown, TriggerValue::RISE, wheel, filterLeft, filterRight); | ||
39 | // custom handling of last event in order to avoid rounding error | |||
40 | 277 | s->addEventClamped(offset + engineCycle, TriggerValue::FALL, wheel, filterLeft, filterRight); | ||
41 | } | |||
42 | ||||
43 | 242 | void initializeSkippedToothTrigger(TriggerWaveform *s, int totalTeethCount, int skippedCount, | ||
44 | operation_mode_e operationMode, SyncEdge syncEdge) { | |||
45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 242 times.
|
242 | if (totalTeethCount <= 0) { |
46 | ✗ | firmwareError(ObdCode::CUSTOM_OBD_TRIGGER_WAVEFORM, "Invalid total tooth count for missing tooth decoder: %d", totalTeethCount); | ||
47 | ✗ | s->setShapeDefinitionError(true); | ||
48 | ✗ | return; | ||
49 | } | |||
50 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
|
242 | efiAssertVoid(ObdCode::CUSTOM_NULL_SHAPE, s != NULL, "TriggerWaveform is NULL"); | |
51 | ||||
52 | 242 | s->initialize(operationMode, syncEdge); | ||
53 | ||||
54 | #if EFI_UNIT_TEST | |||
55 | 242 | s->knownOperationMode = false; | ||
56 | #endif // EFI_UNIT_TEST | |||
57 | ||||
58 | 242 | s->setTriggerSynchronizationGap(skippedCount + 1); | ||
59 |
4/4✓ Branch 0 taken 90 times.
✓ Branch 1 taken 152 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 4 times.
|
2/2✓ Decision 'true' taken 86 times.
✓ Decision 'false' taken 156 times.
|
242 | if (totalTeethCount > 6 && skippedCount > 0) { |
60 | // this gap is not required to synch on perfect signal but is needed to handle to reject cranking transition noise and potentially high rev noise as well | |||
61 | 86 | s->setSecondTriggerSynchronizationGap(1); | ||
62 | } | |||
63 |
4/4✓ Branch 0 taken 127 times.
✓ Branch 1 taken 115 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 99 times.
|
242 | s->shapeWithoutTdc = (totalTeethCount > 1) && (skippedCount == 0); | |
64 |
4/4✓ Branch 0 taken 122 times.
✓ Branch 1 taken 120 times.
✓ Branch 2 taken 97 times.
✓ Branch 3 taken 25 times.
|
242 | s->isSynchronizationNeeded = (totalTeethCount > 2) && (skippedCount != 0); | |
65 | ||||
66 | ||||
67 | 242 | addSkippedToothTriggerEvents(TriggerWheel::T_PRIMARY, s, totalTeethCount, skippedCount, 0.5, 0, getEngineCycle(operationMode), | ||
68 | NO_LEFT_FILTER, NO_RIGHT_FILTER); | |||
69 | } | |||
70 | ||||
71 | 520 | void configureOnePlusOne(TriggerWaveform *s) { | ||
72 | 520 | s->initialize(FOUR_STROKE_CAM_SENSOR, SyncEdge::Rise); | ||
73 | ||||
74 | 520 | s->addEvent360( 90, TriggerValue::RISE, TriggerWheel::T_PRIMARY); | ||
75 | 520 | s->addEvent360(180, TriggerValue::FALL, TriggerWheel::T_PRIMARY); | ||
76 | ||||
77 | 520 | s->addEvent360(270, TriggerValue::RISE, TriggerWheel::T_SECONDARY); | ||
78 | 520 | s->addEvent360(360, TriggerValue::FALL, TriggerWheel::T_SECONDARY); | ||
79 | ||||
80 | 520 | s->isSynchronizationNeeded = false; | ||
81 | 520 | s->useOnlyPrimaryForSync = true; | ||
82 | 520 | } | ||
83 | ||||
84 | 1 | void configure3_1_cam(TriggerWaveform *s) { | ||
85 | 1 | s->initialize(FOUR_STROKE_CAM_SENSOR, SyncEdge::RiseOnly); | ||
86 | ||||
87 | ||||
88 | 1 | const float crankW = 360 / 3 / 2; | ||
89 | ||||
90 | ||||
91 | 1 | TriggerWheel crank = TriggerWheel::T_SECONDARY; | ||
92 | ||||
93 | 1 | s->addEvent720(10, TriggerValue::RISE, TriggerWheel::T_PRIMARY); | ||
94 | 1 | s->addEvent720(50, TriggerValue::FALL, TriggerWheel::T_PRIMARY); | ||
95 | ||||
96 | ||||
97 | 1 | float a = 2 * crankW; | ||
98 | ||||
99 | // #1/3 | |||
100 | 1 | s->addEvent720(a += crankW, TriggerValue::RISE, crank); | ||
101 | 1 | s->addEvent720(a += crankW, TriggerValue::FALL, crank); | ||
102 | // #2/3 | |||
103 | 1 | s->addEvent720(a += crankW, TriggerValue::RISE, crank); | ||
104 | 1 | s->addEvent720(a += crankW, TriggerValue::FALL, crank); | ||
105 | // #3/3 | |||
106 | 1 | a += crankW; | ||
107 | 1 | a += crankW; | ||
108 | ||||
109 | // 2nd #1/3 | |||
110 | 1 | s->addEvent720(a += crankW, TriggerValue::RISE, crank); | ||
111 | 1 | s->addEvent720(a += crankW, TriggerValue::FALL, crank); | ||
112 | ||||
113 | // 2nd #2/3 | |||
114 | 1 | s->addEvent720(a += crankW, TriggerValue::RISE, crank); | ||
115 | 1 | s->addEvent720(a += crankW, TriggerValue::FALL, crank); | ||
116 | ||||
117 | 1 | s->isSynchronizationNeeded = false; | ||
118 | 1 | } | ||
119 | ||||
120 | /** | |||
121 | * https://rusefi.com/forum/viewtopic.php?f=5&t=1977 | |||
122 | */ | |||
123 | 1 | void configureKawaKX450F(TriggerWaveform *s) { | ||
124 | 1 | float engineCycle = FOUR_STROKE_ENGINE_CYCLE; | ||
125 | 1 | s->initialize(FOUR_STROKE_CRANK_SENSOR, SyncEdge::Rise); | ||
126 | ||||
127 | 1 | s->setTriggerSynchronizationGap(2.28); | ||
128 | ||||
129 | 1 | float toothWidth = 3 / 20.0; | ||
130 | ||||
131 | 1 | addSkippedToothTriggerEvents(TriggerWheel::T_PRIMARY, s, 18, 0, toothWidth, 0, engineCycle, | ||
132 | NO_LEFT_FILTER, 720 - 39); | |||
133 | ||||
134 | 1 | s->addToothRiseFall(360, /* width*/10.80); | ||
135 | 1 | } | ||
136 | ||||
137 | // TT_VVT_BOSCH_QUICK_START | |||
138 | 17 | void configureQuickStartSenderWheel(TriggerWaveform *s) { | ||
139 | // todo: most cam wheels are defined as 'SyncEdge::Rise' or 'SyncEdge::RiseOnly' shall we unify? | |||
140 | 17 | s->initialize(FOUR_STROKE_CAM_SENSOR, SyncEdge::Fall); | ||
141 | ||||
142 | // our preference is to sync not too close to crank sync point | |||
143 | 17 | s->setTriggerSynchronizationGap(0.645); | ||
144 | 17 | s->setSecondTriggerSynchronizationGap(1.556); | ||
145 | ||||
146 | 17 | s->addToothRiseFall(90, /* width*/ 70); | ||
147 | 17 | s->addToothRiseFall(130, /* width*/ 20); | ||
148 | 17 | s->addToothRiseFall(220, /* width*/ 20); | ||
149 | 17 | s->addToothRiseFall(360, /* width*/ 70); | ||
150 | 17 | } | ||
151 | ||||
152 | 15 | static void commonSymmetrical(TriggerWaveform* s, int count, float gapFrom, float gapTo) { | ||
153 | 15 | s->shapeWithoutTdc = true; | ||
154 | ||||
155 | // Sync after 2 good teeth | |||
156 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 15 times.
|
2/2✓ Decision 'true' taken 30 times.
✓ Decision 'false' taken 15 times.
|
45 | for (size_t i = 0; i < 2; i++) { |
157 | /** | |||
158 | * https://github.com/rusefi/rusefi/issues/4943#issuecomment-1376289608 | |||
159 | * gaps would be nice during running but horrible during running | |||
160 | * Hopefully we do not want variable gap logic yet? | |||
161 | */ | |||
162 | 30 | s->setTriggerSynchronizationGap3(i, gapFrom, gapTo); | ||
163 | } | |||
164 | ||||
165 | 15 | float width = 360 / count; | ||
166 | ||||
167 | // Just a single tooth with 50% duty cycle | |||
168 | 15 | s->addEventAngle(width / 2, TriggerValue::FALL, TriggerWheel::T_PRIMARY); | ||
169 | 15 | s->addEventAngle(width, TriggerValue::RISE, TriggerWheel::T_PRIMARY); | ||
170 | 15 | } | ||
171 | ||||
172 | // Useful for: | |||
173 | // - Honda 24+1 (set this on crank primary, single tooth cam) | |||
174 | // - AEM 24+1 CAS wheel (same config as Honda) | |||
175 | 3 | void configure12ToothCrank(TriggerWaveform* s) { | ||
176 | 3 | s->initialize(FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR, SyncEdge::RiseOnly); | ||
177 | ||||
178 | // 2JZ would be global trigger offset 65 but same wheel could be Honda, not hard coding for now | |||
179 | 3 | commonSymmetrical(s, 12, 0.2f, 3.4f); | ||
180 | 3 | } | ||
181 | ||||
182 | 11 | void configure3ToothCrank(TriggerWaveform* s) { | ||
183 | 11 | s->initialize(FOUR_STROKE_THREE_TIMES_CRANK_SENSOR, SyncEdge::RiseOnly); | ||
184 | 11 | commonSymmetrical(s, 3, 0.5, 1.4); | ||
185 | 11 | } | ||
186 | ||||
187 | 1 | void configure6ToothCrank(TriggerWaveform* s) { | ||
188 | 1 | s->initialize(FOUR_STROKE_SIX_TIMES_CRANK_SENSOR, SyncEdge::RiseOnly); | ||
189 | 1 | commonSymmetrical(s, 6, 0.7, 1.4); | ||
190 | 1 | } | ||
191 |