GCC Code Coverage Report


Directory: ./
File: firmware/controllers/settings.cpp
Date: 2025-10-03 00:57:22
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 } else if (strEqualCaseInsensitive(param, "verboseIsoTp")) {
382 engineConfiguration->verboseIsoTp = isEnabled;
383 } else if (strEqualCaseInsensitive(param, "artificialMisfire")) {
384 engineConfiguration->artificialTestMisfire = isEnabled;
385 } else if (strEqualCaseInsensitive(param, "logic_level_trigger")) {
386 engineConfiguration->displayLogicLevelsInEngineSniffer = isEnabled;
387 } else if (strEqualCaseInsensitive(param, "can_broadcast")) {
388 engineConfiguration->enableVerboseCanTx = isEnabled;
389 // } else if (strEqualCaseInsensitive(param, "etb_auto")) {
390 // engine->etbAutoTune = isEnabled;
391 } else if (strEqualCaseInsensitive(param, "verboseKLine")) {
392 engineConfiguration->verboseKLine = isEnabled;
393 } else if (strEqualCaseInsensitive(param, "stepperidle")) {
394 engineConfiguration->useStepperIdle = isEnabled;
395 } else if (strEqualCaseInsensitive(param, "two_wire_wasted_spark")) {
396 engineConfiguration->twoWireBatchIgnition = isEnabled;
397 incrementGlobalConfigurationVersion();
398 } else if (strEqualCaseInsensitive(param, "altcontrol")) {
399 engineConfiguration->isAlternatorControlEnabled = isEnabled;
400 } else if (strEqualCaseInsensitive(param, "sd")) {
401 engineConfiguration->isSdCardEnabled = isEnabled;
402 } else if (strEqualCaseInsensitive(param, CMD_FUNCTIONAL_TEST_MODE)) {
403 engine->isFunctionalTestMode = isEnabled;
404 } else if (strEqualCaseInsensitive(param, "can_read")) {
405 engineConfiguration->canReadEnabled = isEnabled;
406 } else if (strEqualCaseInsensitive(param, "can_write")) {
407 engineConfiguration->canWriteEnabled = isEnabled;
408 } else if (strEqualCaseInsensitive(param, CMD_INJECTION)) {
409 engineConfiguration->isInjectionEnabled = isEnabled;
410 } else if (strEqualCaseInsensitive(param, CMD_PWM)) {
411 engine->isPwmEnabled = isEnabled;
412 } else if (strEqualCaseInsensitive(param, "trigger_details")) {
413 engineConfiguration->verboseTriggerSynchDetails = isEnabled;
414 } else if (strEqualCaseInsensitive(param, "vvt_details")) {
415 engineConfiguration->verboseVVTDecoding = isEnabled;
416 } else if (strEqualCaseInsensitive(param, "invertCamVVTSignal")) {
417 engineConfiguration->invertCamVVTSignal = isEnabled;
418 } else if (strEqualCaseInsensitive(param, CMD_IGNITION)) {
419 engineConfiguration->isIgnitionEnabled = isEnabled;
420 #if EFI_EMULATE_POSITION_SENSORS
421 } else if (strEqualCaseInsensitive(param, CMD_SELF_STIMULATION)) {
422 if (isEnabled) {
423 enableTriggerStimulator();
424 } else {
425 disableTriggerStimulator();
426 }
427 } else if (strEqualCaseInsensitive(param, CMD_EXTERNAL_STIMULATION)) {
428 if (isEnabled) {
429 enableExternalTriggerStimulator();
430 } else {
431 disableTriggerStimulator();
432 }
433 #endif // EFI_EMULATE_POSITION_SENSORS
434 } else {
435 efiPrintf("unexpected [%s]", param);
436 return; // well, MISRA would not like this 'return' here :(
437 }
438 efiPrintf("[%s] %s", param, isEnabled ? "enabled" : "disabled");
439 }
440
441 static void enable(const char *param) {
442 enableOrDisable(param, true);
443 }
444
445 static void disable(const char *param) {
446 enableOrDisable(param, false);
447 }
448
449 static void enableSpi(int index) {
450 setSpiMode(index, true);
451 }
452
453 static void disableSpi(int index) {
454 setSpiMode(index, false);
455 }
456
457 /**
458 * See 'LimpManager::isEngineStop' for code which actually stops engine
459 */
460 static void scheduleStopEngine() {
461 doScheduleStopEngine(StopRequestedReason::Console);
462 }
463
464 static void getValue(const char *paramStr) {
465
466 {
467 float value = getConfigValueByName(paramStr);
468 if (value != EFI_ERROR_CODE) {
469 efiPrintf("%s value: %.2f", paramStr, value);
470 return;
471 }
472 }
473
474 if (strEqualCaseInsensitive(paramStr, "tps_min")) {
475 efiPrintf("tps_min=%d", engineConfiguration->tpsMin);
476 } else if (strEqualCaseInsensitive(paramStr, "tps_max")) {
477 efiPrintf("tps_max=%d", engineConfiguration->tpsMax);
478 } else if (strEqualCaseInsensitive(paramStr, "global_trigger_offset_angle")) {
479 efiPrintf("global_trigger_offset=%.2f", engineConfiguration->globalTriggerAngleOffset);
480 #if EFI_SHAFT_POSITION_INPUT
481 } else if (strEqualCaseInsensitive(paramStr, "trigger_hw_input")) {
482 efiPrintf("trigger_hw_input=%s", boolToString(getTriggerCentral()->hwTriggerInputEnabled));
483 #endif // EFI_SHAFT_POSITION_INPUT
484 } else if (strEqualCaseInsensitive(paramStr, CMD_DATE)) {
485 printDateTime();
486 } else {
487 efiPrintf("Invalid Parameter: %s", paramStr);
488 }
489 }
490
491 static void setScriptCurve1Value(float value) {
492 setLinearCurve(config->scriptCurve1, value, value, 1);
493 }
494
495 static void setScriptCurve2Value(float value) {
496 setLinearCurve(config->scriptCurve2, value, value, 1);
497 }
498
499 struct command_i_s {
500 const char *token;
501 VoidInt callback;
502 };
503
504 struct command_f_s {
505 const char *token;
506 VoidFloat callback;
507 };
508
509 const command_f_s commandsF[] = {
510 #if EFI_ENGINE_CONTROL
511 {"global_trigger_offset_angle", setGlobalTriggerAngleOffset},
512 {"cranking_fuel", setCrankingFuel},
513 {"cranking_iac", setCrankingIACExtra},
514 {"cranking_timing_angle", setCrankingTimingAngle},
515 {"flat_injector_lag", setFlatInjectorLag},
516 #endif // EFI_ENGINE_CONTROL
517 {"script_curve_1_value", setScriptCurve1Value},
518 {"script_curve_2_value", setScriptCurve2Value},
519 };
520
521 const command_i_s commandsI[] = {
522 #if EFI_ENGINE_CONTROL
523 {"ignition_mode", setIgnitionMode},
524 {"driveWheelRevPerKm", [](int value) {
525 engineConfiguration->driveWheelRevPerKm = value;
526 }},
527 {"cranking_rpm", setCrankingRpm},
528 {"cranking_injection_mode", setCrankingInjectionMode},
529 {"injection_mode", setInjectionMode},
530 {CMD_ENGINE_TYPE, setEngineTypeAndSave},
531 {"rpm_hard_limit", setRpmHardLimit},
532 {"firing_order", setFiringOrder},
533 {"algorithm", setAlgorithmInt},
534 {"debug_mode", setDebugMode},
535 {"trigger_type", setTriggerType},
536 // used by HW CI
537 {"idle_solenoid_freq", setIdleSolenoidFrequency},
538 #endif // EFI_ENGINE_CONTROL
539 #if EFI_PROD_CODE
540 #if EFI_BOR_LEVEL
541 {"bor", setBor},
542 #endif // EFI_BOR_LEVEL
543 #if EFI_CAN_SUPPORT
544 {"can_mode", setCanType},
545 {"can_vss", setCanVss},
546 #endif // EFI_CAN_SUPPORT
547 #if EFI_IDLE_CONTROL
548 {"idle_position", setManualIdleValvePosition},
549 {"idle_rpm", setTargetIdleRpm},
550 #endif // EFI_IDLE_CONTROL
551 #endif // EFI_PROD_CODE
552
553 // {"", },
554 // {"", },
555 };
556
557 static void setValue(const char *paramStr, const char *valueStr) {
558 float valueF = atoff(valueStr);
559 int valueI = atoi(valueStr);
560
561 const command_f_s *currentF = &commandsF[0];
562 while (currentF < commandsF + sizeof(commandsF)/sizeof(commandsF[0])) {
563 if (strEqualCaseInsensitive(paramStr, currentF->token)) {
564 currentF->callback(valueF);
565 return;
566 }
567 currentF++;
568 }
569
570 const command_i_s *currentI = &commandsI[0];
571 while (currentI < commandsI + sizeof(commandsI)/sizeof(commandsI[0])) {
572 if (strEqualCaseInsensitive(paramStr, currentI->token)) {
573 currentI->callback(valueI);
574 return;
575 }
576 currentI++;
577 }
578
579
580 if (strEqualCaseInsensitive(paramStr, "warning_period")) {
581 engineConfiguration->warningPeriod = valueI;
582 } else if (strEqualCaseInsensitive(paramStr, "dwell")) {
583 setConstantDwell(valueF);
584 } else if (strEqualCaseInsensitive(paramStr, CMD_ENGINESNIFFERRPMTHRESHOLD)) {
585 engineConfiguration->engineSnifferRpmThreshold = valueI;
586 #if EFI_EMULATE_POSITION_SENSORS
587 } else if (strEqualCaseInsensitive(paramStr, CMD_RPM)) {
588 setTriggerEmulatorRPM(valueI);
589 #endif // EFI_EMULATE_POSITION_SENSORS
590 } else if (strEqualCaseInsensitive(paramStr, "mc33_hvolt")) {
591 engineConfiguration->mc33_hvolt = valueI;
592 } else if (strEqualCaseInsensitive(paramStr, "mc33_i_peak")) {
593 engineConfiguration->mc33_i_peak = valueI;
594 } else if (strEqualCaseInsensitive(paramStr, "mc33_i_hold")) {
595 engineConfiguration->mc33_i_hold = valueI;
596 } else if (strEqualCaseInsensitive(paramStr, "mc33_t_max_boost")) {
597 engineConfiguration->mc33_t_max_boost = valueI;
598 } else if (strEqualCaseInsensitive(paramStr, "mc33_t_peak_off")) {
599 engineConfiguration->mc33_t_peak_off = valueI;
600 } else if (strEqualCaseInsensitive(paramStr, "vvt_offset")) {
601 engineConfiguration->vvtOffsets[0] = valueF;
602 } else if (strEqualCaseInsensitive(paramStr, "vvt_mode")) {
603 engineConfiguration->vvtMode[0] = (vvt_mode_e)valueI;
604 } else if (strEqualCaseInsensitive(paramStr, "wwaeTau")) {
605 engineConfiguration->wwaeTau = valueF;
606 } else if (strEqualCaseInsensitive(paramStr, "wwaeBeta")) {
607 engineConfiguration->wwaeBeta = valueF;
608 } else if (strEqualCaseInsensitive(paramStr, "benchTestOffTime")) {
609 engineConfiguration->benchTestOffTime = valueI;
610 } else if (strEqualCaseInsensitive(paramStr, "benchTestCount")) {
611 engineConfiguration->benchTestCount = valueI;
612 } else if (strEqualCaseInsensitive(paramStr, "cranking_dwell")) {
613 engineConfiguration->ignitionDwellForCrankingMs = valueF;
614 #if EFI_PROD_CODE
615 } else if (strEqualCaseInsensitive(paramStr, CMD_VSS_PIN)) {
616 setVssPin(valueStr);
617 #endif // EFI_PROD_CODE
618 } else if (strEqualCaseInsensitive(paramStr, "targetvbatt")) {
619 setTable(config->alternatorVoltageTargetTable, valueF);
620 } else if (strEqualCaseInsensitive(paramStr, CMD_DATE)) {
621 // rusEfi console invokes this method with timestamp in local timezone
622 setDateTime(valueStr);
623 }
624
625 bool isGoodName = setConfigValueByName(paramStr, valueF);
626 if (isGoodName) {
627 efiPrintf("Settings: applying [%s][%f]", paramStr, valueF);
628 }
629
630 engine->resetEngineSnifferIfInTestMode();
631 }
632
633 void initSettings() {
634 #if EFI_SIMULATOR
635 printf("initSettings\n");
636 #endif // EFI_SIMULATOR
637
638 // todo: start saving values into flash right away?
639
640 #if EFI_ENGINE_CONTROL
641 // used by HW CI
642 addConsoleAction(CMD_INDIVIDUAL_INJECTION, setIndividualCoilsIgnition);
643 addConsoleAction("showconfig", printConfiguration);
644 addConsoleActionF("set_whole_timing_map", setWholeTimingMapCmd);
645 #endif // EFI_ENGINE_CONTROL
646
647 addConsoleAction("stopengine", (Void) scheduleStopEngine);
648
649 // todo: refactor this - looks like all boolean flags should be controlled with less code duplication
650 addConsoleActionI("enable_spi", enableSpi);
651 addConsoleActionI("disable_spi", disableSpi);
652
653 addConsoleActionS(CMD_ENABLE, enable);
654 addConsoleActionS(CMD_DISABLE, disable);
655
656 addConsoleActionSS(CMD_SET, setValue);
657 addConsoleActionS(CMD_GET, getValue);
658
659 #if EFI_PROD_CODE
660 addConsoleActionSS(CMD_IGNITION_PIN, setIgnitionPin);
661 addConsoleActionSS(CMD_TRIGGER_PIN, setTriggerInputPin);
662 addConsoleActionSS(CMD_TRIGGER_SIMULATOR_PIN, setTriggerSimulatorPin);
663
664 addConsoleActionI(CMD_ECU_UNLOCK, unlockEcu);
665
666 addConsoleActionS(CMD_ALTERNATOR_PIN, setAlternatorPin);
667 addConsoleActionS(CMD_IDLE_PIN, setIdlePin);
668
669 addConsoleActionS("bench_clearpin", benchClearPin);
670 addConsoleActionS("bench_setpin", benchSetPin);
671 addConsoleActionS("readpin", readPin);
672 addConsoleAction("hw_qc_mode", [](){
673 setHwQcMode();
674 });
675 addConsoleActionS("bench_set_output_mode", [](const char *pinName){
676 brain_pin_e pin = parseBrainPinWithErrorMessage(pinName);
677 if (pin == Gpio::Invalid) {
678 return;
679 }
680 efiSetPadModeWithoutOwnershipAcquisition("manual-mode", pin, PAL_MODE_OUTPUT_PUSHPULL);
681 });
682
683 #if HAL_USE_ADC
684 addConsoleAction("adc_report", printFullAdcReport);
685 addConsoleActionSS("set_analog_input_pin", setAnalogInputPin);
686 #endif // HAL_USE_ADC
687 addConsoleActionSS(CMD_LOGIC_PIN, setLogicInputPin);
688 #endif // EFI_PROD_CODE
689 }
690
691 void printDateTime() {
692 #if EFI_RTC
693 printRtcDateTime();
694 #else // EFI_RTC
695 efiPrintf("Cannot print time: RTC not supported");
696 #endif // EFI_RTC
697 }
698
699 void setDateTime(const char * const isoDateTime) {
700 #if EFI_RTC
701 printRtcDateTime();
702 if (strlen(isoDateTime) >= 19 && isoDateTime[10] == 'T') {
703 efidatetime_t dateTime;
704 dateTime.year = atoi(isoDateTime);
705 dateTime.month = atoi(isoDateTime + 5);
706 dateTime.day = atoi(isoDateTime + 8);
707 dateTime.hour = atoi(isoDateTime + 11);
708 dateTime.minute = atoi(isoDateTime + 14);
709 dateTime.second = atoi(isoDateTime + 17);
710 if (dateTime.year != ATOI_ERROR_CODE &&
711 dateTime.month >= 1 && dateTime.month <= 12 &&
712 dateTime.day >= 1 && dateTime.day <= 31 &&
713 dateTime.hour <= 23 &&
714 dateTime.minute <= 59 &&
715 dateTime.second <= 59) {
716 // doesn't concern about leap years or seconds; ChibiOS doesn't support (added) leap seconds anyway
717 setRtcDateTime(&dateTime);
718 efiPrintf("Time is changed to");
719 printRtcDateTime();
720 return;
721 }
722 }
723 efiPrintf("date_set Date parameter %s is wrong", isoDateTime);
724 #else // EFI_RTC
725 efiPrintf("Cannot set time: RTC not supported");
726 #endif // EFI_RTC
727 }
728
729 #endif // ! EFI_UNIT_TEST
730
731 void setEngineTypeAndSave(int value) {
732 setEngineType(value, true);
733 }
734
735 1 void setEngineType(int value, bool isWriteToFlash) {
736 {
737 #if EFI_PROD_CODE
738 chibios_rt::CriticalSectionLocker csl;
739 #endif // EFI_PROD_CODE
740
741 1 engineConfiguration->engineType = (engine_type_e)value;
742 1 resetConfigurationExt((engine_type_e)value);
743 1 engine->resetEngineSnifferIfInTestMode();
744
745 #if EFI_CONFIGURATION_STORAGE
746 if (isWriteToFlash) {
747 writeToFlashNow();
748 }
749 #endif /* EFI_CONFIGURATION_STORAGE */
750 }
751 1 incrementGlobalConfigurationVersion("engineType");
752 #if EFI_ENGINE_CONTROL && ! EFI_UNIT_TEST
753 printConfiguration();
754 #endif // ! EFI_UNIT_TEST
755 1 }
756