示例#1
0
static void waitTimeout(niport *pniport,double seconds)
{
    epicsEventWaitStatus status;
    transferState_t saveState;

    if(seconds<0.0) {
        status = epicsEventWait(pniport->waitForInterrupt);
    } else {
        status = epicsEventWaitWithTimeout(pniport->waitForInterrupt,seconds);
    }
    if(status==epicsEventWaitOK) return;
    saveState = pniport->transferState;
    pniport->transferState = transferStateIdle;
    switch(saveState) {
    case transferStateRead:
        pniport->status=asynTimeout;
        printStatus(pniport,"waitTimeout transferStateRead\n");
        break;
    case transferStateWrite:
        pniport->status=asynTimeout;
        printStatus(pniport,"waitTimeout transferStateWrite\n");
        break;
    case transferStateCmd:
        pniport->status=asynTimeout;
        printStatus(pniport,"waitTimeout transferStateCmd\n");
        break;
    default:
        pniport->status=asynTimeout;
        printStatus(pniport,"waitTimeout transferState ?\n");
    }
}
示例#2
0
文件: seq_if.c 项目: ukaea/epics
static pvStat wait_complete(
	pvEventType evtype,
	SS_ID ss,
	PVREQ **req,
	DBCHAN *dbch,
	PVMETA *meta,
	double tmo)
{
	const char *call = evtype == pvEventGet ? "pvGet" : "pvPut";
	while (*req)
	{
		switch (epicsEventWaitWithTimeout(ss->syncSem, tmo))
		{
		case epicsEventWaitOK:
			break;
		case epicsEventWaitTimeout:
			*req = NULL;			/* cancel the request */
			completion_timeout(evtype, meta);
			return meta->status;
		case epicsEventWaitError:
			errlogSevPrintf(errlogFatal,
				"%s: epicsEventWaitWithTimeout() failure\n", call);
			*req = NULL;			/* cancel the request */
			completion_failure(evtype, meta);
			return meta->status;
		}
	}
	return check_connected(dbch, meta);
}
/** Simulation task that runs as a separate thread.  When the P_Run parameter is set to 1
  * to rub the simulation it computes a 1 kHz sine wave with 1V amplitude and user-controllable
  * noise, and displays it on
  * a simulated scope.  It computes waveforms for the X (time) and Y (volt) axes, and computes
  * statistics about the waveform. */
void testAsynPortDriver::simTask(void)
{
    /* This thread computes the waveform and does callbacks with it */

    double timePerDiv, voltsPerDiv, voltOffset, triggerDelay, noiseAmplitude;
    double updateTime, minValue, maxValue, meanValue;
    double time, timeStep;
    double noise, yScale;
    int run, i, maxPoints;
    double pi=4.0*atan(1.0);
    
    lock();
    /* Loop forever */    
    while (1) {
        getDoubleParam(P_UpdateTime, &updateTime);
        getIntegerParam(P_Run, &run);
        // Release the lock while we wait for a command to start or wait for updateTime
        unlock();
        if (run) epicsEventWaitWithTimeout(eventId_, updateTime);
        else     (void) epicsEventWait(eventId_);
        // Take the lock again
        lock(); 
        /* run could have changed while we were waiting */
        getIntegerParam(P_Run, &run);
        if (!run) continue;
        getIntegerParam(P_MaxPoints,        &maxPoints);
        getDoubleParam (P_TimePerDiv,       &timePerDiv);
        getDoubleParam (P_VoltsPerDiv,      &voltsPerDiv);
        getDoubleParam (P_VoltOffset,       &voltOffset);
        getDoubleParam (P_TriggerDelay,     &triggerDelay);
        getDoubleParam (P_NoiseAmplitude,   &noiseAmplitude);
        time = triggerDelay;
        timeStep = timePerDiv * NUM_DIVISIONS / maxPoints;
        minValue = 1e6;
        maxValue = -1e6;
        meanValue = 0.;
    
        yScale = 1.0 / voltsPerDiv;
        for (i=0; i<maxPoints; i++) {
            noise = noiseAmplitude * (rand()/(double)RAND_MAX - 0.5);
            pData_[i] = AMPLITUDE * (sin(time*FREQUENCY*2*pi)) + noise;
            /* Compute statistics before doing the yOffset and yScale */
            if (pData_[i] < minValue) minValue = pData_[i];
            if (pData_[i] > maxValue) maxValue = pData_[i];
            meanValue += pData_[i];
            pData_[i] = NUM_DIVISIONS/2 + yScale * (voltOffset + pData_[i]);
            time += timeStep;
        }
        updateTimeStamp();
        meanValue = meanValue/maxPoints;
        setDoubleParam(P_MinValue, minValue);
        setDoubleParam(P_MaxValue, maxValue);
        setDoubleParam(P_MeanValue, meanValue);
        callParamCallbacks();
        doCallbacksFloat64Array(pData_, maxPoints, P_Waveform, 0);
    }
}
示例#4
0
static void ClockTimeSync(void *dummy)
{
    taskwdInsert(0, NULL, NULL);

    for (epicsEventWaitWithTimeout(ClockTimePvt.loopEvent,
             ClockTimeSyncInterval);
         ClockTimePvt.synchronize == CLOCKTIME_SYNC;
         epicsEventWaitWithTimeout(ClockTimePvt.loopEvent,
             ClockTimeSyncInterval)) {
        epicsTimeStamp timeNow;
        int priority;

        if (generalTimeGetExceptPriority(&timeNow, &priority,
                LAST_RESORT_PRIORITY) == epicsTimeOK) {
            struct timespec clockNow;

            epicsTimeToTimespec(&clockNow, &timeNow);
            if (clock_settime(CLOCK_REALTIME, &clockNow)) {
                errlogPrintf("ClockTimeSync: clock_settime failed\n");
                continue;
            }

            epicsMutexMustLock(ClockTimePvt.lock);
            if (!ClockTimePvt.synchronized) {
                ClockTimePvt.startTime    = timeNow;
                ClockTimePvt.synchronized = 1;
            }
            ClockTimePvt.syncFromPriority = priority;
            ClockTimePvt.syncTime         = timeNow;
            epicsMutexUnlock(ClockTimePvt.lock);
        }
    }

    ClockTimePvt.synchronized = 0;
    taskwdRemove(0);
}
/** Array generation ask that runs as a separate thread.  When the P_RunStop parameter is set to 1
  * it periodically generates a burst of arrays. */
