| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @file engine_controller.cpp | |||
| 3 | * @brief Controllers package entry point code | |||
| 4 | * | |||
| 5 | * | |||
| 6 | * | |||
| 7 | * @date Feb 7, 2013 | |||
| 8 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
| 9 | * | |||
| 10 | * This file is part of rusEfi - see http://rusefi.com | |||
| 11 | * | |||
| 12 | * rusEfi is free software; you can redistribute it and/or modify it under the terms of | |||
| 13 | * the GNU General Public License as published by the Free Software Foundation; either | |||
| 14 | * version 3 of the License, or (at your option) any later version. | |||
| 15 | * | |||
| 16 | * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without | |||
| 17 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 18 | * GNU General Public License for more details. | |||
| 19 | * | |||
| 20 | * You should have received a copy of the GNU General Public License along with this program. | |||
| 21 | * If not, see <http://www.gnu.org/licenses/>. | |||
| 22 | */ | |||
| 23 | ||||
| 24 | #include "pch.h" | |||
| 25 | ||||
| 26 | ||||
| 27 | #include "trigger_central.h" | |||
| 28 | #include "script_impl.h" | |||
| 29 | #include "idle_thread.h" | |||
| 30 | #include "main_trigger_callback.h" | |||
| 31 | #include "flash_main.h" | |||
| 32 | #include "bench_test.h" | |||
| 33 | #include "mmc_card.h" | |||
| 34 | #include "electronic_throttle.h" | |||
| 35 | #include "trigger_emulator_algo.h" | |||
| 36 | #include "high_pressure_fuel_pump.h" | |||
| 37 | #include "malfunction_central.h" | |||
| 38 | #include "malfunction_indicator.h" | |||
| 39 | #include "speed_density.h" | |||
| 40 | #include "local_version_holder.h" | |||
| 41 | #include "alternator_controller.h" | |||
| 42 | #include "can_bench_test.h" | |||
| 43 | #include "engine_emulator.h" | |||
| 44 | #include "fuel_math.h" | |||
| 45 | #include "defaults.h" | |||
| 46 | #include "spark_logic.h" | |||
| 47 | #include "status_loop.h" | |||
| 48 | #include "aux_valves.h" | |||
| 49 | #include "accelerometer.h" | |||
| 50 | #include "vvt.h" | |||
| 51 | #include "boost_control.h" | |||
| 52 | #include "launch_control.h" | |||
| 53 | #include "speedometer.h" | |||
| 54 | #include "gppwm.h" | |||
| 55 | #include "date_stamp.h" | |||
| 56 | #include "rusefi_lua.h" | |||
| 57 | #include "buttonshift.h" | |||
| 58 | #include "start_stop.h" | |||
| 59 | #include "dynoview.h" | |||
| 60 | #include "vr_pwm.h" | |||
| 61 | #include "adc_subscription.h" | |||
| 62 | #include "gc_generic.h" | |||
| 63 | ||||
| 64 | #if EFI_TUNER_STUDIO | |||
| 65 | #include "tunerstudio.h" | |||
| 66 | #endif /* EFI_TUNER_STUDIO */ | |||
| 67 | ||||
| 68 | #if EFI_LOGIC_ANALYZER | |||
| 69 | #include "logic_analyzer.h" | |||
| 70 | #endif /* EFI_LOGIC_ANALYZER */ | |||
| 71 | ||||
| 72 | #if defined(EFI_BOOTLOADER_INCLUDE_CODE) | |||
| 73 | #include "bootloader/bootloader.h" | |||
| 74 | #endif /* EFI_BOOTLOADER_INCLUDE_CODE */ | |||
| 75 | ||||
| 76 | #include "periodic_task.h" | |||
| 77 | ||||
| 78 | #ifdef MODULE_MAP_AVERAGING | |||
| 79 | #include "map_averaging.h" | |||
| 80 | #endif | |||
| 81 | ||||
| 82 | #if ! EFI_UNIT_TEST | |||
| 83 | #include "init.h" | |||
| 84 | #include "mpu_util.h" | |||
| 85 | #endif /* EFI_UNIT_TEST */ | |||
| 86 | ||||
| 87 | #if !EFI_UNIT_TEST | |||
| 88 | ||||
| 89 | /** | |||
| 90 | * Would love to pass reference to configuration object into constructor but C++ does allow attributes after parenthesized initializer | |||
| 91 | */ | |||
| 92 | Engine ___engine CCM_OPTIONAL; | |||
| 93 | ||||
| 94 | #else // EFI_UNIT_TEST | |||
| 95 | ||||
| 96 | Engine * engine; | |||
| 97 | ||||
| 98 | #endif /* EFI_UNIT_TEST */ | |||
| 99 | ||||
| 100 | using namespace rusefi::stringutil; | |||
| 101 | ||||
| 102 | 586 | void initDataStructures() { | ||
| 103 | #if EFI_ENGINE_CONTROL | |||
| 104 | 586 | initFuelMap(); | ||
| 105 | 586 | initSpeedDensity(); | ||
| 106 | 586 | IgnitionEventList &events = engine->ignitionEvents; | ||
| 107 |
2/2✓ Branch 1 taken 7032 times.
✓ Branch 2 taken 586 times.
|
2/2✓ Decision 'true' taken 7032 times.
✓ Decision 'false' taken 586 times.
|
7618 | for (size_t i=0;i<efi::size(events.elements);i++) { |
| 108 | // above-zero value helps distinguish events | |||
| 109 | 7032 | events.elements[i].sparkCounter = 1; | ||
| 110 | } | |||
| 111 | // above-zero value helps distinguish events | |||
| 112 | 586 | engine->engineState.globalSparkCounter = 1; | ||
| 113 | #endif // EFI_ENGINE_CONTROL | |||
| 114 | 586 | } | ||
| 115 | ||||
| 116 | #if !EFI_UNIT_TEST | |||
| 117 | ||||
| 118 | static void doPeriodicSlowCallback(); | |||
| 119 | ||||
| 120 | class PeriodicFastController : public PeriodicTimerController { | |||
| 121 | void PeriodicTask() override { | |||
| 122 | engine->periodicFastCallback(); | |||
| 123 | } | |||
| 124 | ||||
| 125 | int getPeriodMs() override { | |||
| 126 | return FAST_CALLBACK_PERIOD_MS; | |||
| 127 | } | |||
| 128 | }; | |||
| 129 | ||||
| 130 | class PeriodicSlowController : public PeriodicTimerController { | |||
| 131 | void PeriodicTask() override { | |||
| 132 | doPeriodicSlowCallback(); | |||
| 133 | } | |||
| 134 | ||||
| 135 | int getPeriodMs() override { | |||
| 136 | // no reason to have this configurable, looks like everyone is happy with 20Hz | |||
| 137 | return SLOW_CALLBACK_PERIOD_MS; | |||
| 138 | } | |||
| 139 | }; | |||
| 140 | ||||
| 141 | static PeriodicFastController fastController; | |||
| 142 | static PeriodicSlowController slowController; | |||
| 143 | ||||
| 144 | class EngineStateBlinkingTask : public PeriodicTimerController { | |||
| 145 | int getPeriodMs() override { | |||
| 146 | return 50; | |||
| 147 | } | |||
| 148 | ||||
| 149 | void PeriodicTask() override { | |||
| 150 | #if EFI_SHAFT_POSITION_INPUT | |||
| 151 | bool is_running = engine->rpmCalculator.isRunning(); | |||
| 152 | #else | |||
| 153 | bool is_running = false; | |||
| 154 | #endif /* EFI_SHAFT_POSITION_INPUT */ | |||
| 155 | ||||
| 156 | if (is_running) { | |||
| 157 | // blink in running mode | |||
| 158 | enginePins.runningLedPin.toggle(); | |||
| 159 | } else { | |||
| 160 | bool is_cranking = engine->rpmCalculator.isCranking(); | |||
| 161 | enginePins.runningLedPin.setValue(is_cranking); | |||
| 162 | } | |||
| 163 | } | |||
| 164 | }; | |||
| 165 | ||||
| 166 | static EngineStateBlinkingTask engineStateBlinkingTask; | |||
| 167 | ||||
| 168 | static void resetAccel() { | |||
| 169 | engine->module<TpsAccelEnrichment>()->resetAE(); | |||
| 170 | ||||
| 171 | #if EFI_ENGINE_CONTROL | |||
| 172 | for (size_t i = 0; i < efi::size(engine->injectionEvents.elements); i++) | |||
| 173 | { | |||
| 174 | engine->injectionEvents.elements[i].getWallFuel().resetWF(); | |||
| 175 | } | |||
| 176 | #endif // EFI_ENGINE_CONTROL | |||
| 177 | } | |||
| 178 | ||||
| 179 | static void doPeriodicSlowCallback() { | |||
| 180 | #if EFI_SHAFT_POSITION_INPUT | |||
| 181 | efiAssertVoid(ObdCode::CUSTOM_ERR_6661, getCurrentRemainingStack() > 64, "lowStckOnEv"); | |||
| 182 | ||||
| 183 | slowStartStopButtonCallback(); | |||
| 184 | ||||
| 185 | engine->rpmCalculator.onSlowCallback(); | |||
| 186 | if (engine->rpmCalculator.isStopped()) { | |||
| 187 | resetAccel(); | |||
| 188 | } | |||
| 189 | #endif /* EFI_SHAFT_POSITION_INPUT */ | |||
| 190 | ||||
| 191 | engine->periodicSlowCallback(); | |||
| 192 | ||||
| 193 | #if EFI_TCU | |||
| 194 | if (engineConfiguration->tcuEnabled && engineConfiguration->gearControllerMode != GearControllerMode::None) { | |||
| 195 | if (engine->gearController == NULL) { | |||
| 196 | initGearController(); | |||
| 197 | } else if (engine->gearController->getMode() != engineConfiguration->gearControllerMode) { | |||
| 198 | initGearController(); | |||
| 199 | } | |||
| 200 | engine->gearController->update(); | |||
| 201 | } | |||
| 202 | #endif // EFI_TCU | |||
| 203 | ||||
| 204 | tryResetWatchdog(); | |||
| 205 | } | |||
| 206 | ||||
| 207 | void initPeriodicEvents() { | |||
| 208 | slowController.start(); | |||
| 209 | fastController.start(); | |||
| 210 | } | |||
| 211 | ||||
| 212 | char * getPinNameByAdcChannel(const char *msg, adc_channel_e hwChannel, char *buffer, size_t bufferSize) { | |||
| 213 | #if HAL_USE_ADC | |||
| 214 | if (!isAdcChannelValid(hwChannel)) { | |||
| 215 | snprintf(buffer, bufferSize, "NONE"); | |||
| 216 | } else { | |||
| 217 | const char *name = portname(getAdcChannelPort(msg, hwChannel)); | |||
| 218 | snprintf(buffer, bufferSize, "%s%d", name ? name : "null", getAdcChannelPin(hwChannel)); | |||
| 219 | } | |||
| 220 | #else | |||
| 221 | snprintf(buffer, bufferSize, "NONE"); | |||
| 222 | #endif /* HAL_USE_ADC */ | |||
| 223 | return buffer; | |||
| 224 | } | |||
| 225 | ||||
| 226 | #if EFI_PROD_CODE | |||
| 227 | static void printSensorInfo() { | |||
| 228 | #if HAL_USE_ADC | |||
| 229 | // Print info about analog mappings | |||
| 230 | AdcSubscription::PrintInfo(); | |||
| 231 | #endif // HAL_USE_ADC | |||
| 232 | ||||
| 233 | // Print info about all sensors | |||
| 234 | Sensor::showAllSensorInfo(); | |||
| 235 | } | |||
| 236 | #endif // EFI_PROD_CODE | |||
| 237 | ||||
| 238 | #define isOutOfBounds(offset) ((offset<0) || (offset) >= (int) sizeof(engine_configuration_s)) | |||
| 239 | ||||
| 240 | static void getShort(int offset) { | |||
| 241 | if (isOutOfBounds(offset)) | |||
| 242 | return; | |||
| 243 | uint16_t *ptr = (uint16_t *) (&((char *) engineConfiguration)[offset]); | |||
| 244 | uint16_t value = *ptr; | |||
| 245 | /** | |||
| 246 | * this response is part of rusEfi console API | |||
| 247 | */ | |||
| 248 | efiPrintf("short%s%d is %d", CONSOLE_DATA_PROTOCOL_TAG, offset, value); | |||
| 249 | } | |||
| 250 | ||||
| 251 | static void getByte(int offset) { | |||
| 252 | if (isOutOfBounds(offset)) | |||
| 253 | return; | |||
| 254 | uint8_t *ptr = (uint8_t *) (&((char *) engineConfiguration)[offset]); | |||
| 255 | uint8_t value = *ptr; | |||
| 256 | /** | |||
| 257 | * this response is part of rusEfi console API | |||
| 258 | */ | |||
| 259 | efiPrintf("byte%s%d is %d", CONSOLE_DATA_PROTOCOL_TAG, offset, value); | |||
| 260 | } | |||
| 261 | ||||
| 262 | static void setBit(const char *offsetStr, const char *bitStr, const char *valueStr) { | |||
| 263 | int offset = atoi(offsetStr); | |||
| 264 | if (absI(offset) == absI(ATOI_ERROR_CODE)) { | |||
| 265 | efiPrintf("invalid offset [%s]", offsetStr); | |||
| 266 | return; | |||
| 267 | } | |||
| 268 | if (isOutOfBounds(offset)) { | |||
| 269 | return; | |||
| 270 | } | |||
| 271 | int bit = atoi(bitStr); | |||
| 272 | if (absI(bit) == absI(ATOI_ERROR_CODE)) { | |||
| 273 | efiPrintf("invalid bit [%s]", bitStr); | |||
| 274 | return; | |||
| 275 | } | |||
| 276 | int value = atoi(valueStr); | |||
| 277 | if (absI(value) == absI(ATOI_ERROR_CODE)) { | |||
| 278 | efiPrintf("invalid value [%s]", valueStr); | |||
| 279 | return; | |||
| 280 | } | |||
| 281 | int *ptr = (int *) (&((char *) engineConfiguration)[offset]); | |||
| 282 | *ptr ^= (-value ^ *ptr) & (1 << bit); | |||
| 283 | /** | |||
| 284 | * this response is part of rusEfi console API | |||
| 285 | */ | |||
| 286 | efiPrintf("bit%s%d/%d is %d", CONSOLE_DATA_PROTOCOL_TAG, offset, bit, value); | |||
| 287 | incrementGlobalConfigurationVersion("setBit"); | |||
| 288 | } | |||
| 289 | ||||
| 290 | static void setShort(const int offset, const int value) { | |||
| 291 | if (isOutOfBounds(offset)) | |||
| 292 | return; | |||
| 293 | uint16_t *ptr = (uint16_t *) (&((char *) engineConfiguration)[offset]); | |||
| 294 | *ptr = (uint16_t) value; | |||
| 295 | getShort(offset); | |||
| 296 | incrementGlobalConfigurationVersion("setShort"); | |||
| 297 | } | |||
| 298 | ||||
| 299 | static void setByte(const int offset, const int value) { | |||
| 300 | if (isOutOfBounds(offset)) | |||
| 301 | return; | |||
| 302 | uint8_t *ptr = (uint8_t *) (&((char *) engineConfiguration)[offset]); | |||
| 303 | *ptr = (uint8_t) value; | |||
| 304 | getByte(offset); | |||
| 305 | incrementGlobalConfigurationVersion("setByte"); | |||
| 306 | } | |||
| 307 | ||||
| 308 | static void getBit(int offset, int bit) { | |||
| 309 | if (isOutOfBounds(offset)) | |||
| 310 | return; | |||
| 311 | int *ptr = (int *) (&((char *) engineConfiguration)[offset]); | |||
| 312 | int value = (*ptr >> bit) & 1; | |||
| 313 | /** | |||
| 314 | * this response is part of rusEfi console API | |||
| 315 | */ | |||
| 316 | efiPrintf("bit%s%d/%d is %d", CONSOLE_DATA_PROTOCOL_TAG, offset, bit, value); | |||
| 317 | } | |||
| 318 | ||||
| 319 | static void getInt(int offset) { | |||
| 320 | if (isOutOfBounds(offset)) | |||
| 321 | return; | |||
| 322 | int *ptr = (int *) (&((char *) engineConfiguration)[offset]); | |||
| 323 | int value = *ptr; | |||
| 324 | /** | |||
| 325 | * this response is part of rusEfi console API | |||
| 326 | */ | |||
| 327 | efiPrintf("int%s%d is %d", CONSOLE_DATA_PROTOCOL_TAG, offset, value); | |||
| 328 | } | |||
| 329 | ||||
| 330 | static void setInt(const int offset, const int value) { | |||
| 331 | if (isOutOfBounds(offset)) | |||
| 332 | return; | |||
| 333 | int *ptr = (int *) (&((char *) engineConfiguration)[offset]); | |||
| 334 | *ptr = value; | |||
| 335 | getInt(offset); | |||
| 336 | incrementGlobalConfigurationVersion("setInt"); | |||
| 337 | } | |||
| 338 | ||||
| 339 | static void getFloat(int offset) { | |||
| 340 | if (isOutOfBounds(offset)) | |||
| 341 | return; | |||
| 342 | float *ptr = (float *) (&((char *) engineConfiguration)[offset]); | |||
| 343 | float value = *ptr; | |||
| 344 | /** | |||
| 345 | * this response is part of rusEfi console API | |||
| 346 | */ | |||
| 347 | efiPrintf("float%s%d is %.5f", CONSOLE_DATA_PROTOCOL_TAG, offset, value); | |||
| 348 | } | |||
| 349 | ||||
| 350 | static void setFloat(const char *offsetStr, const char *valueStr) { | |||
| 351 | int offset = atoi(offsetStr); | |||
| 352 | if (absI(offset) == absI(ATOI_ERROR_CODE)) { | |||
| 353 | efiPrintf("invalid offset [%s]", offsetStr); | |||
| 354 | return; | |||
| 355 | } | |||
| 356 | if (isOutOfBounds(offset)) | |||
| 357 | return; | |||
| 358 | float value = atoff(valueStr); | |||
| 359 | if (std::isnan(value)) { | |||
| 360 | efiPrintf("invalid value [%s]", valueStr); | |||
| 361 | return; | |||
| 362 | } | |||
| 363 | float *ptr = (float *) (&((char *) engineConfiguration)[offset]); | |||
| 364 | *ptr = value; | |||
| 365 | getFloat(offset); | |||
| 366 | incrementGlobalConfigurationVersion("setFloat"); | |||
| 367 | } | |||
| 368 | ||||
| 369 | static void initConfigActions() { | |||
| 370 | addConsoleActionSS("set_float", (VoidCharPtrCharPtr) setFloat); | |||
| 371 | addConsoleActionII("set_int", (VoidIntInt) setInt); | |||
| 372 | addConsoleActionII("set_short", (VoidIntInt) setShort); | |||
| 373 | addConsoleActionII("set_byte", (VoidIntInt) setByte); | |||
| 374 | addConsoleActionSSS("set_bit", setBit); | |||
| 375 | ||||
| 376 | addConsoleActionI("get_float", getFloat); | |||
| 377 | addConsoleActionI("get_int", getInt); | |||
| 378 | addConsoleActionI("get_short", getShort); | |||
| 379 | addConsoleActionI("get_byte", getByte); | |||
| 380 | addConsoleActionII("get_bit", getBit); | |||
| 381 | } | |||
| 382 | #endif /* EFI_UNIT_TEST */ | |||
| 383 | ||||
| 384 | // one-time start-up | |||
| 385 | // this method is used by real firmware and simulator and unit test | |||
| 386 | 585 | void commonInitEngineController() { | ||
| 387 | #if EFI_PROD_CODE | |||
| 388 | addConsoleAction("sensorinfo", printSensorInfo); | |||
| 389 | addConsoleAction("reset_accel", resetAccel); | |||
| 390 | #endif /* EFI_PROD_CODE */ | |||
| 391 | ||||
| 392 | #if EFI_SIMULATOR || EFI_UNIT_TEST | |||
| 393 | 585 | printf("commonInitEngineController\n"); | ||
| 394 | #endif | |||
| 395 | ||||
| 396 | #if !EFI_UNIT_TEST | |||
| 397 | initConfigActions(); | |||
| 398 | #endif /* EFI_UNIT_TEST */ | |||
| 399 | ||||
| 400 | #if EFI_ENGINE_CONTROL | |||
| 401 | /** | |||
| 402 | * This has to go after 'enginePins.startPins()' in order to | |||
| 403 | * properly detect un-assigned output pins | |||
| 404 | */ | |||
| 405 | 585 | prepareOutputSignals(); | ||
| 406 | ||||
| 407 | 585 | engine->injectionEvents.addFuelEvents(); | ||
| 408 | #endif // EFI_ENGINE_CONTROL | |||
| 409 | ||||
| 410 | ||||
| 411 | #if EFI_PROD_CODE || EFI_SIMULATOR | |||
| 412 | initSettings(); | |||
| 413 | ||||
| 414 | if (hasFirmwareError()) { | |||
| 415 | return; | |||
| 416 | } | |||
| 417 | #endif | |||
| 418 | ||||
| 419 | #if ! EFI_UNIT_TEST && EFI_ENGINE_CONTROL | |||
| 420 | initBenchTest(); | |||
| 421 | #endif /* ! EFI_UNIT_TEST && EFI_ENGINE_CONTROL */ | |||
| 422 | ||||
| 423 | #if EFI_ALTERNATOR_CONTROL | |||
| 424 | 585 | initAlternatorCtrl(); | ||
| 425 | #endif /* EFI_ALTERNATOR_CONTROL */ | |||
| 426 | ||||
| 427 | #if EFI_VVT_PID | |||
| 428 | initVvtActuators(); | |||
| 429 | #endif /* EFI_VVT_PID */ | |||
| 430 | ||||
| 431 | #if EFI_MALFUNCTION_INDICATOR | |||
| 432 | initMalfunctionIndicator(); | |||
| 433 | #endif /* EFI_MALFUNCTION_INDICATOR */ | |||
| 434 | ||||
| 435 | #if !EFI_UNIT_TEST | |||
| 436 | // This is tested independently - don't configure sensors for tests. | |||
| 437 | // This lets us selectively mock them for each test. | |||
| 438 | initNewSensors(); | |||
| 439 | #endif /* EFI_UNIT_TEST */ | |||
| 440 | ||||
| 441 | 585 | initSensors(); | ||
| 442 | ||||
| 443 | 585 | initAccelEnrichment(); | ||
| 444 | ||||
| 445 | 585 | initScriptImpl(); | ||
| 446 | ||||
| 447 | 585 | initGpPwm(); | ||
| 448 | ||||
| 449 | #if EFI_IDLE_CONTROL | |||
| 450 | 585 | startIdleThread(); | ||
| 451 | #endif /* EFI_IDLE_CONTROL */ | |||
| 452 | ||||
| 453 | #if EFI_TCU | |||
| 454 | initGearController(); | |||
| 455 | #endif | |||
| 456 | ||||
| 457 | 585 | initButtonDebounce(); | ||
| 458 | ||||
| 459 | #if EFI_ELECTRONIC_THROTTLE_BODY | |||
| 460 | 585 | initElectronicThrottle(); | ||
| 461 | #endif /* EFI_ELECTRONIC_THROTTLE_BODY */ | |||
| 462 | ||||
| 463 | #if EFI_MAP_AVERAGING && defined (MODULE_MAP_AVERAGING) | |||
| 464 | 585 | engine->module<MapAveragingModule>()->init(); | ||
| 465 | #else | |||
| 466 | efiPrintf("No MapAveraging support!"); | |||
| 467 | #endif /* EFI_MAP_AVERAGING */ | |||
| 468 | ||||
| 469 | #if EFI_BOOST_CONTROL | |||
| 470 | 585 | initBoostCtrl(); | ||
| 471 | #endif /* EFI_BOOST_CONTROL */ | |||
| 472 | ||||
| 473 | #if EFI_LAUNCH_CONTROL | |||
| 474 | 585 | initLaunchControl(); | ||
| 475 | #endif | |||
| 476 | ||||
| 477 | 585 | initIgnitionAdvanceControl(); | ||
| 478 | ||||
| 479 | #if EFI_UNIT_TEST | |||
| 480 | 585 | engine->rpmCalculator.Register(); | ||
| 481 | #endif /* EFI_UNIT_TEST */ | |||
| 482 | ||||
| 483 | #if EFI_AUX_VALVES | |||
| 484 | 585 | initAuxValves(); | ||
| 485 | #endif /* EFI_AUX_VALVES */ | |||
| 486 | ||||
| 487 | #ifdef MODULE_TACHOMETER | |||
| 488 | 585 | engine->module<TachometerModule>()->init(); | ||
| 489 | #endif | |||
| 490 | ||||
| 491 | 585 | initSpeedometer(); | ||
| 492 | ||||
| 493 | 585 | initStft(); | ||
| 494 | #if EFI_LTFT_CONTROL | |||
| 495 | 585 | initLtft(); | ||
| 496 | #endif | |||
| 497 | 585 | } | ||
| 498 | ||||
| 499 | 585 | PUBLIC_API_WEAK bool validateBoardConfig() { | ||
| 500 | 585 | return true; | ||
| 501 | } | |||
| 502 | ||||
| 503 | 585 | static bool validateGdi() { | ||
| 504 | 585 | auto lobes = engineConfiguration->hpfpCamLobes; | ||
| 505 |
2/2✓ Branch 0 taken 583 times.
✓ Branch 1 taken 2 times.
|
2/2✓ Decision 'true' taken 583 times.
✓ Decision 'false' taken 2 times.
|
585 | if (!lobes) { |
| 506 | 583 | return true; | ||
| 507 | } | |||
| 508 | 2 | int expectedLastLobeProfileAngle = 360 / lobes; | ||
| 509 | 2 | float actualLastAngle = config->hpfpLobeProfileAngle[efi::size(config->hpfpLobeProfileAngle) - 1]; | ||
| 510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
|
2 | if (expectedLastLobeProfileAngle != actualLastAngle) { |
| 511 | ✗ | criticalError("Last HPFP angle expected %d got %f", expectedLastLobeProfileAngle, actualLastAngle); | ||
| 512 | ✗ | return false; | ||
| 513 | } | |||
| 514 | ||||
| 515 | 2 | return true; | ||
| 516 | } | |||
| 517 | ||||
| 518 | // Returns false if there's an obvious problem with the loaded configuration | |||
| 519 | 585 | bool validateConfigOnStartUpOrBurn() { | ||
| 520 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (!validateBoardConfig()) { |
| 521 | ✗ | return false; | ||
| 522 | } | |||
| 523 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (!validateGdi()) { |
| 524 | ✗ | return false; | ||
| 525 | } | |||
| 526 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (engineConfiguration->etbMinimumPosition + 1 >= engineConfiguration->etbMaximumPosition) { |
| 527 | ✗ | criticalError("Broken ETB min/max %d %d", | ||
| 528 | engineConfiguration->etbMinimumPosition, | |||
| 529 | engineConfiguration->etbMaximumPosition); | |||
| 530 | ✗ | return false; | ||
| 531 | } | |||
| 532 | ||||
| 533 | 585 | defaultsOrFixOnBurn(); | ||
| 534 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (engineConfiguration->cylindersCount > MAX_CYLINDER_COUNT) { |
| 535 | ✗ | criticalError("Invalid cylinder count: %d", engineConfiguration->cylindersCount); | ||
| 536 | ✗ | return false; | ||
| 537 | } | |||
| 538 | #if EFI_PROD_CODE && (BOARD_MC33810_COUNT > 0) | |||
| 539 | float maxConfiguredCorr = config->dwellVoltageCorrValues[0]; | |||
| 540 | for (size_t i = 0;i<efi::size(config->dwellVoltageCorrValues);i++) { | |||
| 541 | maxConfiguredCorr = std::max(maxConfiguredCorr, (float)config->dwellVoltageCorrValues[i]); | |||
| 542 | } | |||
| 543 | float maxConfiguredDwell = config->sparkDwellValues[0]; | |||
| 544 | for (size_t i = 0;i<efi::size(config->sparkDwellValues);i++) { | |||
| 545 | maxConfiguredDwell = std::max(maxConfiguredDwell, (float)config->sparkDwellValues[i]); | |||
| 546 | } | |||
| 547 | int maxAllowedDwell = getMc33810maxDwellTimer(engineConfiguration->mc33810maxDwellTimer); | |||
| 548 | if (maxConfiguredCorr * maxConfiguredDwell > maxAllowedDwell) { | |||
| 549 | criticalError("Dwell=%.2f/corr=%.2f while 33810 limit %d", maxConfiguredDwell, maxConfiguredCorr, maxAllowedDwell); | |||
| 550 | } | |||
| 551 | ||||
| 552 | #endif // EFI_PROD_CODE && (BOARD_MC33810_COUNT > 0) | |||
| 553 |
2/4✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (engineConfiguration->adcVcc > 5.0f || engineConfiguration->adcVcc < 1.0f) { |
| 554 | ✗ | criticalError("Invalid adcVcc: %f", engineConfiguration->adcVcc); | ||
| 555 | ✗ | return false; | ||
| 556 | } | |||
| 557 | ||||
| 558 | 585 | ensureArrayIsAscending("Injector deadtime vBATT", engineConfiguration->injector.battLagCorrBattBins); | ||
| 559 | 585 | ensureArrayIsAscending("Injector deadtime Pressure", engineConfiguration->injector.battLagCorrPressBins); | ||
| 560 | ||||
| 561 | #if EFI_ENGINE_CONTROL | |||
| 562 | // Fueling | |||
| 563 | { | |||
| 564 | 585 | ensureArrayIsAscending("VE load", config->veLoadBins); | ||
| 565 | 585 | ensureArrayIsAscending("VE RPM", config->veRpmBins); | ||
| 566 | ||||
| 567 | 585 | ensureArrayIsAscending("Lambda/AFR load", config->lambdaLoadBins); | ||
| 568 | 585 | ensureArrayIsAscending("Lambda/AFR RPM", config->lambdaRpmBins); | ||
| 569 | ||||
| 570 | 585 | ensureArrayIsAscending("Fuel CLT mult", config->cltFuelCorrBins); | ||
| 571 | 585 | ensureArrayIsAscending("Fuel IAT mult", config->iatFuelCorrBins); | ||
| 572 | ||||
| 573 | 585 | ensureArrayIsAscendingOrDefault("Boost CLT mult", config->cltBoostCorrBins); | ||
| 574 | 585 | ensureArrayIsAscendingOrDefault("Boost IAT mult", config->iatBoostCorrBins); | ||
| 575 | ||||
| 576 | 585 | ensureArrayIsAscending("Injection phase load", config->injPhaseLoadBins); | ||
| 577 | 585 | ensureArrayIsAscending("Injection phase RPM", config->injPhaseRpmBins); | ||
| 578 | ||||
| 579 | 585 | ensureArrayIsAscendingOrDefault("Fuel Level Sensor", config->fuelLevelBins); | ||
| 580 | ||||
| 581 | 585 | ensureArrayIsAscendingOrDefault("STFT Rpm", config->fuelTrimRpmBins); | ||
| 582 | 585 | ensureArrayIsAscendingOrDefault("STFT Load", config->fuelTrimLoadBins); | ||
| 583 | ||||
| 584 | 585 | ensureArrayIsAscendingOrDefault("TC slip", engineConfiguration->tractionControlSlipBins); | ||
| 585 | 585 | ensureArrayIsAscendingOrDefault("TC speed", engineConfiguration->tractionControlSpeedBins); | ||
| 586 | ||||
| 587 | 585 | ensureArrayIsAscending("TPS/TPS AE from", config->tpsTpsAccelFromRpmBins); | ||
| 588 | 585 | ensureArrayIsAscending("TPS/TPS AE to", config->tpsTpsAccelToRpmBins); | ||
| 589 | ||||
| 590 | 585 | ensureArrayIsAscendingOrDefault("TPS TPS RPM correction", config->tpsTspCorrValuesBins); | ||
| 591 | ||||
| 592 | 585 | ensureArrayIsAscendingOrDefault("Staging Load", config->injectorStagingLoadBins); | ||
| 593 | 585 | ensureArrayIsAscendingOrDefault("Staging RPM", config->injectorStagingRpmBins); | ||
| 594 | } | |||
| 595 | ||||
| 596 | // Ignition | |||
| 597 | { | |||
| 598 | 585 | ensureArrayIsAscending("Dwell RPM", config->sparkDwellRpmBins); | ||
| 599 | ||||
| 600 | 585 | ensureArrayIsAscending("Ignition load", config->ignitionLoadBins); | ||
| 601 | 585 | ensureArrayIsAscending("Ignition RPM", config->ignitionRpmBins); | ||
| 602 | 585 | ensureArrayIsAscendingOrDefault("Ign Trim Rpm", config->ignTrimRpmBins); | ||
| 603 | 585 | ensureArrayIsAscendingOrDefault("Ign Trim Load", config->ignTrimLoadBins); | ||
| 604 | ||||
| 605 | 585 | ensureArrayIsAscending("Ignition CLT corr CLT", config->ignitionCltCorrTempBins); | ||
| 606 | 585 | ensureArrayIsAscending("Ignition CLT corr Load", config->ignitionCltCorrLoadBins); | ||
| 607 | ||||
| 608 | 585 | ensureArrayIsAscending("Ignition IAT corr IAT", config->ignitionIatCorrTempBins); | ||
| 609 | 585 | ensureArrayIsAscending("Ignition IAT corr Load", config->ignitionIatCorrLoadBins); | ||
| 610 | } | |||
| 611 | ||||
| 612 | 585 | ensureArrayIsAscendingOrDefault("Map estimate TPS", config->mapEstimateTpsBins); | ||
| 613 | 585 | ensureArrayIsAscendingOrDefault("Map estimate RPM", config->mapEstimateRpmBins); | ||
| 614 | #endif // EFI_ENGINE_CONTROL | |||
| 615 | ||||
| 616 | 585 | ensureArrayIsAscendingOrDefault("Script Curve 1", config->scriptCurve1Bins); | ||
| 617 | 585 | ensureArrayIsAscendingOrDefault("Script Curve 2", config->scriptCurve2Bins); | ||
| 618 | 585 | ensureArrayIsAscendingOrDefault("Script Curve 3", config->scriptCurve3Bins); | ||
| 619 | 585 | ensureArrayIsAscendingOrDefault("Script Curve 4", config->scriptCurve4Bins); | ||
| 620 | 585 | ensureArrayIsAscendingOrDefault("Script Curve 5", config->scriptCurve5Bins); | ||
| 621 | 585 | ensureArrayIsAscendingOrDefault("Script Curve 6", config->scriptCurve6Bins); | ||
| 622 | ||||
| 623 | // todo: huh? why does this not work on CI? ensureArrayIsAscendingOrDefault("Dwell Correction Voltage", engineConfiguration->dwellVoltageCorrVoltBins); | |||
| 624 | ||||
| 625 | 585 | ensureArrayIsAscending("MAF transfer function", config->mafDecodingBins); | ||
| 626 | ||||
| 627 | // Cranking tables | |||
| 628 | 585 | ensureArrayIsAscending("Cranking fuel mult", config->crankingFuelBins); | ||
| 629 | 585 | ensureArrayIsAscending("Cranking duration", config->crankingCycleBins); | ||
| 630 | 585 | ensureArrayIsAscending("Cranking Fuel CLT", config->crankingCycleFuelCltBins); | ||
| 631 | 585 | ensureArrayIsAscending("Cranking TPS", config->crankingTpsBins); | ||
| 632 | ||||
| 633 | // Idle tables | |||
| 634 | 585 | ensureArrayIsAscending("Idle target RPM", config->cltIdleRpmBins); | ||
| 635 | 585 | ensureArrayIsAscending("Idle warmup mult CLT", config->cltIdleCorrBins); | ||
| 636 | 585 | ensureArrayIsAscending("Idle warmup mult RPM", config->rpmIdleCorrBins); | ||
| 637 | 585 | ensureArrayIsAscendingOrDefault("Idle coasting RPM", config->iacCoastingRpmBins); | ||
| 638 | 585 | ensureArrayIsAscendingOrDefault("Idle VE RPM", config->idleVeRpmBins); | ||
| 639 | 585 | ensureArrayIsAscendingOrDefault("Idle VE Load", config->idleVeLoadBins); | ||
| 640 | 585 | ensureArrayIsAscendingOrDefault("Idle timing", config->idleAdvanceBins); | ||
| 641 | ||||
| 642 |
2/2✓ Branch 1 taken 1170 times.
✓ Branch 2 taken 585 times.
|
2/2✓ Decision 'true' taken 1170 times.
✓ Decision 'false' taken 585 times.
|
1755 | for (size_t index = 0; index < efi::size(engineConfiguration->vrThreshold); index++) { |
| 643 | 1170 | auto& cfg = engineConfiguration->vrThreshold[index]; | ||
| 644 | ||||
| 645 |
1/2✓ Branch 0 taken 1170 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 1170 times.
✗ Decision 'false' not taken.
|
1170 | if (cfg.pin == Gpio::Unassigned) { |
| 646 | 1170 | continue; | ||
| 647 | } | |||
| 648 | ✗ | ensureArrayIsAscending("VR threshold", cfg.rpmBins); | ||
| 649 | } | |||
| 650 | ||||
| 651 | #if EFI_BOOST_CONTROL | |||
| 652 | // Boost | |||
| 653 | 585 | ensureArrayIsAscending("Boost control Load [open loop]", config->boostOpenLoopLoadBins); | ||
| 654 | 585 | ensureArrayIsAscending("Boost control Load [closed loop]", config->boostClosedLoopLoadBins); | ||
| 655 | 585 | ensureArrayIsAscending("Boost control RPM [open+closed loop]", config->boostRpmBins); | ||
| 656 | #endif // EFI_BOOST_CONTROL | |||
| 657 | ||||
| 658 | #if EFI_ANTILAG_SYSTEM | |||
| 659 | // ALS | |||
| 660 | 585 | ensureArrayIsAscendingOrDefault("ign ALS TPS", config->alsIgnRetardLoadBins); | ||
| 661 | 585 | ensureArrayIsAscendingOrDefault("ign ALS RPM", config->alsIgnRetardrpmBins); | ||
| 662 | 585 | ensureArrayIsAscendingOrDefault("fuel ALS TPS", config->alsFuelAdjustmentLoadBins); | ||
| 663 | 585 | ensureArrayIsAscendingOrDefault("fuel ALS RPM", config->alsFuelAdjustmentrpmBins); | ||
| 664 | #endif // EFI_ANTILAG_SYSTEM | |||
| 665 | ||||
| 666 | #if EFI_ELECTRONIC_THROTTLE_BODY | |||
| 667 | // ETB | |||
| 668 | 585 | ensureArrayIsAscending("Pedal map pedal", config->pedalToTpsPedalBins); | ||
| 669 | 585 | ensureArrayIsAscending("Pedal map RPM", config->pedalToTpsRpmBins); | ||
| 670 | #endif // EFI_ELECTRONIC_THROTTLE_BODY | |||
| 671 | ||||
| 672 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 583 times.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 583 times.
|
585 | if (isGdiEngine()) { |
| 673 | 2 | ensureArrayIsAscending("HPFP compensation", config->hpfpCompensationRpmBins); | ||
| 674 | 2 | ensureArrayIsAscending("HPFP deadtime", config->hpfpDeadtimeVoltsBins); | ||
| 675 | 2 | ensureArrayIsAscending("HPFP lobe profile", config->hpfpLobeProfileQuantityBins); | ||
| 676 | 2 | ensureArrayIsAscending("HPFP target rpm", config->hpfpTargetRpmBins); | ||
| 677 | 2 | ensureArrayIsAscending("HPFP target load", config->hpfpTargetLoadBins); | ||
| 678 | ||||
| 679 | 2 | ensureArrayIsAscending("HPFP fuel mass compensation fuel pressure", config->hpfpFuelMassCompensationFuelPressure); | ||
| 680 | 2 | ensureArrayIsAscending("HPFP fuel mass compensation fuel mass", config->hpfpFuelMassCompensationFuelMass); | ||
| 681 | ||||
| 682 | } | |||
| 683 | ||||
| 684 | // VVT | |||
| 685 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 580 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 580 times.
|
585 | if (isBrainPinValid(engineConfiguration->camInputs[0])) { |
| 686 | 5 | ensureArrayIsAscending("VVT intake load", config->vvtTable1LoadBins); | ||
| 687 | 5 | ensureArrayIsAscending("VVT intake RPM", config->vvtTable1RpmBins); | ||
| 688 | } | |||
| 689 | ||||
| 690 | #if CAM_INPUTS_COUNT != 1 | |||
| 691 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (isBrainPinValid(engineConfiguration->camInputs[1])) { |
| 692 | ✗ | ensureArrayIsAscending("VVT exhaust load", config->vvtTable2LoadBins); | ||
| 693 | ✗ | ensureArrayIsAscending("VVT exhaust RPM", config->vvtTable2RpmBins); | ||
| 694 | } | |||
| 695 | #endif | |||
| 696 | ||||
| 697 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 585 times.
|
585 | if (engineConfiguration->enableOilPressureProtect) { |
| 698 | ✗ | ensureArrayIsAscending("Oil pressure protection", config->minimumOilPressureBins); | ||
| 699 | } | |||
| 700 | ||||
| 701 | 585 | return true; | ||
| 702 | } | |||
| 703 | ||||
| 704 | #if !EFI_UNIT_TEST | |||
| 705 | ||||
| 706 | void commonEarlyInit() { | |||
| 707 | // Start this early - it will start LED blinking and such | |||
| 708 | startStatusThreads(); | |||
| 709 | ||||
| 710 | #if EFI_SHAFT_POSITION_INPUT | |||
| 711 | // todo: figure out better startup logic | |||
| 712 | initTriggerCentral(); | |||
| 713 | #endif /* EFI_SHAFT_POSITION_INPUT */ | |||
| 714 | ||||
| 715 | /** | |||
| 716 | * Initialize hardware drivers | |||
| 717 | */ | |||
| 718 | initHardware(); | |||
| 719 | ||||
| 720 | initQcBenchControls(); | |||
| 721 | ||||
| 722 | #if EFI_FILE_LOGGING | |||
| 723 | initMmcCard(); | |||
| 724 | #endif /* EFI_FILE_LOGGING */ | |||
| 725 | ||||
| 726 | #if EFI_ENGINE_EMULATOR | |||
| 727 | initEngineEmulator(); | |||
| 728 | #endif | |||
| 729 | ||||
| 730 | #if EFI_LUA | |||
| 731 | startLua(); | |||
| 732 | #endif // EFI_LUA | |||
| 733 | ||||
| 734 | #if EFI_CAN_SERIAL | |||
| 735 | // needs to be called after initCan() inside initHardware() | |||
| 736 | startCanConsole(); | |||
| 737 | #endif /* EFI_CAN_SERIAL */ | |||
| 738 | ||||
| 739 | } | |||
| 740 | ||||
| 741 | // one-time start-up | |||
| 742 | void initRealHardwareEngineController() { | |||
| 743 | commonInitEngineController(); | |||
| 744 | initWarningRunningPins(); | |||
| 745 | ||||
| 746 | #if EFI_LOGIC_ANALYZER | |||
| 747 | if (engineConfiguration->isWaveAnalyzerEnabled) { | |||
| 748 | initWaveAnalyzer(); | |||
| 749 | } | |||
| 750 | #endif /* EFI_LOGIC_ANALYZER */ | |||
| 751 | ||||
| 752 | if (hasFirmwareError()) { | |||
| 753 | return; | |||
| 754 | } | |||
| 755 | ||||
| 756 | engineStateBlinkingTask.start(); | |||
| 757 | ||||
| 758 | initVrThresholdPwm(); | |||
| 759 | } | |||
| 760 | ||||
| 761 | /** | |||
| 762 | * See also SIGNATURE_HASH | |||
| 763 | */ | |||
| 764 | int getRusEfiVersion() { | |||
| 765 | #if defined(EFI_BOOTLOADER_INCLUDE_CODE) | |||
| 766 | // make bootloader code happy too | |||
| 767 | if (initBootloader() != 0) | |||
| 768 | return 123; | |||
| 769 | #endif /* EFI_BOOTLOADER_INCLUDE_CODE */ | |||
| 770 | return VCS_DATE; | |||
| 771 | } | |||
| 772 | #endif /* EFI_UNIT_TEST */ | |||
| 773 |