GCC Code Coverage Report


Directory: ./
File: firmware/controllers/actuators/idle_thread_io.cpp
Date: 2025-12-07 23:45:09
Coverage Exec Excl Total
Lines: 94.6% 35 0 37
Functions: 80.0% 4 0 5
Branches: -% 0 0 0
Decisions: -% 0 - 0

Line Branch Decision Exec Source
1 /*
2 * @file idle_thread_io.cpp
3 *
4 *
5 * enable verbose_idle
6 * disable verbose_idle
7 *
8 * This file is part of rusEfi - see http://rusefi.com
9 *
10 * rusEfi is free software; you can redistribute it and/or modify it under the terms of
11 * the GNU General Public License as published by the Free Software Foundation; either
12 * version 3 of the License, or (at your option) any later version.
13 *
14 * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
15 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with this program.
19 * If not, see <http://www.gnu.org/licenses/>.
20 *
21 * @date Oct 17, 2021
22 * @author Andrey Belomutskiy, (c) 2012-2020
23 */
24
25 #include "pch.h"
26
27 #if ! EFI_UNIT_TEST
28 #include "dc_motors.h"
29 #include "idle_hardware.h"
30
31 void setManualIdleValvePosition(int positionPercent) {
32 if (positionPercent < 1 || positionPercent > 99)
33 return;
34 efiPrintf("setting idle valve position %d", positionPercent);
35 // todo: this is not great that we have to write into configuration here
36 setTable(config->cltIdleCorrTable, positionPercent);
37 }
38
39 #endif /* EFI_UNIT_TEST */
40
41 #if EFI_PROD_CODE
42 static void startInputPinIfValid(const char *msg, brain_pin_e pin, pin_input_mode_e mode) {
43 efiSetPadMode(msg, pin, getInputMode(mode));
44 }
45 #endif // EFI_PROD_CODE
46
47 percent_t getIdlePosition() {
48 #if EFI_IDLE_CONTROL
49 return engine->module<IdleController>().unmock().currentIdlePosition;
50 #else
51 return 0;
52 #endif
53 }
54
55 811 void startSwitchPins() {
56 #if EFI_PROD_CODE
57 // this is neutral/no gear switch input. on Miata it's wired both to clutch pedal and neutral in gearbox
58 // this switch is not used yet
59 startInputPinIfValid("clutch down switch", engineConfiguration->clutchDownPin, engineConfiguration->clutchDownPinMode);
60
61 startInputPinIfValid("clutch up switch", engineConfiguration->clutchUpPin, engineConfiguration->clutchUpPinMode);
62
63 startInputPinIfValid("brake pedal switch", engineConfiguration->brakePedalPin, engineConfiguration->brakePedalPinMode);
64 startInputPinIfValid("Launch Button", engineConfiguration->launchActivatePin, engineConfiguration->launchActivatePinMode);
65 startInputPinIfValid("Antilag Button", engineConfiguration->ALSActivatePin, engineConfiguration->ALSActivatePinMode);
66 startInputPinIfValid("Ignition Switch", engineConfiguration->ignitionKeyDigitalPin, engineConfiguration->ignitionKeyDigitalPinMode);
67 startInputPinIfValid("Torque Reduction Button", engineConfiguration->torqueReductionTriggerPin, engineConfiguration->torqueReductionTriggerPinMode);
68 startInputPinIfValid("Nitrous Button", engineConfiguration->nitrousControlTriggerPin, engineConfiguration->nitrousControlTriggerPinMode);
69 #endif /* EFI_PROD_CODE */
70 811 }
71
72 221 void stopSwitchPins() {
73 221 brain_pin_markUnused(activeConfiguration.clutchUpPin);
74 221 brain_pin_markUnused(activeConfiguration.clutchDownPin);
75 221 brain_pin_markUnused(activeConfiguration.brakePedalPin);
76 221 brain_pin_markUnused(activeConfiguration.launchActivatePin);
77 221 brain_pin_markUnused(activeConfiguration.ALSActivatePin);
78 221 brain_pin_markUnused(activeConfiguration.ignitionKeyDigitalPin);
79 221 brain_pin_markUnused(activeConfiguration.torqueReductionTriggerPin);
80 221 brain_pin_markUnused(activeConfiguration.nitrousControlTriggerPin);
81 221 }
82
83 #if ! EFI_UNIT_TEST
84
85 #if EFI_IDLE_CONTROL
86 static void applyPidSettings() {
87 engine->module<IdleController>().unmock().getIdlePid()->updateFactors(engineConfiguration->idleRpmPid.pFactor, engineConfiguration->idleRpmPid.iFactor, engineConfiguration->idleRpmPid.dFactor);
88 }
89 #endif // EFI_IDLE_CONTROL
90
91 void setTargetIdleRpm(int value) {
92 setTargetRpmCurve(value);
93 efiPrintf("target idle RPM %d", value);
94 }
95
96 /**
97 * Idle test would activate the solenoid for three seconds
98 */
99 void startIdleBench(void) {
100 engine->timeToStopIdleTest = getTimeNowUs() + MS2US(3000); // 3 seconds
101 efiPrintf("idle valve bench test");
102 }
103
104 #endif /* EFI_UNIT_TEST */
105
106 #if EFI_IDLE_CONTROL
107
108 593 void setDefaultIdleParameters() {
109 593 engineConfiguration->idleRpmPid.pFactor = 0.01f;
110 593 engineConfiguration->idleRpmPid.iFactor = 0.05f;
111 593 engineConfiguration->idleRpmPid.dFactor = 0.0f;
112
113 593 engineConfiguration->idlerpmpid_iTermMin = -20;
114 593 engineConfiguration->idlerpmpid_iTermMax = 20;
115
116 // Good starting point is 10 degrees per 100 rpm, aka 0.1 deg/rpm
117 593 engineConfiguration->idleTimingPid.pFactor = 0.1f;
118 593 engineConfiguration->idleTimingPid.iFactor = 0;
119 593 engineConfiguration->idleTimingPid.dFactor = 0;
120
121 // Allow +- 10 degrees adjustment
122 593 engineConfiguration->idleTimingPid.minValue = -10;
123 593 engineConfiguration->idleTimingPid.maxValue = 10;
124
125 // Idle region is target + 300 RPM
126 593 engineConfiguration->idlePidRpmUpperLimit = 300;
127
128 593 engineConfiguration->idlePidRpmDeadZone = 50;
129 593 engineConfiguration->idleReturnTargetRampDuration = 3;
130 593 }
131
132 591 void startIdleThread() {
133 // Force the idle controller to use 0 offset, as this is handled by the open loop table instead.
134 591 engineConfiguration->idleRpmPid.offset = 0;
135
136 591 IdleController *controller = &engine->module<IdleController>().unmock();
137
138 591 controller->init();
139
140 #if ! EFI_UNIT_TEST
141 // todo: we still have to explicitly init all hardware on start in addition to handling configuration change via
142 // 'applyNewHardwareSettings' todo: maybe unify these two use-cases?
143 initIdleHardware();
144 #endif /* EFI_UNIT_TEST */
145
146 591 controller->idleState = INIT;
147 591 controller->baseIdlePosition = -100.0f;
148 591 controller->currentIdlePosition = -100.0f;
149
150 #if ! EFI_UNIT_TEST
151 // split this whole file into manual controller and auto controller? move these commands into the file
152 // which would be dedicated to just auto-controller?
153
154 addConsoleAction("idlebench", startIdleBench);
155 applyPidSettings();
156 #endif /* EFI_UNIT_TEST */
157 591 }
158
159 #endif /* EFI_IDLE_CONTROL */
160