void testArrayRingBuffer::arrayGenTask(void)
{
    double loopDelay;
    int runStop; 
    int i, j;
    int burstLength;
    double burstDelay;
    int maxArrayLength;
    int arrayLength;
    
    lock();
    /* Loop forever */ 
    getIntegerParam(P_MaxArrayLength, &maxArrayLength);   
    while (1) {
        getDoubleParam(P_LoopDelay, &loopDelay);
        getDoubleParam(P_BurstDelay, &burstDelay);
        getIntegerParam(P_RunStop, &runStop);
        // Release the lock while we wait for a command to start or wait for updateTime
        unlock();
        if (runStop) epicsEventWaitWithTimeout(eventId_, loopDelay);
        else         (void)epicsEventWait(eventId_);
        // Take the lock again
        lock(); 
        /* runStop could have changed while we were waiting */
        getIntegerParam(P_RunStop, &runStop);
        if (!runStop) continue;
        getIntegerParam(P_ArrayLength, &arrayLength);
        if (arrayLength > maxArrayLength) {
            arrayLength = maxArrayLength;
            setIntegerParam(P_ArrayLength, arrayLength);
        }
        getIntegerParam(P_BurstLength, &burstLength);
        for (i=0; i<burstLength; i++) {
            for (j=0; j<arrayLength; j++) {
                pData_[j] = i;
            }
            setIntegerParam(P_ScalarData, i);
            callParamCallbacks();
            doCallbacksInt32Array(pData_, arrayLength, P_ArrayData, 0);
            if (burstDelay > 0.0) 
                epicsThreadSleep(burstDelay);
        }
    }
}
示例#6
0
文件: taskwd.c 项目: ukaea/epics
static void twdTask(void *arg)
{
    struct tNode *pt;
    struct mNode *pm;

    while (twdCtl != twdctlExit) {
        if (twdCtl == twdctlRun) {
            epicsMutexMustLock(tLock);
            pt = (struct tNode *)ellFirst(&tList);
            while (pt) {
                int susp = epicsThreadIsSuspended(pt->tid);
                if (susp != pt->suspended) {
                    epicsMutexMustLock(mLock);
                    pm = (struct mNode *)ellFirst(&mList);
                    while (pm) {
                        if (pm->funcs->notify) {
                            pm->funcs->notify(pm->usr, pt->tid, susp);
                        }
                        pm = (struct mNode *)ellNext(&pm->node);
                    }
                    epicsMutexUnlock(mLock);

                    if (susp) {
                        char tName[40];
                        epicsThreadGetName(pt->tid, tName, sizeof(tName));
                        errlogPrintf("Thread %s (%p) suspended\n",
                                    tName, (void *)pt->tid);
                        if (pt->callback) {
                            pt->callback(pt->usr);
                        }
                    }
                    pt->suspended = susp;
                }
                pt = (struct tNode *)ellNext(&pt->node);
            }
            epicsMutexUnlock(tLock);
        }
        epicsEventWaitWithTimeout(loopEvent, TASKWD_DELAY);
    }
    epicsEventSignal(exitEvent);
}
示例#7
0
void FastCCD::dataStatsTask(void)
{
  unsigned int status = 0;
  double timeout = 0.0;
  static const char *functionName = "dataStatsTask";

  while(1) {

    //Read timeout for polling freq.
    this->lock();
    timeout = dataStatsPollingPeriod;
    this->unlock();

    if (timeout != 0.0) {
      status = epicsEventWaitWithTimeout(dataStatsEvent, timeout);
    } else {
      status = epicsEventWait(dataStatsEvent);
    }              
  
    if (status == epicsEventWaitOK) {
      asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
        "%s:%s: Got status event\n",
        driverName, functionName);
    }

    cin_data_stats_t stats;
    cin_data_compute_stats(&stats);
    setIntegerParam(FastCCDDroppedPck, (int)stats.dropped_packets);
    setIntegerParam(FastCCDBadPck, (int)stats.mallformed_packets);
    setIntegerParam(FastCCDLastFrame, stats.last_frame);
    setIntegerParam(FastCCDPacketBuffer, stats.packet_used);
    setIntegerParam(FastCCDFrameBuffer, stats.frame_used);
    setIntegerParam(FastCCDImageBuffer, stats.image_used);

    //setDoubleParam(FastCCDDataRate, stats.datarate);
    
    this->lock();
    callParamCallbacks();
    this->unlock();
  }
}
示例#8
0
文件: callback.c 项目: ukaea/epics
void callbackStop(void)
{
    int i;

    if (cbCtl == ctlExit) return;
    cbCtl = ctlExit;

    for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
        callbackQueue[i].shutdown = 1;
        epicsEventSignal(callbackQueue[i].semWakeUp);
    }

    for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
        cbQueueSet *mySet = &callbackQueue[i];

        while (epicsAtomicGetIntT(&mySet->threadsRunning)) {
            epicsEventSignal(mySet->semWakeUp);
            epicsEventWaitWithTimeout(startStopEvent, 0.1);
        }
    }
}
示例#9
0
int epicsThreadPoolWait(epicsThreadPool *pool, double timeout)
{
    int ret = 0;
    epicsMutexMustLock(pool->guard);

    while (ellCount(&pool->jobs) > 0 || pool->threadsAreAwake > 0) {
        pool->observerCount++;
        epicsMutexUnlock(pool->guard);

        if (timeout < 0.0) {
            epicsEventMustWait(pool->observerWakeup);
        }
        else {
            switch (epicsEventWaitWithTimeout(pool->observerWakeup, timeout)) {
            case epicsEventWaitError:
                cantProceed("epicsThreadPoolWait: failed to wait for Event");
                break;
            case epicsEventWaitTimeout:
                ret = S_pool_timeout;
                break;
            case epicsEventWaitOK:
                ret = 0;
                break;
            }
        }

        epicsMutexMustLock(pool->guard);
        pool->observerCount--;

        if (pool->observerCount)
            epicsEventSignal(pool->observerWakeup);

        if (ret != 0)
            break;
    }

    epicsMutexUnlock(pool->guard);
    return ret;
}
asynStatus BISDetector::readSFRM(const char *fileName, epicsTimeStamp *pStartTime, double timeout, NDArray *pImage)
{
    #define lineLen 80
    #define maxLine 95
    #define blockLen 512
    #define dataOffset 8
    FILE *file=NULL;
    int fileExists=0;
    struct stat statBuff;
    epicsTimeStamp tStart, tCheck;
    time_t acqStartTime;
    double deltaTime;
    int status=-1;
    const char *functionName = "readSFRM";
    int offset, version, format;
    int nPixels;
    size_t nBytes, nRead=0;
    int headerBlocks;
    int numUnderflows, numOverflows1, numOverflows2;
    int nRows, nCols;
    int bytesPerPixel, underflowBytesPerPixel;
    int wordOrder, longOrder;
    int numExposures, bias, baselineOffset, orientation, overscan;
    epicsUInt16 *pOverflows1=NULL;
    epicsUInt32 *pOverflows2=NULL;
    epicsUInt16 *pUnderflows=NULL;
    int i;
    char *buffer=NULL;
    epicsUInt8 *byteBuffer;
    epicsUInt16 *i2Buffer;
    epicsUInt32 *pData = (epicsUInt32 *)pImage->pData;
    int n1=0, n2=0, nu=0;
        
    deltaTime = 0.;
    if (pStartTime) epicsTimeToTime_t(&acqStartTime, pStartTime);
    epicsTimeGetCurrent(&tStart);
    
    while (deltaTime <= timeout) {
        file = fopen(fileName, "rb");
        if (file && (timeout != 0.)) {
            fileExists = 1;
            /* The file exists.  Make sure it is a new file, not an old one.
             * We don't do this check if timeout==0 */
            status = stat(fileName, &statBuff);
            if (status){
                asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s::%s error calling fstat, errno=%d %s\n",
                    driverName, functionName, errno, fileName);
                fclose(file);
                return(asynError);
            }
            /* We allow up to 10 second clock skew between time on machine running this IOC
             * and the machine with the file system returning modification time */
            if (difftime(statBuff.st_mtime, acqStartTime) > -10) break;
            fclose(file);
            file = NULL;
        }
        /* Sleep, but check for stop event, which can be used to abort a long acquisition */
        unlock();
        status = epicsEventWaitWithTimeout(this->stopEventId, FILE_READ_DELAY);
        lock();
        if (status == epicsEventWaitOK) {
            return(asynError);
        }
        epicsTimeGetCurrent(&tCheck);
        deltaTime = epicsTimeDiffInSeconds(&tCheck, &tStart);
    }
    if (file == NULL) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
            "%s::%s timeout waiting for file to be created %s\n",
            driverName, functionName, fileName);
        if (fileExists) {
            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                "  file exists but is more than 10 seconds old, possible clock synchronization problem\n");
        } 
        return(asynError);
    }
    /* Allocate the buffer */
    buffer = (char *)malloc(lineLen * maxLine);
    /* Read the first 3 lines of the header */
    nBytes = fread(buffer, 1, 3*lineLen, file);
    offset = 0*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &format);
    offset = 1*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &version);
    offset = 2*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &headerBlocks);
    free(buffer);
    if ((format != 100) || (version < 11)) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
            "%s:%s: unsupported format=%d or version=%d\n",
            driverName, functionName, format, version);
        fclose(file);
        return(asynError);
    }
    /* Read the entire header now that we know how big it is */
    buffer = (char *)malloc(headerBlocks*blockLen);
    fseek(file, 0, SEEK_SET);
    nBytes = fread(buffer, 1, headerBlocks*blockLen, file);
    offset = 20*lineLen + dataOffset;
    sscanf(buffer+offset, "%d%d%d", &numUnderflows, &numOverflows1, &numOverflows2);
    offset = 39*lineLen + dataOffset;
    sscanf(buffer+offset, "%d%d", &bytesPerPixel, &underflowBytesPerPixel);
    offset = 40*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &nRows);
    offset = 41*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &nCols);
    offset = 42*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &wordOrder);
    offset = 42*lineLen + dataOffset;
    sscanf(buffer+offset, "%d", &longOrder);
    offset = 79*lineLen + dataOffset;
    sscanf(buffer+offset, "%d%d%d%d%d", &numExposures, &bias, &baselineOffset, &orientation, &overscan);
    free(buffer);
    if ((wordOrder !=0) || (longOrder != 0)) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
            "%s:%s: unsupported wordOrder=%d or longOrder=%d\n",
            driverName, functionName, wordOrder, longOrder);
        fclose(file);
        return(asynError);
    }

    asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
        "%s:%s: file=%s, numUnderflows=%d, numOverflows1=%d, numOverflows2=%d, bytesPerPixel=%d, underflowBytesPerPixel=%d, nRows=%d, nCols=%d\n",
        driverName, functionName, fileName, numUnderflows, numOverflows1, numOverflows2, bytesPerPixel, underflowBytesPerPixel, nRows, nCols);
    asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
        "%s:%s: numExposures=%d, bias=%d, baselineOffset=%d, orientation=%d, overscan=%d\n",
        driverName, functionName, numExposures, bias, baselineOffset, orientation, overscan);

    /* We have now read enough of the header to read the data and correct it */
    nPixels = nRows*nCols;
    switch (bytesPerPixel) {
        case 1:
            nBytes = nPixels * 1;
            byteBuffer = (epicsUInt8 *)malloc(nBytes);
            nRead = fread(byteBuffer, 1, nBytes, file);
            for (i=0; i<nPixels; i++) pData[i] = byteBuffer[i];
            free(byteBuffer);
            break;
        case 2:
            nBytes = nPixels * 2;
            i2Buffer = (epicsUInt16 *)malloc(nBytes);
            nRead = fread(i2Buffer, 1, nBytes, file);
            for (i=0; i<nPixels; i++) pData[i] = i2Buffer[i];
            free(i2Buffer);
            break;
        case 4:
            nBytes = nPixels * 4;
            nRead = fread(pData, 1, nBytes, file);
            break;
    }
    if (nRead != nBytes) {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
            "%s:%s: error reading file %s, only read %lu/%lu bytes\n",
            driverName, functionName, fileName, (unsigned long)nRead, (unsigned long)nBytes);
    }
    /* Read the underflow and overflow tables */
    if (numUnderflows > 0) {
        nBytes = ((numUnderflows * underflowBytesPerPixel + 15) / 16) * 16;
        pUnderflows = (epicsUInt16 *)malloc(nBytes);
        fread(pUnderflows, 1, nBytes, file);
    }
    if (numOverflows1 > 0) {
        nBytes = ((numOverflows1 * 2 + 15) / 16) * 16;
        pOverflows1 = (epicsUInt16 *)malloc(nBytes);
        fread(pOverflows1, 1, nBytes, file);
    }    
    if (numOverflows2 > 0) {
        nBytes = ((numOverflows2 * 4 + 15) / 16) * 16;
        pOverflows2 = (epicsUInt32 *)malloc(nBytes);
        fread(pOverflows2, 1, nBytes, file);
    }
    fclose(file);
    if (numUnderflows == -1) baselineOffset = 0;
    for (i=0; i<nPixels; i++) {
        if ((bytesPerPixel == 1) && (pData[i] == 255)) {
            pData[i] = pOverflows1[n1++];
        }
        if ((bytesPerPixel != 4) && (pData[i] == 65535)) {
            pData[i] = pOverflows2[n2++];
        }
        if (pData[i] == 0) {
            if (numUnderflows > 0) {
                pData[i] = pUnderflows[nu++];
            }
            //else printf("0 pixel=%d/%d\n", i, nPixels-1);
        }
        else if (baselineOffset != 0) {
            pData[i] += baselineOffset;
        }
    }
    free(pUnderflows);
    free(pOverflows1);
    free(pOverflows2);
    return(asynSuccess);
}   
示例#11
0
static void NTPTimeSync(void *dummy)
{
    taskwdInsert(0, NULL, NULL);

    for (epicsEventWaitWithTimeout(NTPTimePvt.loopEvent, NTPTimeSyncInterval);
         NTPTimePvt.synchronize;
         epicsEventWaitWithTimeout(NTPTimePvt.loopEvent, NTPTimeSyncInterval)) {
        int             status;
        struct timespec timespecNow;
        epicsTimeStamp  timeNow;
        epicsUInt32     tickNow;
        double          diff;
        double          ntpDelta;

        status = osdNTPGet(&timespecNow);
        tickNow = osdTickGet();

        if (status) {
            if (++NTPTimePvt.syncsFailed > NTPTimeSyncRetries &&
                NTPTimePvt.synchronized) {
                errlogPrintf("NTPTimeSync: NTP requests failing - %s\n",
                    strerror(errno));
                NTPTimePvt.synchronized = 0;
            }
            continue;
        }

        if (timespecNow.tv_sec <= POSIX_TIME_AT_EPICS_EPOCH ||
            epicsTimeFromTimespec(&timeNow, &timespecNow) == epicsTimeERROR) {
            errlogPrintf("NTPTimeSync: Bad time received from NTP server\n");
            NTPTimePvt.synchronized = 0;
            continue;
        }

        ntpDelta = epicsTimeDiffInSeconds(&timeNow, &NTPTimePvt.syncTime);
        if (ntpDelta <= 0.0 && NTPTimePvt.synchronized) {
            errlogPrintf("NTPTimeSync: NTP time not increasing, delta = %g\n",
                ntpDelta);
            NTPTimePvt.synchronized = 0;
            continue;
        }

        NTPTimePvt.syncsFailed = 0;
        if (!NTPTimePvt.synchronized) {
            errlogPrintf("NTPTimeSync: Sync recovered.\n");
        }

        epicsMutexMustLock(NTPTimePvt.lock);
        diff = epicsTimeDiffInSeconds(&timeNow, &NTPTimePvt.clockTime);
        if (diff >= 0.0) {
            NTPTimePvt.ticksToSkip = 0;
        } else { /* dont go back in time */
            NTPTimePvt.ticksToSkip = -diff * osdTickRateGet();
        }
        NTPTimePvt.clockTick = tickNow;
        NTPTimePvt.clockTime = timeNow;
        NTPTimePvt.synchronized = 1;
        epicsMutexUnlock(NTPTimePvt.lock);

        NTPTimePvt.tickRate = (tickNow - NTPTimePvt.syncTick) / ntpDelta;
        NTPTimePvt.syncTick = tickNow;
        NTPTimePvt.syncTime = timeNow;
    }

    NTPTimePvt.synchronized = 0;
    taskwdRemove(0);
}
示例#12
0
/** This thread controls handling of slow events - erase, acquire, change mode */
void mar345::mar345Task()
{
    int status = asynSuccess;
    int numImages, numImagesCounter;
    int imageMode;
    int acquire;
    double acquirePeriod;
    double elapsedTime, delayTime;
    const char *functionName = "mar345Task";

    this->lock();

    /* Loop forever */
    while (1) {
        setStringParam(ADStatusMessage, "Waiting for event");
        callParamCallbacks();
        /* Release the lock while we wait for an event that says acquire has started, then lock again */
        this->unlock();
        asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
            "%s:%s: waiting for start event\n", driverName, functionName);
        status = epicsEventWait(this->startEventId);
        this->lock();

        switch(this->mode) {
            case mar345ModeErase:
                this->erase();
                this->mode = mar345ModeIdle;
                break;

            case mar345ModeAcquire:
                getIntegerParam(ADImageMode, &imageMode);
                getIntegerParam(ADNumImages, &numImages);
                if (numImages < 1) numImages = 1;
                if (imageMode == ADImageSingle) numImages=1;
                for (numImagesCounter=0;
                        numImagesCounter<numImages || (imageMode == ADImageContinuous); 
                        numImagesCounter++) {
                    if (epicsEventTryWait(this->abortEventId) == epicsEventWaitOK) break;
                    setIntegerParam(ADNumImagesCounter, numImagesCounter);
                    callParamCallbacks();
                    status = acquireFrame();
                    if (status) break;
                    /* We get out of the loop in single shot mode or if acquire was set to 0 by client */
                    if (imageMode == ADImageSingle) setIntegerParam(ADAcquire, 0);
                    getIntegerParam(ADAcquire, &acquire);
                    if (!acquire) break;
                    /* We are in continuous or multiple mode.
                     * Sleep until the acquire period expires or acquire is set to stop */
                    epicsTimeGetCurrent(&this->acqEndTime);
                    elapsedTime = epicsTimeDiffInSeconds(&this->acqEndTime, &this->acqStartTime);
                    getDoubleParam(ADAcquirePeriod, &acquirePeriod);
                    delayTime = acquirePeriod - elapsedTime;
                    if (delayTime > 0.) {
                        setIntegerParam(ADStatus, mar345StatusWaiting);
                        callParamCallbacks();
                        this->unlock();
                        status = epicsEventWaitWithTimeout(this->abortEventId, delayTime);
                        this->lock();
                        if (status == epicsEventWaitOK) break;
                    }
                }
                this->mode = mar345ModeIdle;
                setIntegerParam(ADAcquire, 0);
                setIntegerParam(ADStatus, mar345StatusIdle);
                break;

            case mar345ModeChange:
                this->changeMode();
                this->mode = mar345ModeIdle;
                break;
                
            default:
                break;
        }

        /* Call the callbacks to update any changes */
        callParamCallbacks();
    }
}
示例#13
0
asynStatus mar345::acquireFrame()
{
    asynStatus status=asynSuccess;
    epicsTimeStamp startTime, currentTime;
    int eraseMode;
    epicsEventWaitStatus waitStatus;
    int imageCounter;
    int arrayCallbacks;
    double acquireTime;
    double timeRemaining;
    int size, res;
    int shutterMode, useShutter;
    char tempFileName[MAX_FILENAME_LEN];
    char fullFileName[MAX_FILENAME_LEN];
    //const char *functionName = "acquireframe";

    /* Get current values of some parameters */
    getDoubleParam(ADAcquireTime, &acquireTime);
    getIntegerParam(ADShutterMode, &shutterMode);
    getIntegerParam(mar345Size, &size);
    getIntegerParam(mar345Res, &res);
    getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
    getIntegerParam(mar345EraseMode, &eraseMode);
    if (shutterMode == ADShutterModeNone) useShutter=0; else useShutter=1;

    epicsTimeGetCurrent(&this->acqStartTime);

    createFileName(MAX_FILENAME_LEN, tempFileName);
    /* We need to append the extension */
    epicsSnprintf(fullFileName, sizeof(fullFileName), "%s.mar%d", tempFileName, imageSizes[res][size]);

    /* Erase before exposure if set */
    if (eraseMode == mar345EraseBefore) {
        status = this->erase();
        if (status) return(status);
    }
    
    /* Set the the start time for the TimeRemaining counter */
    epicsTimeGetCurrent(&startTime);
    timeRemaining = acquireTime;
    if (useShutter) setShutter(1);

    /* Wait for the exposure time using epicsEventWaitWithTimeout, 
     * so we can abort */
    epicsTimerStartDelay(this->timerId, acquireTime);
    setIntegerParam(ADStatus, mar345StatusExpose);
    callParamCallbacks();
    while(1) {
        if (epicsEventTryWait(this->abortEventId) == epicsEventWaitOK) {
            status = asynError;
            break;
        }
        this->unlock();
        waitStatus = epicsEventWaitWithTimeout(this->stopEventId, MAR345_POLL_DELAY);
        this->lock();
        if (waitStatus == epicsEventWaitOK) {
            /* The acquisition was stopped before the time was complete */
            epicsTimerCancel(this->timerId);
            break;
        }
        epicsTimeGetCurrent(&currentTime);
        timeRemaining = acquireTime - 
            epicsTimeDiffInSeconds(&currentTime, &startTime);
        if (timeRemaining < 0.) timeRemaining = 0.;
        setDoubleParam(ADTimeRemaining, timeRemaining);
        callParamCallbacks();
    }
    setDoubleParam(ADTimeRemaining, 0.0);
    if (useShutter) setShutter(0);
    setIntegerParam(ADStatus, mar345StatusIdle);
    callParamCallbacks();
    // If the exposure was aborted return error
    if (status) return asynError;
    setIntegerParam(ADStatus, mar345StatusScan);
    callParamCallbacks();
    epicsSnprintf(this->toServer, sizeof(this->toServer), "COMMAND SCAN %s", fullFileName);
    setStringParam(NDFullFileName, fullFileName);
    callParamCallbacks();
    writeServer(this->toServer);
    status = waitForCompletion("SCAN_DATA    Ended o.k.", MAR345_COMMAND_TIMEOUT);
    if (status) {
        return asynError;
    }
    getIntegerParam(NDArrayCounter, &imageCounter);
    imageCounter++;
    setIntegerParam(NDArrayCounter, imageCounter);
    /* Call the callbacks to update any changes */
    callParamCallbacks();

    /* If arrayCallbacks is set then read the file back in */
    if (arrayCallbacks) {
        getImageData();
    }

    /* Erase after scanning if set */
    if (eraseMode == mar345EraseAfter) status = this->erase();

    return status;
}
示例#14
0
文件: seq_task.c 项目: ukaea/epics
/*
 * ss_entry() - Thread entry point for all state sets.
 * Provides the main loop for state set processing.
 */
