static void digitalMapWidthCallback(void) { efitick_t nowNt = getTimeNowNt(); mapFreq = 1000000.0 / NT2US(nowNt - prevWidthTimeNt); prevWidthTimeNt = nowNt; }
bool WaveChart::isStartedTooLongAgo() { /** * Say at 300rpm we should get at least four events per revolution. * That's 300/60*4=20 events per second * engineChartSize/20 is the longest meaningful chart. * */ efitime_t chartDurationNt = getTimeNowNt() - startTimeNt; return startTimeNt != 0 && NT2US(chartDurationNt) > engineConfiguration->engineChartSize * 1000000 / 20; }
/** * This method is always invoked under a lock */ void Executor::scheduleTimerCallback() { /** * Let's grab fresh time value */ efitick_t nowNt = getTimeNowNt(); nextEventTimeNt = queue.getNextEventTime(nowNt); efiAssertVoid(nextEventTimeNt > nowNt, "setTimer constraint"); if (nextEventTimeNt == EMPTY_QUEUE) return; // no pending events in the queue int32_t hwAlarmTime = NT2US((int32_t)nextEventTimeNt - (int32_t)nowNt); beforeHwSetTimer = GET_TIMESTAMP(); setHardwareUsTimer(hwAlarmTime == 0 ? 1 : hwAlarmTime); hwSetTimerTime = GET_TIMESTAMP() - beforeHwSetTimer; }
static efitimeus_t getNextSwitchTimeUs(PwmConfig *state) { efiAssert(state->safe.phaseIndex < PWM_PHASE_MAX_COUNT, "phaseIndex range", 0); int iteration = state->safe.iteration; float switchTime = state->multiWave.getSwitchTime(state->safe.phaseIndex); float periodNt = state->safe.periodNt; #if DEBUG_PWM scheduleMsg(&logger, "iteration=%d switchTime=%.2f period=%.2f", iteration, switchTime, period); #endif /** * Once 'iteration' gets relatively high, we might lose calculation precision here. * This is addressed by ITERATION_LIMIT */ efitime_t timeToSwitchNt = (efitime_t) ((iteration + switchTime) * periodNt); #if DEBUG_PWM scheduleMsg(&logger, "start=%d timeToSwitch=%d", state->safe.start, timeToSwitch); #endif return NT2US(state->safe.startNt + timeToSwitchNt); }
/** * @brief Register an event for digital sniffer */ void WaveChart::addEvent3(const char *name, const char * msg) { #if EFI_TEXT_LOGGING if (!ENGINE(isEngineChartEnabled)) { return; } if (skipUntilEngineCycle != 0 && ENGINE(rpmCalculator.getRevolutionCounter()) < skipUntilEngineCycle) return; #if EFI_SIMULATOR // todo: add UI control to enable this for firmware if desired // CONFIG(alignEngineSnifferAtTDC) && if (!collectingData) { return; } #endif efiAssertVoid(CUSTOM_ERR_6651, name!=NULL, "WC: NULL name"); #if EFI_PROD_CODE efiAssertVoid(CUSTOM_ERR_6652, getCurrentRemainingStack() > 32, "lowstck#2c"); #endif /* EFI_PROD_CODE */ efiAssertVoid(CUSTOM_ERR_6653, isInitialized, "chart not initialized"); #if DEBUG_WAVE scheduleSimpleMsg(&debugLogging, "current", chart->counter); #endif /* DEBUG_WAVE */ if (isFull()) { return; } #if EFI_HISTOGRAMS && EFI_PROD_CODE int beforeCallback = hal_lld_get_counter_value(); #endif efitick_t nowNt = getTimeNowNt(); bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer if (counter == 0) { startTimeNt = nowNt; } counter++; /** * We want smaller times within a chart in order to reduce packet size. */ /** * todo: migrate to binary fractions in order to eliminate * this division? I do not like division * * at least that's 32 bit division now */ uint32_t diffNt = nowNt - startTimeNt; uint32_t time100 = NT2US(diffNt / 10); if (remainingSize(&logging) > 35) { /** * printf is a heavy method, append is used here as a performance optimization */ appendFast(&logging, name); appendChar(&logging, CHART_DELIMETER); appendFast(&logging, msg); appendChar(&logging, CHART_DELIMETER); // time100 -= startTime100; itoa10(timeBuffer, time100); appendFast(&logging, timeBuffer); appendChar(&logging, CHART_DELIMETER); logging.linePointer[0] = 0; } if (!alreadyLocked) { unlockOutputBuffer(); } #if EFI_HISTOGRAMS && EFI_PROD_CODE int64_t diff = hal_lld_get_counter_value() - beforeCallback; if (diff > 0) { hsAdd(&engineSnifferHisto, diff); } #endif /* EFI_HISTOGRAMS */ #endif /* EFI_TEXT_LOGGING */ }
void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) { efitick_t nowNt = getTimeNowNt(); if (ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE)) { crankingTime = nowNt; timeSinceCranking = 0.0f; } else { timeSinceCranking = nowNt - crankingTime; } updateAuxValves(PASS_ENGINE_PARAMETER_SIGNATURE); int rpm = ENGINE(rpmCalculator).getRpm(PASS_ENGINE_PARAMETER_SIGNATURE); sparkDwell = getSparkDwell(rpm PASS_ENGINE_PARAMETER_SUFFIX); dwellAngle = sparkDwell / getOneDegreeTimeMs(rpm); if (hasAfrSensor(PASS_ENGINE_PARAMETER_SIGNATURE)) { engine->sensors.currentAfr = getAfr(PASS_ENGINE_PARAMETER_SIGNATURE); } // todo: move this into slow callback, no reason for IAT corr to be here iatFuelCorrection = getIatFuelCorrection(engine->sensors.iat PASS_ENGINE_PARAMETER_SUFFIX); // todo: move this into slow callback, no reason for CLT corr to be here if (boardConfiguration->useWarmupPidAfr && engine->sensors.clt < engineConfiguration->warmupAfrThreshold) { if (rpm < 200) { cltFuelCorrection = 1; warmupAfrPid.reset(); } else { cltFuelCorrection = warmupAfrPid.getValue(warmupTargetAfr, engine->sensors.currentAfr, 1); } #if ! EFI_UNIT_TEST || defined(__DOXYGEN__) if (engineConfiguration->debugMode == DBG_WARMUP_ENRICH) { tsOutputChannels.debugFloatField1 = warmupTargetAfr; warmupAfrPid.postState(&tsOutputChannels); } #endif } else { cltFuelCorrection = getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); } // update fuel consumption states fuelConsumption.update(nowNt PASS_ENGINE_PARAMETER_SUFFIX); // Fuel cut-off isn't just 0 or 1, it can be tapered fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm PASS_ENGINE_PARAMETER_SUFFIX); // post-cranking fuel enrichment. // for compatibility reasons, apply only if the factor is greater than zero (0.01 margin used) if (engineConfiguration->postCrankingFactor > 0.01f) { // convert to microsecs and then to seconds float timeSinceCrankingInSecs = NT2US(timeSinceCranking) / 1000000.0f; // use interpolation for correction taper postCrankingFuelCorrection = interpolateClamped(0.0f, engineConfiguration->postCrankingFactor, engineConfiguration->postCrankingDurationSec, 1.0f, timeSinceCrankingInSecs); } else { postCrankingFuelCorrection = 1.0f; } cltTimingCorrection = getCltTimingCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); engineNoiseHipLevel = interpolate2d("knock", rpm, engineConfiguration->knockNoiseRpmBins, engineConfiguration->knockNoise, ENGINE_NOISE_CURVE_SIZE); baroCorrection = getBaroCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); injectionOffset = getinjectionOffset(rpm PASS_ENGINE_PARAMETER_SUFFIX); float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_SIGNATURE); timingAdvance = getAdvance(rpm, engineLoad PASS_ENGINE_PARAMETER_SUFFIX); if (engineConfiguration->fuelAlgorithm == LM_SPEED_DENSITY) { float coolantC = ENGINE(sensors.clt); float intakeC = ENGINE(sensors.iat); float tps = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE); tChargeK = convertCelsiusToKelvin(getTCharge(rpm, tps, coolantC, intakeC PASS_ENGINE_PARAMETER_SUFFIX)); float map = getMap(); /** * *0.01 because of https://sourceforge.net/p/rusefi/tickets/153/ */ float rawVe = veMap.getValue(rpm, map); // get VE from the separate table for Idle if (CONFIG(useSeparateVeForIdle)) { float idleVe = interpolate2d("idleVe", rpm, config->idleVeBins, config->idleVe, IDLE_VE_CURVE_SIZE); // interpolate between idle table and normal (running) table using TPS threshold rawVe = interpolateClamped(0.0f, idleVe, boardConfiguration->idlePidDeactivationTpsThreshold, rawVe, tps); } currentVE = baroCorrection * rawVe * 0.01; targetAFR = afrMap.getValue(rpm, map); } else { baseTableFuel = getBaseTableFuel(rpm, engineLoad); } }