GCC Code Coverage Report


Directory: ./
File: firmware/controllers/settings.cpp
Date: 2025-10-24 14:26:41
Coverage Exec Excl Total
Lines: 66.7% 6 0 9
Functions: 50.0% 1 0 2
Branches: -% 0 0 0
Decisions: 0.0% 0 - 1

Line Branch Decision Exec Source
1 /**
2 * @file settings.cpp
3 * @brief This file is about configuring engine via the human-readable protocol
4 *
5 * @date Dec 30, 2012
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9 #include "pch.h"
10
11 #if ! EFI_UNIT_TEST
12
13 #include "eficonsole.h"
14 #include "trigger_decoder.h"
15 #include "console_io.h"
16 #include "idle_thread.h"
17 #include "alternator_controller.h"
18 #include "trigger_emulator_algo.h"
19 #include "value_lookup.h"
20 #if EFI_RTC
21 #include "rtc_helper.h"
22 #endif // EFI_RTC
23
24 #if EFI_PROD_CODE
25 #include "can_hw.h"
26 #include "rusefi.h"
27 #include "hardware.h"
28 #endif // EFI_PROD_CODE
29
30 #if EFI_ELECTRONIC_THROTTLE_BODY
31 #include "electronic_throttle.h"
32 #endif // EFI_ELECTRONIC_THROTTLE_BODY
33
34 #if EFI_CONFIGURATION_STORAGE
35 #include "flash_main.h"
36 #endif // EFI_CONFIGURATION_STORAGE
37
38 #if EFI_ENGINE_SNIFFER
39 #include "engine_sniffer.h"
40 extern int waveChartUsedSize;
41 extern WaveChart waveChart;
42 #endif // EFI_ENGINE_SNIFFER
43
44 using namespace rusefi::stringutil;
45
46 void printSpiState() {
47 efiPrintf("spi 1=%s/2=%s/3=%s/4=%s",
48 boolToString(engineConfiguration->is_enabled_spi_1),
49 boolToString(engineConfiguration->is_enabled_spi_2),
50 boolToString(engineConfiguration->is_enabled_spi_3),
51 boolToString(engineConfiguration->is_enabled_spi_4));
52 }
53
54 /**
55 * @brief Prints current engine configuration to human-readable console.
56 */
57 void printConfiguration() {
58
59 efiPrintf("Template %s/%d trigger %s/%s/%d", getEngine_type_e(engineConfiguration->engineType),
60 (int)engineConfiguration->engineType,
61 getTrigger_type_e(engineConfiguration->trigger.type),
62 Enum2String(engineConfiguration->fuelAlgorithm), (int)engineConfiguration->fuelAlgorithm);
63
64 efiPrintf("configurationVersion=%d", engine->getGlobalConfigurationVersion());
65
66 #if EFI_PROD_CODE
67 printSpiState();
68 #endif // EFI_PROD_CODE
69 }
70
71 #if EFI_ENGINE_CONTROL
72 static void setIdleSolenoidFrequency(int value) {
73 engineConfiguration->idle.solenoidFrequency = value;
74 incrementGlobalConfigurationVersion();
75 }
76 #endif // EFI_ENGINE_CONTROL
77
78 #if EFI_ENGINE_CONTROL
79 static void setCrankingRpm(int value) {
80 engineConfiguration->cranking.rpm = value;
81 printConfiguration();
82 }
83
84 /**
85 * this method is used in console - it also prints current configuration
86 */
87 static void setAlgorithmInt(int value) {
88 setAlgorithm((engine_load_mode_e) value);
89 printConfiguration();
90 }
91
92 static void setFiringOrder(int value) {
93 engineConfiguration->firingOrder = (firing_order_e) value;
94 printConfiguration();
95 }
96
97 static void setRpmHardLimit(int value) {
98 engineConfiguration->rpmHardLimit = value;
99 printConfiguration();
100 }
101
102 static void setCrankingIACExtra(float percent) {
103 for (uint8_t i = 0; i < CLT_CRANKING_CURVE_SIZE; i++) {
104 config->cltCrankingCorr[i] = percent;
105 }
106 efiPrintf("cranking_iac %.2f", percent);
107 }
108
109 static void setCrankingFuel(float fuelMilligram) {
110 setTable(config->crankingCycleBaseFuel, fuelMilligram);
111 efiPrintf("cranking_fuel %.2f", fuelMilligram);
112 }
113
114 static void setGlobalTriggerAngleOffset(float value) {
115 engineConfiguration->globalTriggerAngleOffset = value;
116 incrementGlobalConfigurationVersion();
117 printConfiguration();
118 }
119
120 static void setCrankingTimingAngle(float value) {
121 engineConfiguration->crankingTimingAngle = value;
122 incrementGlobalConfigurationVersion();
123 printConfiguration();
124 }
125
126 static void setCrankingInjectionMode(int value) {
127 engineConfiguration->crankingInjectionMode = (injection_mode_e) value;
128 incrementGlobalConfigurationVersion();
129 printConfiguration();
130 }
131
132 static void setInjectionMode(int value) {
133 engineConfiguration->injectionMode = (injection_mode_e) value;
134 incrementGlobalConfigurationVersion();
135 printConfiguration();
136 }
137
138 static void setIgnitionMode(int value) {
139 #if EFI_ENGINE_CONTROL
140 engineConfiguration->ignitionMode = (ignition_mode_e) value;
141 incrementGlobalConfigurationVersion();
142 prepareOutputSignals();
143 #endif // EFI_ENGINE_CONTROL
144 }
145
146 static void setIndividualCoilsIgnition() {
147 setIgnitionMode((int)IM_INDIVIDUAL_COILS);
148 }
149
150 static void setTriggerType(int value) {
151 engineConfiguration->trigger.type = (trigger_type_e) value;
152 incrementGlobalConfigurationVersion();
153 printConfiguration();
154 efiPrintf("Do you need to also invoke set operation_mode X?");
155 engine->resetEngineSnifferIfInTestMode();
156 }
157
158 static void setDebugMode(int value) {
159 engineConfiguration->debugMode = (debug_mode_e) value;
160 }
161
162 static void setWholeTimingMap(float value) {
163 setTable(config->ignitionTable, value);
164 }
165
166 static void setWholeTimingMapCmd(float value) {
167 efiPrintf("Setting whole timing advance map to %.2f", value);
168 setWholeTimingMap(value);
169 engine->resetEngineSnifferIfInTestMode();
170 }
171
172 #endif // EFI_ENGINE_CONTROL
173
174 #if EFI_PROD_CODE
175
176 static brain_pin_e parseBrainPinWithErrorMessage(const char *pinName) {
177 brain_pin_e pin = parseBrainPin(pinName);
178 if (pin == Gpio::Invalid) {
179 efiPrintf("invalid pin name [%s]", pinName);
180 }
181 return pin;
182 }
183
184 /**
185 * For example:
186 * set_ignition_pin 1 PD7
187 * todo: this method counts index from 1 while at least 'set_trigger_input_pin' counts from 0.
188 * todo: make things consistent
189 */
190 static void setIgnitionPin(const char *indexStr, const char *pinName) {
191 int index = atoi(indexStr) - 1; // convert from human index into software index
192 if (index < 0 || index >= MAX_CYLINDER_COUNT)
193 return;
194 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
195 if (pin == Gpio::Invalid) {
196 return;
197 }
198 efiPrintf("setting ignition pin[%d] to %s please save&restart", index, hwPortname(pin));
199 engineConfiguration->ignitionPins[index] = pin;
200 incrementGlobalConfigurationVersion();
201 }
202
203 // this method is useful for desperate time debugging
204 // readpin PA0
205 void readPin(const char *pinName) {
206 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
207 if (pin == Gpio::Invalid) {
208 return;
209 }
210 int physicalValue = palReadPad(getHwPort("read", pin), getHwPin("read", pin));
211 efiPrintf("pin %s value %d", hwPortname(pin), physicalValue);
212 }
213
214 // this method is useful for desperate time debugging or hardware validation
215 static void benchSetPinValue(const char *pinName, int bit) {
216 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
217 if (pin == Gpio::Invalid) {
218 return;
219 }
220 efiSetPadModeWithoutOwnershipAcquisition("bench_pin_test", pin, PAL_MODE_OUTPUT_PUSHPULL);
221 // low-level API which does not care about 'qcDirectPinControlMode'
222 palWritePad(getHwPort("write", pin), getHwPin("write", pin), bit);
223 efiPrintf("pin %s set value", hwPortname(pin));
224 readPin(pinName);
225 }
226
227 static void benchClearPin(const char *pinName) {
228 benchSetPinValue(pinName, 0);
229 }
230
231 static void benchSetPin(const char *pinName) {
232 benchSetPinValue(pinName, 1);
233 }
234
235 static void setIndividualPin(const char *pinName, brain_pin_e *targetPin, const char *name) {
236 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
237 if (pin == Gpio::Invalid) {
238 return;
239 }
240 efiPrintf("setting %s pin to %s please save&restart", name, hwPortname(pin));
241 *targetPin = pin;
242 incrementGlobalConfigurationVersion();
243 }
244
245 // set vss_pin
246 static void setVssPin(const char *pinName) {
247 setIndividualPin(pinName, &engineConfiguration->vehicleSpeedSensorInputPin, "VSS");
248 }
249
250 // set_idle_pin none
251 static void setIdlePin(const char *pinName) {
252 setIndividualPin(pinName, &engineConfiguration->idle.solenoidPin, "idle");
253 }
254
255 static void setAlternatorPin(const char *pinName) {
256 setIndividualPin(pinName, &engineConfiguration->alternatorControlPin, "alternator");
257 }
258
259 /**
260 * For example:
261 * set_trigger_input_pin 0 PA5
262 * todo: this method counts index from 0 while at least 'set_ignition_pin' counts from 1.
263 * todo: make things consistent
264 */
265 static void setTriggerInputPin(const char *indexStr, const char *pinName) {
266 int index = atoi(indexStr);
267 if (index < 0 || index > 2)
268 return;
269 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
270 if (pin == Gpio::Invalid) {
271 return;
272 }
273 efiPrintf("setting trigger pin[%d] to %s please save&restart", index, hwPortname(pin));
274 engineConfiguration->triggerInputPins[index] = pin;
275 incrementGlobalConfigurationVersion();
276 }
277
278 static void setTriggerSimulatorPin(const char *indexStr, const char *pinName) {
279 int index = atoi(indexStr);
280 if (index < 0 || index >= TRIGGER_SIMULATOR_PIN_COUNT)
281 return;
282 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
283 if (pin == Gpio::Invalid) {
284 return;
285 }
286 efiPrintf("setting trigger simulator pin[%d] to %s please save&restart", index, hwPortname(pin));
287 engineConfiguration->triggerSimulatorPins[index] = pin;
288 incrementGlobalConfigurationVersion();
289 }
290
291 #if HAL_USE_ADC
292 // set_analog_input_pin pps pa4
293 // set_analog_input_pin afr none
294 static void setAnalogInputPin(const char *sensorStr, const char *pinName) {
295 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
296 if (pin == Gpio::Invalid) {
297 return;
298 }
299 adc_channel_e channel = getAdcChannel(pin);
300 if (channel == EFI_ADC_ERROR) {
301 efiPrintf("Error with [%s]", pinName);
302 return;
303 }
304 if (strEqual("map", sensorStr)) {
305 engineConfiguration->map.sensor.hwChannel = channel;
306 efiPrintf("setting MAP to %s/%d", pinName, channel);
307 } else if (strEqual("pps", sensorStr)) {
308 engineConfiguration->throttlePedalPositionAdcChannel = channel;
309 efiPrintf("setting PPS to %s/%d", pinName, channel);
310 } else if (strEqual("afr", sensorStr)) {
311 engineConfiguration->afr.hwChannel = channel;
312 efiPrintf("setting AFR to %s/%d", pinName, channel);
313 } else if (strEqual("clt", sensorStr)) {
314 engineConfiguration->clt.adcChannel = channel;
315 efiPrintf("setting CLT to %s/%d", pinName, channel);
316 } else if (strEqual("iat", sensorStr)) {
317 engineConfiguration->iat.adcChannel = channel;
318 efiPrintf("setting IAT to %s/%d", pinName, channel);
319 } else if (strEqual("tps", sensorStr)) {
320 engineConfiguration->tps1_1AdcChannel = channel;
321 efiPrintf("setting TPS1 to %s/%d", pinName, channel);
322 } else if (strEqual("tps2", sensorStr)) {
323 engineConfiguration->tps2_1AdcChannel = channel;
324 efiPrintf("setting TPS2 to %s/%d", pinName, channel);
325 }
326 incrementGlobalConfigurationVersion();
327 }
328 #endif // HAL_USE_ADC
329
330 static void setLogicInputPin(const char *indexStr, const char *pinName) {
331 int index = atoi(indexStr);
332 if (index < 0 || index > 2) {
333 return;
334 }
335 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
336 if (pin == Gpio::Invalid) {
337 return;
338 }
339 efiPrintf("setting logic input pin[%d] to %s please save&restart", index, hwPortname(pin));
340 engineConfiguration->logicAnalyzerPins[index] = pin;
341 incrementGlobalConfigurationVersion();
342 }
343
344 #endif // EFI_PROD_CODE
345
346 static void setSpiMode(int index, bool mode) {
347 switch (index) {
348 case 1:
349 engineConfiguration->is_enabled_spi_1 = mode;
350 break;
351 case 2:
352 engineConfiguration->is_enabled_spi_2 = mode;
353 break;
354 case 3:
355 engineConfiguration->is_enabled_spi_3 = mode;
356 break;
357 default:
358 efiPrintf("invalid spi index %d", index);
359 return;
360 }
361 printSpiState();
362 }
363
364 bool verboseRxCan = false;
365
366 static void enableOrDisable(const char *param, bool isEnabled) {
367 if (strEqualCaseInsensitive(param, "useTLE8888_cranking_hack")) {
368 engineConfiguration->useTLE8888_cranking_hack = isEnabled;
369 #if EFI_SHAFT_POSITION_INPUT
370 } else if (strEqualCaseInsensitive(param, CMD_TRIGGER_HW_INPUT)) {
371 getTriggerCentral()->hwTriggerInputEnabled = isEnabled;
372 #endif // EFI_SHAFT_POSITION_INPUT
373 } else if (strEqualCaseInsensitive(param, "verboseTLE8888")) {
374 engineConfiguration->verboseTLE8888 = isEnabled;
375 } else if (strEqualCaseInsensitive(param, "verboseRxCan")) {
376 verboseRxCan = isEnabled;
377 } else if (strEqualCaseInsensitive(param, "verboseCan")) {
378 engineConfiguration->verboseCan = isEnabled;
379 } else if (strEqualCaseInsensitive(param, "verboseCan2")) {
380 engineConfiguration->verboseCan2 = isEnabled;
381 #if (EFI_CAN_BUS_COUNT >= 3)
382 } else if (strEqualCaseInsensitive(param, "verboseCan3")) {
383 engineConfiguration->verboseCan3 = isEnabled;
384 #endif
385 } else if (strEqualCaseInsensitive(param, "verboseIsoTp")) {
386 engineConfiguration->verboseIsoTp = isEnabled;
387 } else if (strEqualCaseInsensitive(param, "artificialMisfire")) {
388 engineConfiguration->artificialTestMisfire = isEnabled;
389 } else if (strEqualCaseInsensitive(param, "logic_level_trigger")) {
390 engineConfiguration->displayLogicLevelsInEngineSniffer = isEnabled;
391 } else if (strEqualCaseInsensitive(param, "can_broadcast")) {
392 engineConfiguration->enableVerboseCanTx = isEnabled;
393 // } else if (strEqualCaseInsensitive(param, "etb_auto")) {
394 // engine->etbAutoTune = isEnabled;
395 } else if (strEqualCaseInsensitive(param, "verboseKLine")) {
396 engineConfiguration->verboseKLine = isEnabled;
397 } else if (strEqualCaseInsensitive(param, "stepperidle")) {
398 engineConfiguration->useStepperIdle = isEnabled;
399 } else if (strEqualCaseInsensitive(param, "two_wire_wasted_spark")) {
400 engineConfiguration->twoWireBatchIgnition = isEnabled;
401 incrementGlobalConfigurationVersion();
402 } else if (strEqualCaseInsensitive(param, "altcontrol")) {
403 engineConfiguration->isAlternatorControlEnabled = isEnabled;
404 } else if (strEqualCaseInsensitive(param, "sd")) {
405 engineConfiguration->isSdCardEnabled = isEnabled;
406 } else if (strEqualCaseInsensitive(param, CMD_FUNCTIONAL_TEST_MODE)) {
407 engine->isFunctionalTestMode = isEnabled;
408 } else if (strEqualCaseInsensitive(param, "can_read")) {
409 engineConfiguration->canReadEnabled = isEnabled;
410 } else if (strEqualCaseInsensitive(param, "can_write")) {
411 engineConfiguration->canWriteEnabled = isEnabled;
412 } else if (strEqualCaseInsensitive(param, CMD_INJECTION)) {
413 engineConfiguration->isInjectionEnabled = isEnabled;
414 } else if (strEqualCaseInsensitive(param, CMD_PWM)) {
415 engine->isPwmEnabled = isEnabled;
416 } else if (strEqualCaseInsensitive(param, "trigger_details")) {
417 engineConfiguration->verboseTriggerSynchDetails = isEnabled;
418 } else if (strEqualCaseInsensitive(param, "vvt_details")) {
419 engineConfiguration->verboseVVTDecoding = isEnabled;
420 } else if (strEqualCaseInsensitive(param, "invertCamVVTSignal")) {
421 engineConfiguration->invertCamVVTSignal = isEnabled;
422 } else if (strEqualCaseInsensitive(param, CMD_IGNITION)) {
423 engineConfiguration->isIgnitionEnabled = isEnabled;
424 #if EFI_EMULATE_POSITION_SENSORS
425 } else if (strEqualCaseInsensitive(param, CMD_SELF_STIMULATION)) {
426 if (isEnabled) {
427 enableTriggerStimulator();
428 } else {
429 disableTriggerStimulator();
430 }
431 } else if (strEqualCaseInsensitive(param, CMD_EXTERNAL_STIMULATION)) {
432 if (isEnabled) {
433 enableExternalTriggerStimulator();
434 } else {
435 disableTriggerStimulator();
436 }
437 #endif // EFI_EMULATE_POSITION_SENSORS
438 } else {
439 efiPrintf("unexpected [%s]", param);
440 return; // well, MISRA would not like this 'return' here :(
441 }
442 efiPrintf("[%s] %s", param, isEnabled ? "enabled" : "disabled");
443 }
444
445 static void enable(const char *param) {
446 enableOrDisable(param, true);
447 }
448
449 static void disable(const char *param) {
450 enableOrDisable(param, false);
451 }
452
453 static void enableSpi(int index) {
454 setSpiMode(index, true);
455 }
456
457 static void disableSpi(int index) {
458 setSpiMode(index, false);
459 }
460
461 /**
462 * See 'LimpManager::isEngineStop' for code which actually stops engine
463 */
464 static void scheduleStopEngine() {
465 doScheduleStopEngine(StopRequestedReason::Console);
466 }
467
468 static void getValue(const char *paramStr) {
469
470 {
471 float value = getConfigValueByName(paramStr);
472 if (value != EFI_ERROR_CODE) {
473 efiPrintf("%s value: %.2f", paramStr, value);
474 return;
475 }
476 }
477
478 if (strEqualCaseInsensitive(paramStr, "tps_min")) {
479 efiPrintf("tps_min=%d", engineConfiguration->tpsMin);
480 } else if (strEqualCaseInsensitive(paramStr, "tps_max")) {
481 efiPrintf("tps_max=%d", engineConfiguration->tpsMax);
482 } else if (strEqualCaseInsensitive(paramStr, "global_trigger_offset_angle")) {
483 efiPrintf("global_trigger_offset=%.2f", engineConfiguration->globalTriggerAngleOffset);
484 #if EFI_SHAFT_POSITION_INPUT
485 } else if (strEqualCaseInsensitive(paramStr, "trigger_hw_input")) {
486 efiPrintf("trigger_hw_input=%s", boolToString(getTriggerCentral()->hwTriggerInputEnabled));
487 #endif // EFI_SHAFT_POSITION_INPUT
488 } else if (strEqualCaseInsensitive(paramStr, CMD_DATE)) {
489 printDateTime();
490 } else {
491 efiPrintf("Invalid Parameter: %s", paramStr);
492 }
493 }
494
495 static void setScriptCurve1Value(float value) {
496 setLinearCurve(config->scriptCurve1, value, value, 1);
497 }
498
499 static void setScriptCurve2Value(float value) {
500 setLinearCurve(config->scriptCurve2, value, value, 1);
501 }
502
503 struct command_i_s {
504 const char *token;
505 VoidInt callback;
506 };
507
508 struct command_f_s {
509 const char *token;
510 VoidFloat callback;
511 };
512
513 const command_f_s commandsF[] = {
514 #if EFI_ENGINE_CONTROL
515 {"global_trigger_offset_angle", setGlobalTriggerAngleOffset},
516 {"cranking_fuel", setCrankingFuel},
517 {"cranking_iac", setCrankingIACExtra},
518 {"cranking_timing_angle", setCrankingTimingAngle},
519 {"flat_injector_lag", setFlatInjectorLag},
520 #endif // EFI_ENGINE_CONTROL
521 {"script_curve_1_value", setScriptCurve1Value},
522 {"script_curve_2_value", setScriptCurve2Value},
523 };
524
525 const command_i_s commandsI[] = {
526 #if EFI_ENGINE_CONTROL
527 {"ignition_mode", setIgnitionMode},
528 {"driveWheelRevPerKm", [](int value) {
529 engineConfiguration->driveWheelRevPerKm = value;
530 }},
531 {"cranking_rpm", setCrankingRpm},
532 {"cranking_injection_mode", setCrankingInjectionMode},
533 {"injection_mode", setInjectionMode},
534 {CMD_ENGINE_TYPE, setEngineTypeAndSave},
535 {"rpm_hard_limit", setRpmHardLimit},
536 {"firing_order", setFiringOrder},
537 {"algorithm", setAlgorithmInt},
538 {"debug_mode", setDebugMode},
539 {"trigger_type", setTriggerType},
540 // used by HW CI
541 {"idle_solenoid_freq", setIdleSolenoidFrequency},
542 #endif // EFI_ENGINE_CONTROL
543 #if EFI_PROD_CODE
544 #if EFI_BOR_LEVEL
545 {"bor", setBor},
546 #endif // EFI_BOR_LEVEL
547 #if EFI_CAN_SUPPORT
548 {"can_mode", setCanType},
549 {"can_vss", setCanVss},
550 #endif // EFI_CAN_SUPPORT
551 #if EFI_IDLE_CONTROL
552 {"idle_position", setManualIdleValvePosition},
553 {"idle_rpm", setTargetIdleRpm},
554 #endif // EFI_IDLE_CONTROL
555 #endif // EFI_PROD_CODE
556
557 // {"", },
558 // {"", },
559 };
560
561 static void setValue(const char *paramStr, const char *valueStr) {
562 float valueF = atoff(valueStr);
563 int valueI = atoi(valueStr);
564
565 const command_f_s *currentF = &commandsF[0];
566 while (currentF < commandsF + sizeof(commandsF)/sizeof(commandsF[0])) {
567 if (strEqualCaseInsensitive(paramStr, currentF->token)) {
568 currentF->callback(valueF);
569 return;
570 }
571 currentF++;
572 }
573
574 const command_i_s *currentI = &commandsI[0];
575 while (currentI < commandsI + sizeof(commandsI)/sizeof(commandsI[0])) {
576 if (strEqualCaseInsensitive(paramStr, currentI->token)) {
577 currentI->callback(valueI);
578 return;
579 }
580 currentI++;
581 }
582
583
584 if (strEqualCaseInsensitive(paramStr, "warning_period")) {
585 engineConfiguration->warningPeriod = valueI;
586 } else if (strEqualCaseInsensitive(paramStr, "dwell")) {
587 setConstantDwell(valueF);
588 } else if (strEqualCaseInsensitive(paramStr, CMD_ENGINESNIFFERRPMTHRESHOLD)) {
589 engineConfiguration->engineSnifferRpmThreshold = valueI;
590 #if EFI_EMULATE_POSITION_SENSORS
591 } else if (strEqualCaseInsensitive(paramStr, CMD_RPM)) {
592 setTriggerEmulatorRPM(valueI);
593 #endif // EFI_EMULATE_POSITION_SENSORS
594 } else if (strEqualCaseInsensitive(paramStr, "mc33_hvolt")) {
595 engineConfiguration->mc33_hvolt = valueI;
596 } else if (strEqualCaseInsensitive(paramStr, "mc33_i_peak")) {
597 engineConfiguration->mc33_i_peak = valueI;
598 } else if (strEqualCaseInsensitive(paramStr, "mc33_i_hold")) {
599 engineConfiguration->mc33_i_hold = valueI;
600 } else if (strEqualCaseInsensitive(paramStr, "mc33_t_max_boost")) {
601 engineConfiguration->mc33_t_max_boost = valueI;
602 } else if (strEqualCaseInsensitive(paramStr, "mc33_t_peak_off")) {
603 engineConfiguration->mc33_t_peak_off = valueI;
604 } else if (strEqualCaseInsensitive(paramStr, "vvt_offset")) {
605 engineConfiguration->vvtOffsets[0] = valueF;
606 } else if (strEqualCaseInsensitive(paramStr, "vvt_mode")) {
607 engineConfiguration->vvtMode[0] = (vvt_mode_e)valueI;
608 } else if (strEqualCaseInsensitive(paramStr, "wwaeTau")) {
609 engineConfiguration->wwaeTau = valueF;
610 } else if (strEqualCaseInsensitive(paramStr, "wwaeBeta")) {
611 engineConfiguration->wwaeBeta = valueF;
612 } else if (strEqualCaseInsensitive(paramStr, "benchTestOffTime")) {
613 engineConfiguration->benchTestOffTime = valueI;
614 } else if (strEqualCaseInsensitive(paramStr, "benchTestCount")) {
615 engineConfiguration->benchTestCount = valueI;
616 } else if (strEqualCaseInsensitive(paramStr, "cranking_dwell")) {
617 engineConfiguration->ignitionDwellForCrankingMs = valueF;
618 #if EFI_PROD_CODE
619 } else if (strEqualCaseInsensitive(paramStr, CMD_VSS_PIN)) {
620 setVssPin(valueStr);
621 #endif // EFI_PROD_CODE
622 } else if (strEqualCaseInsensitive(paramStr, "targetvbatt")) {
623 setTable(config->alternatorVoltageTargetTable, valueF);
624 } else if (strEqualCaseInsensitive(paramStr, CMD_DATE)) {
625 // rusEfi console invokes this method with timestamp in local timezone
626 setDateTime(valueStr);
627 }
628
629 bool isGoodName = setConfigValueByName(paramStr, valueF);
630 if (isGoodName) {
631 efiPrintf("Settings: applying [%s][%f]", paramStr, valueF);
632 }
633
634 engine->resetEngineSnifferIfInTestMode();
635 }
636
637 void initSettings() {
638 #if EFI_SIMULATOR
639 printf("initSettings\n");
640 #endif // EFI_SIMULATOR
641
642 // todo: start saving values into flash right away?
643
644 #if EFI_ENGINE_CONTROL
645 // used by HW CI
646 addConsoleAction(CMD_INDIVIDUAL_INJECTION, setIndividualCoilsIgnition);
647 addConsoleAction("showconfig", printConfiguration);
648 addConsoleActionF("set_whole_timing_map", setWholeTimingMapCmd);
649 #endif // EFI_ENGINE_CONTROL
650
651 addConsoleAction("stopengine", (Void) scheduleStopEngine);
652
653 // todo: refactor this - looks like all boolean flags should be controlled with less code duplication
654 addConsoleActionI("enable_spi", enableSpi);
655 addConsoleActionI("disable_spi", disableSpi);
656
657 addConsoleActionS(CMD_ENABLE, enable);
658 addConsoleActionS(CMD_DISABLE, disable);
659
660 addConsoleActionSS(CMD_SET, setValue);
661 addConsoleActionS(CMD_GET, getValue);
662
663 #if EFI_PROD_CODE
664 addConsoleActionSS(CMD_IGNITION_PIN, setIgnitionPin);
665 addConsoleActionSS(CMD_TRIGGER_PIN, setTriggerInputPin);
666 addConsoleActionSS(CMD_TRIGGER_SIMULATOR_PIN, setTriggerSimulatorPin);
667
668 addConsoleActionI(CMD_ECU_UNLOCK, unlockEcu);
669
670 addConsoleActionS(CMD_ALTERNATOR_PIN, setAlternatorPin);
671 addConsoleActionS(CMD_IDLE_PIN, setIdlePin);
672
673 addConsoleActionS("bench_clearpin", benchClearPin);
674 addConsoleActionS("bench_setpin", benchSetPin);
675 addConsoleActionS("readpin", readPin);
676 addConsoleAction("hw_qc_mode", [](){
677 setHwQcMode();
678 });
679 addConsoleActionS("bench_set_output_mode", [](const char *pinName){
680 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
681 if (pin == Gpio::Invalid) {
682 return;
683 }
684 efiSetPadModeWithoutOwnershipAcquisition("manual-mode", pin, PAL_MODE_OUTPUT_PUSHPULL);
685 });
686
687 #if HAL_USE_ADC
688 addConsoleAction("adc_report", printFullAdcReport);
689 addConsoleActionSS("set_analog_input_pin", setAnalogInputPin);
690 #endif // HAL_USE_ADC
691 addConsoleActionSS(CMD_LOGIC_PIN, setLogicInputPin);
692 #endif // EFI_PROD_CODE
693 }
694
695 void printDateTime() {
696 #if EFI_RTC
697 printRtcDateTime();
698 #else // EFI_RTC
699 efiPrintf("Cannot print time: RTC not supported");
700 #endif // EFI_RTC
701 }
702
703 void setDateTime(const char * const isoDateTime) {
704 #if EFI_RTC
705 printRtcDateTime();
706 if (strlen(isoDateTime) >= 19 && isoDateTime[10] == 'T') {
707 efidatetime_t dateTime;
708 dateTime.year = atoi(isoDateTime);
709 dateTime.month = atoi(isoDateTime + 5);
710 dateTime.day = atoi(isoDateTime + 8);
711 dateTime.hour = atoi(isoDateTime + 11);
712 dateTime.minute = atoi(isoDateTime + 14);
713 dateTime.second = atoi(isoDateTime + 17);
714 if (dateTime.year != ATOI_ERROR_CODE &&
715 dateTime.month >= 1 && dateTime.month <= 12 &&
716 dateTime.day >= 1 && dateTime.day <= 31 &&
717 dateTime.hour <= 23 &&
718 dateTime.minute <= 59 &&
719 dateTime.second <= 59) {
720 // doesn't concern about leap years or seconds; ChibiOS doesn't support (added) leap seconds anyway
721 setRtcDateTime(&dateTime);
722 efiPrintf("Time is changed to");
723 printRtcDateTime();
724 return;
725 }
726 }
727 efiPrintf("date_set Date parameter %s is wrong", isoDateTime);
728 #else // EFI_RTC
729 efiPrintf("Cannot set time: RTC not supported");
730 #endif // EFI_RTC
731 }
732
733 #endif // ! EFI_UNIT_TEST
734
735 void setEngineTypeAndSave(int value) {
736 setEngineType(value, true);
737 }
738
739 1 void setEngineType(int value, bool isWriteToFlash) {
740 {
741 #if EFI_PROD_CODE
742 chibios_rt::CriticalSectionLocker csl;
743 #endif // EFI_PROD_CODE
744
745 1 engineConfiguration->engineType = (engine_type_e)value;
746 1 resetConfigurationExt((engine_type_e)value);
747 1 engine->resetEngineSnifferIfInTestMode();
748
749 #if EFI_CONFIGURATION_STORAGE
750 if (isWriteToFlash) {
751 writeToFlashNow();
752 }
753 #endif /* EFI_CONFIGURATION_STORAGE */
754 }
755 1 incrementGlobalConfigurationVersion("engineType");
756 #if EFI_ENGINE_CONTROL && ! EFI_UNIT_TEST
757 printConfiguration();
758 #endif // ! EFI_UNIT_TEST
759 1 }
760