static void ss_entry(void *arg)
{
	SSCB		*ss = (SSCB *)arg;
	PROG		*sp = ss->prog;

	/* Attach to PV system; was already done for the first state set */
	if (ss != sp->ss)
	{
		ss->threadId = epicsThreadGetIdSelf();
		createOrAttachPvSystem(sp);
	}

	/* Register this thread with the EPICS watchdog (no callback func) */
	taskwdInsert(ss->threadId, 0, 0);

	/* In safe mode, update local var buffer with global one before
	   entering the event loop. Must do this using
	   ss_read_all_buffer since CA and other state sets could
	   already post events resp. pvPut. */
	if (optTest(sp, OPT_SAFE))
		ss_read_all_buffer(sp, ss);

	/* Initial state is the first one */
	ss->currentState = 0;
	ss->nextState = -1;
	ss->prevState = -1;

	DEBUG("ss %s: entering main loop\n", ss->ssName);

	/*
	 * ============= Main loop ==============
	 */
	while (TRUE)
	{
		boolean	ev_trig;
		int	transNum = 0;	/* highest prio trans. # triggered */
		STATE	*st = ss->states + ss->currentState;
		double	now;

		/* Set state to current state */
		assert(ss->currentState >= 0);

		/* Set state set event mask to this state's event mask */
		ss->mask = st->eventMask;

		/* If we've changed state, do any entry actions. Also do these
		 * even if it's the same state if option to do so is enabled.
		 */
		if (st->entryFunc && (ss->prevState != ss->currentState
			|| optTest(st, OPT_DOENTRYFROMSELF)))
		{
			st->entryFunc(ss);
		}

		/* Flush any outstanding DB requests */
		pvSysFlush(sp->pvSys);

		/* Setting this semaphore here guarantees that a when() is
		 * always executed at least once when a state is first entered.
		 */
		epicsEventSignal(ss->syncSem);

		pvTimeGetCurrentDouble(&now);

		/* Set time we entered this state if transition from a different
		 * state or else if option not to do so is off for this state.
		 */
		if ((ss->currentState != ss->prevState) ||
			!optTest(st, OPT_NORESETTIMERS))
		{
			ss->timeEntered = now;
		}
		ss->wakeupTime = epicsINF;

		/* Loop until an event is triggered, i.e. when() returns TRUE
		 */
		do {
			/* Wake up on PV event, event flag, or expired delay */
			DEBUG("before epicsEventWaitWithTimeout(ss=%d,timeout=%f)\n",
				ss - sp->ss, ss->wakeupTime - now);
			epicsEventWaitWithTimeout(ss->syncSem, ss->wakeupTime - now);
			DEBUG("after epicsEventWaitWithTimeout()\n");

			/* Check whether we have been asked to exit */
			if (sp->die) goto exit;

			/* Copy dirty variable values from CA buffer
			 * to user (safe mode only).
			 */
			if (optTest(sp, OPT_SAFE))
				ss_read_all_buffer(sp, ss);

			ss->wakeupTime = epicsINF;

			/* Check state change conditions */
			ev_trig = st->eventFunc(ss,
				&transNum, &ss->nextState);

			/* Clear all event flags (old ef mode only) */
			if (ev_trig && !optTest(sp, OPT_NEWEF))
			{
				unsigned i;
				for (i = 0; i < NWORDS(sp->numEvFlags); i++)
				{
					sp->evFlags[i] &= ~ss->mask[i];
				}
			}
			if (!ev_trig)
				pvTimeGetCurrentDouble(&now);
		} while (!ev_trig);

		/* Execute the state change action */
		st->actionFunc(ss, transNum, &ss->nextState);

		/* Check whether we have been asked to exit */
		if (sp->die) goto exit;

		/* If changing state, do exit actions */
		if (st->exitFunc && (ss->currentState != ss->nextState
			|| optTest(st, OPT_DOEXITTOSELF)))
		{
			st->exitFunc(ss);
		}

		/* Change to next state */
		ss->prevState = ss->currentState;
		ss->currentState = ss->nextState;
	}

	/* Thread exit has been requested */
exit:
	taskwdRemove(ss->threadId);
	/* Declare ourselves dead */
	if (ss != sp->ss)
		epicsEventSignal(ss->dead);
}
示例#15
0
文件: seq_if.c 项目: ukaea/epics
static pvStat check_pending(
	pvEventType evtype,
	SS_ID ss,
	PVREQ **req,
	const char *varName,
	DBCHAN *dbch,
	PVMETA *meta,
	enum compType compType,
	double tmo)
{
	const char *call = evtype == pvEventGet ? "pvGet" : "pvPut";

	assert(evtype != pvEventMonitor);
	if (compType == SYNC)
	{
		if (tmo <= 0.0)
		{
			errlogSevPrintf(errlogMajor,
				"%s(%s,SYNC,%f): user error (timeout must be positive)\n",
				call, varName, tmo);
			return pvStatERROR;
		}
		while (*req)
		{
			/* a request is already pending (must be an async request) */
			double before, after;
			pvStat status;

			pvTimeGetCurrentDouble(&before);
			switch (epicsEventWaitWithTimeout(ss->syncSem, tmo))
			{
			case epicsEventWaitOK:
				status = check_connected(dbch, meta);
				if (status != pvStatOK)
					return status;
				pvTimeGetCurrentDouble(&after);
				tmo -= (after - before);
				if (tmo > 0.0)
					break;
				/* else: fall through to timeout */
			case epicsEventWaitTimeout:
				errlogSevPrintf(errlogMajor,
					"%s(ss %s, var %s, pv %s): failed (timeout "
					"waiting for other %s requests to finish)\n",
					call, ss->ssName, varName, dbch->dbName, call
				);
				completion_timeout(evtype, meta);
				return meta->status;
			case epicsEventWaitError:
				errlogSevPrintf(errlogFatal,
					"%s: epicsEventWaitWithTimeout() failure\n", call);
				completion_failure(evtype, meta);
				return meta->status;
			}
		}
	}
	else if (compType == ASYNC)
	{
		if (*req) {
			errlogSevPrintf(errlogMajor,
				"%s(ss %s, var %s, pv %s): user error "
				"(there is already a %s pending for this channel/"
				"state set combination)\n",
				call, ss->ssName, varName, dbch->dbName, call
			);
			return pvStatERROR;
		}
	}
	return pvStatOK;
}
示例#16
0
/** This thread controls acquisition, reads image files to get the image data,
  * and does the callbacks to send it to higher layers */
void hdf5Driver::hdf5Task (void)
{
    const char *functionName = "hdf5Task";
    int status = asynSuccess;
    epicsTimeStamp startTime, endTime;
    int imageMode, currentFrame, colorMode;
    double acquirePeriod, elapsedTime, delay;

    this->lock();

    for(;;)
    {
        int acquire;
        getIntegerParam(ADAcquire, &acquire);

        if (!acquire)
        {
            this->unlock(); // Wait for semaphore unlocked

            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
                    "%s:%s: waiting for acquire to start\n",
                    driverName, functionName);

            status = epicsEventWait(this->mStartEventId);

            this->lock();

            acquire = 1;
            setStringParam(ADStatusMessage, "Acquiring data");
            setIntegerParam(ADNumImagesCounter, 0);
        }

        // Are there datasets loaded?
        if(!mDatasetsCount)
        {
            setStringParam(ADStatusMessage, "No datasets loaded");
            goto error;
        }

        // Get acquisition parameters
        epicsTimeGetCurrent(&startTime);
        getIntegerParam(ADImageMode, &imageMode);
        getDoubleParam(ADAcquirePeriod, &acquirePeriod);
        getIntegerParam(HDF5CurrentFrame, &currentFrame);
        setIntegerParam(ADStatus, ADStatusAcquire);
        callParamCallbacks();

        // Get information to allocate NDArray
        size_t dims[2];
        NDDataType_t dataType;
        if(getFrameInfo(currentFrame, dims, &dataType))
        {
            setStringParam(ADStatusMessage, "Failed to get frame info");
            goto error;
        }

        // Allocate NDArray
        NDArray *pImage;
        if(!(pImage = pNDArrayPool->alloc(2, dims, dataType, 0, NULL)))
        {
            setStringParam(ADStatusMessage, "Failed to allocate frame");
            goto error;
        }

        // Copy data into NDArray
        if(getFrameData(currentFrame, pImage->pData))
        {
            setStringParam(ADStatusMessage, "Failed to read frame data");
            goto error;
        }

        // Set ColorMode
        colorMode = NDColorModeMono;
        pImage->pAttributeList->add("ColorMode", "Color mode", NDAttrInt32,
                &colorMode);

        // Call plugins callbacks
        int arrayCallbacks;
        getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
        if (arrayCallbacks)
        {
          this->unlock();
          asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
                    "%s:%s: calling imageData callback\n",
                    driverName, functionName);
          doCallbacksGenericPointer(pImage, NDArrayData, 0);
          this->lock();
        }
        pImage->release();

        // Get the current parameters
        int lastFrame, imageCounter, numImages, numImagesCounter;
        getIntegerParam(HDF5LastFrame,      &lastFrame);
        getIntegerParam(NDArrayCounter,     &imageCounter);
        getIntegerParam(ADNumImages,        &numImages);
        getIntegerParam(ADNumImagesCounter, &numImagesCounter);

        setIntegerParam(NDArrayCounter,     ++imageCounter);
        setIntegerParam(ADNumImagesCounter, ++numImagesCounter);
        setIntegerParam(HDF5CurrentFrame,   ++currentFrame);

        // Put the frame number and time stamp into the buffer
        pImage->uniqueId = imageCounter;
        pImage->timeStamp = startTime.secPastEpoch + startTime.nsec / 1.e9;
        updateTimeStamp(&pImage->epicsTS);

        // Prepare loop if necessary
        int loop;
        getIntegerParam(HDF5Loop, &loop);

        if (loop && currentFrame > lastFrame)
        {
            getIntegerParam(HDF5FirstFrame,   &currentFrame);
            setIntegerParam(HDF5CurrentFrame, currentFrame);
        }

        // See if acquisition is done
        if (imageMode == ADImageSingle || currentFrame > lastFrame ||
            (imageMode == ADImageMultiple && numImagesCounter >= numImages))
        {
          // First do callback on ADStatus
          setStringParam(ADStatusMessage, "Waiting for acquisition");
          setIntegerParam(ADStatus, ADStatusIdle);

          acquire = 0;
          setIntegerParam(ADAcquire, acquire);

          asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
                  "%s:%s: acquisition completed\n",
                  driverName, functionName);
        }

        callParamCallbacks();

        // Delay next acquisition and check if received STOP signal
        if(acquire)
        {
            epicsTimeGetCurrent(&endTime);
            elapsedTime = epicsTimeDiffInSeconds(&endTime, &startTime);
            delay = acquirePeriod - elapsedTime;
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
                      "%s:%s: delay=%f\n",
                      driverName, functionName, delay);
            if(delay > 0.0)
            {
                // Set the status to waiting to indicate we are in the delay
                setIntegerParam(ADStatus, ADStatusWaiting);
                callParamCallbacks();
                this->unlock();
                status = epicsEventWaitWithTimeout(mStopEventId, delay);
                this->lock();

                if (status == epicsEventWaitOK)
                {
                    acquire = 0;
                    if (imageMode == ADImageContinuous)
                        setIntegerParam(ADStatus, ADStatusIdle);
                    else
                        setIntegerParam(ADStatus, ADStatusAborted);

                  callParamCallbacks();
                }
            }
        }
        continue;

