static ALWAYS_INLINE void handleFuelInjectionEvent(int eventIndex, bool limitedFuel, InjectionEvent *event, int rpm DECLARE_ENGINE_PARAMETER_S) { if (limitedFuel) return; // todo: move this check up /** * todo: this is a bit tricky with batched injection. is it? Does the same * wetting coefficient works the same way for any injection mode, or is something * x2 or /2? */ floatms_t injectionDuration = ENGINE(wallFuel).adjust(event->injectorIndex, ENGINE(fuelMs) PASS_ENGINE_PARAMETER); ENGINE(actualLastInjection) = injectionDuration; if (cisnan(injectionDuration)) { warning(OBD_PCM_Processor_Fault, "NaN injection pulse"); return; } if (injectionDuration < 0) { warning(OBD_PCM_Processor_Fault, "Negative injection pulse %f", injectionDuration); return; } if (engine->isCylinderCleanupMode) return; floatus_t injectionStartDelayUs = ENGINE(rpmCalculator.oneDegreeUs) * event->injectionStart.angleOffset; OutputSignal *signal = &ENGINE(engineConfiguration2)->fuelActuators[eventIndex]; if (event->isSimultanious) { if (injectionDuration < 0) { firmwareError("duration cannot be negative: %d", injectionDuration); return; } if (cisnan(injectionDuration)) { firmwareError("NaN in scheduleOutput", injectionDuration); return; } /** * this is pretty much copy-paste of 'scheduleOutput' * 'scheduleOutput' is currently only used for injection, so maybe it should be * changed into 'scheduleInjection' and unified? todo: think about it. */ efiAssertVoid(signal!=NULL, "signal is NULL"); int index = getRevolutionCounter() % 2; scheduling_s * sUp = &signal->signalTimerUp[index]; scheduling_s * sDown = &signal->signalTimerDown[index]; scheduleTask("out up", sUp, (int) injectionStartDelayUs, (schfunc_t) &startSimultaniousInjection, engine); scheduleTask("out down", sDown, (int) injectionStartDelayUs + MS2US(injectionDuration), (schfunc_t) &endSimultaniousInjection, engine); } else { #if EFI_UNIT_TEST || defined(__DOXYGEN__) printf("scheduling injection angle=%f/delay=%f injectionDuration=%f\r\n", event->injectionStart.angleOffset, injectionStartDelayUs, injectionDuration); #endif scheduleOutput(signal, getTimeNowUs(), injectionStartDelayUs, MS2US(injectionDuration), event->output); } }
static void testCallback(void *arg) { /** * 0.1ms from now please squirt for 1.6ms */ float delayMs = 0.1; float durationMs = 1.6; efitimeus_t nowUs = getTimeNowUs(); scheduleOutput(&outSignals[0], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[1], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[2], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[3], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[4], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[5], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[6], nowUs, delayMs, durationMs); scheduleOutput(&outSignals[7], nowUs, delayMs, durationMs); /** * this would re-schedule another callback in 2ms from now */ scheduleTask("test", &ioTest, MS2US(2), testCallback, NULL); }
void scheduleComponent (void (*F) (void *schedulee, void *context, void *scheduler), void *C1, void *C, void *C2, uint8_t p, Time *t, uint16_t id) { if(t != NULL) { TimedTask *TT = getEmptyTimedTask(); TT->T->context = C; TT->T->function = F; TT->T->identifier = id; TT->T->priority = 0xFF - p; TT->T->schedulee = C1; TT->T->scheduler = C2; TT->t.sec = t->sec; TT->t.msec = t->msec; Log(LOG_SCHEDINTF, "[scheduleComponent] Scheduling Component as TimedTask with t %lu.%u\n", TT->t.sec, TT->t.msec); scheduleTimedTask(TT); } else { Task *T = getEmptyTask(); Log(LOG_SCHEDINTF, "[scheduleComponent] Scheduling Component as Task\n"); T->context = C; T->function = F; T->identifier = id; T->priority = 0xFF - p; T->schedulee = C1; T->scheduler = C2; scheduleTask(T); } }
void VideoThread::setEQ(int b, int c, int s) { class EQTask : public QRunnable { public: EQTask(VideoFrameConverter *c) : brightness(0) , contrast(0) , saturation(0) , conv(c) { //qDebug("EQTask tid=%p", QThread::currentThread()); } void run() { conv->setEq(brightness, contrast, saturation); } int brightness, contrast, saturation; private: VideoFrameConverter *conv; }; DPTR_D(VideoThread); EQTask *task = new EQTask(&d.conv); task->brightness = b; task->contrast = c; task->saturation = s; if (isRunning()) { scheduleTask(task); } else { task->run(); delete task; } }
void Renderer::taskLoop(int threadIndex) { while(task[threadIndex].type != Task::SUSPEND) { scheduleTask(threadIndex); executeTask(threadIndex); } }
/** * * @param delay the number of ticks before the output signal * immediate output if delay is zero * @param dwell the number of ticks of output duration * */ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) { if (durationMs < 0) { firmwareError("duration cannot be negative: %d", durationMs); return; } if (cisnan(durationMs)) { firmwareError("NaN in scheduleOutput", durationMs); return; } int index = getRevolutionCounter() % 2; scheduling_s * sUp = &signal->signalTimerUp[index]; scheduling_s * sDown = &signal->signalTimerDown[index]; scheduleTask("out up", sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal->io_pin); scheduleTask("out down", sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal->io_pin); }
void Schedule::scheduleEndFishSlotTask(void callback()) { // Require called during fish slot // i.e. assert startTimeOfFishSlot > nowTime > startTimeOfFishSlot + SlotDuration // else fish slot end is in the past. LongTime time = startTimeOfFishSlot + SlotDuration; assert(time >= longClock.nowTime()); assert(time <= startTimeOfNextPeriod()); scheduleTask(callback, clampedTimeDifferenceFromNow(time)); }
void Schedule::scheduleStartFishSlotTask(void callback()) { /* * Chosen randomly from sleeping slots. * Remember it, to schedule end. */ startTimeOfFishSlot = startTimeOfPeriod + randInt(FirstSleepingSlotOrdinal-1, CountSlots-1) * SlotDuration; assert(startTimeOfFishSlot >= longClock.nowTime()); assert(startTimeOfFishSlot <= startTimeOfNextPeriod()); scheduleTask(callback, clampedTimeDifferenceFromNow(startTimeOfFishSlot)); }
void Schedule::scheduleStartMergeSlotTask(void callback(), DeltaTime offset) { /* * !!!Not like others, is not aligned with slots. * Is scheduled within some usual sleepSlot of this period, but need not at start of slot. * offset is from CliqueMerger. */ LongTime time = startTimeOfPeriod + offset; assert(time >= longClock.nowTime()); assert(time <= startTimeOfNextPeriod()); scheduleTask(callback, clampedTimeDifferenceFromNow(time)); }
bool HostInputHandler::handleInput ( std::string& usrInput ) { Task task = getHostTaskFrom ( usrInput ); if ( task ) { scheduleTask( task ); }else{ if ( false == plugin_handleInput ( usrInput ) ) { // report error -- invalid input return false; } } return true; }
LL_FOREACH_SAFE(iHead, current, tmp) { if (current->sparkPosition.eventIndex == eventIndex) { // time to fire a spark which was scheduled previously LL_DELETE(iHead, current); scheduling_s * sDown = ¤t->signalTimerDown; float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * current->sparkPosition.angleOffset; scheduleTask("spark 2down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, current->output); } }
/** * Schedules a callback 'angle' degree of crankshaft from now. * The callback would be executed once after the duration of time which * it takes the crankshaft to rotate to the specified angle. */ void scheduleByAngle(int rpm, scheduling_s *timer, angle_t angle, schfunc_t callback, void *param) { if (!isValidRpm(rpm)) { /** * this might happen in case of a single trigger event after a pause - this is normal, so no * warning here */ return; } float delayUs = getOneDegreeTimeUs(rpm) * angle; if (cisnan(delayUs)) { firmwareError("NaN delay?"); return; } scheduleTask("by angle", timer, (int) delayUs, callback, param); }
void VideoThread::addCaptureTask() { if (!isRunning()) return; class CaptureTask : public QRunnable { public: CaptureTask(VideoThread *vt) : vthread(vt) {} void run() { VideoCapture *vc = vthread->videoCapture(); if (!vc) return; VideoFrame frame(vthread->displayedFrame()); //vthread->applyFilters(frame); vc->setVideoFrame(frame); vc->start(); } private: VideoThread *vthread; }; scheduleTask(new CaptureTask(this)); }
void initPwmTester(void) { initLogging(&logger, "pwm test"); addConsoleActionI("pwmtest", startPwmTest); startPwmTest(1000); /** * injector channels #4-#8 are used for individual squirt test */ // todo: yet, it's some horrible code duplication outSignals[0].output = &enginePins.injectors[4]; outSignals[1].output = &enginePins.injectors[5]; outSignals[2].output = &enginePins.injectors[6]; outSignals[3].output = &enginePins.injectors[7]; outSignals[4].output = &enginePins.injectors[8]; outSignals[5].output = &enginePins.injectors[9]; outSignals[6].output = &enginePins.injectors[10]; outSignals[7].output = &enginePins.injectors[11]; /** * this would schedule a callback in 2ms from now */ scheduleTask("test", &ioTest, MS2US(2), testCallback, NULL); }
void Schedule::scheduleEndSyncSlotTask(void callback()) { scheduleTask(callback, clampedTimeDifference(timeOfThisSyncSlotEnd(), longClock.nowTime())); }
// Sync is first slot of next period void Schedule::scheduleStartSyncSlotTask(void callback()) { scheduleTask(callback, clampedTimeDifferenceFromNow(startTimeOfNextPeriod()));}
void scheduleByTime(const char *prefix, scheduling_s *scheduling, efitimeus_t time, schfunc_t callback, void *param) { scheduleTask(prefix, scheduling, time - getTimeNowUs(), callback, param); }
void IDBTransactionBackendLevelDB::scheduleVersionChangeOperation(int64_t transactionId, int64_t requestedVersion, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, const IDBDatabaseMetadata& metadata) { scheduleTask(IDBDatabaseBackendLevelDB::VersionChangeOperation::create(this, transactionId, requestedVersion, callbacks, databaseCallbacks), IDBDatabaseBackendLevelDB::VersionChangeAbortOperation::create(this, String::number(metadata.version), metadata.version)); }
void IDBTransactionBackendLevelDB::scheduleClearOperation(int64_t objectStoreId, PassRefPtr<IDBCallbacks> callbacks) { scheduleTask(ClearOperation::create(this, m_backingStore.get(), database()->id(), objectStoreId, callbacks)); }
void IDBTransactionBackendLevelDB::scheduleDeleteRangeOperation(int64_t objectStoreId, PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks) { scheduleTask(DeleteRangeOperation::create(this, m_backingStore.get(), database()->id(), objectStoreId, keyRange, callbacks)); }
void IDBTransactionBackendLevelDB::scheduleOpenCursorOperation(int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange> keyRange, IndexedDB::CursorDirection direction, IndexedDB::CursorType cursorType, IDBDatabaseBackendInterface::TaskType taskType, PassRefPtr<IDBCallbacks> callbacks) { scheduleTask(OpenCursorOperation::create(this, m_backingStore.get(), database()->id(), objectStoreId, indexId, keyRange, direction, cursorType, taskType, callbacks)); }
void IDBTransactionBackendLevelDB::schedulePutOperation(const IDBObjectStoreMetadata& objectStoreMetadata, PassRefPtr<SharedBuffer> value, PassRefPtr<IDBKey> key, IDBDatabaseBackendInterface::PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, const Vector<int64_t>& indexIds, const Vector<IDBDatabaseBackendInterface::IndexKeys>& indexKeys) { scheduleTask(PutOperation::create(this, m_backingStore.get(), database()->id(), objectStoreMetadata, value, key, putMode, callbacks, indexIds, indexKeys)); }
void IDBTransactionBackendLevelDB::scheduleGetOperation(const IDBDatabaseMetadata& metadata, int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange> keyRange, IndexedDB::CursorType cursorType, PassRefPtr<IDBCallbacks> callbacks) { scheduleTask(GetOperation::create(this, m_backingStore.get(), metadata, objectStoreId, indexId, keyRange, cursorType, callbacks)); }
void IDBTransactionBackendLevelDB::scheduleDeleteIndexOperation(int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) { scheduleTask(DeleteIndexOperation::create(this, m_backingStore.get(), objectStoreId, indexMetadata), DeleteIndexAbortOperation::create(this, objectStoreId, indexMetadata)); }
void Schedule::scheduleEndWorkSlotTask(void callback()) { scheduleTask(callback, clampedTimeDifferenceFromNow(timeOfThisWorkSlotEnd())); }
static ALWAYS_INLINE void handleSparkEvent(uint32_t eventIndex, IgnitionEvent *iEvent, int rpm DECLARE_ENGINE_PARAMETER_S) { float dwellMs = engine->engineState.sparkDwell; if (cisnan(dwellMs) || dwellMs < 0) { firmwareError("invalid dwell: %f at %d", dwellMs, rpm); return; } floatus_t chargeDelayUs = engine->rpmCalculator.oneDegreeUs * iEvent->dwellPosition.angleOffset; int isIgnitionError = chargeDelayUs < 0; ignitionErrorDetection.add(isIgnitionError); if (isIgnitionError) { #if EFI_PROD_CODE scheduleMsg(logger, "Negative spark delay=%f", chargeDelayUs); #endif chargeDelayUs = 0; return; } if (cisnan(dwellMs)) { firmwareError("NaN in scheduleOutput", dwellMs); return; } /** * We are alternating two event lists in order to avoid a potential issue around revolution boundary * when an event is scheduled within the next revolution. */ scheduling_s * sUp = &iEvent->signalTimerUp; scheduling_s * sDown = &iEvent->signalTimerDown; /** * The start of charge is always within the current trigger event range, so just plain time-based scheduling */ scheduleTask("spark up", sUp, chargeDelayUs, (schfunc_t) &turnPinHigh, iEvent->output); /** * Spark event is often happening during a later trigger event timeframe * TODO: improve precision */ findTriggerPosition(&iEvent->sparkPosition, iEvent->advance PASS_ENGINE_PARAMETER); if (iEvent->sparkPosition.eventIndex == eventIndex) { /** * Spark should be fired before the next trigger event - time-based delay is best precision possible */ float timeTillIgnitionUs = engine->rpmCalculator.oneDegreeUs * iEvent->sparkPosition.angleOffset; scheduleTask("spark 1down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, iEvent->output); } else { /** * Spark should be scheduled in relation to some future trigger event, this way we get better firing precision */ bool isPending = assertNotInList<IgnitionEvent>(iHead, iEvent); if (isPending) return; LL_APPEND(iHead, iEvent); } }
void scheduleByAngle(scheduling_s *timer, float angle, schfunc_t callback, void *param) { int delay = (int)(getOneDegreeTime(getRpm()) * angle); scheduleTask(timer, delay, callback, param); }
void IDBTransactionBackendLevelDB::scheduleSetIndexesReadyOperation(size_t indexCount) { scheduleTask(IDBDatabaseBackendInterface::PreemptiveTask, SetIndexesReadyOperation::create(this, indexCount)); }
void IDBTransactionBackendLevelDB::scheduleDeleteObjectStoreOperation(const IDBObjectStoreMetadata& objectStoreMetadata) { scheduleTask(DeleteObjectStoreOperation::create(this, m_backingStore.get(), objectStoreMetadata), DeleteObjectStoreAbortOperation::create(this, objectStoreMetadata)); }