rusEFI
The most advanced open source ECU
trigger_universal.cpp
Go to the documentation of this file.
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  */
16  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 void addSkippedToothTriggerEvents(TriggerWheel wheel, TriggerWaveform *s, int totalTeethCount, int skippedCount,
23  float toothWidth, float offset, float engineCycle, float filterLeft, float filterRight) {
24  efiAssertVoid(ObdCode::CUSTOM_ERR_6586, totalTeethCount > 0, "total count");
25  efiAssertVoid(ObdCode::CUSTOM_ERR_6587, skippedCount >= 0, "skipped count");
26 
27  float oneTooth = engineCycle / totalTeethCount;
28 
29  for (int i = 0; i < totalTeethCount - skippedCount - 1; i++) {
30  float angleDown = oneTooth * (i + (1 - toothWidth));
31  float angleUp = oneTooth * (i + 1);
32  s->addEventClamped(offset + angleDown, TriggerValue::RISE, wheel, filterLeft, filterRight);
33  s->addEventClamped(offset + angleUp, TriggerValue::FALL, wheel, filterLeft, filterRight);
34  }
35 
36  float angleDown = oneTooth * (totalTeethCount - skippedCount - 1 + (1 - toothWidth));
37  s->addEventClamped(offset + angleDown, TriggerValue::RISE, wheel, filterLeft, filterRight);
38  // custom handling of last event in order to avoid rounding error
39  s->addEventClamped(offset + engineCycle, TriggerValue::FALL, wheel, filterLeft, filterRight);
40 }
41 
42 void initializeSkippedToothTrigger(TriggerWaveform *s, int totalTeethCount, int skippedCount,
43  operation_mode_e operationMode, SyncEdge syncEdge) {
44  if (totalTeethCount <= 0) {
45  firmwareError(ObdCode::CUSTOM_OBD_TRIGGER_WAVEFORM, "Invalid total tooth count for missing tooth decoder: %d", totalTeethCount);
46  s->setShapeDefinitionError(true);
47  return;
48  }
49  efiAssertVoid(ObdCode::CUSTOM_NULL_SHAPE, s != NULL, "TriggerWaveform is NULL");
50 
51  s->initialize(operationMode, syncEdge);
52 
53 #if EFI_UNIT_TEST
54  s->knownOperationMode = false;
55 #endif // EFI_UNIT_TEST
56 
57  s->setTriggerSynchronizationGap(skippedCount + 1);
58  if (totalTeethCount > 6 && skippedCount > 0) {
59  // 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  }
62  s->shapeWithoutTdc = (totalTeethCount > 1) && (skippedCount == 0);
63  s->isSynchronizationNeeded = (totalTeethCount > 2) && (skippedCount != 0);
64 
65 
66  addSkippedToothTriggerEvents(TriggerWheel::T_PRIMARY, s, totalTeethCount, skippedCount, 0.5, 0, getEngineCycle(operationMode),
67  NO_LEFT_FILTER, NO_RIGHT_FILTER);
68 }
69 
72 
75 
78 
79  s->isSynchronizationNeeded = false;
80  s->useOnlyPrimaryForSync = true;
81 }
82 
85 
86 
87  const float crankW = 360 / 3 / 2;
88 
89 
91 
94 
95 
96  float a = 2 * crankW;
97 
98  // #1/3
99  s->addEvent720(a += crankW, TriggerValue::RISE, crank);
100  s->addEvent720(a += crankW, TriggerValue::FALL, crank);
101  // #2/3
102  s->addEvent720(a += crankW, TriggerValue::RISE, crank);
103  s->addEvent720(a += crankW, TriggerValue::FALL, crank);
104  // #3/3
105  a += crankW;
106  a += crankW;
107 
108  // 2nd #1/3
109  s->addEvent720(a += crankW, TriggerValue::RISE, crank);
110  s->addEvent720(a += crankW, TriggerValue::FALL, crank);
111 
112  // 2nd #2/3
113  s->addEvent720(a += crankW, TriggerValue::RISE, crank);
114  s->addEvent720(a += crankW, TriggerValue::FALL, crank);
115 
116  s->isSynchronizationNeeded = false;
117 }
118 
119 /**
120  * https://rusefi.com/forum/viewtopic.php?f=5&t=1977
121  */
123  float engineCycle = FOUR_STROKE_ENGINE_CYCLE;
125 
127 
128  float toothWidth = 3 / 20.0;
129 
130  addSkippedToothTriggerEvents(TriggerWheel::T_PRIMARY, s, 18, 0, toothWidth, 0, engineCycle,
131  NO_LEFT_FILTER, 720 - 39);
132 
133  s->addToothRiseFall(360, /* width*/10.80);
134 }
135 
137  // todo: most cam wheels are defined as 'SyncEdge::Rise' or 'SyncEdge::RiseOnly' shall we unify?
139 
140  // our preference is to sync not too close to crank sync point
143 
144  s->addToothRiseFall(90, /* width*/ 70);
145  s->addToothRiseFall(130, /* width*/ 20);
146  s->addToothRiseFall(220, /* width*/ 20);
147  s->addToothRiseFall(360, /* width*/ 70);
148 }
149 
150 static void commonSymmetrical(TriggerWaveform* s, int count) {
151  s->shapeWithoutTdc = true;
152 
153  // Sync after 2 good teeth
154  for (size_t i = 0; i < 2; i++) {
155  /**
156  * https://github.com/rusefi/rusefi/issues/4943#issuecomment-1376289608
157  * gaps would be nice during running but horrible during running
158  * Hopefully we do not want variable gap logic yet?
159  */
160  s->setTriggerSynchronizationGap3(i, 0.2f, 3.4f);
161  }
162 
163  float width = 360 / count;
164 
165  // Just a single tooth with 50% duty cycle
168 }
169 
170 // Useful for:
171 // - Honda 24+1 (set this on crank primary, single tooth cam)
172 // - AEM 24+1 CAS wheel (same config as Honda)
175 
176  // 2JZ would be global trigger offset 65 but same wheel could be Honda, not hard coding for now
177  commonSymmetrical(s, 12);
178 }
179 
182  commonSymmetrical(s, 3);
183 }
184 
187  commonSymmetrical(s, 6);
188 }
Trigger shape has all the fields needed to describe and decode trigger signal.
void setShapeDefinitionError(bool value)
void initialize(operation_mode_e operationMode, SyncEdge syncEdge)
void setSecondTriggerSynchronizationGap(float syncRatio)
void setTriggerSynchronizationGap(float syncRatio)
void addToothRiseFall(angle_t angle, angle_t width=10, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
void addEventAngle(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
void addEvent720(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
void addEvent360(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
void setTriggerSynchronizationGap3(int index, float syncRatioFrom, float syncRatioTo)
void addEventClamped(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex, float filterLeft, float filterRight)
void firmwareError(ObdCode code, const char *fmt,...)
@ CUSTOM_NULL_SHAPE
@ CUSTOM_OBD_TRIGGER_WAVEFORM
@ CUSTOM_ERR_6586
@ CUSTOM_ERR_6587
operation_mode_e
Definition: rusefi_enums.h:247
@ FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:278
@ FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:273
@ FOUR_STROKE_CRANK_SENSOR
Definition: rusefi_enums.h:254
@ FOUR_STROKE_CAM_SENSOR
Definition: rusefi_enums.h:258
@ TWO_STROKE
Definition: rusefi_enums.h:262
@ FOUR_STROKE_SIX_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:283
TriggerWheel
Definition: rusefi_enums.h:47
float angle_t
Definition: rusefi_types.h:58
SyncEdge
Definition: sync_edge.h:3
void configure3ToothCrank(TriggerWaveform *s)
void configureQuickStartSenderWheel(TriggerWaveform *s)
void configureKawaKX450F(TriggerWaveform *s)
void configureOnePlusOne(TriggerWaveform *s)
void configure12ToothCrank(TriggerWaveform *s)
angle_t getEngineCycle(operation_mode_e operationMode)
void addSkippedToothTriggerEvents(TriggerWheel wheel, TriggerWaveform *s, int totalTeethCount, int skippedCount, float toothWidth, float offset, float engineCycle, float filterLeft, float filterRight)
static void commonSymmetrical(TriggerWaveform *s, int count)
void initializeSkippedToothTrigger(TriggerWaveform *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode, SyncEdge syncEdge)
void configure3_1_cam(TriggerWaveform *s)
void configure6ToothCrank(TriggerWaveform *s)