error:
        setIntegerParam(ADAcquire, 0);
        setIntegerParam(ADStatus, ADStatusError);
        callParamCallbacks();
        continue;
    }
}
static int
mySend(epicsMessageQueueId pmsg, void *message, unsigned int size, bool wait, bool haveTimeout, double timeout)
{
    char *myInPtr, *nextPtr;
    struct threadNode *pthr;

    if(size > pmsg->maxMessageSize)
        return -1;

    /*
     * See if message can be sent
     */
    epicsMutexLock(pmsg->mutex);
    if ((pmsg->numberOfSendersWaiting > 0)
            || (pmsg->full && (ellFirst(&pmsg->receiveQueue) == NULL))) {
        /*
         * Return if not allowed to wait
         */
        if (!wait) {
            epicsMutexUnlock(pmsg->mutex);
            return -1;
        }

        /*
         * Wait
         */
        struct threadNode threadNode;
        threadNode.evp = getEventNode(pmsg);
        threadNode.eventSent = false;
        ellAdd(&pmsg->sendQueue, &threadNode.link);
        pmsg->numberOfSendersWaiting++;
        epicsMutexUnlock(pmsg->mutex);
        if(haveTimeout)
            epicsEventWaitWithTimeout(threadNode.evp->event, timeout);
        else
            epicsEventWait(threadNode.evp->event);
        epicsMutexLock(pmsg->mutex);
        if(!threadNode.eventSent)
            ellDelete(&pmsg->sendQueue, &threadNode.link);
        pmsg->numberOfSendersWaiting--;
        ellAdd(&pmsg->eventFreeList, &threadNode.evp->link);
        if (pmsg->full && (ellFirst(&pmsg->receiveQueue) == NULL)) {
            epicsMutexUnlock(pmsg->mutex);
            return -1;
        }
    }

    /*
     * Copy message to waiting receiver
     */
    if ((pthr = reinterpret_cast < struct threadNode * >
                ( ellGet(&pmsg->receiveQueue) ) ) != NULL) {
        if(size <= pthr->size)
            memcpy(pthr->buf, message, size);
        pthr->size = size;
        pthr->eventSent = true;
        epicsEventSignal(pthr->evp->event);
        epicsMutexUnlock(pmsg->mutex);
        return 0;
    }

    /*
     * Copy to queue
     */
    myInPtr = (char *)pmsg->inPtr;
    if (myInPtr == pmsg->lastMessageSlot)
        nextPtr = pmsg->firstMessageSlot;
    else
        nextPtr = myInPtr + pmsg->slotSize;
    if (nextPtr == (char *)pmsg->outPtr)
        pmsg->full = true;
    *(volatile unsigned long *)myInPtr = size;
    memcpy((unsigned long *)myInPtr + 1, message, size);
    pmsg->inPtr = nextPtr;
    epicsMutexUnlock(pmsg->mutex);
    return 0;
}
示例#18
0
文件: logClient.c 项目: ukaea/epics
/*
 * logClientDestroy
 */
static void logClientDestroy (logClientId id)
{
    enum epicsSocketSystemCallInterruptMechanismQueryInfo interruptInfo;
    logClient *pClient = (logClient *) id;
    epicsTimeStamp begin, current;
    double diff;

    /* command log client thread to shutdown - taking mutex here */
    /* forces cache flush on SMP machines */
    epicsMutexMustLock ( pClient->mutex );
    pClient->shutdown = 1u;
    epicsMutexUnlock ( pClient->mutex );

    /* unblock log client thread blocking in send() or connect() */
    interruptInfo =
        epicsSocketSystemCallInterruptMechanismQuery ();
    switch ( interruptInfo ) {
    case esscimqi_socketCloseRequired:
        logClientClose ( pClient );
        break;
    case esscimqi_socketBothShutdownRequired:
        shutdown ( pClient->sock, SHUT_WR );
        break;
    case esscimqi_socketSigAlarmRequired:
        epicsSignalRaiseSigAlarm ( pClient->restartThreadId );
        break;
    default:
        break;
    };

    /* wait for confirmation that the thread exited - taking */
    /* mutex here forces cache update on SMP machines */
    epicsTimeGetCurrent ( & begin );
    epicsMutexMustLock ( pClient->mutex );
    do {
        epicsMutexUnlock ( pClient->mutex );
        epicsEventWaitWithTimeout ( 
            pClient->stateChangeNotify, 
            LOG_SERVER_SHUTDOWN_TIMEOUT / 10.0 ); 
        epicsTimeGetCurrent ( & current );
        diff = epicsTimeDiffInSeconds ( & current, & begin );
        epicsMutexMustLock ( pClient->mutex );
    }
    while ( ! pClient->shutdownConfirm && diff < LOG_SERVER_SHUTDOWN_TIMEOUT );
    epicsMutexUnlock ( pClient->mutex );

    if ( ! pClient->shutdownConfirm ) {
        fprintf ( stderr, "log client shutdown: timed out stopping"
            " reconnect thread for \"%s\" after %.1f seconds - cleanup aborted\n",
            pClient->name, LOG_SERVER_SHUTDOWN_TIMEOUT );
        return;
    }

    logClientClose ( pClient );

    epicsMutexDestroy ( pClient->mutex );
   
    epicsEventDestroy ( pClient->stateChangeNotify );

    free ( pClient );
}
示例#19
0
文件: logClient.c 项目: ukaea/epics
/*
 *  logClientCreate()
 */
logClientId epicsShareAPI logClientCreate (
    struct in_addr server_addr, unsigned short server_port)
{
    epicsTimeStamp begin, current;
    logClient *pClient;
    double diff;

    pClient = calloc (1, sizeof (*pClient));
    if (pClient==NULL) {
        return NULL;
    }

    pClient->addr.sin_family = AF_INET;
    pClient->addr.sin_addr = server_addr;
    pClient->addr.sin_port = htons(server_port);
    ipAddrToDottedIP (&pClient->addr, pClient->name, sizeof(pClient->name));

    pClient->mutex = epicsMutexCreate ();
    if ( ! pClient->mutex ) {
        free ( pClient );
        return NULL;
    }

    pClient->sock = INVALID_SOCKET;
    pClient->connected = 0u;
    pClient->connFailStatus = 0;
    pClient->shutdown = 0;
    pClient->shutdownConfirm = 0;

    epicsAtExit (logClientDestroy, (void*) pClient);
    
    pClient->stateChangeNotify = epicsEventCreate (epicsEventEmpty);
    if ( ! pClient->stateChangeNotify ) {
        epicsMutexDestroy ( pClient->mutex );
        free ( pClient );
        return NULL;
    }
   
    pClient->restartThreadId = epicsThreadCreate (
        "logRestart", epicsThreadPriorityLow, 
        epicsThreadGetStackSize(epicsThreadStackSmall),
        logClientRestart, pClient );
    if ( pClient->restartThreadId == NULL ) {
        epicsMutexDestroy ( pClient->mutex );
        epicsEventDestroy ( pClient->stateChangeNotify );
        free (pClient);
        fprintf(stderr, "log client: unable to start log client connection watch dog thread\n");
        return NULL;
    }

    /*
     * attempt to synchronize with circuit connect
     */
    epicsTimeGetCurrent ( & begin );
    epicsMutexMustLock ( pClient->mutex );
    do {
        epicsMutexUnlock ( pClient->mutex );
        epicsEventWaitWithTimeout ( 
            pClient->stateChangeNotify, 
            LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT / 10.0 ); 
        epicsTimeGetCurrent ( & current );
        diff = epicsTimeDiffInSeconds ( & current, & begin );
        epicsMutexMustLock ( pClient->mutex );
    }
    while ( ! pClient->connected && diff < LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT );
    epicsMutexUnlock ( pClient->mutex );

    if ( ! pClient->connected ) {
        fprintf (stderr, "log client create: timed out synchronizing with circuit connect to \"%s\" after %.1f seconds\n",
            pClient->name, LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT );
    }
        
    return (void *) pClient;
}
 int NDPluginDLL::madSimCallback(genCamControllerEnum::callbackReasons reason, void *pp)
{

	genCamController* cam=(genCamController*)pp;
	int k;
	unsigned short valx;
	unsigned short *datax;

    NDDataType_t dataType;
    int binX, binY, minX, minY, sizeX, sizeY, reverseX, reverseY;
    int maxSizeX, maxSizeY;
    NDDimension_t dimsOut[2];
    NDArrayInfo_t arrayInfo;

	// which thread object is calling back.
	// need wither several callbacks, or we need to make this one threadsafe.
	int id;
    int status;
		NDArray *pImage;
		   int dims[2];

	//madSimPtr->lock();
	id=cam->getThisID();




//	pImage = madSimPtr->pArrays[0];

	switch (reason)
	{


		case genCamControllerEnum::general:
			madSimPtr->lock();
			madSimPtr->copyParamsFromDet(1);
			madSimPtr->callParamCallbacks();
			madSimPtr->unlock();
		break;

		case genCamControllerEnum::before_image:
			madSimPtr->lock();

			if (is_debug_mess)
				printf("before image callback\n");

    		madSimPtr->getIntegerParam(genCamControllerEnum::ADSizeX, &dims[0]);
    		madSimPtr->getIntegerParam(genCamControllerEnum::ADSizeY, &dims[1]);
    		madSimPtr->pRaw->release();

			if (is_debug_mess)
    			printf("released praw\n");

			do
			{
				madSimPtr->pRaw =
					madSimPtr->
						pNDArrayPool->
							alloc(2, dims, NDUInt16, 0, NULL);

				if (madSimPtr->pRaw == 0)
				{
			//		printf("Could not alloc NDArray, try again afte 1s\n");
					Sleep(1000);
					madSimPtr->setIntegerParam(
						genCamControllerEnum::ADStatus,
						genCamControllerEnum::ADStatusError);
				}

			} while((madSimPtr->pRaw)==0);


			if (is_debug_mess)
			{
				printf("allocated praw %i \n",(long)madSimPtr->pRaw->pData);
				//printf("references coiunts %i \n",madSimPtr->pRaw->referenceCount);
			}
			cam->putPtrParam(genCamControllerEnum::image_mem_ptr,madSimPtr->pRaw->pData);

			madSimPtr->unlock();

		break;

		case genCamControllerEnum::add_image_attribute:

			// must have called before_image callback to set pRaw to new NDARRAY
			madSimPtr->pRaw->pAttributeList->add(
				(const char *)cam->attribute_name,
				(const char *)cam->attribute_description,
                (NDAttrDataType_t)cam->attribute_datatype,
                cam->attribute_pvalue);


		break;



		case genCamControllerEnum::new_image:
			madSimPtr->lock();

			if (is_debug_mess)
			  printf("new image callback\n");

		      madSimPtr->getIntegerParam(genCamControllerEnum::ADBinX,         &binX);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADBinY,         &binY);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADMinX,         &minX);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADMinY,         &minY);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADSizeX,        &sizeX);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADSizeY,        &sizeY);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADReverseX,     &reverseX);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADReverseY,     &reverseY);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADMaxSizeX,     &maxSizeX);
		      madSimPtr->getIntegerParam(genCamControllerEnum::ADMaxSizeY,     &maxSizeY);
		      madSimPtr->getIntegerParam(genCamControllerEnum::NDDataType,     (int *)&dataType);


		     /* Extract the region of interest with binning.
		       * If the entire image is being used (no ROI or binning) that's OK because
		       * convertImage detects that case and is very efficient */
		      madSimPtr->pRaw->initDimension(&dimsOut[0], sizeX);
		      dimsOut[0].binning = binX;
		      dimsOut[0].offset = minX;
		      dimsOut[0].reverse = reverseX;
		      madSimPtr->pRaw->initDimension(&dimsOut[1], sizeY);
		      dimsOut[1].binning = binY;
		      dimsOut[1].offset = minY;
		      dimsOut[1].reverse = reverseY;
		      /* We save the most recent image buffer so it can be used in the read() function.
		       * Now release it before getting a new version. */
		     // if (madSimPtr->pArrays[0]) madSimPtr->pArrays[0]->release();
			if (is_debug_mess)
				printf("mem ptr %i\n",(long)(madSimPtr->pRaw->pData));

			if (is_debug_mess)
				for (k=0;k<16;k++)
				{
					datax= (unsigned short *)(madSimPtr->pRaw->pData);
					valx = datax[k * sizeX*sizeY / 16];
					printf("pRaw data %i %i \n", k * sizeX*sizeY / 16, valx);
				}

			madSimPtr->pRaw->dims[0].size=sizeX;
			madSimPtr->pRaw->dims[0].offset=minX;
			madSimPtr->pRaw->dims[0].binning=binX;
			madSimPtr->pRaw->dims[0].reverse=reverseX;

			madSimPtr->pRaw->dims[1].size=sizeY;
			madSimPtr->pRaw->dims[1].offset=minY;
			madSimPtr->pRaw->dims[1].binning=binY;
			madSimPtr->pRaw->dims[1].reverse=reverseY;
//			madSimPtr->pRaw->dataSize = sizeY*sizeX*sizeof(unsigned short);
			madSimPtr->pRaw->dataType = NDUInt16;
			madSimPtr->pRaw->uniqueId=img_dumb_count;
			img_dumb_count++;




			//epicsMutexUnlock(madSimPtr->mutexId);
		// madSimPtr->doCallbacksGenericPointer(madSimPtr->pArrays[0], NDArrayData, 0);
		 madSimPtr->doCallbacksGenericPointer(madSimPtr->pRaw, madSimPtr->NDArrayDataPub, 0);

		//for (k=0; k<10; k++)
		//   printf(" %i ", * ((unsigned short *)(pImage->pData) +k));
			madSimPtr->callParamCallbacks();

		if (is_debug_mess)
			 printf("image callback done\n");

			madSimPtr->unlock();

		break;

		case genCamControllerEnum::make_new_thread:
			madSimPtr->lock();
			thread_suspend_counters[id] = 0;
		    thread_name[id]=new char[128];
		    sprintf(thread_name[id],"Thread %i",id);
		 /* Create the thread that updates the images */
		    status = (epicsThreadCreate(thread_name[id],
		                                epicsThreadPriorityMedium,
		                                epicsThreadGetStackSize(epicsThreadStackMedium),
		                                (EPICSTHREADFUNC)madTaskC,
		                                cam) == NULL);
		    if (status)
		        {
		        printf("epicsThreadCreate failure for image task\n");

    			}
    		else
    		 //printf("Thread Created\n");



			resume_event[id]= epicsEventCreate(epicsEventEmpty);

			if (!resume_event[id])
		        printf("epicsEventCreate failure for stop event\n");
       		else
    		 //printf("Epics Event Created\n");

			madSimPtr->unlock();
		break;

		case genCamControllerEnum::exiting:

		break;

		case genCamControllerEnum::grab_mutex:
				madSimPtr->lock();
//		        epicsMutexLock(madSimPtr->mutexId);


		break;

		case genCamControllerEnum::release_mutex:
			madSimPtr->unlock();
