GCC Code Coverage Report


Directory: ./
File: firmware/controllers/actuators/alternator_controller.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 85.4% 35 0 41
Functions: 100.0% 9 0 9
Branches: 76.5% 13 0 17
Decisions: 60.0% 6 - 10

Line Branch Decision Exec Source
1 /**
2 * @file alternator_controller.cpp
3 * @brief alternator controller - some newer vehicles control alternator with ECU
4 *
5 * @date Apr 6, 2014
6 * @author Dmitry Sidin
7 * @author Andrey Belomutskiy, (c) 2012-2020
8 */
9
10 #include "pch.h"
11
12 #if EFI_ALTERNATOR_CONTROL
13 #include "alternator_controller.h"
14 #include "efi_pid.h"
15 #include "local_version_holder.h"
16 #include "periodic_task.h"
17
18 #if defined(HAS_OS_ACCESS)
19 #error "Unexpected OS ACCESS HERE"
20 #endif /* HAS_OS_ACCESS */
21
22 static SimplePwm alternatorControl("alt");
23
24 680 AlternatorController::AlternatorController() {
25 680 alternatorPid.initPidClass(&engineConfiguration->alternatorControl);
26 680 }
27
28 1120 void AlternatorController::onFastCallback() {
29
1/2
✓ Branch 1 taken 1120 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 1120 times.
✗ Decision 'false' not taken.
1120 if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) {
30 1120 return;
31 }
32
33 // this block could be executed even in on/off alternator control mode
34 // but at least we would reflect latest state
35 #if EFI_TUNER_STUDIO
36 alternatorPid.postState(engine->outputChannels.alternatorStatus);
37 #endif /* EFI_TUNER_STUDIO */
38
39 update();
40 }
41
42 25 expected<float> AlternatorController::getSetpoint() {
43 25 const float rpm = Sensor::getOrZero(SensorType::Rpm);
44 25 bool alternatorShouldBeEnabledAtCurrentRpm = rpm > engineConfiguration->cranking.rpm;
45
46
4/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 22 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 22 times.
25 if (!engineConfiguration->isAlternatorControlEnabled || !alternatorShouldBeEnabledAtCurrentRpm) {
47 3 return unexpected;
48 }
49
50 22 const float load = getEngineState()->fuelingLoad;
51 return interpolate3d(
52 22 config->alternatorVoltageTargetTable,
53 22 config->alternatorVoltageTargetLoadBins, load,
54 22 config->alternatorVoltageTargetRpmBins, rpm
55
1/1
✓ Branch 2 taken 22 times.
22 );
56 }
57
58 1 expected<float> AlternatorController::observePlant() {
59 1 return Sensor::get(SensorType::BatteryVoltage);
60 }
61
62 2 expected<percent_t> AlternatorController::getOpenLoop(float /*target*/) {
63 // see "idle air Bump for AC" comment
64
3/3
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 1 time.
2 return engine->module<AcController>().unmock().acButtonState ? engineConfiguration->acRelayAlternatorDutyAdder : 0;
65 }
66
67 1 expected<percent_t> AlternatorController::getClosedLoop(float setpoint, float observation) {
68 1 alternatorPid.iTermMin = engineConfiguration->alternator_iTermMin;
69 1 alternatorPid.iTermMax = engineConfiguration->alternator_iTermMax;
70
1/1
✓ Branch 3 taken 1 time.
1 return alternatorPid.getOutput(setpoint, observation, FAST_CALLBACK_PERIOD_MS / 1000.0f);
71 }
72
73 1 void AlternatorController::setOutput(expected<percent_t> outputValue) {
74
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 time.
1 if (outputValue) {
75 alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(outputValue.Value));
76 } else {
77 // Shut off output if not needed
78 1 alternatorPid.reset();
79 1 alternatorControl.setSimplePwmDutyCycle(0);
80 }
81 1 }
82
83 219 void AlternatorController::onConfigurationChange(engine_configuration_s const * previousConfiguration) {
84
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 219 times.
219 if(!alternatorPid.isSame(&previousConfiguration->alternatorControl)) {
85 alternatorPid.reset();
86 }
87 219 }
88
89 584 void initAlternatorCtrl() {
90
1/2
✓ Branch 1 taken 584 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 584 times.
✗ Decision 'false' not taken.
584 if (!isBrainPinValid(engineConfiguration->alternatorControlPin))
91 584 return;
92
93 startSimplePwm(&alternatorControl,
94 "Alternator control",
95 &engine->scheduler,
96 &enginePins.alternatorPin,
97 engineConfiguration->alternatorPwmFrequency, 0);
98 }
99
100 #endif /* EFI_ALTERNATOR_CONTROL */
101