void start(bool useTwoWires, brain_pin_e pinEnable, brain_pin_e pinDir1, brain_pin_e pinDir2) { dcMotor.SetType(useTwoWires ? TwoPinDcMotor::ControlType::PwmDirectionPins : TwoPinDcMotor::ControlType::PwmEnablePin); m_pinEnable.initPin("ETB Enable", pinEnable); m_pinDir1.initPin("ETB Dir 1", pinDir1); m_pinDir2.initPin("ETB Dir 2", pinDir2); // Clamp to >100hz int freq = maxI(100, engineConfiguration->etbFreq); startSimplePwm(&m_pwmEnable, "ETB Enable", &engine->executor, &m_pinEnable, freq, 0, (pwm_gen_callback*)applyPinState); startSimplePwm(&m_pwmDir1, "ETB Dir 1", &engine->executor, &m_pinDir1, freq, 0, (pwm_gen_callback*)applyPinState); startSimplePwm(&m_pwmDir2, "ETB Dir 2", &engine->executor, &m_pinDir2, freq, 0, (pwm_gen_callback*)applyPinState); }
/** * this thread has a lower-then-usual stack size so we cannot afford *print* methods here */ static void blinkingThread(void *arg) { (void) arg; chRegSetThreadName("communication blinking"); initialLedsBlink(); while (true) { int delayMs = isConsoleReady() ? 3 * blinkingPeriod : blinkingPeriod; #if EFI_INTERNAL_FLASH || defined(__DOXYGEN__) if (getNeedToWriteConfiguration()) { delayMs = 2 * delayMs; } #endif communicationPin.setValue(0); warningPin.setValue(0); chThdSleepMilliseconds(delayMs); communicationPin.setValue(1); #if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) if (isTriggerErrorNow() || isIgnitionTimingError()) warningPin.setValue(1); #endif chThdSleepMilliseconds(delayMs); } }
void onElectricThink() { InputPin *value = getInputPin("value"); OutputPin *control = getOutputPin("control"); Signal::Voltage fValue = value->outputSignal().getVoltage(); bool controlOutput = control->outputSignal().isHigh(); if(mBelowMax) { if(fValue < mHigher) controlOutput = true; else { mBelowMax = false; controlOutput = false; } } else { if(fValue > mLower) controlOutput = false; else { mBelowMax = true; controlOutput = true; } } if(control->outputSignal().isHigh() != controlOutput) control->inputSignal(Signal(controlOutput)); Device::sleep(); }
static void blink_digits(int digit, int duration) { for (int iter = 0; iter < digit; iter++) { checkEnginePin.setValue(0); chThdSleepMilliseconds(duration); checkEnginePin.setValue(1); chThdSleepMilliseconds(MFI_BLINK_SEPARATOR); } }
static void applyIdleSolenoidPinState(PwmConfig *state, int stateIndex) { efiAssertVoid(stateIndex < PWM_PHASE_MAX_COUNT, "invalid stateIndex"); efiAssertVoid(state->multiWave.waveCount == 1, "invalid idle waveCount"); OutputPin *output = state->outputPins[0]; int value = state->multiWave.waves[0].pinStates[stateIndex]; if (!value /* always allow turning solenoid off */ || (engine->rpmCalculator.rpmValue != 0 || timeToStopIdleTest != 0) /* do not run solenoid unless engine is spinning or bench testing in progress */ ) { output->setValue(value); } }
void OutputPin::write(uint8_t value, OutputPin& clk, Direction order) { uint8_t bits = CHARBITS; if (order == MSB_FIRST) { synchronized do { _write(value & 0x80); clk._toggle(); value <<= 1; clk._toggle(); } while (--bits); }
void VideoRendererEVR::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation) { InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first(); OutputPin source; if (FAILED(sink->ConnectedTo(source.pparam()))) { return; //it must be connected to work } // Get the "Video Processor" (used for brightness/contrast/saturation/hue) ComPointer<IMFVideoProcessor> processor = getService<IMFVideoProcessor>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoProcessor); Q_ASSERT(processor); DXVA2_ValueRange contrastRange; DXVA2_ValueRange brightnessRange; DXVA2_ValueRange saturationRange; DXVA2_ValueRange hueRange; if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &contrastRange))) return; if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &brightnessRange))) return; if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &saturationRange))) return; if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Hue, &hueRange))) return; DXVA2_ProcAmpValues values; values.Contrast = DXVA2FloatToFixed(((contrast < 0 ? DXVA2FixedToFloat(contrastRange.MinValue) : DXVA2FixedToFloat(contrastRange.MaxValue)) - DXVA2FixedToFloat(contrastRange.DefaultValue)) * qAbs(contrast) + DXVA2FixedToFloat(contrastRange.DefaultValue)); values.Brightness = DXVA2FloatToFixed(((brightness < 0 ? DXVA2FixedToFloat(brightnessRange.MinValue) : DXVA2FixedToFloat(brightnessRange.MaxValue)) - DXVA2FixedToFloat(brightnessRange.DefaultValue)) * qAbs(brightness) + DXVA2FixedToFloat(brightnessRange.DefaultValue)); values.Saturation = DXVA2FloatToFixed(((saturation < 0 ? DXVA2FixedToFloat(saturationRange.MinValue) : DXVA2FixedToFloat(saturationRange.MaxValue)) - DXVA2FixedToFloat(saturationRange.DefaultValue)) * qAbs(saturation) + DXVA2FixedToFloat(saturationRange.DefaultValue)); values.Hue = DXVA2FloatToFixed(((hue < 0 ? DXVA2FixedToFloat(hueRange.MinValue) : DXVA2FixedToFloat(hueRange.MaxValue)) - DXVA2FixedToFloat(hueRange.DefaultValue)) * qAbs(hue) + DXVA2FixedToFloat(hueRange.DefaultValue)); //finally set the settings processor->SetProcAmpValues(DXVA2_ProcAmp_Contrast | DXVA2_ProcAmp_Brightness | DXVA2_ProcAmp_Saturation | DXVA2_ProcAmp_Hue, &values); }
static msg_t hipThread(void *arg) { chRegSetThreadName("hip9011 init"); // some time to let the hardware start hipCs.setValue(true); chThdSleepMilliseconds(100); hipCs.setValue(false); chThdSleepMilliseconds(100); hipCs.setValue(true); while (true) { chThdSleepMilliseconds(100); if (needToInit) { hipStartupCode(); needToInit = false; } } return -1; }
void OutputPin::write(uint8_t value, OutputPin& clk, Direction order) const { uint8_t bits = CHARBITS; if (order == MSB_FIRST) { do { _write(value & 0x80); clk._toggle(); value <<= 1; clk._toggle(); } while (--bits); } else { do { _write(value & 0x01); clk._toggle(); value >>= 1; clk._toggle(); } while (--bits); } }
static msg_t seThread(void *arg) { (void)arg; chRegSetThreadName("servo"); while (true) { OutputPin *pin = &pins[0]; pin->setValue(1); percent_t position = (currentTimeMillis() / 5) % 200; if (position > 100) position = 200 - position; float durationMs = 0 + position * 0.02f; scheduleForLater(&servoTurnSignalOff, (int)MS2US(durationMs), (schfunc_t) &servoTachPinLow, pin); chThdSleepMilliseconds(19); } return 0; }
virtual void onThink() { SinkConnector *energyIn = getInput("energy-in"); SourceConnector *energyOut = getOutput("energy-out"); OutputPin *readout = getOutputPin("readout"); mStored.attemptPumpSource(energyIn, Testing::Generator::ENERGY_PER_GENERATION); mStored.attemptPumpSink(energyOut, Testing::Generator::ENERGY_PER_GENERATION / 2); // 'waste' some output energyOut->pumpSource(Testing::Generator::ENERGY_PER_GENERATION / 4); Resource::Quantity stored = mStored.getQuantity() + energyOut->sourceQuantity(); float percentFull = (float) stored / mStored.getCapacity(); if(readout->outputSignal().getVoltage() != percentFull) readout->inputSignal(Signal(percentFull)); cout << "[capacitor] percent full: " << (percentFull * 100.0) << endl; // go to sleep if(mStored.getQuantity() <= 0) Module::sleep(); }
static msg_t csThread(void) { chRegSetThreadName("status"); #if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) while (true) { int rpm = getRpmE(engine); int is_cranking = isCrankingR(rpm); int is_running = rpm > 0 && !is_cranking; if (is_running) { // blinking while running runningPin.setValue(0); chThdSleepMilliseconds(50); runningPin.setValue(1); chThdSleepMilliseconds(50); } else { // constant on while cranking and off if engine is stopped runningPin.setValue(is_cranking); chThdSleepMilliseconds(100); } } #endif /* EFI_SHAFT_POSITION_INPUT */ return -1; }
uint8_t Pin::read(OutputPin& clk, Direction order) const { uint8_t value = 0; uint8_t bits = CHARBITS; if (order == MSB_FIRST) { do { value <<= 1; if (is_set()) value |= 0x01; clk.toggle(); clk.toggle(); } while (--bits); } else { do { value >>= 1; if (is_set()) value |= 0x80; clk.toggle(); clk.toggle(); } while (--bits); } return (value); }
/** * @brief Trigger decoding happens here * This method changes the state of trigger_state_s data structure according to the trigger event */ 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; eventCount[triggerWheel]++; eventCountExt[signal]++; 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; if (isLessImportant(signal)) { #if EFI_UNIT_TEST if (printTriggerDebug) { printf("%s isLessImportant %s\r\n", getTrigger_type_e(engineConfiguration->trigger.type), getTrigger_event_e(signal)); } #endif /** * For less important events we simply increment the index. */ nextTriggerEvent() ; if (TRIGGER_SHAPE(gapBothDirections)) { toothed_previous_duration = currentDuration; isFirstEvent = false; toothed_previous_time = nowNt; } return; } isFirstEvent = false; // todo: skip a number of signal from the beginning #if EFI_PROD_CODE // 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)) { isSynchronizationPoint = currentDuration > toothed_previous_duration * TRIGGER_SHAPE(syncRatioFrom) && currentDuration < toothed_previous_duration * TRIGGER_SHAPE(syncRatioTo); #if EFI_PROD_CODE if (engineConfiguration->isPrintTriggerSynchDetails) { #else if (printTriggerDebug) { #endif /* EFI_PROD_CODE */ float gap = 1.0 * currentDuration / toothed_previous_duration; #if EFI_PROD_CODE scheduleMsg(logger, "gap=%f @ %d", gap, current_index); #else actualSynchGap = gap; print("current gap %f\r\n", gap); #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 || (current_index >= TRIGGER_SHAPE(size) - d); } #if EFI_UNIT_TEST if (printTriggerDebug) { printf("%s isSynchronizationPoint=%d index=%d %s\r\n", getTrigger_type_e(engineConfiguration->trigger.type), isSynchronizationPoint, 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 = eventCount[0] != TRIGGER_SHAPE(expectedEventCount[0]) || eventCount[1] != TRIGGER_SHAPE(expectedEventCount[1]) || eventCount[2] != TRIGGER_SHAPE(expectedEventCount[2]); triggerDecoderErrorPin.setValue(isDecodingError); if (isDecodingError) { lastDecodingErrorTime = getTimeNowNt(); totalTriggerErrorCounter++; if (engineConfiguration->isPrintTriggerSynchDetails) { #if EFI_PROD_CODE scheduleMsg(logger, "error: synchronizationPoint @ index %d expected %d/%d/%d got %d/%d/%d", current_index, TRIGGER_SHAPE(expectedEventCount[0]), TRIGGER_SHAPE(expectedEventCount[1]), TRIGGER_SHAPE(expectedEventCount[2]), eventCount[0], eventCount[1], 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]), eventCount[0], eventCount[1], eventCount[2]); } shaft_is_synchronized = true; // this call would update duty cycle values nextTriggerEvent() ; nextRevolution(); } else { nextTriggerEvent() ; } toothed_previous_duration = currentDuration; toothed_previous_time = 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); }
/** * @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 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; thirdPreviousDuration = durationBeforePrevious; 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 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) // this is getting a little out of hand, any ideas? && durationBeforePrevious > thirdPreviousDuration * TRIGGER_SHAPE(thirdSyncRatioFrom) && durationBeforePrevious < thirdPreviousDuration * TRIGGER_SHAPE(thirdSyncRatioTo) ; #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; float gap3 = 1.0 * durationBeforePrevious / thirdPreviousDuration; #if EFI_PROD_CODE || defined(__DOXYGEN__) scheduleMsg(logger, "gap=%f/%f/%f @ %d while expected %f/%f and %f/%f error=%d", gap, prevGap, gap3, currentCycle.current_index, TRIGGER_SHAPE(syncRatioFrom), TRIGGER_SHAPE(syncRatioTo), TRIGGER_SHAPE(secondSyncRatioFrom), TRIGGER_SHAPE(secondSyncRatioTo), someSortOfTriggerError); #else actualSynchGap = gap; print("current gap %f/%f/%f c=%d prev=%d\r\n", gap, prevGap, gap3, 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() ; } thirdPreviousDuration = durationBeforePrevious; 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 (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(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]); // todo: re-implement this as a subclass. we need two instances of // 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; } } angle_t 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_RISE, filterLeft, filterRight); s->addEvent(offset + angleUp, wheel, TV_FALL, filterLeft, filterRight); } float angleDown = engineCycle / totalTeethCount * (totalTeethCount - skippedCount - 1 + (1 - toothWidth)); s->addEvent(offset + angleDown, wheel, TV_RISE, filterLeft, filterRight); s->addEvent(offset + engineCycle, wheel, TV_FALL, filterLeft, filterRight); }