Merge pull request #15 from mpdunning/master
Add support for Frame Transfer Mode, Vertical Shift Speed
This commit is contained in:
@@ -22,6 +22,11 @@ files respectively, in the configure/ directory of the appropriate release of th
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
RX-X ()
|
||||
----
|
||||
* Added support for Frame Transfer mode.
|
||||
* Added support for setting the Vertical Shift Period.
|
||||
|
||||
R2-6 (July 4, 2017)
|
||||
----
|
||||
* Changed from using TinyXml to libxml2. This is used when saving SPE files. This change was made
|
||||
|
||||
@@ -387,6 +387,40 @@ record(mbbi, "$(P)$(R)AndorReadOutMode_RBV")
|
||||
field(SCAN, "I/O Intr")
|
||||
}
|
||||
|
||||
# Frame Transfer Mode
|
||||
record(bo, "$(P)$(R)AndorFTMode")
|
||||
{
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt32")
|
||||
field(ZNAM, "Disabled")
|
||||
field(ONAM, "Enabled")
|
||||
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ANDOR_FT_MODE")
|
||||
}
|
||||
|
||||
record(bi, "$(P)$(R)AndorFTMode_RBV")
|
||||
{
|
||||
field(DTYP, "asynInt32")
|
||||
field(ZNAM, "Disabled")
|
||||
field(ONAM, "Enabled")
|
||||
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ANDOR_FT_MODE")
|
||||
field(SCAN, "I/O Intr")
|
||||
}
|
||||
|
||||
# The Vertical Shift Period enum values are constructed at run-time based on camera capabilities
|
||||
record(mbbo, "$(P)$(R)AndorVSPeriod")
|
||||
{
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ANDOR_VS_PERIOD")
|
||||
}
|
||||
|
||||
record(mbbi, "$(P)$(R)AndorVSPeriod_RBV")
|
||||
{
|
||||
field(DTYP, "asynInt32")
|
||||
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ANDOR_VS_PERIOD")
|
||||
field(SCAN, "I/O Intr")
|
||||
}
|
||||
|
||||
#Records in ADBase that do not apply to Andor
|
||||
|
||||
record(mbbo, "$(P)$(R)ColorMode")
|
||||
|
||||
@@ -9,6 +9,8 @@ $(P)$(R)AndorEMGainMode
|
||||
$(P)$(R)AndorEMGainAdvanced
|
||||
$(P)$(R)AndorADCSpeed
|
||||
$(P)$(R)AndorReadOutMode
|
||||
$(P)$(R)AndorFTMode
|
||||
$(P)$(R)AndorVSPeriod
|
||||
file "ADBase_settings.req", P=$(P), R=$(R)
|
||||
file "NDFile_settings.req", P=$(P), R=$(R)
|
||||
|
||||
|
||||
@@ -153,6 +153,8 @@ AndorCCD::AndorCCD(const char *portName, const char *installPath, int shamrockID
|
||||
createParam(AndorAdcSpeedString, asynParamInt32, &AndorAdcSpeed);
|
||||
createParam(AndorBaselineClampString, asynParamInt32, &AndorBaselineClamp);
|
||||
createParam(AndorReadOutModeString, asynParamInt32, &AndorReadOutMode);
|
||||
createParam(AndorFrameTransferModeString, asynParamInt32, &AndorFrameTransferMode);
|
||||
createParam(AndorVerticalShiftPeriodString, asynParamInt32, &AndorVerticalShiftPeriod);
|
||||
|
||||
// Create the epicsEvent for signaling to the status task when parameters should have changed.
|
||||
// This will cause it to do a poll immediately, rather than wait for the poll time period.
|
||||
@@ -181,6 +183,12 @@ AndorCCD::AndorCCD(const char *portName, const char *installPath, int shamrockID
|
||||
mPreAmpGains[i].EnumString = (char *)calloc(MAX_ENUM_STRING_SIZE, sizeof(char));
|
||||
}
|
||||
|
||||
// Initialize Vertical Shift Period enums
|
||||
for (i=0; i<MAX_VS_PERIODS; i++) {
|
||||
mVSPeriods[i].EnumValue = i;
|
||||
mVSPeriods[i].EnumString = (char *)calloc(MAX_ENUM_STRING_SIZE, sizeof(char));
|
||||
}
|
||||
|
||||
// Initialize camera
|
||||
try {
|
||||
printf("%s:%s: initializing camera\n",
|
||||
@@ -196,6 +204,7 @@ AndorCCD::AndorCCD(const char *portName, const char *installPath, int shamrockID
|
||||
checkStatus(SetReadMode(ARImage));
|
||||
checkStatus(SetImage(binX, binY, minX+1, minX+sizeX, minY+1, minY+sizeY));
|
||||
checkStatus(GetShutterMinTimes(&mMinShutterCloseTime, &mMinShutterOpenTime));
|
||||
checkStatus(GetFastestRecommendedVSSpeed(&mVSIndex, &mVSPeriod));
|
||||
mCapabilities.ulSize = sizeof(mCapabilities);
|
||||
checkStatus(GetCapabilities(&mCapabilities));
|
||||
callParamCallbacks();
|
||||
@@ -249,9 +258,12 @@ AndorCCD::AndorCCD(const char *portName, const char *installPath, int shamrockID
|
||||
status |= setDoubleParam(ADShutterOpenDelay, 0.);
|
||||
status |= setDoubleParam(ADShutterCloseDelay, 0.);
|
||||
status |= setIntegerParam(AndorReadOutMode, ARImage);
|
||||
status |= setIntegerParam(AndorFrameTransferMode, 0);
|
||||
|
||||
setupADCSpeeds();
|
||||
setupPreAmpGains();
|
||||
setupVerticalShiftPeriods();
|
||||
status |= setIntegerParam(AndorVerticalShiftPeriod, mVSIndex);
|
||||
status |= setupShutter(-1);
|
||||
|
||||
callParamCallbacks();
|
||||
@@ -395,6 +407,14 @@ asynStatus AndorCCD::readEnum(asynUser *pasynUser, char *strings[], int values[]
|
||||
severities[i] = 0;
|
||||
}
|
||||
}
|
||||
else if (function == AndorVerticalShiftPeriod) {
|
||||
for (i=0; ((i<mNumVSPeriods) && (i<(int)nElements)); i++) {
|
||||
if (strings[i]) free(strings[i]);
|
||||
strings[i] = epicsStrDup(mVSPeriods[i].EnumString);
|
||||
values[i] = mVSPeriods[i].EnumValue;
|
||||
severities[i] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*nIn = 0;
|
||||
return asynError;
|
||||
@@ -434,6 +454,25 @@ void AndorCCD::setupADCSpeeds()
|
||||
}
|
||||
}
|
||||
|
||||
void AndorCCD::setupVerticalShiftPeriods()
|
||||
{
|
||||
int i, numVSPeriods;
|
||||
float VSPeriod;
|
||||
AndorVSPeriod_t *pPeriod = mVSPeriods;
|
||||
|
||||
mNumVSPeriods = 0;
|
||||
checkStatus(GetNumberVSSpeeds(&numVSPeriods));
|
||||
for (i=0; i<numVSPeriods; i++) {
|
||||
checkStatus(GetVSSpeed(i, &VSPeriod));
|
||||
pPeriod->Index = i;
|
||||
pPeriod->Period = VSPeriod;
|
||||
epicsSnprintf(pPeriod->EnumString, MAX_ENUM_STRING_SIZE,
|
||||
"%.2f us", VSPeriod);
|
||||
mNumVSPeriods++;
|
||||
if (mNumVSPeriods >= MAX_VS_PERIODS) return;
|
||||
pPeriod++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Report status of the driver.
|
||||
@@ -455,6 +494,8 @@ void AndorCCD::report(FILE *fp, int details)
|
||||
unsigned int uIntParam5;
|
||||
unsigned int uIntParam6;
|
||||
AndorADCSpeed_t *pSpeed;
|
||||
int vsIndex;
|
||||
float vsPeriod;
|
||||
static const char *functionName = "report";
|
||||
|
||||
fprintf(fp, "Andor CCD port=%s\n", this->portName);
|
||||
@@ -496,6 +537,16 @@ void AndorCCD::report(FILE *fp, int details)
|
||||
fprintf(fp, " Index=%d, Gain=%f\n",
|
||||
mPreAmpGains[i].EnumValue, mPreAmpGains[i].Gain);
|
||||
}
|
||||
|
||||
fprintf(fp, " Vertical Shift Periods available: %d\n", mNumVSPeriods);
|
||||
for (i=0; i<mNumVSPeriods; i++) {
|
||||
fprintf(fp, " Index=%d, Period=%f [us per pixel shift]\n",
|
||||
mVSPeriods[i].EnumValue, mVSPeriods[i].Period);
|
||||
}
|
||||
fprintf(fp, " Fastest recommended Vertical Shift Period:\n");
|
||||
checkStatus(GetFastestRecommendedVSSpeed(&vsIndex, &vsPeriod));
|
||||
fprintf(fp, " Index=%d, Period=%f [us per pixel shift]\n", vsIndex, vsPeriod);
|
||||
|
||||
fprintf(fp, " Capabilities\n");
|
||||
fprintf(fp, " AcqModes=0x%X\n", (int)mCapabilities.ulAcqModes);
|
||||
fprintf(fp, " ReadModes=0x%X\n", (int)mCapabilities.ulReadModes);
|
||||
@@ -574,16 +625,17 @@ asynStatus AndorCCD::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((function == ADNumExposures) || (function == ADNumImages) ||
|
||||
(function == ADImageMode) ||
|
||||
(function == ADBinX) || (function == ADBinY) ||
|
||||
(function == ADMinX) || (function == ADMinY) ||
|
||||
(function == ADSizeX) || (function == ADSizeY) ||
|
||||
(function == ADReverseX) || (function == ADReverseY) ||
|
||||
(function == ADTriggerMode) || (function == AndorEmGain) ||
|
||||
(function == AndorEmGainMode)|| (function == AndorEmGainAdvanced) ||
|
||||
(function == AndorAdcSpeed) || (function == AndorPreAmpGain) ||
|
||||
(function == AndorReadOutMode)) {
|
||||
else if ((function == ADNumExposures) || (function == ADNumImages) ||
|
||||
(function == ADImageMode) ||
|
||||
(function == ADBinX) || (function == ADBinY) ||
|
||||
(function == ADMinX) || (function == ADMinY) ||
|
||||
(function == ADSizeX) || (function == ADSizeY) ||
|
||||
(function == ADReverseX) || (function == ADReverseY) ||
|
||||
(function == ADTriggerMode) || (function == AndorEmGain) ||
|
||||
(function == AndorEmGainMode) || (function == AndorEmGainAdvanced) ||
|
||||
(function == AndorAdcSpeed) || (function == AndorPreAmpGain) ||
|
||||
(function == AndorReadOutMode) || (function == AndorFrameTransferMode) ||
|
||||
(function == AndorVerticalShiftPeriod)) {
|
||||
status = setupAcquisition();
|
||||
if (function == AndorAdcSpeed) setupPreAmpGains();
|
||||
if (status != asynSuccess) setIntegerParam(function, oldValue);
|
||||
@@ -616,7 +668,14 @@ asynStatus AndorCCD::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
||||
status = setupShutter(-1);
|
||||
}
|
||||
else if (function == AndorBaselineClamp) {
|
||||
checkStatus(SetBaselineClamp(value));
|
||||
try {
|
||||
checkStatus(SetBaselineClamp(value));
|
||||
} catch (const std::string &e) {
|
||||
asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"%s:%s: %s\n",
|
||||
driverName, functionName, e.c_str());
|
||||
status = asynError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = ADDriver::writeInt32(pasynUser, value);
|
||||
@@ -1006,6 +1065,8 @@ asynStatus AndorCCD::setupAcquisition()
|
||||
int FKOffset;
|
||||
AndorADCSpeed_t *pSpeed;
|
||||
int readOutMode;
|
||||
int frameTransferMode;
|
||||
int verticalShiftPeriod;
|
||||
static const char *functionName = "setupAcquisition";
|
||||
|
||||
if (!mInitOK) {
|
||||
@@ -1094,6 +1155,10 @@ asynStatus AndorCCD::setupAcquisition()
|
||||
// for the actual size of the image, so we must compute it.
|
||||
setIntegerParam(NDArraySizeX, sizeX/binX);
|
||||
setIntegerParam(NDArraySizeY, sizeY/binY);
|
||||
|
||||
getIntegerParam(AndorFrameTransferMode, &frameTransferMode);
|
||||
|
||||
getIntegerParam(AndorVerticalShiftPeriod, &verticalShiftPeriod);
|
||||
|
||||
try {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||
@@ -1165,6 +1230,16 @@ asynStatus AndorCCD::setupAcquisition()
|
||||
checkStatus(SetEMCCDGain(emGain));
|
||||
}
|
||||
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||
"%s:%s:, SetFrameTransferMode(%d)\n",
|
||||
driverName, functionName, frameTransferMode);
|
||||
checkStatus(SetFrameTransferMode(frameTransferMode));
|
||||
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||
"%s:%s:, SetVSSpeed(%d)\n",
|
||||
driverName, functionName, verticalShiftPeriod);
|
||||
checkStatus(SetVSSpeed(verticalShiftPeriod));
|
||||
|
||||
switch (imageMode) {
|
||||
case ADImageSingle:
|
||||
if (numExposures == 1) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define MAX_ENUM_STRING_SIZE 26
|
||||
#define MAX_ADC_SPEEDS 16
|
||||
#define MAX_PREAMP_GAINS 16
|
||||
#define MAX_VS_PERIODS 16
|
||||
|
||||
#define AndorCoolerParamString "ANDOR_COOLER"
|
||||
#define AndorTempStatusMessageString "ANDOR_TEMP_STAT"
|
||||
@@ -35,6 +36,8 @@
|
||||
#define AndorAdcSpeedString "ANDOR_ADC_SPEED"
|
||||
#define AndorBaselineClampString "ANDOR_BASELINE_CLAMP"
|
||||
#define AndorReadOutModeString "ANDOR_READOUT_MODE"
|
||||
#define AndorFrameTransferModeString "ANDOR_FT_MODE"
|
||||
#define AndorVerticalShiftPeriodString "ANDOR_VS_PERIOD"
|
||||
|
||||
/**
|
||||
* Structure defining an ADC speed for the ADAndor driver.
|
||||
@@ -60,6 +63,16 @@ typedef struct {
|
||||
int EnumValue;
|
||||
} AndorPreAmpGain_t;
|
||||
|
||||
/*
|
||||
* Structure defining a Vertical Shift Period for the ADAndor driver.
|
||||
*/
|
||||
typedef struct {
|
||||
float Period;
|
||||
int Index;
|
||||
char *EnumString;
|
||||
int EnumValue;
|
||||
} AndorVSPeriod_t;
|
||||
|
||||
/**
|
||||
* Driver for Andor CCD cameras using version 2 of their SDK; inherits from ADDriver class in ADCore.
|
||||
*
|
||||
@@ -97,7 +110,9 @@ class AndorCCD : public ADDriver {
|
||||
int AndorAdcSpeed;
|
||||
int AndorBaselineClamp;
|
||||
int AndorReadOutMode;
|
||||
#define LAST_ANDOR_PARAM AndorReadOutMode
|
||||
int AndorFrameTransferMode;
|
||||
int AndorVerticalShiftPeriod;
|
||||
#define LAST_ANDOR_PARAM AndorVerticalShiftPeriod
|
||||
|
||||
private:
|
||||
|
||||
@@ -107,6 +122,7 @@ class AndorCCD : public ADDriver {
|
||||
void saveDataFrame(int frameNumber);
|
||||
void setupADCSpeeds();
|
||||
void setupPreAmpGains();
|
||||
void setupVerticalShiftPeriods();
|
||||
unsigned int SaveAsSPE(char *fullFileName);
|
||||
/**
|
||||
* Additional image mode to those in ADImageMode_t
|
||||
@@ -193,6 +209,13 @@ class AndorCCD : public ADDriver {
|
||||
int mNumPreAmpGains;
|
||||
AndorPreAmpGain_t mPreAmpGains[MAX_PREAMP_GAINS];
|
||||
|
||||
// Vertical Shift Period parameters
|
||||
int mTotalVSPeriods;
|
||||
int mNumVSPeriods;
|
||||
int mVSIndex;
|
||||
float mVSPeriod;
|
||||
AndorVSPeriod_t mVSPeriods[MAX_VS_PERIODS];
|
||||
|
||||
//Shutter control parameters
|
||||
float mAcquireTime;
|
||||
float mAcquirePeriod;
|
||||
|
||||
@@ -48,11 +48,12 @@
|
||||
<li>Support for all of the Andor shutter modes</li>
|
||||
<li>Support for reading the detectors with 16-bit or 32-bit depth</li>
|
||||
<li>Saving files using the Andor SDK and/or with the standard areaDetector plugins</li>
|
||||
<li>Change the ADC sampling speed (0.05MHz and 2.5MHz on the iKon)</li>
|
||||
<li>Change the ADC sampling speed (0.05MHz and 2.5MHz on the iKon) and the Vertical Shift Period</li>
|
||||
<li>Set a region of interest (a smaller region can be read out faster)</li>
|
||||
<li>Set and monitor the CCD temperature</li>
|
||||
<li>Electron Multiplying (EM) Gain on supported detectors</li>
|
||||
<li>Support for selecting between Full Vertical Binning (FVB) and Image readout modes</li>
|
||||
<li>Support for Frame Transfer mode</li>
|
||||
</ul>
|
||||
<p>
|
||||
The Andor module includes a separate driver to control the Andor Shamrock spectrographs.
|
||||
@@ -732,6 +733,56 @@
|
||||
mbbo<br />
|
||||
mbbi</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
AndorFTMode</td>
|
||||
<td>
|
||||
asynInt32</td>
|
||||
<td>
|
||||
R/W</td>
|
||||
<td>
|
||||
Set Frame Transfer mode. Choices are:
|
||||
<ul>
|
||||
<li>Disabled</li>
|
||||
<li>Enabled</li>
|
||||
</ul>
|
||||
Note: Only available on supported CCDs.
|
||||
</td>
|
||||
<td>
|
||||
ANDOR_FT_MODE</td>
|
||||
<td>
|
||||
AndorFTMode<br />
|
||||
AndorFTMode_RBV</td>
|
||||
<td>
|
||||
bo<br />
|
||||
bi</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
AndorVSPeriod</td>
|
||||
<td>
|
||||
asynInt32</td>
|
||||
<td>
|
||||
R/W</td>
|
||||
<td>
|
||||
Sets Vetical Shift Period, in units of microseconds per pixel shift.<br/>
|
||||
Choices are constructed at runtime. For example, the choices for an iDus are:
|
||||
<ul>
|
||||
<li>4.25 us</li>
|
||||
<li>8.25 us</li>
|
||||
<li>16.25 us</li>
|
||||
<li>32.25 us</li>
|
||||
<li>64.25 us</li>
|
||||
</ul>
|
||||
<td>
|
||||
ANDOR_VS_PERIOD</td>
|
||||
<td>
|
||||
AndorVSPeriod<br />
|
||||
AndorVSPeriod_RBV</td>
|
||||
<td>
|
||||
mbbo<br />
|
||||
mbbi</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="Unsupported" style="text-align: left">
|
||||
|
||||
Reference in New Issue
Block a user