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