GCC Code Coverage Report


Directory: ./
File: firmware/controllers/algo/event_registry.h
Date: 2025-10-24 14:26:41
Coverage Exec Excl Total
Lines: 100.0% 5 0 5
Functions: 100.0% 2 0 2
Branches: -% 0 0 0
Decisions: -% 0 - 0

Line Branch Decision Exec Source
1 /**
2 * @file event_registry.h
3 *
4 * @date Nov 27, 2013
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8 #pragma once
9
10 #include "global.h"
11 #include "efi_gpio.h"
12 #include "scheduler.h"
13 #include "fl_stack.h"
14 #include "trigger_structure.h"
15
16 struct AngleBasedEvent {
17 scheduling_s eventScheduling;
18 action_s action;
19 /**
20 * Trigger-based scheduler maintains a linked list of all pending tooth-based events.
21 */
22 AngleBasedEvent *nextToothEvent = nullptr;
23
24 // angular position of this event
25 2077 angle_t getAngle() const {
26 2077 return enginePhase;
27 }
28
29 9676 void setAngle(angle_t p_enginePhase) {
30 9676 enginePhase = p_enginePhase;
31 9676 }
32
33 bool shouldSchedule(float currentPhase, float nextPhase) const;
34 float getAngleFromNow(float currentPhase) const;
35 private:
36 angle_t enginePhase;
37 };
38
39 // this is related to wasted spark idea where engines fire each spark twice per 4 stroke 720 degree cycle of operations
40 // first spark is happens on intake stroke and actually ignites fuel mixture, that's the useful one
41 // the other spark 360 degrees later happens during exhaust stroke meaning there is nothing to ignite, that spark is known as "wasted" spark
42 // historically this was about sharing ignition coils between opposite cylinders and having two high voltage wire coming from one physical coil
43 // more recently same idea happens with two individual physical coils (meaning two outputs) since wasted spark of operation is useful
44 // while exact engine phase is either not known YET (cranking) or just not known (broken cam sensor)
45 // so, while in wasted spark we manage half of cylinder count _events_ potentially with each event having two outputs
46 //
47 // an interesting corner case is when we transition from wasted spark mode into individual/sequential mode
48 #define MAX_OUTPUTS_FOR_IGNITION 2
49
50 class IgnitionEvent {
51 public:
52 IgnitionEvent();
53 // IgnitionEvent to IgnitionOutputPin is either 1 to 1 or 1 to 2 relationship, see large comment at 'MAX_OUTPUTS_FOR_IGNITION'
54 IgnitionOutputPin *outputs[MAX_OUTPUTS_FOR_IGNITION];
55 scheduling_s dwellStartTimer;
56 AngleBasedEvent sparkEvent;
57
58 scheduling_s trailingSparkCharge;
59 scheduling_s trailingSparkFire;
60
61 // How many additional sparks should we fire after the first one?
62 // For single sparks, this should be zero.
63 uint8_t sparksRemaining = 0;
64
65 // Track whether coil charge was intentionally skipped (spark limiter)
66 bool wasSparkLimited = false;
67
68 // Track whether coil charge was canceled due to overcharge
69 bool wasSparkCanceled = false;
70
71 /**
72 * Desired timing advance
73 */
74 angle_t sparkAngle = NAN;
75 floatms_t sparkDwell = 0;
76
77 // this timer allows us to measure actual dwell time
78 Timer actualDwellTimer;
79
80 float dwellAngle = 0;
81
82 /**
83 * Sequential number of currently processed spark event
84 * @see engineState.globalSparkCounter
85 */
86 uint32_t sparkCounter = 0;
87 /**
88 * [0, cylindersCount)
89 */
90 int cylinderIndex = 0;
91 // previously known as cylinderNumber
92 int8_t coilIndex = 0;
93 char *name = nullptr;
94 IgnitionOutputPin *getOutputForLoggins();
95 };
96
97 class IgnitionEventList {
98 public:
99 /**
100 * ignition events, per cylinder
101 */
102 IgnitionEvent elements[MAX_CYLINDER_COUNT];
103 bool isReady = false;
104 };
105
106 class AuxActor {
107 public:
108 int phaseIndex;
109 int valveIndex;
110 angle_t extra;
111
112 AngleBasedEvent open;
113 AngleBasedEvent close;
114 };
115
116
117 IgnitionEventList *getIgnitionEvents();
118