GCC Code Coverage Report


Directory: ./
File: firmware/controllers/algo/event_registry.h
Date: 2025-10-03 00:57:22
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 1299 angle_t getAngle() const {
26 1299 return enginePhase;
27 }
28
29 8898 void setAngle(angle_t p_enginePhase) {
30 8898 enginePhase = p_enginePhase;
31 8898 }
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 /**
69 * Desired timing advance
70 */
71 angle_t sparkAngle = NAN;
72 floatms_t sparkDwell = 0;
73
74 // this timer allows us to measure actual dwell time
75 Timer actualDwellTimer;
76
77 float dwellAngle = 0;
78
79 /**
80 * Sequential number of currently processed spark event
81 * @see engineState.globalSparkCounter
82 */
83 uint32_t sparkCounter = 0;
84 /**
85 * [0, cylindersCount)
86 */
87 int cylinderIndex = 0;
88 // previously known as cylinderNumber
89 int8_t coilIndex = 0;
90 char *name = nullptr;
91 IgnitionOutputPin *getOutputForLoggins();
92 };
93
94 class IgnitionEventList {
95 public:
96 /**
97 * ignition events, per cylinder
98 */
99 IgnitionEvent elements[MAX_CYLINDER_COUNT];
100 bool isReady = false;
101 };
102
103 class AuxActor {
104 public:
105 int phaseIndex;
106 int valveIndex;
107 angle_t extra;
108
109 AngleBasedEvent open;
110 AngleBasedEvent close;
111 };
112
113
114 IgnitionEventList *getIgnitionEvents();
115