/** Sets an int32 parameter. * \param[in] pasynUser asynUser structure that contains the function code in pasynUser->reason. * \param[in] value The value for this parameter * * Takes action if the function code requires it. Currently only ADShutterControl requires * action here. This method is normally called from the writeInt32 method in derived classes, which * should set the value of the parameter in the parameter library. */ asynStatus ADDriver::writeInt32(asynUser *pasynUser, epicsInt32 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; const char *functionName = "writeInt32"; status = setIntegerParam(function, value); if (function == ADShutterControl) { setShutter(value); } else { /* If this parameter belongs to a base class call its method */ if (function < FIRST_AD_PARAM) status = asynNDArrayDriver::writeInt32(pasynUser, value); } /* Do callbacks so higher layers see any changes */ callParamCallbacks(); if (status) asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s:%s: error, status=%d function=%d, value=%d\n", driverName, functionName, status, function, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, value=%d\n", driverName, functionName, function, value); return status; }
/*! Set the gain and the shutter values. \sa setGain(), setShutter() */ void vp1394CMUGrabber::setControl(unsigned short gain, unsigned short shutter) { setShutter(shutter); setGain(gain); }
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(¤tTime); timeRemaining = acquireTime - epicsTimeDiffInSeconds(¤tTime, &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; }
/** 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(); } } } }