Ejemplo n.º 1
0
bool ScheduledActions::execute() {
    if (node) {
        node->cancel();
    }

    timeScheduled = clock->getCurrentTimeUS();
    scheduledDelay = MWTime(*delay);
    scheduledInterval = MWTime(*interval);
    nRepeated = 0;

    boost::weak_ptr<ScheduledActions> weakThis(component_shared_from_this<ScheduledActions>());
    node = Scheduler::instance()->scheduleUS(FILELINE,
            scheduledDelay,
            scheduledInterval,
            int(*n_repeats),
    [weakThis]() {
        if (auto sharedThis = weakThis.lock()) {
            sharedThis->executeOnce();
        }
        return nullptr;
    },
    M_DEFAULT_PRIORITY,
    M_DEFAULT_WARN_SLOP_US,
    M_DEFAULT_FAIL_SLOP_US,
    M_MISSED_EXECUTION_CATCH_UP);

    return true;
}
Ejemplo n.º 2
0
CVReturn StimulusDisplay::displayLinkCallback(CVDisplayLinkRef _displayLink,
                                              const CVTimeStamp *now,
                                              const CVTimeStamp *outputTime,
                                              CVOptionFlags flagsIn,
                                              CVOptionFlags *flagsOut,
                                              void *_display)
{
    StimulusDisplay *display = static_cast<StimulusDisplay*>(_display);
    
    {
        unique_lock lock(display->display_lock);
        
        if (bool(warnOnSkippedRefresh->getValue())) {
            if (display->lastFrameTime) {
                int64_t delta = (outputTime->videoTime - display->lastFrameTime) - outputTime->videoRefreshPeriod;
                if (delta) {
                    mwarning(M_DISPLAY_MESSAGE_DOMAIN,
                             "Skipped %g display refresh cycles",
                             (double)delta / (double)(outputTime->videoRefreshPeriod));
                }
            }
        }
        
        display->lastFrameTime = outputTime->videoTime;
        
        //
        // Here's how the time calculation works:
        //
        // outputTime->hostTime is the (estimated) time that the frame we're currently drawing will be displayed.
        // The value is in units of the "host time base", which appears to mean that it's directly comparable to
        // the value returned by mach_absolute_time().  However, the relationship to mach_absolute_time() is not
        // explicitly stated in the docs, so presumably we can't depend on it.
        //
        // What the CoreVideo docs *do* say is "the host time base for Core Video and the one for CoreAudio are
        // identical, and the values returned from either API can be used interchangeably".  Hence, we can use the
        // CoreAudio function AudioConvertHostTimeToNanos() to convert from the host time base to nanoseconds.
        //
        // Once we have a system time in nanoseconds, we substract the system base time and convert to
        // microseconds, which leaves us with a value that can be compared to clock->getCurrentTimeUS().
        //
        display->currentOutputTimeUS = (MWTime(AudioConvertHostTimeToNanos(outputTime->hostTime)) -
                                        display->clock->getSystemBaseTimeNS()) / 1000LL;
        
        display->refreshDisplay();
        display->waitingForRefresh = false;
    }
    
    // Signal waiting threads that refresh is complete
    display->refreshCond.notify_all();
    
    return kCVReturnSuccess;
}
Ejemplo n.º 3
0
NIDAQDevice::NIDAQDevice(const ParameterValueMap &parameters) :
    IODevice(parameters),
    deviceName(parameters[NAME].str()),
    requestSemName(generateUniqueID()),
    responseSemName(generateUniqueID()),
    controlChannel(boost::interprocess::create_only, requestSemName, responseSemName),
    sharedMemoryName(generateUniqueID()),
    sharedMemory(boost::interprocess::create_only, sharedMemoryName),
    controlMessage(NULL),
    helperPID(-1),
    updateInterval(parameters[UPDATE_INTERVAL]),
    analogInputDataInterval(parameters[ANALOG_INPUT_DATA_INTERVAL]),
    analogReadTimeout(updateInterval),
    assumeMultiplexedADC(parameters[ASSUME_MULTIPLEXED_ADC]),
    analogInputSampleBufferSize(0),
    analogInputTaskRunning(false),
    analogOutputDataInterval(parameters[ANALOG_OUTPUT_DATA_INTERVAL]),
    analogOutputSampleBufferSize(0),
    analogOutputEnabled(parameters[ANALOG_OUTPUT_ENABLED]),
    analogOutputTaskRunning(false),
    digitalInputSampleBufferSize(0),
    digitalInputTaskRunning(false),
    digitalOutputSampleBufferSize(0),
    digitalOutputTasksRunning(false),
    counterInputCountEdgesTasksRunning(false)
{
    if (updateInterval <= 0) {
        throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid update interval");
    }
    
    if (analogInputDataInterval <= 0) {
        throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid analog input data interval");
    }
    if (updateInterval % analogInputDataInterval != 0) {
        throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN,
                              "Update interval must be an integer multiple of analog input data interval");
    }
    
    if (!(parameters[ANALOG_READ_TIMEOUT].empty())) {
        analogReadTimeout = MWTime(parameters[ANALOG_READ_TIMEOUT]);
        if (analogReadTimeout < 0) {
            throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid analog read timeout");
        }
    }
    
    if (analogOutputDataInterval <= 0) {
        throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid analog output data interval");
    }
}
Ejemplo n.º 4
0
MovingDots::MovingDots(const ParameterValueMap &parameters) :
    StandardDynamicStimulus(parameters),
    fieldRadius(registerVariable(parameters[FIELD_RADIUS])),
    fieldCenterX(registerVariable(parameters[FIELD_CENTER_X])),
    fieldCenterY(registerVariable(parameters[FIELD_CENTER_Y])),
    dotDensity(registerVariable(parameters[DOT_DENSITY])),
    dotSize(registerVariable(parameters[DOT_SIZE])),
    alpha(registerVariable(parameters[ALPHA_MULTIPLIER])),
    direction(registerVariable(parameters[DIRECTION])),
    speed(registerVariable(parameters[SPEED])),
    coherence(registerVariable(parameters[COHERENCE])),
    lifetime(registerVariable(parameters[LIFETIME])),
    announceDots(parameters[ANNOUNCE_DOTS]),
    previousFieldRadius(1.0f),
    currentFieldRadius(1.0f),
    previousNumDots(0),
    currentNumDots(0),
    previousSpeed(0.0f),
    currentSpeed(0.0f),
    previousCoherence(1.0f),
    currentCoherence(1.0f),
    previousLifetime(0.0f),
    currentLifetime(0.0f),
    dotSizeToPixels(0.0f),
    previousTime(-1),
    currentTime(-1)
{
    ParsedColorTrio color(parameters[COLOR]);
    red = registerVariable(color.getR());
    green = registerVariable(color.getG());
    blue = registerVariable(color.getB());
    
    if (parameters[RAND_SEED].empty()) {
        randSeed = Clock::instance()->getSystemTimeNS();
    } else {
        randSeed = MWTime(parameters[RAND_SEED]);
    }
    randGen.seed(randSeed);
}
Ejemplo n.º 5
0
void HighPrecisionClock::sleepNS(MWTime time) {
    wait(mach_absolute_time() + timebase.nanosToAbsolute(std::max(MWTime(0), time)));
}