GCC Code Coverage Report


Directory: ./
File: firmware/controllers/trigger/trigger_simulator.cpp
Date: 2025-11-16 14:52:24
Coverage Exec Excl Total
Lines: 96.1% 49 0 51
Functions: 100.0% 5 0 5
Branches: 92.1% 35 0 38
Decisions: 95.5% 21 - 22

Line Branch Decision Exec Source
1 /*
2 * @file trigger_simulator.cpp
3 *
4 * @date Sep 23, 2015
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8 #include "pch.h"
9
10 #include "trigger_simulator.h"
11 #include "trigger_emulator_algo.h"
12
13 #if EFI_UNIT_TEST
14 extern bool printTriggerTrace;
15 #endif
16
17 /**
18 * todo: should this method be invoked somewhere deeper? at the moment we have too many usages too high
19 * @return true if front should be decoded further, false if we are not interested
20 */
21 260671 bool isUsefulSignal(trigger_event_e signal, const TriggerWaveform& shape) {
22
2/2
✓ Branch 0 taken 145281 times.
✓ Branch 1 taken 115390 times.
2/2
✓ Decision 'true' taken 145281 times.
✓ Decision 'false' taken 115390 times.
260671 if (shape.useOnlyRisingEdges) {
23 145281 return isTriggerUpEvent(signal);
24 }
25
26 // consider both edges, so all edges are useful
27 115390 return true;
28 }
29
30 #if EFI_UNIT_TEST
31 extern bool printTriggerDebug;
32 #endif /* ! EFI_UNIT_TEST */
33
34 188876 int getSimulatedEventTime(const TriggerWaveform& shape, int i) {
35 188876 int stateIndex = i % shape.getSize();
36 188876 int loopIndex = i / shape.getSize();
37
38 188876 return (int) (SIMULATION_CYCLE_PERIOD * (loopIndex + shape.wave.getSwitchTime(stateIndex)));
39 }
40
41 188803 void TriggerStimulatorHelper::feedSimulatedEvent(
42 const TriggerConfiguration& triggerConfiguration,
43 TriggerDecoderBase& state,
44 const TriggerWaveform& shape,
45 int index
46 ) {
47
2/4
✓ Branch 1 taken 188803 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188803 times.
✗ Branch 6 not taken.
188803 efiAssertVoid(ObdCode::CUSTOM_ERR_6593, shape.getSize() > 0, "size not zero");
48
1/1
✓ Branch 1 taken 188803 times.
188803 int stateIndex = index % shape.getSize();
49
50
1/1
✓ Branch 1 taken 188803 times.
188803 int time = getSimulatedEventTime(shape, index);
51
52 188803 const auto & multiChannelStateSequence = shape.wave;
53
54 #if EFI_UNIT_TEST
55
2/2
✓ Branch 1 taken 188803 times.
✓ Branch 4 taken 188803 times.
188803 int prevIndex = getPreviousIndex(stateIndex, shape.getSize());
56
57 188803 pin_state_t primaryWheelState = multiChannelStateSequence.getChannelState(0, prevIndex);
58 188803 pin_state_t newPrimaryWheelState = multiChannelStateSequence.getChannelState(0, stateIndex);
59
60 188803 pin_state_t secondaryWheelState = multiChannelStateSequence.getChannelState(1, prevIndex);
61 188803 pin_state_t newSecondaryWheelState = multiChannelStateSequence.getChannelState(1, stateIndex);
62
63 // pin_state_t thirdWheelState = multiChannelStateSequence->getChannelState(2, prevIndex);
64 // pin_state_t new3rdWheelState = multiChannelStateSequence->getChannelState(2, stateIndex);
65
66
2/2
✓ Branch 0 taken 885 times.
✓ Branch 1 taken 187918 times.
2/2
✓ Decision 'true' taken 885 times.
✓ Decision 'false' taken 187918 times.
188803 if (printTriggerDebug) {
67
1/1
✓ Branch 1 taken 885 times.
885 printf("TriggerStimulator: simulatedEvent: %d>%d primary %d>%d secondary %d>%d\r\n", prevIndex, stateIndex, primaryWheelState, newPrimaryWheelState,
68 secondaryWheelState, newSecondaryWheelState );
69 }
70 #endif /* EFI_UNIT_TEST */
71
72
73 // todo: code duplication with TriggerEmulatorHelper::handleEmulatorCallback?
74
75 188803 constexpr trigger_event_e riseEvents[] = { SHAFT_PRIMARY_RISING, SHAFT_SECONDARY_RISING };
76 188803 constexpr trigger_event_e fallEvents[] = { SHAFT_PRIMARY_FALLING, SHAFT_SECONDARY_FALLING };
77
78
2/2
✓ Branch 0 taken 377606 times.
✓ Branch 1 taken 188803 times.
2/2
✓ Decision 'true' taken 377606 times.
✓ Decision 'false' taken 188803 times.
566409 for (size_t i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
79
3/3
✓ Branch 1 taken 377606 times.
✓ Branch 3 taken 188803 times.
✓ Branch 4 taken 188803 times.
2/2
✓ Decision 'true' taken 188803 times.
✓ Decision 'false' taken 188803 times.
377606 if (needEvent(stateIndex, multiChannelStateSequence, i)) {
80 188803 pin_state_t currentValue = multiChannelStateSequence.getChannelState(/*phaseIndex*/i, stateIndex);
81
2/2
✓ Branch 0 taken 94867 times.
✓ Branch 1 taken 93936 times.
188803 trigger_event_e event = (currentValue == TriggerValue::RISE ? riseEvents : fallEvents)[i];
82
3/3
✓ Branch 1 taken 188803 times.
✓ Branch 3 taken 149485 times.
✓ Branch 4 taken 39318 times.
2/2
✓ Decision 'true' taken 149485 times.
✓ Decision 'false' taken 39318 times.
188803 if (isUsefulSignal(event, shape)) {
83
1/1
✓ Branch 1 taken 149485 times.
149485 state.decodeTriggerEvent(
84 "sim",
85 shape,
86 /* override */ nullptr,
87 triggerConfiguration,
88 event, time);
89 }
90 }
91 }
92 }
93
94 1080 void TriggerStimulatorHelper::assertSyncPosition(
95 const TriggerConfiguration& triggerConfiguration,
96 const uint32_t syncIndex,
97 TriggerDecoderBase& state,
98 TriggerWaveform& shape
99 ) {
100
101 // todo: is anything limiting this TEST_REVOLUTIONS? why does value '8' not work for example?
102 #define TEST_REVOLUTIONS 6
103
104 /**
105 * let's feed two more cycles to validate shape definition
106 */
107
2/2
✓ Branch 1 taken 100740 times.
✓ Branch 2 taken 1080 times.
2/2
✓ Decision 'true' taken 100740 times.
✓ Decision 'false' taken 1080 times.
101820 for (uint32_t i = syncIndex + 1; i <= syncIndex + TEST_REVOLUTIONS * shape.getSize(); i++) {
108 100740 feedSimulatedEvent(triggerConfiguration, state, shape, i);
109 }
110
111 1080 int revolutionCounter = state.getSynchronizationCounter();
112
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1078 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1078 times.
1080 if (revolutionCounter != TEST_REVOLUTIONS) {
113 2 warning(ObdCode::CUSTOM_OBD_TRIGGER_WAVEFORM, "sync failed/wrong gap parameters trigger=%s revolutionCounter=%d",
114 2 getTrigger_type_e(triggerConfiguration.TriggerType.type),
115 revolutionCounter);
116 2 shape.setShapeDefinitionError(true);
117 2 return;
118 }
119 1078 shape.shapeDefinitionError = false;
120 #if EFI_UNIT_TEST
121
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1053 times.
2/2
✓ Decision 'true' taken 25 times.
✓ Decision 'false' taken 1053 times.
1078 if (printTriggerTrace) {
122 25 printf("Happy %s revolutionCounter=%d\r\n",
123 25 getTrigger_type_e(triggerConfiguration.TriggerType.type),
124 revolutionCounter);
125 }
126 #endif /* EFI_UNIT_TEST */
127 }
128
129 /**
130 * @return trigger synchronization point index, or error code if not found
131 */
132 1146 expected<uint32_t> TriggerStimulatorHelper::findTriggerSyncPoint(
133 TriggerWaveform& shape,
134 const TriggerConfiguration& triggerConfiguration,
135 TriggerDecoderBase& state) {
136
2/2
✓ Branch 1 taken 88063 times.
✓ Branch 2 taken 66 times.
2/2
✓ Decision 'true' taken 88063 times.
✓ Decision 'false' taken 66 times.
88129 for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) {
137
1/1
✓ Branch 1 taken 88063 times.
88063 feedSimulatedEvent(triggerConfiguration, state, shape, i);
138
139
3/3
✓ Branch 1 taken 88063 times.
✓ Branch 3 taken 1080 times.
✓ Branch 4 taken 86983 times.
2/2
✓ Decision 'true' taken 1080 times.
✓ Decision 'false' taken 86983 times.
88063 if (state.getShaftSynchronized()) {
140 1080 return i;
141 }
142 }
143 66 shape.setShapeDefinitionError(true);
144
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 66 times.
66 if (engineConfiguration->overrideTriggerGaps) {
146 firmwareError(ObdCode::CUSTOM_ERR_CUSTOM_GAPS_BAD, "The custom trigger gaps are invalid for the current trigger type.");
147 } else {
148 66 firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_SYNC, "findTriggerZeroEventIndex() failed");
149 }
150 return unexpected;
151 }
152