//                epicsMutexUnlock(madSimPtr->mutexId);

		break;

		case genCamControllerEnum::call_error:

		break;

		case genCamControllerEnum::thread_suspend:
			// a resume event incs counter. if the thread is not suspended it does not
			// need to be woken up./ If we get resume event, then thread suspends it may suspend
			// forever. IN this way we dont miss resume events.
		 // thread_suspend_counters[id]=thread_suspend_counters[id]-1;

		  //if (thread_suspend_counters[id] < 0)
		  //	thread_suspend_counters[id] = 0;

		  //if (thread_suspend_counters[id]<=0)// this way we dont miss wake up events
		     //epicsEventWait(resume_event[id]);
		     // cannot suspend for more than 20sec
		     epicsEventWaitWithTimeout(resume_event[id],  ((double)(cam->sleepy_time))/1000.0 );

		break;

		case genCamControllerEnum::thread_resume:
			//thread_suspend_counters[id] = thread_suspend_counters[id]+1;
			epicsEventSignal(resume_event[id]);

		break;

		case genCamControllerEnum::wakeup_everyone:

			for (k = 0; k<madSimPtr->num_controllers; k++)
			{
				epicsEventSignal(resume_event[ madSimPtr->controllers[k]->getThisID()  ]);
				//thread_suspend_counters[ madSimPtr->controllers[k]->getThisID()] =
				//	thread_suspend_counters[ madSimPtr->controllers[k]->getThisID() ]+1;
			}


		break;

		case genCamControllerEnum::sleep:
			// need the epics sleep!!
			epicsThreadSleep( ((double)(cam->sleepy_time))/1000.0 );
			// in this way it can be awakened by a signal.
			//epicsEventWaitWithTimeout(resume_event[id],((double)(cam->sleepy_time))/1000.0 );


		default:
		break;

	}
	//madSimPtr->unlock();

  return 0;
}
示例#21
0
/** This thread computes new image data and does the callbacks to send it to higher layers */
void roper::roperTask()
{
    int status = asynSuccess;
    int imageCounter;
    int numAcquisitions, numAcquisitionsCounter;
    int imageMode;
    int arrayCallbacks;
    int acquire, autoSave;
    NDArray *pImage;
    double acquireTime, acquirePeriod, delay;
    epicsTimeStamp startTime, endTime;
    double elapsedTime;
    const char *functionName = "roperTask";
    VARIANT varArg;
    IDispatch *pDocFileDispatch;
    HRESULT hr;

    /* Initialize the COM system for this thread */
    hr = INITIALIZE_COM;
    if (hr == S_FALSE) {
        /* COM was already initialized for this thread */
        CoUninitialize();
    } else if (hr != S_OK) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
            "%s:%s: error initializing COM\n",
            driverName, functionName);
    }
    VariantInit(&varArg);

    this->lock();
    /* Loop forever */
    while (1) {
        /* Is acquisition active? */
        getIntegerParam(ADAcquire, &acquire);
        
        /* If we are not acquiring then wait for a semaphore that is given when acquisition is started */
        if (!acquire) {
            setIntegerParam(ADStatus, ADStatusIdle);
            callParamCallbacks();
            /* Release the lock while we wait for an event that says acquire has started, then lock again */
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s:%s: waiting for acquire to start\n", driverName, functionName);
            this->unlock();
            status = epicsEventWait(this->startEventId);
            this->lock();
            getIntegerParam(ADAcquire, &acquire);
            setIntegerParam(RoperNumAcquisitionsCounter, 0);
        }
        
        /* We are acquiring. */
        /* Get the current time */
        epicsTimeGetCurrent(&startTime);
        
        /* Get the exposure parameters */
        getDoubleParam(ADAcquireTime, &acquireTime);
        getDoubleParam(ADAcquirePeriod, &acquirePeriod);
        getIntegerParam(ADImageMode, &imageMode);
        getIntegerParam(RoperNumAcquisitions, &numAcquisitions);
        
        setIntegerParam(ADStatus, ADStatusAcquire);
        
        /* Open the shutter */
        setShutter(ADShutterOpen);

        /* Call the callbacks to update any changes */
        callParamCallbacks();

        try {
            /* Collect the frame(s) */
            /* Stop current exposure, if any */
            this->pExpSetup->Stop();
            this->pDocFile->Close();
            switch (imageMode) {
                case RoperImageNormal:
                case RoperImageContinuous:
                    pDocFileDispatch = pExpSetup->Start2(&varArg);
                    break;
                case RoperImageFocus:
                    pDocFileDispatch = pExpSetup->StartFocus2(&varArg);
                    break;
            }
            pDocFile->AttachDispatch(pDocFileDispatch);

            /* Wait for acquisition to complete, but allow acquire stop events to be handled */
            while (1) {
                this->unlock();
                status = epicsEventWaitWithTimeout(this->stopEventId, ROPER_POLL_TIME);
                this->lock();
                if (status == epicsEventWaitOK) {
                    /* We got a stop event, abort acquisition */
                    this->pExpSetup->Stop();
                    acquire = 0;
                } else {
                    acquire = this->getAcquireStatus();
                }
                if (!acquire) {
                    /* Close the shutter */
                    setShutter(ADShutterClosed);
                    break;
                }
            }
        }
        catch(CException *pEx) {
            pEx->GetErrorMessage(this->errorMessage, sizeof(this->errorMessage));
            asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s: exception = %s\n", 
                driverName, functionName, this->errorMessage);
            pEx->Delete();
        }
        
        /* Get the current parameters */
        getIntegerParam(NDAutoSave,         &autoSave);
        getIntegerParam(NDArrayCounter,     &imageCounter);
        getIntegerParam(RoperNumAcquisitionsCounter, &numAcquisitionsCounter);
        getIntegerParam(NDArrayCallbacks,   &arrayCallbacks);
        imageCounter++;
        numAcquisitionsCounter++;
        setIntegerParam(NDArrayCounter, imageCounter);
        setIntegerParam(RoperNumAcquisitionsCounter, numAcquisitionsCounter);
        
        if (arrayCallbacks) {
            /* Get the data from the DocFile */
            pImage = this->getData();
            if (pImage)  {
                /* Put the frame number and time stamp into the buffer */
                pImage->uniqueId = imageCounter;
                pImage->timeStamp = startTime.secPastEpoch + startTime.nsec / 1.e9;
                /* Get any attributes that have been defined for this driver */        
                this->getAttributes(pImage->pAttributeList);
                /* Call the NDArray callback */
                /* Must release the lock here, or we can get into a deadlock, because we can
                 * block on the plugin lock, and the plugin can be calling us */
                this->unlock();
                asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                     "%s:%s: calling imageData callback\n", driverName, functionName);
                doCallbacksGenericPointer(pImage, NDArrayData, 0);
                this->lock();
                pImage->release();
            }
        }
        
        /* See if we should save the file */
        if ((imageMode != RoperImageFocus) && autoSave) {
            setIntegerParam(ADStatus, ADStatusSaving);
            callParamCallbacks();
            this->saveFile();
            callParamCallbacks();
        }
        
        /* See if acquisition is done */
        if ((imageMode == RoperImageFocus) ||
            ((imageMode == RoperImageNormal) && 
             (numAcquisitionsCounter >= numAcquisitions))) {
            setIntegerParam(ADAcquire, 0);
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                  "%s:%s: acquisition completed\n", driverName, functionName);
        }
        
        /* Call the callbacks to update any changes */
        callParamCallbacks();
        getIntegerParam(ADAcquire, &acquire);
        
        /* If we are acquiring then sleep for the acquire period minus elapsed time. */
        if (acquire) {
            epicsTimeGetCurrent(&endTime);
            elapsedTime = epicsTimeDiffInSeconds(&endTime, &startTime);
            delay = acquirePeriod - elapsedTime;
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                     "%s:%s: delay=%f\n",
                      driverName, functionName, delay);            
            if (delay >= 0.0) {
                /* We set the status to indicate we are in the period delay */
                setIntegerParam(ADStatus, ADStatusWaiting);
                callParamCallbacks();
                this->unlock();
                status = epicsEventWaitWithTimeout(this->stopEventId, delay);
                this->lock();
            }
        }
    }
}
示例#22
0
int main (int argc, char *argv[])
{
    int i;
    int result;                 /* CA result */
    OutputT format = plain;     /* User specified format */
    RequestT request = get;     /* User specified request type */
    int isArray = 0;            /* Flag for array operation */
    int enumAsString = 0;       /* Force ENUM values to be strings */

    int count = 1;
    int opt;                    /* getopt() current option */
    chtype dbrType = DBR_STRING;
    char *pend;
    EpicsStr *sbuf;
    double *dbuf;
    char *cbuf = 0;
    char *ebuf = 0;
    void *pbuf;
    int len = 0;
    int waitStatus;
    struct dbr_gr_enum bufGrEnum;

    int nPvs;                   /* Number of PVs */
    pv* pvs;                /* Array of PV structures */

    LINE_BUFFER(stdout);        /* Configure stdout buffering */
    putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */

    while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
        switch (opt) {
        case 'h':               /* Print usage */
            usage();
            return 0;
        case 'n':               /* Force interpret ENUM as index number */
            enumAsNr = 1;
            enumAsString = 0;
            break;
        case 's':               /* Force interpret ENUM as menu string */
            enumAsString = 1;
            enumAsNr = 0;
            break;
        case 'S':               /* Treat char array as (long) string */
            charArrAsStr = 1;
            isArray = 0;
            break;
        case 't':               /* Select terse output format */
            format = terse;
            break;
        case 'l':               /* Select long output format */
            format = all;
            break;
        case 'a':               /* Select array mode */
            isArray = 1;
            charArrAsStr = 0;
            break;
        case 'c':               /* Select put_callback mode */
            request = callback;
            break;
        case 'w':               /* Set CA timeout value */
            if(epicsScanDouble(optarg, &caTimeout) != 1)
            {
                fprintf(stderr, "'%s' is not a valid timeout value "
                        "- ignored. ('caput -h' for help.)\n", optarg);
                caTimeout = DEFAULT_TIMEOUT;
            }
            break;
        case '#':               /* Array count */
            if (sscanf(optarg,"%d", &count) != 1)
            {
                fprintf(stderr, "'%s' is not a valid array element count "
                        "- ignored. ('caput -h' for help.)\n", optarg);
                count = 0;
            }
            break;
        case 'p':               /* CA priority */
            if (sscanf(optarg,"%u", &caPriority) != 1)
            {
                fprintf(stderr, "'%s' is not a valid CA priority "
                        "- ignored. ('caget -h' for help.)\n", optarg);
                caPriority = DEFAULT_CA_PRIORITY;
            }
            if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX;
            break;
        case 'F':               /* Store this for output and tool_lib formatting */
            fieldSeparator = (char) *optarg;
            break;
        case '?':
            fprintf(stderr,
                    "Unrecognized option: '-%c'. ('caput -h' for help.)\n",
                    optopt);
            return 1;
        case ':':
            fprintf(stderr,
                    "Option '-%c' requires an argument. ('caput -h' for help.)\n",
                    optopt);
            return 1;
        default :
            usage();
            return 1;
        }
    }

    nPvs = argc - optind;       /* Remaining arg list are PV names and values */

    if (nPvs < 1) {
        fprintf(stderr, "No pv name specified. ('caput -h' for help.)\n");
        return 1;
    }
    if (nPvs == 1) {
        fprintf(stderr, "No value specified. ('caput -h' for help.)\n");
        return 1;
    }

    nPvs = 1;                   /* One PV - the rest is value(s) */

    epId = epicsEventCreate(epicsEventEmpty);  /* Create empty EPICS event (semaphore) */

                                /* Start up Channel Access */

    result = ca_context_create(ca_enable_preemptive_callback);
    if (result != ECA_NORMAL) {
        fprintf(stderr, "CA error %s occurred while trying "
                "to start channel access.\n", ca_message(result));
        return 1;
    }
                                /* Allocate PV structure array */

    pvs = calloc (nPvs, sizeof(pv));
    if (!pvs) {
        fprintf(stderr, "Memory allocation for channel structure failed.\n");
        return 1;
    }
                                /* Connect channels */

    pvs[0].name = argv[optind] ;   /* Copy PV name from command line */

    result = connect_pvs(pvs, nPvs); /* If the connection fails, we're done */
    if (result) {
        ca_context_destroy();
        return result;
    }

                                /* Get values from command line */
    optind++;

    if (isArray) {
        optind++;               /* In case of array skip first value (nr
                                 * of elements) - actual number of values is used */
        count = argc - optind;

    } else {                    /* Concatenate the remaining line to one string
                                 * (sucks but is compatible to the former version) */
        for (i = optind; i < argc; i++) {
            len += strlen(argv[i]);
            len++;
        }
        cbuf = calloc(len, sizeof(char));
        if (!cbuf) {
            fprintf(stderr, "Memory allocation failed.\n");
            return 1;
        }
        strcpy(cbuf, argv[optind]);

        if (argc > optind+1) {
            for (i = optind + 1; i < argc; i++) {
                strcat(cbuf, " ");
                strcat(cbuf, argv[i]); 
            }
        }

        if ((argc - optind) >= 1)
            count = 1;
        argv[optind] = cbuf;
    }

    sbuf = calloc (count, sizeof(EpicsStr));
    dbuf = calloc (count, sizeof(double));
    if(!sbuf || !dbuf) {
        fprintf(stderr, "Memory allocation failed\n");
        return 1;
    }

                                /*  ENUM? Special treatment */

    if (ca_field_type(pvs[0].chid) == DBR_ENUM) {

                                /* Get the ENUM strings */

        result = ca_array_get (DBR_GR_ENUM, 1, pvs[0].chid, &bufGrEnum);
        result = ca_pend_io(caTimeout);
        if (result == ECA_TIMEOUT) {
            fprintf(stderr, "Read operation timed out: ENUM data was not read.\n");
            return 1;
        }

        if (enumAsNr) {         /* Interpret values as numbers */

            for (i = 0; i < count; ++i) {
                dbuf[i] = epicsStrtod(*(argv+optind+i), &pend);
                if (*(argv+optind+i) == pend) { /* Conversion didn't work */
                    fprintf(stderr, "Enum index value '%s' is not a number.\n",
                            *(argv+optind+i));
                    return 1;
                }
                if (dbuf[i] >= bufGrEnum.no_str) {
                    fprintf(stderr, "Warning: enum index value '%s' may be too large.\n",
                            *(argv+optind+i));
                }
            }
            dbrType = DBR_DOUBLE;

        } else {                /* Interpret values as strings */

            for (i = 0; i < count; ++i) {
                epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
                *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
                dbrType = DBR_STRING;

                                /* Compare to ENUM strings */
                for (len = 0; len < bufGrEnum.no_str; len++)
                    if (!strcmp(sbuf[i], bufGrEnum.strs[len]))
                        break;

                if (len >= bufGrEnum.no_str) {
                                         /* Not a string? Try as number */
                    dbuf[i] = epicsStrtod(sbuf[i], &pend);
                    if (sbuf[i] == pend || enumAsString) {
                        fprintf(stderr, "Enum string value '%s' invalid.\n", sbuf[i]);
                        return 1;
                    }
                    if (dbuf[i] >= bufGrEnum.no_str) {
                        fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", sbuf[i]);
                    }
                    dbrType = DBR_DOUBLE;
                }
            }
        }

    } else {                    /* Not an ENUM */

        if (charArrAsStr) {
            dbrType = DBR_CHAR;
            ebuf = calloc(len, sizeof(char));
            if(!ebuf) {
                fprintf(stderr, "Memory allocation failed\n");
                return 1;
            }
            count = epicsStrnRawFromEscaped(ebuf, len, cbuf, len-1) + 1;
        } else {
            for (i = 0; i < count; ++i) {
                epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));
                *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0';
            }
            dbrType = DBR_STRING;
        }
    }

                                /* Read and print old data */
    if (format != terse) {
        printf("Old : ");
        result = caget(pvs, nPvs, format, 0, 0);
    }

                                /* Write new data */
    if (dbrType == DBR_STRING) pbuf = sbuf;
    else if (dbrType == DBR_CHAR) pbuf = ebuf;
    else pbuf = dbuf;

    if (request == callback) {
        /* Use callback version of put */
        pvs[0].status = ECA_NORMAL;   /* All ok at the moment */
        result = ca_array_put_callback (
            dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *) pvs);
    } else {
        /* Use standard put with defined timeout */
        result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
    }
    result = ca_pend_io(caTimeout);
    if (result == ECA_TIMEOUT) {
        fprintf(stderr, "Write operation timed out: Data was not written.\n");
        return 1;
    }
    if (request == callback) {   /* Also wait for callbacks */
        waitStatus = epicsEventWaitWithTimeout( epId, caTimeout );
        if (waitStatus)
            fprintf(stderr, "Write callback operation timed out\n");

        /* retrieve status from callback */
        result = pvs[0].status;
    }

    if (result != ECA_NORMAL) {
        fprintf(stderr, "Error occured writing data.\n");
        return 1;
    }

                                /* Read and print new data */
    if (format != terse)
        printf("New : ");

    result = caget(pvs, nPvs, format, 0, 0);

                                /* Shut down Channel Access */
    ca_context_destroy();

    return result;
}
static int
myReceive(epicsMessageQueueId pmsg, void *message, unsigned int size, bool wait, bool haveTimeout, double timeout)
{
    char *myOutPtr;
    unsigned long l;
    struct threadNode *pthr;

    /*
     * If there's a message on the queue, copy it
     */
    epicsMutexLock(pmsg->mutex);
    myOutPtr = (char *)pmsg->outPtr;
    if ((myOutPtr != pmsg->inPtr) || pmsg->full) {
        int ret;
        l = *(unsigned long *)myOutPtr;
        if (l <= size) {
            memcpy(message, (unsigned long *)myOutPtr + 1, l);
            ret = l;
        }
        else {
            ret = -1;
        }
        if (myOutPtr == pmsg->lastMessageSlot)
            pmsg->outPtr = pmsg->firstMessageSlot;
        else
            pmsg->outPtr += pmsg->slotSize;
        pmsg->full = false;

        /*
         * Wake up the oldest task waiting to send
         */
        if ((pthr = reinterpret_cast < struct threadNode * >
                    ( ellGet(&pmsg->sendQueue) ) ) != NULL) {
            pthr->eventSent = true;
            epicsEventSignal(pthr->evp->event);
        }
        epicsMutexUnlock(pmsg->mutex);
        return ret;
    }

    /*
     * Return if not allowed to wait
     */
    if (!wait) {
        epicsMutexUnlock(pmsg->mutex);
        return -1;
    }

    /*
     * Wake up the oldest task waiting to send
     */
    if ((pthr = reinterpret_cast < struct threadNode * >
                ( ellGet(&pmsg->sendQueue) ) ) != NULL) {
        pthr->eventSent = true;
        epicsEventSignal(pthr->evp->event);
    }

    /*
     * Wait for message to arrive
     */
    struct threadNode threadNode;
    threadNode.evp = getEventNode(pmsg);
    threadNode.buf = message;
    threadNode.size = size;
    threadNode.eventSent = false;
    ellAdd(&pmsg->receiveQueue, &threadNode.link);
    epicsMutexUnlock(pmsg->mutex);
    if(haveTimeout)
        epicsEventWaitWithTimeout(threadNode.evp->event, timeout);
    else
        epicsEventWait(threadNode.evp->event);
    epicsMutexLock(pmsg->mutex);
    if(!threadNode.eventSent)
        ellDelete(&pmsg->receiveQueue, &threadNode.link);
    ellAdd(&pmsg->eventFreeList, &threadNode.evp->link);
    epicsMutexUnlock(pmsg->mutex);
    if(threadNode.eventSent && (threadNode.size <= size))
        return threadNode.size;
    return -1;
}
示例#24
0
/** This thread is woken up by an interrupt or a request to read status
  * It loops calling readFIFO until acquiring_ goes to false.
  * readFIFO only reads a limited amount of FIFO data at once in order
  * to avoid blocking the device support threads. */
