GCC Code Coverage Report


Directory: ./
File: firmware/controllers/trigger/trigger_simulator.cpp
Date: 2025-10-03 00:57:22
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 253915 bool isUsefulSignal(trigger_event_e signal, const TriggerWaveform& shape) {
22
2/2
✓ Branch 0 taken 138650 times.
✓ Branch 1 taken 115265 times.
2/2
✓ Decision 'true' taken 138650 times.
✓ Decision 'false' taken 115265 times.
253915 if (shape.useOnlyRisingEdges) {
23 138650 return isTriggerUpEvent(signal);
24 }
25
26 // consider both edges, so all edges are useful
27 115265 return true;
28 }
29
30 #if EFI_UNIT_TEST
31 extern bool printTriggerDebug;
32 #endif /* ! EFI_UNIT_TEST */
33
34 186825 int getSimulatedEventTime(const TriggerWaveform& shape, int i) {
35 186825 int stateIndex = i % shape.getSize();
36 186825 int loopIndex = i / shape.getSize();
37
38 186825 return (int) (SIMULATION_CYCLE_PERIOD * (loopIndex + shape.wave.getSwitchTime(stateIndex)));
39 }
40
41 186752 void TriggerStimulatorHelper::feedSimulatedEvent(
42 const TriggerConfiguration& triggerConfiguration,
43 TriggerDecoderBase& state,
44 const TriggerWaveform& shape,
45 int index
46 ) {
47
2/4
✓ Branch 1 taken 186752 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 186752 times.
✗ Branch 6 not taken.
186752 efiAssertVoid(ObdCode::CUSTOM_ERR_6593, shape.getSize() > 0, "size not zero");
48
1/1
✓ Branch 1 taken 186752 times.
186752 int stateIndex = index % shape.getSize();
49
50
1/1
✓ Branch 1 taken 186752 times.
186752 int time = getSimulatedEventTime(shape, index);
51
52 186752 const auto & multiChannelStateSequence = shape.wave;
53
54 #if EFI_UNIT_TEST
55
2/2
✓ Branch 1 taken 186752 times.
✓ Branch 4 taken 186752 times.
186752 int prevIndex = getPreviousIndex(stateIndex, shape.getSize());
56
57 186752 pin_state_t primaryWheelState = multiChannelStateSequence.getChannelState(0, prevIndex);
58 186752 pin_state_t newPrimaryWheelState = multiChannelStateSequence.getChannelState(0, stateIndex);
59
60 186752 pin_state_t secondaryWheelState = multiChannelStateSequence.getChannelState(1, prevIndex);
61 186752 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 76648 times.
✓ Branch 1 taken 110104 times.
2/2
✓ Decision 'true' taken 76648 times.
✓ Decision 'false' taken 110104 times.
186752 if (printTriggerDebug) {
67
1/1
✓ Branch 1 taken 76648 times.
76648 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 186752 constexpr trigger_event_e riseEvents[] = { SHAFT_PRIMARY_RISING, SHAFT_SECONDARY_RISING };
76 186752 constexpr trigger_event_e fallEvents[] = { SHAFT_PRIMARY_FALLING, SHAFT_SECONDARY_FALLING };
77
78
2/2
✓ Branch 0 taken 373504 times.
✓ Branch 1 taken 186752 times.
2/2
✓ Decision 'true' taken 373504 times.
✓ Decision 'false' taken 186752 times.
560256 for (size_t i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
79
3/3
✓ Branch 1 taken 373504 times.
✓ Branch 3 taken 186752 times.
✓ Branch 4 taken 186752 times.
2/2
✓ Decision 'true' taken 186752 times.
✓ Decision 'false' taken 186752 times.
373504 if (needEvent(stateIndex, multiChannelStateSequence, i)) {
80 186752 pin_state_t currentValue = multiChannelStateSequence.getChannelState(/*phaseIndex*/i, stateIndex);
81
2/2
✓ Branch 0 taken 93836 times.
✓ Branch 1 taken 92916 times.
186752 trigger_event_e event = (currentValue == TriggerValue::RISE ? riseEvents : fallEvents)[i];
82
3/3
✓ Branch 1 taken 186752 times.
✓ Branch 3 taken 148394 times.
✓ Branch 4 taken 38358 times.
2/2
✓ Decision 'true' taken 148394 times.
✓ Decision 'false' taken 38358 times.
186752 if (isUsefulSignal(event, shape)) {
83
1/1
✓ Branch 1 taken 148394 times.
148394 state.decodeTriggerEvent(
84 "sim",
85 shape,
86 /* override */ nullptr,
87 triggerConfiguration,
88 event, time);
89 }
90 }
91 }
92 }
93
94 1069 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 98988 times.
✓ Branch 2 taken 1069 times.
2/2
✓ Decision 'true' taken 98988 times.
✓ Decision 'false' taken 1069 times.
100057 for (uint32_t i = syncIndex + 1; i <= syncIndex + TEST_REVOLUTIONS * shape.getSize(); i++) {
108 98988 feedSimulatedEvent(triggerConfiguration, state, shape, i);
109 }
110
111 1069 int revolutionCounter = state.getSynchronizationCounter();
112
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1067 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1067 times.
1069 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 1067 shape.shapeDefinitionError = false;
120 #if EFI_UNIT_TEST
121
2/2
✓ Branch 0 taken 795 times.
✓ Branch 1 taken 272 times.
2/2
✓ Decision 'true' taken 795 times.
✓ Decision 'false' taken 272 times.
1067 if (printTriggerTrace) {
122 795 printf("Happy %s revolutionCounter=%d\r\n",
123 795 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 1135 expected<uint32_t> TriggerStimulatorHelper::findTriggerSyncPoint(
133 TriggerWaveform& shape,
134 const TriggerConfiguration& triggerConfiguration,
135 TriggerDecoderBase& state) {
136
2/2
✓ Branch 1 taken 87764 times.
✓ Branch 2 taken 66 times.
2/2
✓ Decision 'true' taken 87764 times.
✓ Decision 'false' taken 66 times.
87830 for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) {
137
1/1
✓ Branch 1 taken 87764 times.
87764 feedSimulatedEvent(triggerConfiguration, state, shape, i);
138
139
3/3
✓ Branch 1 taken 87764 times.
✓ Branch 3 taken 1069 times.
✓ Branch 4 taken 86695 times.
2/2
✓ Decision 'true' taken 1069 times.
✓ Decision 'false' taken 86695 times.
87764 if (state.getShaftSynchronized()) {
140 1069 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