Merge pull request #34 from dls-controls/fix/wait-for-acquire
Now set ADAcquire parameter to 1 after detector acquisition has started
This commit is contained in:
@@ -318,9 +318,9 @@ AndorCCD::AndorCCD(const char *portName, const char *installPath, int cameraSeri
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Define the polling periods for the status thread.
|
// Define the polling periods for the status thread.
|
||||||
mPollingPeriod = 0.2; //seconds
|
mPollingPeriod = 0.2; // seconds
|
||||||
mFastPollingPeriod = 0.05; //seconds
|
mFastPollingPeriod = 0.05; // seconds
|
||||||
|
|
||||||
mAcquiringData = 0;
|
mAcquiringData = 0;
|
||||||
|
|
||||||
@@ -639,16 +639,33 @@ asynStatus AndorCCD::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
|||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
static const char *functionName = "writeInt32";
|
static const char *functionName = "writeInt32";
|
||||||
|
|
||||||
//Set in param lib so the user sees a readback straight away. Save a backup in case of errors.
|
// Set in param lib so the user sees a readback straight away. Save a backup in case of errors.
|
||||||
getIntegerParam(function, &oldValue);
|
getIntegerParam(function, &oldValue);
|
||||||
status = setIntegerParam(function, value);
|
status = setIntegerParam(function, value);
|
||||||
|
|
||||||
if (function == ADAcquire) {
|
if (function == ADAcquire) {
|
||||||
getIntegerParam(ADStatus, &adstatus);
|
getIntegerParam(ADStatus, &adstatus);
|
||||||
if (value && (adstatus == ADStatusIdle)) {
|
if (value && (adstatus == ADStatusIdle)) {
|
||||||
|
// Start the acqusition here, then send an event to the dataTask at the end of this function
|
||||||
try {
|
try {
|
||||||
|
// Set up acquisition
|
||||||
mAcquiringData = 1;
|
mAcquiringData = 1;
|
||||||
//We send an event at the bottom of this function.
|
status = setupAcquisition();
|
||||||
|
if (status != asynSuccess) throw std::string("Setup acquisition failed");
|
||||||
|
// Open the shutter if we control it
|
||||||
|
int adShutterMode;
|
||||||
|
getIntegerParam(ADShutterMode, &adShutterMode);
|
||||||
|
if (adShutterMode == ADShutterModeEPICS) {
|
||||||
|
ADDriver::setShutter(ADShutterOpen);
|
||||||
|
}
|
||||||
|
// Start acquisition
|
||||||
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
|
"%s:%s:, StartAcquisition()\n",
|
||||||
|
driverName, functionName);
|
||||||
|
checkStatus(StartAcquisition());
|
||||||
|
// Reset the counters
|
||||||
|
setIntegerParam(ADNumImagesCounter, 0);
|
||||||
|
setIntegerParam(ADNumExposuresCounter, 0);
|
||||||
} catch (const std::string &e) {
|
} catch (const std::string &e) {
|
||||||
asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
|
asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"%s:%s: %s\n",
|
"%s:%s: %s\n",
|
||||||
@@ -736,9 +753,6 @@ asynStatus AndorCCD::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
|||||||
status = ADDriver::writeInt32(pasynUser, value);
|
status = ADDriver::writeInt32(pasynUser, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
//For a successful write, clear the error message.
|
|
||||||
setStringParam(AndorMessage, " ");
|
|
||||||
|
|
||||||
/* Do callbacks so higher layers see any changes */
|
/* Do callbacks so higher layers see any changes */
|
||||||
callParamCallbacks();
|
callParamCallbacks();
|
||||||
|
|
||||||
@@ -749,7 +763,7 @@ asynStatus AndorCCD::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
|||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
"%s:%s:, Sending dataEvent to dataTask ...\n",
|
"%s:%s:, Sending dataEvent to dataTask ...\n",
|
||||||
driverName, functionName);
|
driverName, functionName);
|
||||||
//Also signal the data readout thread
|
// Also signal the data readout thread
|
||||||
epicsEventSignal(dataEvent);
|
epicsEventSignal(dataEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,6 +775,8 @@ asynStatus AndorCCD::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
|||||||
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
|
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
|
||||||
"%s:%s: function=%d, value=%d\n",
|
"%s:%s: function=%d, value=%d\n",
|
||||||
driverName, functionName, function, value);
|
driverName, functionName, function, value);
|
||||||
|
// For a successful write, clear the error message.
|
||||||
|
setStringParam(AndorMessage, " ");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,7 +1100,7 @@ void AndorCCD::statusTask(void)
|
|||||||
printf("%s:%s: Status thread started...\n", driverName, functionName);
|
printf("%s:%s: Status thread started...\n", driverName, functionName);
|
||||||
while(!mExiting) {
|
while(!mExiting) {
|
||||||
|
|
||||||
//Read timeout for polling freq.
|
// Read timeout for polling freq.
|
||||||
this->lock();
|
this->lock();
|
||||||
if (forcedFastPolls > 0) {
|
if (forcedFastPolls > 0) {
|
||||||
timeout = mFastPollingPeriod;
|
timeout = mFastPollingPeriod;
|
||||||
@@ -1103,10 +1119,10 @@ void AndorCCD::statusTask(void)
|
|||||||
asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
|
asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
"%s:%s: Got status event\n",
|
"%s:%s: Got status event\n",
|
||||||
driverName, functionName);
|
driverName, functionName);
|
||||||
//We got an event, rather than a timeout. This is because other software
|
// We got an event, rather than a timeout. This is because other software
|
||||||
//knows that data has arrived, or device should have changed state (parameters changed, etc.).
|
// knows that data has arrived, or device should have changed state (parameters changed, etc.).
|
||||||
//Force a minimum number of fast polls, because the device status
|
// Force a minimum number of fast polls, because the device status
|
||||||
//might not have changed in the first few polls
|
// might not have changed in the first few polls
|
||||||
forcedFastPolls = 5;
|
forcedFastPolls = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1114,17 +1130,17 @@ void AndorCCD::statusTask(void)
|
|||||||
this->lock();
|
this->lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//Only read these if we are not acquiring data
|
// Only read these if we are not acquiring data
|
||||||
if (!mAcquiringData) {
|
if (!mAcquiringData) {
|
||||||
//Read cooler status
|
// Read cooler status
|
||||||
checkStatus(IsCoolerOn(&value));
|
checkStatus(IsCoolerOn(&value));
|
||||||
status = setIntegerParam(AndorCoolerParam, value);
|
status = setIntegerParam(AndorCoolerParam, value);
|
||||||
//Read temperature of CCD
|
// Read temperature of CCD
|
||||||
checkStatus(GetTemperatureF(&temperature));
|
checkStatus(GetTemperatureF(&temperature));
|
||||||
status = setDoubleParam(ADTemperatureActual, temperature);
|
status = setDoubleParam(ADTemperatureActual, temperature);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read detector status (idle, acquiring, error, etc.)
|
// Read detector status (idle, acquiring, error, etc.)
|
||||||
checkStatus(GetStatus(&value));
|
checkStatus(GetStatus(&value));
|
||||||
uvalue = static_cast<unsigned int>(value);
|
uvalue = static_cast<unsigned int>(value);
|
||||||
if (uvalue == ASIdle) {
|
if (uvalue == ASIdle) {
|
||||||
@@ -1163,7 +1179,7 @@ void AndorCCD::statusTask(void)
|
|||||||
callParamCallbacks();
|
callParamCallbacks();
|
||||||
this->unlock();
|
this->unlock();
|
||||||
|
|
||||||
} //End of loop
|
} // End of loop
|
||||||
asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
|
asynPrint(pasynUserSelf, ASYN_TRACE_FLOW,
|
||||||
"%s:%s: Status thread exiting ...\n",
|
"%s:%s: Status thread exiting ...\n",
|
||||||
driverName, functionName);
|
driverName, functionName);
|
||||||
@@ -1511,7 +1527,7 @@ void AndorCCD::dataTask(void)
|
|||||||
|
|
||||||
errorString = NULL;
|
errorString = NULL;
|
||||||
|
|
||||||
//Wait for event from main thread to signal that data acquisition has started.
|
// Wait for event from main thread to signal that data acquisition has started.
|
||||||
this->unlock();
|
this->unlock();
|
||||||
status = epicsEventWait(dataEvent);
|
status = epicsEventWait(dataEvent);
|
||||||
if (mExiting)
|
if (mExiting)
|
||||||
@@ -1521,41 +1537,23 @@ void AndorCCD::dataTask(void)
|
|||||||
driverName, functionName);
|
driverName, functionName);
|
||||||
this->lock();
|
this->lock();
|
||||||
|
|
||||||
//Sanity check that main thread thinks we are acquiring data
|
// Sanity check that main thread thinks we are acquiring data
|
||||||
if (mAcquiringData) {
|
if (mAcquiringData) {
|
||||||
try {
|
// Read some parameters
|
||||||
status = setupAcquisition();
|
getIntegerParam(ADShutterMode, &adShutterMode);
|
||||||
if (status != asynSuccess) continue;
|
getIntegerParam(AndorReadOutMode, &readOutMode);
|
||||||
getIntegerParam(ADShutterMode, &adShutterMode);
|
|
||||||
getIntegerParam(AndorReadOutMode, &readOutMode);
|
|
||||||
if (adShutterMode == ADShutterModeEPICS) {
|
|
||||||
ADDriver::setShutter(ADShutterOpen);
|
|
||||||
}
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
|
||||||
"%s:%s:, StartAcquisition()\n",
|
|
||||||
driverName, functionName);
|
|
||||||
checkStatus(StartAcquisition());
|
|
||||||
acquiring = 1;
|
|
||||||
} catch (const std::string &e) {
|
|
||||||
asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"%s:%s: %s\n",
|
|
||||||
driverName, functionName, e.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//Read some parameters
|
|
||||||
getIntegerParam(NDDataType, &itemp); dataType = (NDDataType_t)itemp;
|
getIntegerParam(NDDataType, &itemp); dataType = (NDDataType_t)itemp;
|
||||||
getIntegerParam(NDAutoSave, &autoSave);
|
getIntegerParam(NDAutoSave, &autoSave);
|
||||||
getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
|
getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
|
||||||
getIntegerParam(NDArraySizeX, &sizeX);
|
getIntegerParam(NDArraySizeX, &sizeX);
|
||||||
getIntegerParam(NDArraySizeY, &sizeY);
|
getIntegerParam(NDArraySizeY, &sizeY);
|
||||||
// Reset the counters
|
// Set acquiring to 1
|
||||||
setIntegerParam(ADNumImagesCounter, 0);
|
acquiring = 1;
|
||||||
setIntegerParam(ADNumExposuresCounter, 0);
|
|
||||||
callParamCallbacks();
|
|
||||||
} else {
|
} else {
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
"%s:%s:, Data thread is running but main thread thinks we are not acquiring.\n",
|
"%s:%s:, Data thread is running but main thread thinks we are not acquiring.\n",
|
||||||
driverName, functionName);
|
driverName, functionName);
|
||||||
|
// Set acquiring to 0
|
||||||
acquiring = 0;
|
acquiring = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1654,19 +1652,20 @@ void AndorCCD::dataTask(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the shutter if we are controlling it
|
||||||
if (adShutterMode == ADShutterModeEPICS) {
|
if (adShutterMode == ADShutterModeEPICS) {
|
||||||
ADDriver::setShutter(ADShutterClosed);
|
ADDriver::setShutter(ADShutterClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now clear main thread flag
|
// Now clear main thread flag
|
||||||
mAcquiringData = 0;
|
mAcquiringData = 0;
|
||||||
setIntegerParam(ADAcquire, 0);
|
setIntegerParam(ADAcquire, 0);
|
||||||
//setIntegerParam(ADStatus, 0); //Dont set this as the status thread sets it.
|
//setIntegerParam(ADStatus, 0); //Dont set this as the status thread sets it.
|
||||||
|
|
||||||
/* Call the callbacks to update any changes */
|
/* Call the callbacks to update any changes */
|
||||||
callParamCallbacks();
|
callParamCallbacks();
|
||||||
} //End of loop
|
} // End of loop
|
||||||
mExited++;
|
mExited++;
|
||||||
this->unlock();
|
this->unlock();
|
||||||
}
|
}
|
||||||
@@ -1955,7 +1954,7 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//C utility functions to tie in with EPICS
|
// C utility functions to tie in with EPICS
|
||||||
|
|
||||||
static void andorStatusTaskC(void *drvPvt)
|
static void andorStatusTaskC(void *drvPvt)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user