void drvSIS3801::readFIFOThread()
{
  int count;
  int signal;
  int chan;
  int nChans;
  int status;
  int i;
  bool acquiring;  // We have a separate flag because we need to continue processing one last
                   // time even if acquiring_ goes to false because acquisition was manually stopped
  epicsUInt32 scalerPresets[SIS38XX_MAX_SIGNALS];
  epicsUInt32 *pOut=NULL;
  epicsTimeStamp t1, t2;
  static const char* functionName="readFIFOThread";

  while(true)
  {
    epicsEventWait(readFIFOEventId_);
    // We got an event, which can come from acquisition starting, or FIFO full interrupt
    asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
              "%s:%s: got readFIFOEvent, eventType=%d, interrupt status=0x%8.8x\n",
              driverName, functionName, eventType_, registers_->csr_reg & 0xFFF00000);
    lock();
    acquiring = acquiring_;
    unlock();
    while (acquiring) {
      lock();
      for (i=0; i<maxSignals_; i++) 
        getIntegerParam(i, scalerPresets_, (int *)&scalerPresets[i]);
      getIntegerParam(mcaNumChannels_, &nChans);
      asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
                "%s:%s: scaler presets[0]=%d, scalerData[0]=%d\n",
                driverName, functionName, scalerPresets[0], scalerData_[0]);
      signal = nextSignal_;
      chan = nextChan_;
      count = 0;
      // This block of code can be slow and does not require the asynPortDriver lock because we are not
      // accessing object data that could change.  
      // It does require the FIFO lock so no one resets the FIFO while it executes
      epicsMutexLock(fifoLockId_);
      unlock();
      epicsTimeGetCurrent(&t1);

      /* Read out FIFO. It would be more efficient not to check the empty
       * flag on each transfer, using the almost empty flag.  But this has gotten
       * too complex, and is unlikely to save time on new boards with lots of
       * memory.
       */
      if (acquireMode_== ACQUIRE_MODE_MCS) {
        // Copy the data from the FIFO to the mcsBuffer
        pOut = mcsData_ + signal*maxChans_ + chan;
        asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
                  "%s:%s: pOut=%p, signal=%d, chan=%d\n",
                  driverName, functionName, pOut, signal, chan);
        while (((registers_->csr_reg & STATUS_M_FIFO_FLAG_EMPTY)==0) && (chan < nChans) && acquiring_) {
          *pOut = registers_->fifo_reg;
          signal++;
          count++;
          if (signal >= maxSignals_) {
            signal = 0;
            chan++;
            pOut = mcsData_ + chan;
          } else {
            pOut += maxChans_;
          }
        }
      } else if (acquireMode_ == ACQUIRE_MODE_SCALER) {
        while ((registers_->csr_reg & STATUS_M_FIFO_FLAG_EMPTY)==0 && acquiring_) {
          scalerData_[signal] += registers_->fifo_reg;
          signal++;
          count++;
          if (signal >= maxSignals_) {
            for (i=0; i<maxSignals_; i++) {
              if ((scalerPresets[i] != 0) && 
                  (scalerData_[i] >= scalerPresets[i]))
                acquiring = false;
            }
            asynPrintIO(pasynUserSelf, ASYN_TRACEIO_DRIVER, 
                      (const char*)scalerData_, maxSignals_*sizeof(epicsUInt32), 
                      "%s:%s:\n",
                      driverName, functionName);
            if (!acquiring) break;
            signal = 0;
          }
        }
      }
      epicsTimeGetCurrent(&t2);

      asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s:%s: read FIFO (%d) in %fs, acquiring=%d\n",
                driverName, functionName, count, epicsTimeDiffInSeconds(&t2, &t1), acquiring_);
      // Release the FIFO lock, we are done accessing the FIFO
      epicsMutexUnlock(fifoLockId_);
      
      // Take the lock since we are now changing object data
      lock();
      nextChan_ = chan;
      nextSignal_ = signal;
      if (acquireMode_ == ACQUIRE_MODE_MCS) {
        asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
                  "%s:%s: pOut=%p,signal=%d, chan=%d\n",
                  driverName, functionName, pOut, signal, chan);
        checkMCSDone();
      } else if (acquireMode_ == ACQUIRE_MODE_SCALER) {
        if (!acquiring) acquiring_ = false;
        if (!acquiring_) {
          asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
                    "%s:%s: scaler done, doing callbacks\n",
                    driverName, functionName);
          stopScaler();
          setIntegerParam(scalerDone_, 1);
          callParamCallbacks();
        }
      }
      /* Reenable interrupts in case we were woken up by an interrupt for FIFO almost full */
      enableInterrupts();
      acquiring = acquiring_;
      // Release the lock
      unlock();
      // If we are still acquiring then sleep for a short time, but wake up if there is an interrupt
      if (acquiring) {
        status = epicsEventWaitWithTimeout(readFIFOEventId_, epicsThreadSleepQuantum());
        if (status == epicsEventWaitOK) 
          asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
                    "%s:%s: got interrupt in epicsEventWaitWithTimeout, eventType=%d\n",
                    driverName, functionName, eventType_);
      }
    }  
  }
}
示例#25
0
int main(int argc,char **argv)
{
    char   *pval;
    double sleepSecs = 0.0;
    int	    clearEvery = 0;
    int     indValue = 1;
    int     indNumberCallback = 1;

    while((argc>1) && (argv[1][0] == '-')) {
        int i;
        char option;
        int  narg;
        option = toupper((argv[1])[1]);
        pval = argv[2];
        argc -= 1; narg = 1;
        if(option=='S') {
            sscanf(pval,"%lf",&sleepSecs);
            argc -= 1; ++narg;
        } else if(option=='C') {
            sscanf(pval,"%d",&clearEvery);
            argc -= 1; ++narg;
        } else if(option=='V') {
            verbose = 1;
        } else {
            usageExit();
        }
        for(i=1; i<argc; i++) argv[i] = argv[i + narg];
    }

    if(argc != 4) usageExit();
    pvname = argv[1];
    pvalue1 = argv[2];
    pvalue2 = argv[3];
    pevent = epicsEventCreate(epicsEventEmpty);
    SEVCHK(ca_context_create(ca_enable_preemptive_callback),
        "ca_task_initialize");
    while(1) {
        SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect");
        if(ca_pend_io(3.0)!=ECA_NORMAL) {
            epicsThreadSleep(5.0);
            continue;
        }
        while(1) {
            epicsEventWaitStatus status;
            if(indValue==0) {
                indValue = 1; pvalue = pvalue2;
            } else {
                indValue = 0; pvalue=pvalue1;
            }
            if(++indNumberCallback >= MAXnumberCallback) indNumberCallback=0;
            numberCallback[indNumberCallback] = ++expectedCallback;
            status = ca_array_put_callback(DBR_STRING,1,mychid,
                pvalue,putCallback,&numberCallback[indNumberCallback]);
            if(status!=ECA_NORMAL) {
                printf("ca_array_put_callback %s\n",ca_message(status));
                epicsThreadSleep(2.0);
                continue;
            }
            if((clearEvery>0) 
            && ((expectedCallback % clearEvery)==0)) {
                ca_flush_io();
                epicsThreadSleep(sleepSecs);
                SEVCHK(ca_clear_channel(mychid),"ca_clear_channel");
                ca_flush_io();
                expectedCallback = 0;
                epicsThreadSleep(sleepSecs);
                if(verbose) {
                    printTime();
                    printf("Issued ca_clear_channel expectedCallback %d\n",
                        expectedCallback);
                }
                break;
            }
            ca_flush_io();
            if(verbose) {
                printTime();
                printf("Issued ca_put_callback expectedCallback %d\n",
                    expectedCallback);
            }
            while(1) {
                status = epicsEventWaitWithTimeout(pevent,10.0);
                if(status==epicsEventWaitTimeout) {
                    if(verbose) {
                        printTime();
                        printf("timeout after 10 seconds\n");
                    }
                    continue;
                }
                break;
            }
            if(status!=epicsEventWaitOK) {
                int i;
                printTime();
                printf("eventWait status %d\n",status);
                for(i=0; i<MAXnumberCallback; i++) numberCallback[i]=0;
            }
            epicsThreadSleep(sleepSecs);
        }
    }
    ca_task_exit();
    return(0);
}
示例#26
0
/*
 * Get value from a channel.
 * TODO: add optional timeout argument.
 */
