rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
trigger_structure.cpp
Go to the documentation of this file.
1/**
2 * @file trigger_structure.cpp
3 *
4 * @date Jan 20, 2014
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 *
7 * This file is part of rusEfi - see http://rusefi.com
8 *
9 * rusEfi is free software; you can redistribute it and/or modify it under the terms of
10 * the GNU General Public License as published by the Free Software Foundation; either
11 * version 3 of the License, or (at your option) any later version.
12 *
13 * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
14 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program.
18 * If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "pch.h"
22
23#include "trigger_chrysler.h"
24#include "trigger_ford.h"
25#include "trigger_gm.h"
26#include "trigger_nissan.h"
27#include "trigger_mazda.h"
28#include "trigger_misc.h"
29#include "trigger_mitsubishi.h"
30#include "trigger_renault.h"
31#include "trigger_subaru.h"
32#include "trigger_suzuki.h"
33#include "trigger_structure.h"
34#include "trigger_toyota.h"
35#include "trigger_renix.h"
36#include "trigger_rover.h"
37#include "trigger_honda.h"
38#include "trigger_vw.h"
39#include "trigger_universal.h"
40#include "trigger_mercedes.h"
41#include "engine_state.h"
42
43void wrapAngle(angle_t& angle, const char* msg, ObdCode code) {
44 if (std::isnan(angle)) {
46 angle = 0;
47 }
48
49 assertAngleRange(angle, msg, code);
50 float engineCycle = getEngineState()->engineCycle;
51
52 while (angle < 0) {
53 angle += engineCycle;
54 }
55
56 while (angle >= engineCycle) {
57 angle -= engineCycle;
58 }
59}
60
64
65void TriggerWaveform::initialize(operation_mode_e p_operationMode, SyncEdge p_syncEdge) {
66 operationMode = p_operationMode;
67 syncEdge = p_syncEdge;
68
69 isSynchronizationNeeded = true; // that's default value
70 isSecondWheelCam = false;
72 shapeWithoutTdc = false;
73
74 // If RiseOnly, ignore falling edges completely.
76
78 for (int gapIndex = 1; gapIndex < GAP_TRACKING_LENGTH ; gapIndex++) {
79 // NaN means do not use this gap ratio
80 setTriggerSynchronizationGap3(gapIndex, NAN, 100000);
81 }
83
84 tdcPosition = 0;
87
90 wave.reset();
91 wave.waveCount = TRIGGER_INPUT_PIN_COUNT;
92 wave.phaseCount = 0;
93 previousAngle = 0;
95#if EFI_UNIT_TEST
97 memset(&triggerSignalStates, 0, sizeof(triggerSignalStates));
98 knownOperationMode = true;
99#endif // EFI_UNIT_TEST
100}
101
103 return wave.phaseCount;
104}
105
109
110/**
111 * physical primary trigger duration
112 * @see getEngineCycle
113 * @see getCrankDivider
114 */
116 switch (operationMode) {
118 return FOUR_STROKE_CYCLE_DURATION / SYMMETRICAL_CRANK_SENSOR_DIVIDER;
120 return FOUR_STROKE_CYCLE_DURATION / SYMMETRICAL_THREE_TIMES_CRANK_SENSOR_DIVIDER;
122 return FOUR_STROKE_CYCLE_DURATION / SYMMETRICAL_SIX_TIMES_CRANK_SENSOR_DIVIDER;
124 return FOUR_STROKE_CYCLE_DURATION / SYMMETRICAL_TWELVE_TIMES_CRANK_SENSOR_DIVIDER;
126 case TWO_STROKE:
127 return TWO_STROKE_CYCLE_DURATION;
128 case OM_NONE:
130 return FOUR_STROKE_CYCLE_DURATION;
131 }
132 criticalError("unreachable getCycleDuration");
133 return 0;
134}
135
137 switch (getWheelOperationMode()) {
143 return true;
145 case TWO_STROKE:
146 case OM_NONE:
147 return false;
148 /* let's NOT handle default in order to benefit from -Werror=switch */
149 }
150 criticalError("unreachable needsDisambiguation");
151 return true;
152}
153
154/**
155 * Trigger event count equals engine cycle event count if we have a cam sensor.
156 * Two trigger cycles make one engine cycle in case of a four stroke engine If we only have a cranksensor.
157 *
158 * 'engine->engineCycleEventCount' hold a pre-calculated copy of this value as a performance optimization
159 */
161 /**
162 * 24 for FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR
163 * 6 for FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
164 * 4 for FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR
165 * 2 for FOUR_STROKE_CRANK_SENSOR
166 * 1 otherwise
167 */
168 int multiplier = getEngineCycle(operationMode) / getCycleDuration();
169 return multiplier * getSize();
170}
171
173 /**
174 * FOUR_STROKE_CRANK_SENSOR magic:
175 * We have two crank shaft revolutions for each engine cycle
176 * See also trigger_central.cpp
177 * See also getEngineCycleEventCount()
178 */
179 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, wave.phaseCount != 0, "shapeSize=0", NAN);
180 int crankCycle = index / wave.phaseCount;
181 int remainder = index % wave.phaseCount;
182
183 auto cycleStartAngle = getCycleDuration() * crankCycle;
184 auto positionWithinCycle = getSwitchAngle(remainder);
185
186 return cycleStartAngle + positionWithinCycle;
187}
188
189void TriggerWaveform::addEventClamped(angle_t angle, TriggerValue const stateParam, TriggerWheel const channelIndex, float filterLeft, float filterRight) {
190 if (angle > filterLeft && angle < filterRight) {
191#if EFI_UNIT_TEST
192// printf("addEventClamped %f %s\r\n", angle, getTrigger_value_e(stateParam));
193#endif /* EFI_UNIT_TEST */
194 addEvent(angle / getEngineCycle(operationMode), stateParam, channelIndex);
195 }
196}
197
198/**
199 * See also Engine#getOperationMode which accounts for additional settings which are
200 * needed to resolve precise mode for vague wheels
201 */
205
206#if EFI_UNIT_TEST
207extern bool printTriggerDebug;
208#endif
209
211 return expectedEventCount[(int)channelIndex];
212}
213
215 if (!useOnlyRisingEdges) {
216 for (size_t i = 0; i < efi::size(expectedEventCount); i++) {
217 if (getExpectedEventCount((TriggerWheel)i) % 2 != 0) {
218 firmwareError(ObdCode::ERROR_TRIGGER_DRAMA, "Trigger: should be even number of events index=%d count=%d", i, getExpectedEventCount((TriggerWheel)i));
219 }
220 }
221 }
222
224 // todo: next step would be to set 'isSynchronizationNeeded' automatically based on the logic we have here
225 if (!shapeWithoutTdc && isSingleToothOnPrimaryChannel != !isSynchronizationNeeded) {
226 firmwareError(ObdCode::ERROR_TRIGGER_DRAMA, "shapeWithoutTdc isSynchronizationNeeded isSingleToothOnPrimaryChannel constraint violation");
227 }
228 if (isSingleToothOnPrimaryChannel) {
230 } else {
232 firmwareError(ObdCode::ERROR_TRIGGER_DRAMA, "why would you set useOnlyPrimaryForSync with only one trigger wheel?");
233 }
234 }
235
236// todo: move the following logic from below here
237 // if (!useOnlyRisingEdgeForTrigger || stateParam == TriggerValue::RISE) {
238// expectedEventCount[channelIndex]++;
239// }
240
241}
242
243/**
244 * See header for documentation
245 */
247 addEvent(angle / FOUR_STROKE_CYCLE_DURATION, state, channelIndex);
248}
249
252#define CRANK_MODE_MULTIPLIER 2.0f
253 addEvent(CRANK_MODE_MULTIPLIER * angle / FOUR_STROKE_CYCLE_DURATION, state, channelIndex);
254}
255
256void TriggerWaveform::addToothRiseFall(angle_t angle, angle_t width, TriggerWheel const channelIndex) {
257 addEvent360(angle - width, TriggerValue::RISE, channelIndex);
258 addEvent360(angle, TriggerValue::FALL, channelIndex);
259}
260
261void TriggerWaveform::addToothFallRise(angle_t angle, angle_t width, TriggerWheel const channelIndex) {
262 addEvent360(angle - width, TriggerValue::FALL, channelIndex);
263 addEvent360(angle, TriggerValue::RISE, channelIndex);
264}
265
267 addEvent(angle / getCycleDuration(), state, channelIndex);
268}
269
270void TriggerWaveform::addEvent(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex) {
271 efiAssertVoid(ObdCode::CUSTOM_OMODE_UNDEF, operationMode != OM_NONE, "operationMode not set");
272
273 if (channelIndex == TriggerWheel::T_SECONDARY) {
275 }
276
277#if EFI_UNIT_TEST
278 if (printTriggerDebug) {
279 printf("addEvent2 %.2f i=%d front=%d\r\n", angle, channelIndex, state);
280 }
281#endif
282
283#if EFI_UNIT_TEST
284 assertIsInBounds(wave.phaseCount, triggerSignalIndeces, "trigger shape overflow");
285 triggerSignalIndeces[wave.phaseCount] = channelIndex;
287#endif // EFI_UNIT_TEST
288
289
290 // todo: the whole 'useOnlyRisingEdgeForTrigger' parameter and logic should not be here
291 // todo: see calculateExpectedEventCounts
292 // related calculation should be done once trigger is initialized outside of trigger shape scope
294 expectedEventCount[(int)channelIndex]++;
295 }
296
297 if (angle <= 0 || angle > 1) {
298 firmwareError(ObdCode::CUSTOM_ERR_6599, "angle should be positive not above 1: index=%d angle %f", (int)channelIndex, angle);
299 return;
300 }
301 if (wave.phaseCount > 0) {
302 if (angle <= previousAngle) {
303 warning(ObdCode::CUSTOM_ERR_TRG_ANGLE_ORDER, "invalid angle order %s %s: new=%.2f/%f and prev=%.2f/%f, size=%d",
304 getTriggerWheel(channelIndex),
306 angle, angle * getCycleDuration(),
310 return;
311 }
312 }
313 previousAngle = angle;
314 if (wave.phaseCount == 0) {
315 wave.phaseCount = 1;
316 for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
317 wave.setChannelState(i, /* switchIndex */ 0, TriggerValue::FALL);
318 }
319
321 wave.setSwitchTime(0, angle);
322 wave.setChannelState((int)channelIndex, /* channelIndex */ 0, /* value */ state);
323 return;
324 }
325
326 if (wave.findAngleMatch(angle)) {
327 warning(ObdCode::CUSTOM_ERR_SAME_ANGLE, "same angle: not supported");
329 return;
330 }
331
332 int index = wave.findInsertionAngle(angle);
333
334 /**
335 * todo: it would be nice to be able to provide trigger angles without sorting them externally
336 * The idea here is to shift existing data - including handling high vs low state of the signals
337 */
338 // todo: does this logic actually work? I think it does not! due to broken state handling
339/*
340 for (int i = size - 1; i >= index; i--) {
341 for (int j = 0; j < PWM_PHASE_MAX_WAVE_PER_PWM; j++) {
342 wave.waves[j].pinStates[i + 1] = wave.getChannelState(j, index);
343 }
344 wave.setSwitchTime(i + 1, wave.getSwitchTime(i));
345 }
346*/
348
349 if ((unsigned)index != wave.phaseCount) {
350 firmwareError(ObdCode::ERROR_TRIGGER_DRAMA, "are we ever here?");
351 }
352
354
355 for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
356 pin_state_t value = wave.getChannelState(/* channelIndex */i, index - 1);
357 wave.setChannelState(i, index, value);
358 }
359 wave.setSwitchTime(index, angle);
360 wave.setChannelState((int)channelIndex, index, state);
361}
362
364 return getCycleDuration() * wave.getSwitchTime(index);
365}
366
367void TriggerWaveform::setTriggerSynchronizationGap2(float syncRatioFrom, float syncRatioTo) {
368 setTriggerSynchronizationGap3(/*gapIndex*/0, syncRatioFrom, syncRatioTo);
369}
370
371void TriggerWaveform::setTriggerSynchronizationGap3(int gapIndex, float syncRatioFrom, float syncRatioTo) {
373 criticalAssertVoid(gapIndex >= 0 && gapIndex < GAP_TRACKING_LENGTH, "gapIndex out of range");
374 synchronizationRatioFrom[gapIndex] = syncRatioFrom;
375 synchronizationRatioTo[gapIndex] = syncRatioTo;
376 if (gapIndex == 0) {
377 // we have a special case here - only sync with one gap has this feature
378 this->syncRatioAvg = (int)efiRound((syncRatioFrom + syncRatioTo) * 0.5f, 1.0f);
379 }
380 gapTrackingLength = maxI(1 + gapIndex, gapTrackingLength);
381
382#if EFI_UNIT_TEST
383 if (printTriggerDebug) {
384 printf("setTriggerSynchronizationGap3 %d %.2f %.2f\r\n", gapIndex, syncRatioFrom, syncRatioTo);
385 }
386#endif /* EFI_UNIT_TEST */
387
388}
389
390uint16_t TriggerWaveform::findAngleIndex(TriggerFormDetails *details, angle_t targetAngle) const {
391 size_t engineCycleEventCount = getLength();
392
393 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, engineCycleEventCount != 0 && engineCycleEventCount <= 0xFFFF,
394 "engineCycleEventCount", 0);
395
396 uint32_t left = 0;
397 uint32_t right = engineCycleEventCount - 1;
398
399 /**
400 * Let's find the last trigger angle which is less or equal to the desired angle
401 * todo: extract binary search as template method?
402 */
403 do {
404 uint32_t middle = (left + right) / 2;
405
406 if (details->eventAngles[middle] <= targetAngle) {
407 left = middle + 1;
408 } else {
409 right = middle - 1;
410 }
411 } while (left <= right);
412 left -= 1;
413 if (useOnlyRisingEdges) {
414 left &= ~1U;
415 }
416 return left;
417}
418
422
424 setTriggerSynchronizationGap4(/*gapIndex*/0, syncRatio);
425}
426
428 setTriggerSynchronizationGap4(/*gapIndex*/1, syncRatio);
429}
430
431void TriggerWaveform::setSecondTriggerSynchronizationGap2(float syncRatioFrom, float syncRatioTo) {
432 setTriggerSynchronizationGap3(/*gapIndex*/1, syncRatioFrom, syncRatioTo);
433}
434
436 setTriggerSynchronizationGap4(/*gapIndex*/2, syncRatio);
437}
438
439PUBLIC_API_WEAK void customTrigger(operation_mode_e triggerOperationMode, TriggerWaveform *s, trigger_type_e type) {
441 initializeSkippedToothTrigger(s, 1, 0, triggerOperationMode, SyncEdge::Rise);
442 return;
443 }
445 warning(ObdCode::CUSTOM_ERR_NO_SHAPE, "initializeTriggerWaveform() not implemented: %d", type);
446}
447
448/**
449 * External logger is needed because at this point our logger is not yet initialized
450 */
452
453#if EFI_PROD_CODE
454 efiAssertVoid(ObdCode::CUSTOM_ERR_6641, hasLotsOfRemainingStack(), "init t");
455 efiPrintf("initializeTriggerWaveform(%s/%d)", getTrigger_type_e(triggerType.type), (int)triggerType.type);
456#endif
457
458 shapeDefinitionError = false;
459
460 switch (triggerType.type) {
462 initializeSkippedToothTrigger(this, triggerType.customTotalToothCount,
463 triggerType.customSkippedToothCount, triggerOperationMode, SyncEdge::RiseOnly);
464 break;
465
468 break;
469
472 break;
473
476 break;
477
480 break;
481
483 configureFordPip(this);
484 break;
485
487 configureFordST170(this);
488 break;
489
492 break;
493
496 break;
497
500 break;
501
504 break;
505
509 break;
510
513 break;
514
517 break;
518
521// configureNeon2003TriggerWaveformCrank(triggerShape);
522 break;
523
526 break;
527
530 break;
531
533 initializeVvt6G72(this);
534 break;
535
537 initializeVvt3A92(this);
538 break;
539
541 initializeUzCam(this);
542 break;
543
545 initializeSkippedToothTrigger(this, 4, 1, triggerOperationMode, SyncEdge::RiseOnly);
546 setTriggerSynchronizationGap3(/*gapIndex*/0, /*from*/1.60, 2.40);
547 setTriggerSynchronizationGap3(/*gapIndex*/1, /*from*/0.75, 1.25);
548 break;
549
552 break;
553
556 break;
557
560 break;
561
564 break;
565
568 break;
569
572 break;
573
575 setSkodaFavorit(this);
576 break;
577
580 break;
581
584 break;
585
588 break;
589
592 break;
593
595 configure3_1_cam(this);
596 break;
597
600 break;
601
603 /** @note TT_HALF_MOON setup events as 180 and 360 degrees. It uses SyncEdge::Rise
604 * for additional phase align on falling edge and will not work with non-
605 * symmetrical blind type where open and closed sections are not equal */
606 initializeSkippedToothTrigger(this, 1, 0, triggerOperationMode, SyncEdge::Rise);
607 break;
608
610 /** different from TT_HALF_MOON */
611 initializeSkippedToothTrigger(this, 1, 0, triggerOperationMode, SyncEdge::RiseOnly);
612 break;
613
616 break;
617
620 break;
621
624 break;
625
627 initializeSkippedToothTrigger(this, 3, 0, triggerOperationMode, SyncEdge::RiseOnly);
628 break;
629
631 initialize36_2_1_1(this);
632 break;
633
635 initialize36_2_1(this);
636 break;
637
639 initializeSkippedToothTrigger(this, 32, 2, triggerOperationMode, SyncEdge::RiseOnly);
640 // todo: why is this 32/2 asking for third gap while 60/2 is happy with just two gaps?
641 // method above sets second gap, here we add third
642 // this third gap is not required to sync on perfect signal but is needed to handle to reject cranking transition noise
644 break;
645
647 initializeSkippedToothTrigger(this, 60, 2, triggerOperationMode, SyncEdge::RiseOnly);
648 break;
649
651 initializeSkippedToothTrigger(this, 36, 2, triggerOperationMode, SyncEdge::RiseOnly);
652 setTriggerSynchronizationGap3(/*gapIndex*/0, /*from*/1.6, 3.5);
653 setTriggerSynchronizationGap3(/*gapIndex*/1, /*from*/0.7, 1.3); // second gap is not required to synch on perfect signal but is needed to handle to reject cranking transition noise
654 break;
655
657 setVwConfiguration(this);
658 break;
659
661 initializeSkippedToothTrigger(this, 36, 1, triggerOperationMode, SyncEdge::RiseOnly);
662 break;
663
666 break;
667
670 break;
671
674 break;
675
678 break;
679
682 break;
683
686 break;
687
690 break;
691
694 break;
695
697 configureBenelli(this);
698 break;
699
702 break;
706 break;
708 /** @note
709 * Have a something like TT_ONE_PHASED trigger with
710 * externally setuped blind width will be a good
711 * approach to utilize ::Rise(and::Both in future)
712 * with both edges phase-sync, but to stay simple I suggest
713 * just to use another enum for each trigger type. */
715 break;
718 break;
721 break;
724 break;
725
729 break;
730
733 break;
736 break;
737
740 break;
741
743 initDodgeRam(this);
744 break;
745
748 break;
749
751 initJeep18_2_2_2(this);
752 break;
753
756 break;
757
759 initialize36_2_2_2(this);
760 break;
761
764 break;
765
768 break;
769
772 break;
773
776 break;
777
779 configureArcticCat(this);
780 break;
781
784 break;
787 break;
790 break;
791
793 initializeRoverK(this);
794 break;
795
798 break;
799
801 configureTriTach(this);
802 break;
803
805 initGmLS24_5deg(this);
806 break;
807
809 initGmLS24_3deg(this);
810 break;
811
814 break;
815
818 break;
819
822 break;
823
826 break;
827
830 break;
831
834 break;
835
836
837 default:
838 customTrigger(triggerOperationMode, this, triggerType.type);
839 }
840
841 if (isCrankWheel && !needSecondTriggerInput &&
842#if EFI_UNIT_TEST
843 engineConfiguration != nullptr &&
844#endif
846// todo: technical debt: HW CI should not require special treatment
847#ifndef HARDWARE_CI
848 criticalError("Single-channel trigger %s selected while two inputs were configured", getTrigger_type_e(triggerType.type));
849#endif
850 }
851
852 /**
853 * Feb 2019 suggestion: it would be an improvement to remove 'expectedEventCount' logic from 'addEvent'
854 * and move it here, after all events were added.
855 */
857 version++;
858
861 }
862}
const char * getTriggerWheel(TriggerWheel value)
const char * getTrigger_type_e(trigger_type_e value)
uint8_t code
Definition bluetooth.cpp:40
angle_t engineCycle
void checkSwitchTimes(float scale) const
int findInsertionAngle(float angle) const
expected< int > findAngleMatch(float angle) const
pin_state_t getChannelState(int channelIndex, int phaseIndex) const override
float getSwitchTime(int phaseIndex) const override
void setSwitchTime(const int phaseIndex, const float value)
void setChannelState(const int channelIndex, const int phaseIndex, pin_state_t state)
angle_t eventAngles[2 *PWM_PHASE_MAX_COUNT]
Trigger shape has all the fields needed to describe and decode trigger signal.
void setShapeDefinitionError(bool value)
int getTriggerWaveformSynchPointIndex() const
void initialize(operation_mode_e operationMode, SyncEdge syncEdge)
bool isRiseEvent[PWM_PHASE_MAX_COUNT]
void setSecondTriggerSynchronizationGap(float syncRatio)
bool needsDisambiguation() const
angle_t getCycleDuration() const
void setTriggerSynchronizationGap(float syncRatio)
void addToothFallRise(angle_t angle, angle_t width=10, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
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)
uint16_t findAngleIndex(TriggerFormDetails *details, angle_t angle) const
float synchronizationRatioFrom[GAP_TRACKING_LENGTH]
TriggerValue triggerSignalStates[PWM_PHASE_MAX_COUNT]
void initializeTriggerWaveform(operation_mode_e triggerOperationMode, const trigger_config_s &triggerType, bool isCrankWheel=true)
size_t getLength() const
void addEvent720(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
float synchronizationRatioTo[GAP_TRACKING_LENGTH]
void addEvent360(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
void setSecondTriggerSynchronizationGap2(float syncRatioFrom, float syncRatioTo)
void setThirdTriggerSynchronizationGap(float syncRatio)
operation_mode_e getWheelOperationMode() const
angle_t getAngle(int phaseIndex) const
void setTriggerSynchronizationGap4(int index, float syncRatio)
angle_t getSwitchAngle(int index) const
void setTriggerSynchronizationGap2(float syncRatioFrom, float syncRatioTo)
void setTriggerSynchronizationGap3(int index, float syncRatioFrom, float syncRatioTo)
operation_mode_e operationMode
MultiChannelStateSequenceWithData< PWM_PHASE_MAX_COUNT > wave
TriggerWheel triggerSignalIndeces[PWM_PHASE_MAX_COUNT]
size_t getExpectedEventCount(TriggerWheel channelIndex) const
size_t getSize() const
void addEvent(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex=TriggerWheel::T_PRIMARY)
void addEventClamped(angle_t angle, TriggerValue const state, TriggerWheel const channelIndex, float filterLeft, float filterRight)
size_t expectedEventCount[PWM_PHASE_MAX_WAVE_PER_PWM]
@ Unassigned
float efiRound(float value, float precision)
Definition efilib.cpp:34
EngineState * getEngineState()
Definition engine.cpp:577
static constexpr engine_configuration_s * engineConfiguration
One header which acts as gateway to current engine state.
trigger_type_e
@ TT_2JZ_3_34_SIMULATION_ONLY
@ TT_DODGE_NEON_1995_ONLY_CRANK
bool warning(ObdCode code, const char *fmt,...)
void firmwareError(ObdCode code, const char *fmt,...)
ObdCode
@ CUSTOM_ERR_6641
@ CUSTOM_ERR_NO_SHAPE
@ CUSTOM_ERR_SAME_ANGLE
@ CUSTOM_ERR_6599
@ CUSTOM_OMODE_UNDEF
@ CUSTOM_ERR_ANGLE
@ CUSTOM_ERR_TRG_ANGLE_ORDER
@ CUSTOM_ERR_ASSERT
@ ERROR_TRIGGER_DRAMA
operation_mode_e
@ FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR
@ FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR
@ FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
@ FOUR_STROKE_CRANK_SENSOR
@ OM_NONE
@ FOUR_STROKE_CAM_SENSOR
@ TWO_STROKE
@ FOUR_STROKE_SIX_TIMES_CRANK_SENSOR
TriggerWheel
float angle_t
state("state", SensorCategory.SENSOR_INPUTS, FieldType.INT8, 1871, 1.0, -1.0, -1.0, "")
TriggerValue
brain_input_pin_e triggerInputPins[TRIGGER_INPUT_PIN_COUNT]
SyncEdge
Definition sync_edge.h:3
void setArrayValues(TValue(&array)[TSize], float value)
void configureChryslerVtt15(TriggerWaveform *s)
void configureDodgeStratusTriggerWaveform(TriggerWaveform *s)
void configureChryslerNGC_36_2_2(TriggerWaveform *s)
void initJeep18_2_2_2(TriggerWaveform *s)
void initJeep_XJ_4cyl_2500(TriggerWaveform *s)
void configureNeon2003TriggerWaveformCam(TriggerWaveform *s)
void configureNeon1995TriggerWaveformOnlyCrank(TriggerWaveform *s)
void configureJeepEVD_36_2_2(TriggerWaveform *s)
void initDodgeRam(TriggerWaveform *s)
const char * getTrigger_value_e(TriggerValue value)
void configureFordCoyote(TriggerWaveform *s)
void initGmLS24_3deg(TriggerWaveform *s)
void configureGmTriggerWaveform(TriggerWaveform *s)
void initGmLS24_5deg(TriggerWaveform *s)
void configureGm60_2_2_2(TriggerWaveform *s)
void configureHondaCbr600(TriggerWaveform *s)
void configureHondaK_12_1(TriggerWaveform *s)
void configureHondaJ30A2_24_1_1(TriggerWaveform *s)
void configureHondaK_4_1(TriggerWaveform *s)
triggerType
void configureMazdaProtegeSOHC(TriggerWaveform *s)
void configureMazdaProtegeLx(TriggerWaveform *s)
void initializeMazdaMiataVVtTestShape(TriggerWaveform *s)
void initializeMazdaMiataNaShape(TriggerWaveform *s)
void initializeMazdaLCam(TriggerWaveform *s)
void initializeMazdaMiataVVtCamShape(TriggerWaveform *s)
void initializeMazdaMiataNb2Crank(TriggerWaveform *s)
void initializeMazdaSkyactivCam(TriggerWaveform *s)
void setMercedesTwoSegment(TriggerWaveform *s)
void configureDaihatsu4cyl(TriggerWaveform *s)
void configureDaihatsu3cyl(TriggerWaveform *s)
void configureBarra3plus1cam(TriggerWaveform *s)
void configureFordPip(TriggerWaveform *s)
void configureTriTach(TriggerWaveform *s)
void configureFiatIAQ_P8(TriggerWaveform *s)
void configureFordST170(TriggerWaveform *s)
void configure60degSingleTooth(TriggerWaveform *s)
Configure trigger as Sovek or Saruman ignition.
void configureArcticCat(TriggerWaveform *s)
void configureBenelli(TriggerWaveform *s)
void initializeVvt6G72(TriggerWaveform *s)
void initialize36_2_1(TriggerWaveform *s)
void initializeMitsubishi4gSymmetricalCrank(TriggerWaveform *s)
void initializeVvt3A92(TriggerWaveform *s)
void initializeMitsubishi4g63Cam(TriggerWaveform *s)
void initializeMitsubishi4G69Cam(TriggerWaveform *s)
void configureFordAspireTriggerWaveform(TriggerWaveform *s)
void initialize36_2_1_1(TriggerWaveform *s)
void initializeNissanVQvvt(TriggerWaveform *s)
void initializeNissanSR20VE_4(TriggerWaveform *s)
void initializeNissanQR25crank(TriggerWaveform *s)
void initializeNissanVQ35crank(TriggerWaveform *s)
void initializeNissanHRvvtIn(TriggerWaveform *s)
void initializeNissanVQ30cam(TriggerWaveform *s)
void initializeNissanMR18crank(TriggerWaveform *s)
void initializeNissanHRcrank(TriggerWaveform *s)
void initializeNissanMRvvt(TriggerWaveform *s)
void initialize60_2_2_Renault_F(TriggerWaveform *s)
void initializeRenix66_2_2(TriggerWaveform *s)
void initializeRenix44_2_2(TriggerWaveform *s)
void initializeJeepRenix66_2_2(TriggerWaveform *s)
void initializeRoverK(TriggerWaveform *s)
PUBLIC_API_WEAK void customTrigger(operation_mode_e triggerOperationMode, TriggerWaveform *s, trigger_type_e type)
bool printTriggerDebug
void wrapAngle(angle_t &angle, const char *msg, ObdCode code)
void initializeSubaru_SVX(TriggerWaveform *s)
void initializeSubaru7_6_crankOnly(TriggerWaveform *s)
void initialize36_2_2_2(TriggerWaveform *s)
static void initializeSubaru7_6(TriggerWaveform *s, bool withCrankWheel)
void initializeSubaruOnly7(TriggerWaveform *s)
void initializeSubaruEZ30(TriggerWaveform *s)
void initializeSuzukiK6A(TriggerWaveform *s)
void initializeSuzukiG13B(TriggerWaveform *s)
void initialize2jzGE3_34_simulation_shape(TriggerWaveform *s)
void initializeUzCam(TriggerWaveform *s)
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 initializeSkippedToothTrigger(TriggerWaveform *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode, SyncEdge syncEdge)
void configure3_1_cam(TriggerWaveform *s)
void configure6ToothCrank(TriggerWaveform *s)
void setVwConfiguration(TriggerWaveform *s)
void setSkodaFavorit(TriggerWaveform *s)
printf("\n")