/** * @brief Trigger decoding happens here * This method is invoked every time we have a fall or rise on one of the trigger sensors. * This method changes the state of trigger_state_s data structure according to the trigger event * @param signal type of event which just happened * @param nowNt current time */ void TriggerState::decodeTriggerEvent(trigger_event_e const signal, efitime_t nowNt DECLARE_ENGINE_PARAMETER_S) { efiAssertVoid(signal <= SHAFT_3RD_UP, "unexpected signal"); trigger_wheel_e triggerWheel = eventIndex[signal]; if (!engineConfiguration->useOnlyFrontForTrigger && curSignal == prevSignal) { orderingErrorCounter++; } prevSignal = curSignal; curSignal = signal; currentCycle.eventCount[triggerWheel]++; efitime_t currentDurationLong = getCurrentGapDuration(nowNt); /** * For performance reasons, we want to work with 32 bit values. If there has been more then * 10 seconds since previous trigger event we do not really care. */ currentDuration = currentDurationLong > 10 * US2NT(US_PER_SECOND_LL) ? 10 * US2NT(US_PER_SECOND_LL) : currentDurationLong; bool_t isPrimary = triggerWheel == T_PRIMARY; if (isLessImportant(signal)) { #if EFI_UNIT_TEST || defined(__DOXYGEN__) if (printTriggerDebug) { printf("%s isLessImportant %s %d\r\n", getTrigger_type_e(engineConfiguration->trigger.type), getTrigger_event_e(signal), nowNt); } #endif /** * For less important events we simply increment the index. */ nextTriggerEvent() ; if (TRIGGER_SHAPE(gapBothDirections) && considerEventForGap()) { isFirstEvent = false; durationBeforePrevious = toothed_previous_duration; toothed_previous_duration = currentDuration; toothed_previous_time = nowNt; } } else { #if EFI_UNIT_TEST || defined(__DOXYGEN__) if (printTriggerDebug) { printf("%s event %s %d\r\n", getTrigger_type_e(engineConfiguration->trigger.type), getTrigger_event_e(signal), nowNt); } #endif isFirstEvent = false; // todo: skip a number of signal from the beginning #if EFI_PROD_CODE || defined(__DOXYGEN__) // scheduleMsg(&logger, "from %f to %f %d %d", triggerConfig->syncRatioFrom, triggerConfig->syncRatioTo, currentDuration, shaftPositionState->toothed_previous_duration); // scheduleMsg(&logger, "ratio %f", 1.0 * currentDuration/ shaftPositionState->toothed_previous_duration); #else if (toothed_previous_duration != 0) { // printf("ratio %f: cur=%d pref=%d\r\n", 1.0 * currentDuration / shaftPositionState->toothed_previous_duration, // currentDuration, shaftPositionState->toothed_previous_duration); } #endif bool_t isSynchronizationPoint; if (TRIGGER_SHAPE(isSynchronizationNeeded)) { /** * Here I prefer to have two multiplications instead of one division, that's a micro-optimization */ isSynchronizationPoint = currentDuration > toothed_previous_duration * TRIGGER_SHAPE(syncRatioFrom) && currentDuration < toothed_previous_duration * TRIGGER_SHAPE(syncRatioTo) && toothed_previous_duration > durationBeforePrevious * TRIGGER_SHAPE(secondSyncRatioFrom) && toothed_previous_duration < durationBeforePrevious * TRIGGER_SHAPE(secondSyncRatioTo) ; #if EFI_PROD_CODE || defined(__DOXYGEN__) if (engineConfiguration->isPrintTriggerSynchDetails || someSortOfTriggerError) { #else if (printTriggerDebug) { #endif /* EFI_PROD_CODE */ float gap = 1.0 * currentDuration / toothed_previous_duration; float prevGap = 1.0 * toothed_previous_duration / durationBeforePrevious; #if EFI_PROD_CODE || defined(__DOXYGEN__) scheduleMsg(logger, "gap=%f/%f @ %d while expected %f/%f and %f/%f", gap, prevGap, currentCycle.current_index, TRIGGER_SHAPE(syncRatioFrom), TRIGGER_SHAPE(syncRatioTo), TRIGGER_SHAPE(secondSyncRatioFrom), TRIGGER_SHAPE(secondSyncRatioTo)); #else actualSynchGap = gap; print("current gap %f/%f c=%d prev=%d\r\n", gap, prevGap, currentDuration, toothed_previous_duration); #endif /* EFI_PROD_CODE */ } } else { /** * in case of noise the counter could be above the expected number of events */ int d = engineConfiguration->useOnlyFrontForTrigger ? 2 : 1; isSynchronizationPoint = !shaft_is_synchronized || (currentCycle.current_index >= TRIGGER_SHAPE(size) - d); } #if EFI_UNIT_TEST || defined(__DOXYGEN__) if (printTriggerDebug) { printf("%s isSynchronizationPoint=%d index=%d %s\r\n", getTrigger_type_e(engineConfiguration->trigger.type), isSynchronizationPoint, currentCycle.current_index, getTrigger_event_e(signal)); } #endif if (isSynchronizationPoint) { /** * We can check if things are fine by comparing the number of events in a cycle with the expected number of event. */ bool isDecodingError = currentCycle.eventCount[0] != TRIGGER_SHAPE(expectedEventCount[0]) || currentCycle.eventCount[1] != TRIGGER_SHAPE(expectedEventCount[1]) || currentCycle.eventCount[2] != TRIGGER_SHAPE(expectedEventCount[2]); triggerDecoderErrorPin.setValue(isDecodingError); if (isDecodingError) { lastDecodingErrorTime = getTimeNowNt(); someSortOfTriggerError = true; totalTriggerErrorCounter++; if (engineConfiguration->isPrintTriggerSynchDetails || someSortOfTriggerError) { #if EFI_PROD_CODE || defined(__DOXYGEN__) scheduleMsg(logger, "error: synchronizationPoint @ index %d expected %d/%d/%d got %d/%d/%d", currentCycle.current_index, TRIGGER_SHAPE(expectedEventCount[0]), TRIGGER_SHAPE(expectedEventCount[1]), TRIGGER_SHAPE(expectedEventCount[2]), currentCycle.eventCount[0], currentCycle.eventCount[1], currentCycle.eventCount[2]); #endif /* EFI_PROD_CODE */ } } errorDetection.add(isDecodingError); if (isTriggerDecoderError()) { warning(OBD_PCM_Processor_Fault, "trigger decoding issue. expected %d/%d/%d got %d/%d/%d", TRIGGER_SHAPE(expectedEventCount[0]), TRIGGER_SHAPE(expectedEventCount[1]), TRIGGER_SHAPE(expectedEventCount[2]), currentCycle.eventCount[0], currentCycle.eventCount[1], currentCycle.eventCount[2]); } shaft_is_synchronized = true; // this call would update duty cycle values nextTriggerEvent() ; nextRevolution(); } else { nextTriggerEvent() ; } durationBeforePrevious = toothed_previous_duration; toothed_previous_duration = currentDuration; toothed_previous_time = nowNt; } if (!isValidIndex(PASS_ENGINE_PARAMETER_F)) { warning(OBD_PCM_Processor_Fault, "unexpected eventIndex=%d while size %d", currentCycle.current_index, TRIGGER_SHAPE(size)); lastDecodingErrorTime = getTimeNowNt(); someSortOfTriggerError = true; } if (someSortOfTriggerError) { if (getTimeNowNt() - lastDecodingErrorTime > US2NT(US_PER_SECOND_LL)) { someSortOfTriggerError = false; } } if (boardConfiguration->sensorChartMode == SC_RPM_ACCEL || boardConfiguration->sensorChartMode == SC_DETAILED_RPM) { angle_t currentAngle = TRIGGER_SHAPE(eventAngles[currentCycle.current_index]); // todo: make this '90' depend on cylinder count? angle_t prevAngle = currentAngle - 90; fixAngle(prevAngle); // todo: prevIndex should be pre-calculated int prevIndex = TRIGGER_SHAPE(triggerIndexByAngle[(int)prevAngle]); // now let's get precise angle for that event prevAngle = TRIGGER_SHAPE(eventAngles[prevIndex]); uint32_t time = nowNt - timeOfLastEvent[prevIndex]; angle_t angleDiff = currentAngle - prevAngle; // todo: angle diff should be pre-calculated fixAngle(angleDiff); float r = (60000000.0 / 360 * US_TO_NT_MULTIPLIER) * angleDiff / time; #if EFI_SENSOR_CHART || defined(__DOXYGEN__) if (boardConfiguration->sensorChartMode == SC_DETAILED_RPM) { scAddData(currentAngle, r); } else { scAddData(currentAngle, r / instantRpmValue[prevIndex]); } #endif instantRpmValue[currentCycle.current_index] = r; timeOfLastEvent[currentCycle.current_index] = nowNt; } } float getEngineCycle(operation_mode_e operationMode) { return operationMode == TWO_STROKE ? 360 : 720; } void addSkippedToothTriggerEvents(trigger_wheel_e wheel, TriggerShape *s, int totalTeethCount, int skippedCount, float toothWidth, float offset, float engineCycle, float filterLeft, float filterRight) { efiAssertVoid(totalTeethCount > 0, "total count"); efiAssertVoid(skippedCount >= 0, "skipped count"); for (int i = 0; i < totalTeethCount - skippedCount - 1; i++) { float angleDown = engineCycle / totalTeethCount * (i + (1 - toothWidth)); float angleUp = engineCycle / totalTeethCount * (i + 1); s->addEvent(offset + angleDown, wheel, TV_HIGH, filterLeft, filterRight); s->addEvent(offset + angleUp, wheel, TV_LOW, filterLeft, filterRight); } float angleDown = engineCycle / totalTeethCount * (totalTeethCount - skippedCount - 1 + (1 - toothWidth)); s->addEvent(offset + angleDown, wheel, TV_HIGH, filterLeft, filterRight); s->addEvent(offset + engineCycle, wheel, TV_LOW, filterLeft, filterRight); }
static void testMath(const int count) { time_t start, time; int64_t temp64 = 0; start = currentTimeMillis(); for (int64_t i = 0; i < count; i++) { temp64 += i; } time = currentTimeMillis() - start; if (temp64 != 0) { scheduleMsg(logger, "Finished %d iterations of int64_t summation in %dms", count, time); } temp64 = 1; start = currentTimeMillis(); for (int64_t i = 0; i < count; i++) { temp64 *= i; } time = currentTimeMillis() - start; if (temp64 == 0) { scheduleMsg(logger, "Finished %d iterations of int64_t multiplication in %dms", count, time); } start = currentTimeMillis(); for (int i = 0; i < count; i++) ; time = currentTimeMillis() - start; scheduleMsg(logger, "Finished %d iterations of empty loop in %dms", count, time); uint32_t tempi = 1; start = currentTimeMillis(); for (int i = 0; i < count; i++) { tempi += tempi; } time = currentTimeMillis() - start; if (tempi == 0) { // 11ms is 1848000 ticks // 18.48 ticks per iteration // Finished 100000 iterations of uint32_t summation in 11ms scheduleMsg(logger, "Finished %d iterations of uint32_t summation in %dms", count, time); } start = currentTimeMillis(); tempi = 1; for (int i = 0; i < count; i++) { tempi += (tempi + 100) / 130; } time = currentTimeMillis() - start; if (tempi != 0) { // Finished 100000 iterations of uint32_t division in 16ms scheduleMsg(logger, "Finished %d iterations of uint32_t division in %dms", count, time); } start = currentTimeMillis(); temp64 = 1; for (int i = 0; i < count; i++) { temp64 += temp64; } time = currentTimeMillis() - start; if (temp64 == 0) { // Finished 100000 iterations of int64_t summation in 21ms scheduleMsg(logger, "Finished %d iterations of int64_t summation in %dms", count, time); } start = currentTimeMillis(); temp64 = 1; for (int i = 0; i < count; i++) { temp64 += (temp64 + 100) / 130; } time = currentTimeMillis() - start; if (temp64 != 0) { // Finished 100000 iterations of int64_t division in 181ms scheduleMsg(logger, "Finished %d iterations of int64_t division in %dms", count, time); } start = currentTimeMillis(); float tempf = 1; for (int i = 0; i < count; i++) { tempf += tempf; } time = currentTimeMillis() - start; if (tempf != 0) { scheduleMsg(logger, "Finished %d iterations of float summation in %dms", count, time); } start = currentTimeMillis(); tempf = 1; for (int i = 0; i < count; i++) { tempf += tempf * 130.0f; } time = currentTimeMillis() - start; if (tempf != 0) { // ms = ticks // ticks per iteration // Finished 100000 iterations of float division in ms scheduleMsg(logger, "Finished %d iterations of float multiplication in %dms", count, time); } start = currentTimeMillis(); tempf = 1; for (int i = 0; i < count; i++) { tempf += (tempf + 100) / 130.0; } time = currentTimeMillis() - start; if (tempf != 0) { // 65 ms = 10920000 ticks // 109.2 ticks per iteration // Finished 100000 iterations of float division in 65ms scheduleMsg(logger, "Finished %d iterations of float division in %dms", count, time); } start = currentTimeMillis(); tempf = 1; for (int i = 0; i < count; i++) { tempf += logf(tempf); } time = currentTimeMillis() - start; if (tempf != 0) { // Finished 100000 iterations of float log in 191ms scheduleMsg(logger, "Finished %d iterations of float log in %dms", count, time); } start = currentTimeMillis(); double tempd = 1; for (int i = 0; i < count; i++) tempd += tempd / 2; time = currentTimeMillis() - start; if (tempd != 0) { // Finished 100000 iterations of double summation in 80ms scheduleMsg(logger, "Finished %d iterations of double summation in %dms", count, time); } start = currentTimeMillis(); tempd = 1; for (int i = 0; i < count; i++) tempd += (tempd + 100) / 130.0; time = currentTimeMillis() - start; if (tempd != 0) { // Finished 100000 iterations of double division in 497ms scheduleMsg(logger, "Finished %d iterations of double division in %dms", count, time); } start = currentTimeMillis(); tempd = 1; for (int i = 0; i < count; i++) { tempd += log(tempd); } time = currentTimeMillis() - start; if (tempd != 0) { // Finished 100000 iterations of double log in 242ms scheduleMsg(logger, "Finished %d iterations of double log in %dms", count, time); } }
static void runTests(const int count) { scheduleMsg(logger, "Running tests: %d", count); testRusefiMethods(count / 10); testSystemCalls(count); testMath(count); }
static void showFuelInfo2(float rpm, float engineLoad) { float baseFuelMs = getBaseTableFuel(engineConfiguration, (int) rpm, engineLoad); float magicAir = getAirMass(engineConfiguration, 1, 100, convertCelsiusToKelvin(20)); scheduleMsg(&logger, "SD magic fuel %f", sdMath(engineConfiguration, magicAir, 14.7)); scheduleMsg(&logger, "inj flow %fcc/min displacement %fL", engineConfiguration->injector.flow, engineConfiguration->specs.displacement); scheduleMsg(&logger2, "algo=%s/pump=%s", getEngine_load_mode_e(engineConfiguration->fuelAlgorithm), boolToString(enginePins.fuelPumpRelay.getLogicValue())); scheduleMsg(&logger2, "injection phase=%f/global fuel correction=%f", getinjectionOffset(rpm), engineConfiguration->globalFuelCorrection); scheduleMsg(&logger2, "baro correction=%f", engine->engineState.baroCorrection); #if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) scheduleMsg(&logger, "base cranking fuel %f", engineConfiguration->cranking.baseFuel); scheduleMsg(&logger2, "cranking fuel: %f", getCrankingFuel(PASS_ENGINE_PARAMETER_F)); if (engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_F)) { float iatCorrection = engine->engineState.iatFuelCorrection; float cltCorrection = engine->engineState.cltFuelCorrection; floatms_t injectorLag = engine->engineState.injectorLag; scheduleMsg(&logger2, "rpm=%f engineLoad=%f", rpm, engineLoad); scheduleMsg(&logger2, "baseFuel=%f", baseFuelMs); scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection, injectorLag); float value = getRunningFuel(baseFuelMs, (int) rpm PASS_ENGINE_PARAMETER); scheduleMsg(&logger2, "injection pulse width: %f", value); } #endif }