/**
 * @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);
}
Beispiel #2
0
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);
	}
}
Beispiel #3
0
static void runTests(const int count) {
	scheduleMsg(logger, "Running tests: %d", count);
	testRusefiMethods(count / 10);
	testSystemCalls(count);
	testMath(count);
}
Beispiel #4
0
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
}