| 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 |