epicsShareFunc pvStat epicsShareAPI seq_pvGet(SS_ID ss, VAR_ID varId, enum compType compType)
{
	SPROG		*sp = ss->sprog;
	CHAN		*ch = sp->chan + varId;
	pvStat		status;
	PVREQ		*req;
	epicsEventId	getSem = ss->getSemId[varId];
	DBCHAN		*dbch = ch->dbch;
	PVMETA		*meta = metaPtr(ch,ss);
	double		tmo = seq_sync_timeout;

	/* Anonymous PV and safe mode, just copy from shared buffer.
	   Note that completion is always immediate, so no distinction
	   between SYNC and ASYNC needed. See also pvGetComplete. */
	if ((sp->options & OPT_SAFE) && !dbch)
	{
		/* Copy regardless of whether dirty flag is set or not */
		ss_read_buffer(ss, ch, FALSE);
		return pvStatOK;
	}
	/* No named PV and traditional mode => user error */
	if (!dbch)
	{
		errlogSevPrintf(errlogMajor,
			"pvGet(%s): user error (variable not assigned)\n",
			ch->varName
		);
		return pvStatERROR;
	}

	if (compType == DEFAULT)
	{
		compType = (sp->options & OPT_ASYNC) ? ASYNC : SYNC;
	}

	if (compType == SYNC)
	{
		double before, after;
		pvTimeGetCurrentDouble(&before);
		switch (epicsEventWaitWithTimeout(getSem, tmo))
		{
		case epicsEventWaitOK:
			status = check_connected(dbch, meta);
			if (status) return epicsEventSignal(getSem), status;
			pvTimeGetCurrentDouble(&after);
			tmo -= (after - before);
			break;
		case epicsEventWaitTimeout:
			errlogSevPrintf(errlogMajor,
				"pvGet(ss %s, var %s, pv %s): failed (timeout "
				"waiting for other get requests to finish)\n",
				ss->ssName, ch->varName, dbch->dbName
			);
			return pvStatERROR;
		case epicsEventWaitError:
			/* try to recover */
			ss->getReq[varId] = NULL;
			epicsEventSignal(getSem);
			errlogSevPrintf(errlogFatal,
				"pvGet: epicsEventWaitWithTimeout() failure\n");
			return pvStatERROR;
		}
	}
	else if (compType == ASYNC)
	{
		switch (epicsEventTryWait(getSem))
		{
		case epicsEventWaitOK:
			if (ss->getReq[varId] != NULL)
			{
				/* previous request timed out but user
				   did not call pvGetComplete */
				ss->getReq[varId] = NULL;
			}
			status = check_connected(dbch, meta);
			if (status) return epicsEventSignal(getSem), status;
			break;
		case epicsEventWaitTimeout:
			errlogSevPrintf(errlogMajor,
				"pvGet(ss %s, var %s, pv %s): user error "
				"(there is already a get pending for this variable/"
				"state set combination)\n",
				ss->ssName, ch->varName, dbch->dbName
			);
			return pvStatERROR;
		case epicsEventWaitError:
			/* try to recover */
			ss->getReq[varId] = NULL;
			epicsEventSignal(getSem);
			errlogSevPrintf(errlogFatal,
				"pvGet: epicsEventTryWait() failure\n");
			return pvStatERROR;
		}
	}

	/* Allocate and initialize a pv request */
	req = (PVREQ *)freeListMalloc(sp->pvReqPool);
	req->ss = ss;
	req->ch = ch;

	assert(ss->getReq[varId] == NULL);
	ss->getReq[varId] = req;

	/* Perform the PV get operation with a callback routine specified.
	   Requesting more than db channel has available is ok. */
	status = pvVarGetCallback(
			dbch->pvid,		/* PV id */
			ch->type->getType,	/* request type */
			ch->count,		/* element count */
			seq_get_handler,	/* callback handler */
			req);			/* user arg */
	if (status != pvStatOK)
	{
		meta->status = pvStatERROR;
		meta->severity = pvSevrMAJOR;
		meta->message = "get failure";
		errlogSevPrintf(errlogFatal, "pvGet(var %s, pv %s): pvVarGetCallback() failure: %s\n",
			ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
		ss->getReq[varId] = NULL;
		freeListFree(sp->pvReqPool, req);
		epicsEventSignal(getSem);
		check_connected(dbch, meta);
		return status;
	}

	/* Synchronous: wait for completion */
	if (compType == SYNC)
	{
		epicsEventWaitStatus event_status;

		pvSysFlush(sp->pvSys);
		event_status = epicsEventWaitWithTimeout(getSem, tmo);
		ss->getReq[varId] = NULL;
		epicsEventSignal(getSem);
		switch (event_status)
		{
		case epicsEventWaitOK:
			status = check_connected(dbch, meta);
			if (status) return status;
			if (sp->options & OPT_SAFE)
				/* Copy regardless of whether dirty flag is set or not */
				ss_read_buffer(ss, ch, FALSE);
			break;
		case epicsEventWaitTimeout:
			meta->status = pvStatTIMEOUT;
			meta->severity = pvSevrMAJOR;
			meta->message = "get completion timeout";
			return meta->status;
		case epicsEventWaitError:
			meta->status = pvStatERROR;
			meta->severity = pvSevrMAJOR;
			meta->message = "get completion failure";
			return meta->status;
		}
	}

	return pvStatOK;
}
示例#27
0
/**
 * Readout thread function
 */
void ADSBIG::readoutTask(void)
{
  epicsEventWaitStatus eventStatus;
  epicsFloat64 timeout = 0.001;
  bool error = false;
  size_t dims[2];
  int nDims = 2;
  epicsInt32 sizeX = 0;
  epicsInt32 sizeY = 0;
  epicsInt32 minX = 0;
  epicsInt32 minY = 0;
  NDDataType_t dataType;
  epicsInt32 iDataType = 0;
  epicsUInt32 dataSize = 0;
  epicsTimeStamp nowTime;
  NDArray *pArray = NULL;
  epicsInt32 numImagesCounter = 0;
  epicsInt32 imageCounter = 0;
  PAR_ERROR cam_err = CE_NO_ERROR;

  const char* functionName = "ADSBIG::readoutTask";
  asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Started Readout Thread.\n", functionName);

  while (1) {

    //Wait for a stop event, with a short timeout, to catch any that were done after last one.
    eventStatus = epicsEventWaitWithTimeout(m_stopEvent, timeout);          
    if (eventStatus == epicsEventWaitOK) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Got Stop Event Before Start Event.\n", functionName);
    }

    lock();
    if (!error) {
      setStringParam(ADStatusMessage, "Idle");
    }
    callParamCallbacks();
    unlock();

    eventStatus = epicsEventWait(m_startEvent);          
    if (eventStatus == epicsEventWaitOK) {
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Got Start Event.\n", functionName);
      error = false;
      setStringParam(ADStatusMessage, " ");
      lock();
      setIntegerParam(ADNumImagesCounter, 0);
      setIntegerParam(ADNumExposuresCounter, 0);

      //Sanity checks
      if ((p_Cam == NULL) || (p_Img == NULL)) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s NULL pointer.\n", functionName);
        break;
      }

      //printf("%s Time before acqusition: ", functionName);
      //epicsTime::getCurrent().show(0);

      //Read the frame sizes 
      getIntegerParam(ADMinX, &minX);
      getIntegerParam(ADMinY, &minY);
      getIntegerParam(ADSizeX, &sizeX);
      getIntegerParam(ADSizeY, &sizeY);
      p_Cam->SetSubFrame(minX, minY, sizeX, sizeY);

      //Read what type of image we want - light field or dark field?
      int darkField = 0;
      getIntegerParam(ADSBIGDarkFieldParam, &darkField);

      if (darkField > 0) {
        cam_err = p_Cam->GrabSetup(p_Img, SBDF_DARK_ONLY);
      } else {
        cam_err = p_Cam->GrabSetup(p_Img, SBDF_LIGHT_ONLY);
      }
      if (cam_err != CE_NO_ERROR) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                "%s. CSBIGCam::GrabSetup returned an error. %s\n", 
              functionName, p_Cam->GetErrorString(cam_err).c_str());
        error = true;
        setStringParam(ADStatusMessage, p_Cam->GetErrorString(cam_err).c_str());
      } 

      unsigned short binX = 0;
      unsigned short binY = 0;
      p_Img->GetBinning(binX, binY);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " binX: %d\n", binY);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " binY: %d\n", binX);
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " PixelHeight: %f\n", p_Img->GetPixelHeight());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " PixelWidth: %f\n", p_Img->GetPixelWidth());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Height: %d\n", p_Img->GetHeight());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Width: %d\n", p_Img->GetWidth());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Readout Mode: %d\n", p_Cam->GetReadoutMode());
      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, " Dark Field: %d\n", darkField);

      if (!error) {

        //Do exposure
        callParamCallbacks();
        unlock();
        if (darkField > 0) {
          cam_err = p_Cam->GrabMain(p_Img, SBDF_DARK_ONLY);
        } else {
          cam_err = p_Cam->GrabMain(p_Img, SBDF_LIGHT_ONLY);
        }
        lock();
        if (cam_err != CE_NO_ERROR) {
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                    "%s. CSBIGCam::GrabMain returned an error. %s\n", 
                    functionName, p_Cam->GetErrorString(cam_err).c_str());
          error = true;
          setStringParam(ADStatusMessage, p_Cam->GetErrorString(cam_err).c_str());
        }

        setDoubleParam(ADSBIGPercentCompleteParam, 100.0);

        if (!m_aborted) { 
        
        unsigned short *pData = p_Img->GetImagePointer();
        
        //printf("%s Time after acqusition: ", functionName);
        //epicsTime::getCurrent().show(0);

        //Update counters
        getIntegerParam(NDArrayCounter, &imageCounter);
        imageCounter++;
        setIntegerParam(NDArrayCounter, imageCounter);
        getIntegerParam(ADNumImagesCounter, &numImagesCounter);
        numImagesCounter++;
        setIntegerParam(ADNumImagesCounter, numImagesCounter);

        //NDArray callbacks
        int arrayCallbacks = 0;
        getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
        getIntegerParam(NDDataType, &iDataType);
        dataType = static_cast<NDDataType_t>(iDataType);
        if (dataType == NDUInt8) {
          dataSize = sizeX*sizeY*sizeof(epicsUInt8);
        } else if (dataType == NDUInt16) {
          dataSize = sizeX*sizeY*sizeof(epicsUInt16);
        } else if (dataType == NDUInt32) {
          dataSize = sizeX*sizeY*sizeof(epicsUInt32);
        } else {
          asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                    "%s. ERROR: We can't handle this data type. dataType: %d\n", 
                    functionName, dataType);
          error = true;
          dataSize = 0;
        }
        setIntegerParam(NDArraySize, dataSize);
        
        if (!error) {
          
          if (arrayCallbacks) {
            //Allocate an NDArray
            dims[0] = sizeX;
            dims[1] = sizeY;
            if ((pArray = this->pNDArrayPool->alloc(nDims, dims, dataType, 0, NULL)) == NULL) {
              asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
                        "%s. ERROR: pArray is NULL.\n", 
                        functionName);
            } else {
              epicsTimeGetCurrent(&nowTime);
              pArray->uniqueId = imageCounter;
              pArray->timeStamp = nowTime.secPastEpoch + nowTime.nsec / 1.e9;
              updateTimeStamp(&pArray->epicsTS);
              //Get any attributes that have been defined for this driver
              this->getAttributes(pArray->pAttributeList);
              //We copy data because the SBIG class library holds onto the original buffer until the next acqusition
              asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                        "%s: Copying data. dataSize: %d\n", functionName, dataSize);
              memcpy(pArray->pData, pData, dataSize);
                
              unlock();
              asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s: Calling NDArray callback\n", functionName);
              doCallbacksGenericPointer(pArray, NDArrayData, 0);
              lock();
              pArray->release();
            }
            
          }
          
          setIntegerParam(ADStatus, ADStatusIdle);
          
        } else {
          setIntegerParam(ADStatus, ADStatusError);
        }

        } else { //end if (!m_aborted)
          setIntegerParam(ADStatus, ADStatusAborted);
          m_aborted = false;
        }
        
      }
      
      callParamCallbacks();
      //Complete Acquire callback
      setIntegerParam(ADAcquire, 0);
      callParamCallbacks();
      unlock();

      asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s Completed acqusition.\n", functionName);

    } //end of start event

  } //end of while(1)

  asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
            "%s: ERROR: Exiting ADSBIGReadoutTask main loop.\n", functionName);

}
/** This thread controls acquisition, reads SFRM files to get the image data, and
  * does the callbacks to send it to higher layers */
