It is almost always a good idea to provide _RBV records so the user can see the parameter value actually being used by the driver in case it differs from the requested value. It is also possible to make the output record update to reflect
the new choice by setting the info tag asyn:READBACK in the database. Sometimes this is desirable and sometimes it is not.
Thanks Mark.
Out of interest: in the case of the CMOS cameras you choose to ignore the error rather than force the binning value to 1, whereas if binning is set to less than one then you do change the value of the parameter. Is there a 'philosophy' guideline you're applying
there? (I'm still struggling with whether to provide _RBV database records for all settings, and when to change the parameter and when to just override it).
Phil
Hi Phil,
You are correct.
The units of ADSize are intended to be in unbinned detector pixels. The ADProsilica::setGeometry is a good example. Their API defines the readout region
size in binned pixels, so the driver sets it to ADSizeX/ADBinX. I can’t promise that all detector drivers have been written to follow this convention, but they should be.
Here is the code for the Prosilica driver.
asynStatus prosilica::setGeometry()
{
int status = asynSuccess;
int s;
int binX, binY, minY, minX, sizeX, sizeY, maxSizeX, maxSizeY;
static const char *functionName = "setGeometry";
/* Get all of the current geometry parameters from the parameter library */
status |= getIntegerParam(ADBinX, &binX);
if (binX < 1) binX = 1;
status |= getIntegerParam(ADBinY, &binY);
if (binY < 1) binY = 1;
status |= getIntegerParam(ADMinX, &minX);
status |= getIntegerParam(ADMinY, &minY);
status |= getIntegerParam(ADSizeX, &sizeX);
status |= getIntegerParam(ADSizeY, &sizeY);
status |= getIntegerParam(ADMaxSizeX, &maxSizeX);
status |= getIntegerParam(ADMaxSizeY, &maxSizeY);
if (minX + sizeX > maxSizeX) {
sizeX = maxSizeX - minX;
setIntegerParam(ADSizeX, sizeX);
}
if (minY + sizeY > maxSizeY) {
sizeY = maxSizeY - minY;
setIntegerParam(ADSizeY, sizeY);
}
/* CMOS cameras don't support binning, so ignore ePvErrNotFound errors */
s = PvAttrUint32Set(this->PvHandle, "BinningX", binX);
if (s != ePvErrNotFound) status |= s;
s = PvAttrUint32Set(this->PvHandle, "BinningY", binY);
if (s != ePvErrNotFound) status |= s;
if(!status){
status |= PvAttrUint32Set(this->PvHandle, "RegionX", minX/binX);
status |= PvAttrUint32Set(this->PvHandle, "RegionY", minY/binY);
status |= PvAttrUint32Set(this->PvHandle, "Width", sizeX/binX);
status |= PvAttrUint32Set(this->PvHandle, "Height", sizeY/binY);
}
if (status) asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: error, status=%d\n",
driverName, functionName, status);
return((asynStatus)status);
}
Mark
As I understand it, the ADSize parameters are intended to determine the dimensions of the _physical_ region of the sensor that is read out. That's why the constraint imposed is
ADMin + ADSize <= ADMaxSize
This means that the output array from an areaDetector driver should have dimensions given approximately by ADSize/ADBin for each dimension.
Is this correct?
Thanks,
Phil Atkin
--
Pixel Analytics is a limited company registered in England. Company number:
7747526; Registered office: 93A New Road, Haslingfield, Cambridge CB23 1LP