Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sim/xspdSimulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"""
FastAPI + ZMQ based simulator for the ADXSPD driver.

Loads initial state from a JSON dump file (same format as
xspdApp/tests/samples/xspd_sample_responses.json) and serves
Loads initial state from a JSON dump file created with the
generate_sample_response_json.py script and serves
the REST API expected by the ADXSPD EPICS driver while streaming
simulated image data over ZMQ.

Expand Down
58 changes: 43 additions & 15 deletions xspdApp/src/ADXSPD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ void ADXSPD::acquisitionThread() {
// void* prevFrameBuffer = nullptr;

int arrayCallbacks, decompress;
int collectedImages;
int collectedImages, summedFrames;

void* zmqSubscriber = zmq_socket(this->zmqContext, ZMQ_SUB);
int rc = zmq_connect(zmqSubscriber, this->pDetector->GetActiveDataPort()->GetURI().c_str());
Expand Down Expand Up @@ -718,12 +718,32 @@ asynStatus ADXSPD::writeInt32(asynUser* pasynUser, epicsInt32 value) {
string endpoint;
if (function == ADXSPD_BitDepth) {
actualValue = this->pDetector->SetVar<int>("bit_depth", value);
setIntegerParam(NDDataType, static_cast<int>(getDataTypeForBitDepth(actualValue)));
int summedFrames = this->pDetector->GetVar<int>("summed_frames");
if (summedFrames > 1) {
// If summed frames > 1, libxsp will always return uint32 data regardless of bit depth, so set that here to avoid confusion
setIntegerParam(NDDataType, NDUInt32);
} else {
setIntegerParam(NDDataType, static_cast<int>(getDataTypeForBitDepth(actualValue)));
}
for (auto& module : this->modules) {
module->getMaxNumImages();
}
} else if (function == ADXSPD_SummedFrames) {
actualValue = this->pDetector->SetVar<int>("summed_frames", value);
XSPD::CounterMode counterMode;
getIntegerParam(ADXSPD_CounterMode, (int*) &counterMode);
if (counterMode == XSPD::CounterMode::DUAL && value > 1) {
ERR_TO_STATUS("Dual counter mode not supporeted with summed frames > 1");
status = asynError;
} else {
actualValue = this->pDetector->SetVar<int>("summed_frames", value);
if (actualValue > 1) {
// If summed frames > 1, libxsp will always return uint32 data regardless of bit depth, so set that here to avoid confusion
setIntegerParam(NDDataType, NDUInt32);
} else {
int bitDepth = static_cast<int>(this->pDetector->GetVar<int>("bit_depth"));
setIntegerParam(NDDataType, static_cast<int>(getDataTypeForBitDepth(bitDepth)));
}
}
} else if (function == ADXSPD_RoiRows) {
actualValue = static_cast<int>(this->pDetector->SetVar<int>("roi_rows", value));
for (auto& module : this->modules) {
Expand All @@ -745,11 +765,17 @@ asynStatus ADXSPD::writeInt32(asynUser* pasynUser, epicsInt32 value) {
actualValue = static_cast<int>(this->pDetector->SetVar<XSPD::OnOff>(
"countrate_correction", static_cast<XSPD::OnOff>(value)));
} else if (function == ADXSPD_CounterMode) {
actualValue = static_cast<int>(this->pDetector->SetVar<XSPD::CounterMode>(
"counter_mode", static_cast<XSPD::CounterMode>(value)));
for (auto& module : this->modules) {
module->getMaxNumImages();
module->getFlatfieldState(); // FF is different for each counter mode
int framesSummed;
getIntegerParam(ADXSPD_SummedFrames, &framesSummed);
if (framesSummed > 1) {
ERR_TO_STATUS("Dual counter mode not supporeted with summed frames > 1");
} else {
actualValue = static_cast<int>(this->pDetector->SetVar<XSPD::CounterMode>(
"counter_mode", static_cast<XSPD::CounterMode>(value)));
for (auto& module : this->modules) {
module->getMaxNumImages();
module->getFlatfieldState(); // FF is different for each counter mode
}
}
} else if (function == ADXSPD_SaturationFlag) {
actualValue = static_cast<int>(this->pDetector->SetVar<XSPD::OnOff>(
Expand All @@ -763,13 +789,15 @@ asynStatus ADXSPD::writeInt32(asynUser* pasynUser, epicsInt32 value) {
}
}

setIntegerParam(function, actualValue);
if (actualValue != value) {
WARN_ARGS("Requested value %d for parameter %s, but set value is %d", value,
paramName, actualValue);
status = asynError;
if (status != asynError) {
setIntegerParam(function, actualValue);
if (actualValue != value) {
WARN_ARGS("Requested value %d for parameter %s, but set value is %d", value,
paramName, actualValue);
status = asynError;
}
INFO_TO_STATUS_ARGS("Set %s to %d", formatParamName(paramName).c_str(), actualValue);
}
INFO_TO_STATUS_ARGS("Set %s to %d", formatParamName(paramName).c_str(), actualValue);
} catch (std::invalid_argument& e) {
ERR_TO_STATUS_ARGS("Invalid argument when setting parameter %s: %s", paramName,
e.what());
Expand All @@ -782,7 +810,7 @@ asynStatus ADXSPD::writeInt32(asynUser* pasynUser, epicsInt32 value) {
callParamCallbacks();

if (status) {
ERR_TO_STATUS_ARGS("status=%d, parameter=%s, value=%d", status, paramName, value);
ERR_ARGS("status=%d, parameter=%s, value=%d", status, paramName, value);
return asynError;
} else {
DEBUG_ARGS("parameter=%s value=%d", paramName, value);
Expand Down