void BISDetector::BISTask()
{
    int status = asynSuccess;
    int imageCounter;
        int numImages, numImagesCounter;
    int imageMode;
    int acquire;
    NDArray *pImage;
    double acquireTime, timeRemaining;
    ADShutterMode_t shutterMode;
    int frameType;
    int numDarks;
    double readSFRMTimeout;
    epicsTimeStamp startTime, currentTime;
    const char *functionName = "BISTask";
    char fullFileName[MAX_FILENAME_LEN];
    char statusMessage[MAX_MESSAGE_SIZE];
    size_t dims[2];
    int itemp;
    int arrayCallbacks;
    
    this->lock();

    /* Loop forever */
    while (1) {
        /* Is acquisition active? */
        getIntegerParam(ADAcquire, &acquire);
        
        /* If we are not acquiring then wait for a semaphore that is given when acquisition is started */
        if (!acquire) {
            setStringParam(ADStatusMessage, "Waiting for acquire command");
            setIntegerParam(ADStatus, ADStatusIdle);
            callParamCallbacks();
            /* Release the lock while we wait for an event that says acquire has started, then lock again */
            this->unlock();
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                "%s:%s: waiting for acquire to start\n", driverName, functionName);
            status = epicsEventWait(this->startEventId);
            this->lock();
            setIntegerParam(ADNumImagesCounter, 0);
        }
        
        /* Get current values of some parameters */
        getIntegerParam(ADFrameType, &frameType);
        /* Get the exposure parameters */
        getDoubleParam(ADAcquireTime, &acquireTime);
        getIntegerParam(ADShutterMode, &itemp);  shutterMode = (ADShutterMode_t)itemp;
        getDoubleParam(BISSFRMTimeout, &readSFRMTimeout);
        
        setIntegerParam(ADStatus, ADStatusAcquire);

        /* Create the full filename */
        createFileName(sizeof(fullFileName), fullFileName);
        
        setStringParam(ADStatusMessage, "Starting exposure");
        /* Call the callbacks to update any changes */
        setStringParam(NDFullFileName, fullFileName);
        callParamCallbacks();
        switch (frameType) {
            case BISFrameNormal:
                epicsSnprintf(this->toBIS, sizeof(this->toBIS), 
                    "[Scan /Filename=%s /scantime=%f /Rescan=0]", fullFileName, acquireTime);
                break;
            case BISFrameDark:
                getIntegerParam(BISNumDarks, &numDarks);
                epicsSnprintf(this->toBIS, sizeof(this->toBIS), 
                    "[Dark /AddTime=%f /Repetitions=%d]", acquireTime, numDarks);
                break;
            case BISFrameRaw:
                epicsSnprintf(this->toBIS, sizeof(this->toBIS), 
                    "[Scan /Filename=%s /scantime=%f /Rescan=0 /DarkFlood=0]", fullFileName, acquireTime);
                break;
            case BISFrameDoubleCorrelation:
                epicsSnprintf(this->toBIS, sizeof(this->toBIS), 
                    "[Scan /Filename=%s /scantime=%f /Rescan=1]", fullFileName, acquireTime);
                break;
        }
        /* Send the acquire command to BIS */
        writeBIS(2.0);

        setStringParam(ADStatusMessage, "Waiting for Acquisition");
        callParamCallbacks();
        /* Set the the start time for the TimeRemaining counter */
        epicsTimeGetCurrent(&startTime);
        timeRemaining = acquireTime;

        /* BIS will control the shutter if we are using the hardware shutter signal.
         * If we are using the EPICS shutter then tell it to open */
        if (shutterMode == ADShutterModeEPICS) ADDriver::setShutter(1);

        /* Wait for the exposure time using epicsEventWaitWithTimeout, 
         * so we can abort. */
        epicsTimerStartDelay(this->timerId, acquireTime);
        while(1) {
            this->unlock();
            status = epicsEventWaitWithTimeout(this->stopEventId, BIS_POLL_DELAY);
            this->lock();
            if (status == epicsEventWaitOK) {
                /* The acquisition was stopped before the time was complete */
                epicsTimerCancel(this->timerId);
                break;
            }
            epicsTimeGetCurrent(&currentTime);
            timeRemaining = acquireTime -  epicsTimeDiffInSeconds(&currentTime, &startTime);
            if (timeRemaining < 0.) timeRemaining = 0.;
            setDoubleParam(ADTimeRemaining, timeRemaining);
            callParamCallbacks();
        }
        if (shutterMode == ADShutterModeEPICS) ADDriver::setShutter(0);
        setDoubleParam(ADTimeRemaining, 0.0);
        callParamCallbacks();
        this->unlock();
        status = epicsEventWaitWithTimeout(this->readoutEventId, 5.0);
        this->lock();
        /* If there was an error jump to bottom of loop */
        if (status != epicsEventWaitOK) {
            setIntegerParam(ADAcquire, 0);
            asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                "%s:%s: error waiting for readout to complete\n",
                driverName, functionName);
            goto done;
        }
        getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
        getIntegerParam(NDArrayCounter, &imageCounter);
        imageCounter++;
        setIntegerParam(NDArrayCounter, imageCounter);
        getIntegerParam(ADNumImagesCounter, &numImagesCounter);
        numImagesCounter++;
        setIntegerParam(ADNumImagesCounter, numImagesCounter);
        callParamCallbacks();

        if (arrayCallbacks && frameType != BISFrameDark) {
            /* Get an image buffer from the pool */
            getIntegerParam(ADSizeX, &itemp); dims[0] = itemp;
            getIntegerParam(ADSizeY, &itemp); dims[1] = itemp;
            pImage = this->pNDArrayPool->alloc(2, dims, NDInt32, 0, NULL);
            epicsSnprintf(statusMessage, sizeof(statusMessage), "Reading from File %s", fullFileName);
            setStringParam(ADStatusMessage, statusMessage);
            callParamCallbacks();
            status = readSFRM(fullFileName, &startTime, acquireTime + readSFRMTimeout, pImage); 
            /* If there was an error jump to bottom of loop */
            if (status) {
                setIntegerParam(ADAcquire, 0);
                pImage->release();
                goto done;
            } 

            /* Put the frame number and time stamp into the buffer */
            pImage->uniqueId = imageCounter;
            pImage->timeStamp = startTime.secPastEpoch + startTime.nsec / 1.e9;
            updateTimeStamp(&pImage->epicsTS);

            /* Get any attributes that have been defined for this driver */        
            this->getAttributes(pImage->pAttributeList);

            /* Call the NDArray callback */
            /* Must release the lock here, or we can get into a deadlock, because we can
             * block on the plugin lock, and the plugin can be calling us */
            this->unlock();
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, 
                 "%s:%s: calling NDArray callback\n", driverName, functionName);
            doCallbacksGenericPointer(pImage, NDArrayData, 0);
            this->lock();
            /* Free the image buffer */
            pImage->release();
        }
        getIntegerParam(ADImageMode, &imageMode);
        if (imageMode == ADImageMultiple) {
            getIntegerParam(ADNumImages, &numImages);
            if (numImagesCounter >= numImages) setIntegerParam(ADAcquire, 0);
        }    
        if (imageMode == ADImageSingle) setIntegerParam(ADAcquire, 0);
        done:
        callParamCallbacks();
    }
}
示例#29
0
static void MM4000Poller(MM4000Controller *pController)
{
    /* This is the task that polls the MM4000 */
    double timeout;
    AXIS_HDL pAxis;
    int status;
    int itera, j;
    int axisDone;
    int offset;
    int anyMoving;
    int comStatus;
    int forcedFastPolls=0;
    char *p, *tokSave;
    char statusAllString[BUFFER_SIZE];
    char positionAllString[BUFFER_SIZE];
    char buff[BUFFER_SIZE];

    timeout = pController->idlePollPeriod;
    epicsEventSignal(pController->pollEventId);  /* Force on poll at startup */

    while (1)
    {
        if (timeout != 0.)
            status = epicsEventWaitWithTimeout(pController->pollEventId, timeout);
        else
            status = epicsEventWait(pController->pollEventId);

        if (status == epicsEventWaitOK)
        {
            /* We got an event, rather than a timeout.  This is because other software
             * knows that an axis should have changed state (started moving, etc.).
             * Force a minimum number of fast polls, because the controller status
             * might not have changed the first few polls
             */
            forcedFastPolls = 10;
        }

        anyMoving = 0;

        /* Lock all the controller's axis. */
        for (itera = 0; itera < pController->numAxes; itera++)
        {
            pAxis = &pController->pAxis[itera];
            if (!pAxis->mutexId)
                break;
            epicsMutexLock(pAxis->mutexId);
        }

        comStatus = sendAndReceive(pController, "MS;", statusAllString, sizeof(statusAllString));
        if (comStatus == 0)
            comStatus = sendAndReceive(pController, "TP;", positionAllString, sizeof(positionAllString));

        for (itera=0; itera < pController->numAxes; itera++)
        {
            pAxis = &pController->pAxis[itera];
            if (!pAxis->mutexId)
                break;
            if (comStatus != 0)
            {
                PRINT(pAxis->logParam, MOTOR_ERROR, "MM4000Poller: error reading status=%d\n", comStatus);
                motorParam->setInteger(pAxis->params, motorAxisCommError, 1);
            }
            else
            {
                PARAMS params = pAxis->params;
                int intval, axisStatus;

                motorParam->setInteger(params, motorAxisCommError, 0);
                /*
                 * Parse the status string
                 * Status string format: 1MSx,2MSy,3MSz,... where x, y and z are the status
                 * bytes for the motors
                 */
                offset = pAxis->axis*5 + 3;  /* Offset in status string */
                axisStatus = pAxis->axisStatus = statusAllString[offset];
                if (axisStatus & MM4000_MOVING)
                {
                    axisDone = 0;
                    anyMoving = 1;
                }
                else
                    axisDone = 1;
                motorParam->setInteger(params, motorAxisDone, axisDone);

                motorParam->setInteger(params, motorAxisHomeSignal,    (axisStatus & MM4000_HOME));
                motorParam->setInteger(params, motorAxisHighHardLimit, (axisStatus & MM4000_HIGH_LIMIT));
                motorParam->setInteger(params, motorAxisLowHardLimit,  (axisStatus & MM4000_LOW_LIMIT));
                motorParam->setInteger(params, motorAxisDirection,     (axisStatus & MM4000_DIRECTION));
                motorParam->setInteger(params, motorAxisPowerOn,      !(axisStatus & MM4000_POWER_OFF));

                /*
                 * Parse motor position
                 * Position string format: 1TP5.012,2TP1.123,3TP-100.567,...
                 * Skip to substring for this motor, convert to double
                 */

                strcpy(buff, positionAllString);
                tokSave = NULL;
                p = epicsStrtok_r(buff, ",", &tokSave);
                for (j=0; j < pAxis->axis; j++)
                    p = epicsStrtok_r(NULL, ",", &tokSave);
                pAxis->currentPosition = atof(p+3);
                motorParam->setDouble(params, motorAxisPosition,    (pAxis->currentPosition/pAxis->stepSize));
                motorParam->setDouble(params, motorAxisEncoderPosn, (pAxis->currentPosition/pAxis->stepSize));
                PRINT(pAxis->logParam, IODRIVER, "MM4000Poller: axis %d axisStatus=%x, position=%f\n",
                      pAxis->axis, pAxis->axisStatus, pAxis->currentPosition);

                /* We would like a way to query the actual velocity, but this is not possible.  If we could we could
                 * set the direction, and Moving flags */

                /* Check for controller error. */
                comStatus = sendAndReceive(pController, "TE;", buff, sizeof(statusAllString));
                if (buff[2] == '@')
                    intval = 0;
                else
                {
                    intval = 1;
                    PRINT(pAxis->logParam, MOTOR_ERROR, "MM4000Poller: controller error %s\n", buff);
                }
                motorParam->setInteger(params, motorAxisProblem, intval);
            }

            motorParam->callCallback(pAxis->params);
        } /* Next axis */

        /* UnLock all the controller's axis. */
        for (itera = 0; itera < pController->numAxes; itera++)
        {
            pAxis = &pController->pAxis[itera];
            if (!pAxis->mutexId)
                break;
            epicsMutexUnlock(pAxis->mutexId);
        }

        if (forcedFastPolls > 0)
        {
            timeout = pController->movingPollPeriod;
            forcedFastPolls--;
        }
        else if (anyMoving)
            timeout = pController->movingPollPeriod;
        else
            timeout = pController->idlePollPeriod;
    } /* End while */
}
void ReadASCII::rampThread(void)
{
	//Ramps SP values when the ramp is on
	double wait, rate, target, curSP, newSP, SPRBV;
	int ramping, rampOn, lookUpOn;

	lock();

	while (1)
	{
		//check running
		getIntegerParam(P_Ramping, &ramping);

		//check ramp mode
		getIntegerParam(P_RampOn, &rampOn);

		unlock();

		if ((!ramping) || (!rampOn)) {
			//wait for run to change
			epicsEventWait(eventId_);

			lock();

			continue;
		}

		lock();

		//get SP:RBV
		getDoubleParam(P_SPRBV, &SPRBV);

		//get current SP
		getDoubleParam(P_SPOut, &curSP);

		//get target
		getDoubleParam(P_Target, &target);

		if ((abs(SPRBV - target) < EPSILON) && (abs(curSP - target) < EPSILON))
		{
			setIntegerParam(P_Ramping, 0);
			continue;
		}

		callParamCallbacks();
		unlock(); 
		wait = 5.0; //default wait

		//wait
		epicsEventWaitWithTimeout(eventId_, wait);

		//check near final SP (Doesn't work as requires long time to write to Eurotherm) 
		//if (diff < (wait * rate))
		//{
		//	//wait less time
		//	wait = diff / rate;
		//}
		
		lock();

		//check rampOn (could have changed whilst waiting)
		getIntegerParam(P_RampOn, &rampOn);
		
		if (!rampOn)
		{
			//no longer ramping
			setIntegerParam(P_Ramping, 0);
			continue;
		}

		//rate may have changed whilst waiting
		getDoubleParam(P_RampRate, &rate);
			
		//SP may have changed
		getDoubleParam(P_SPOut, &curSP);

		//target may have changed
		double oldTarget = target;
		getDoubleParam(P_Target, &target);

		if (oldTarget != target)
		{
			//start back at current temp
			getDoubleParam(P_CurTemp, &curSP);
			setDoubleParam(P_SPOut, curSP);
			continue;
		}

		double diff = abs(target - curSP);

		if (diff < (wait * rate))
		{
			newSP = target;
		}else{
			if (curSP > target)
				rate = -rate;

			//update SP with wait*rate
			newSP = curSP + wait*rate;
		}

		setDoubleParam(P_SPOut, newSP);

		callParamCallbacks();

		//check PID table in use
		getIntegerParam(P_LookUpOn, &lookUpOn);

		if (lookUpOn)
		{
			checkLookUp(newSP, curSP);
		}
	}

}