Skip to content

Commit e5e93a8

Browse files
committed
don't send blank frame when EraseOnStart is enabled
while clearing API buffers and driver statistics can be reasonable to do when starting an acquisition, also sending a blank frame is not. when acquisition is started, clients like the HDF5 and ROI plugins are already enabled, so they will process this blank frame, leading to user confusion and data loss. for the HDF5 plugin, the resulting file will have an initial frame with empty data, and, if it's configured without knowledge of the empty frame, the last real frame will be discarded. for ROI plugins, CA clients should be able to expect a number of monitor events equal to the number of acquisitions, leading to similar issues. the blank frame creation was added by 734caa0 (update code to better match APS-update, but with trig_b / deadtime corrections, 2016-09-28). EraseOnStart was enabled by default for deployments using the provided startup snippets by 8354d65 (add dbpf for EraseOnStart to start as Yes, 2021-09-08). fix this issue by adding a sendFrame parameter to erase() and clearDriverAndPlugins(). This allows them to differentiate between being called by someone writing to the Erase PV (where we want to send a blank frame) and someone writing to the Acquire PV when EraseOnStart is enabled (where we don't want a blank frame).
1 parent edc708a commit e5e93a8

2 files changed

Lines changed: 28 additions & 26 deletions

File tree

xspress3App/src/xspress3Epics.cpp

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ Xspress3::Xspress3(const char *portName, int numChannels, int numCards, const ch
142142
// Initialize non static, non const, data members
143143
xsp3_handle_ = 0;
144144
bool paramStatus = this->setInitialParameters(maxFrames, maxDriverFrames, numCards, maxSpectra);
145-
paramStatus = ((clearDriverAndPlugins() == asynSuccess) && paramStatus);
145+
paramStatus = ((clearDriverAndPlugins(true) == asynSuccess) && paramStatus);
146146
// Create the thread that reads out the data
147147
status = (epicsThreadCreate("GeDataTask",
148148
epicsThreadPriorityHigh,
@@ -201,7 +201,7 @@ Xspress3::Xspress3(const char *portName, int numChannels)
201201
// Initialize non static, non const, data members
202202
xsp3_handle_ = 0;
203203
bool paramStatus = this->setInitialParameters(maxFrames, maxDriverFrames, numCards, maxSpectra);
204-
paramStatus = ((clearDriverAndPlugins() == asynSuccess) && paramStatus);
204+
paramStatus = ((clearDriverAndPlugins(true) == asynSuccess) && paramStatus);
205205
if (simTest) {
206206
paramStatus = ((setStringParam(ADStatusMessage, "Init. Simulation Mode.") == asynSuccess) && paramStatus);
207207
xsp3 = new xsp3Simulator(this->pasynUserSelf, numChannels, maxSpectra);
@@ -963,7 +963,7 @@ asynStatus Xspress3::checkRoi(int channel, int roi, int llm, int hlm)
963963
* Call xsp3_histogram_clear, and clear scalar data.
964964
* @return asynStatus
965965
*/
966-
asynStatus Xspress3::erase(void)
966+
asynStatus Xspress3::erase(bool sendFrame)
967967
{
968968
asynStatus status = asynSuccess;
969969
int xsp3_status = 0;
@@ -1000,7 +1000,7 @@ asynStatus Xspress3::erase(void)
10001000
setIntegerParam(ADStatus, ADStatusError);
10011001
status = asynError;
10021002
} else {
1003-
status = clearDriverAndPlugins();
1003+
status = clearDriverAndPlugins(sendFrame);
10041004
if (status == asynSuccess) {
10051005
setStringParam(ADStatusMessage, "Erased Data");
10061006
} else {
@@ -1018,13 +1018,13 @@ asynStatus Xspress3::erase(void)
10181018
/**
10191019
* Function to clear the driver parameters and any connected plugins (by sending an empty frame).
10201020
*/
1021-
asynStatus Xspress3::clearDriverAndPlugins(void)
1021+
asynStatus Xspress3::clearDriverAndPlugins(bool sendFrame)
10221022
{
10231023
int status = asynSuccess;
10241024
int xsp3_num_channels = 0;
10251025
const char *functionName = "Xspress3::clearDriverAndPlugins";
10261026

1027-
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Clear SCA data, MCA ROI data and all arrays.\n", functionName);
1027+
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Clear driver parameters%s.\n", functionName, sendFrame ? " and connected plugins" : "");
10281028

10291029
getIntegerParam(xsp3NumChannelsParam, &xsp3_num_channels);
10301030

@@ -1047,29 +1047,31 @@ asynStatus Xspress3::clearDriverAndPlugins(void)
10471047
this->callParamCallbacks(chan);
10481048
}
10491049

1050-
// Send a blank frame
1051-
NDArray *pMCA;
1052-
int xsp3_max_spectra = 0;
1053-
getIntegerParam(xsp3MaxSpectraParam, &xsp3_max_spectra);
1050+
if (sendFrame) {
1051+
// Send a blank frame
1052+
NDArray *pMCA;
1053+
int xsp3_max_spectra = 0;
1054+
getIntegerParam(xsp3MaxSpectraParam, &xsp3_max_spectra);
10541055

1055-
NDDataType_t dataType = this->getDataType();
1056+
NDDataType_t dataType = this->getDataType();
10561057

1057-
size_t dims[2];
1058-
this->getDims(dims);
1058+
size_t dims[2];
1059+
this->getDims(dims);
10591060

1060-
pMCA = this->pNDArrayPool->alloc(2, dims, dataType, 0, NULL);
1061+
pMCA = this->pNDArrayPool->alloc(2, dims, dataType, 0, NULL);
10611062

1062-
if (pMCA != NULL) {
1063-
memset(pMCA->pData, 0, pMCA->dataSize);
1064-
this->setNDArrayAttributes(pMCA, -1);
1063+
if (pMCA != NULL) {
1064+
memset(pMCA->pData, 0, pMCA->dataSize);
1065+
this->setNDArrayAttributes(pMCA, -1);
10651066

1066-
this->lock();
1067+
this->lock();
10671068

1068-
this->callParamCallbacks();
1069-
this->unlock();
1070-
this->doNDCallbacksIfRequired(pMCA);
1069+
this->callParamCallbacks();
1070+
this->unlock();
1071+
this->doNDCallbacksIfRequired(pMCA);
10711072

1072-
pMCA->release();
1073+
pMCA->release();
1074+
}
10731075
}
10741076

10751077
if (!paramStatus) {
@@ -1299,7 +1301,7 @@ asynStatus Xspress3::writeInt32(asynUser *pasynUser, epicsInt32 value)
12991301
}
13001302
} else if (function == xsp3EraseParam) {
13011303
if (adStatus != ADStatusAcquire) {
1302-
status = erase();
1304+
status = erase(true);
13031305
}
13041306
} else if (function == xsp3SoftTriggerParam) {
13051307

@@ -1322,7 +1324,7 @@ asynStatus Xspress3::writeInt32(asynUser *pasynUser, epicsInt32 value)
13221324
getIntegerParam(xsp3EraseStartParam, &xsp3_erasestart);
13231325
// printf(" erase on start %d\n", xsp3_erasestart);
13241326
if (xsp3_erasestart) {
1325-
erase();
1327+
erase(false);
13261328
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s Erased Before Data Collection\n", functionName);
13271329
} else {
13281330
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s No Erase Before Data Collection\n", functionName);

xspress3App/src/xspress3Epics.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ class Xspress3 : public ADDriver {
166166
asynStatus checkConnected(void);
167167
asynStatus setWindow(int channel, int sca, int llm, int hlm);
168168
asynStatus checkRoi(int channel, int roi, int llm, int hlm);
169-
asynStatus erase(void);
170-
asynStatus clearDriverAndPlugins(void);
169+
asynStatus erase(bool sendFrame);
170+
asynStatus clearDriverAndPlugins(bool sendFrame);
171171
asynStatus checkSaveDir(const char *dirName);
172172
asynStatus readSCAParams(void);
173173
asynStatus readDTCParams(void);

0 commit comments

Comments
 (0)