Current draft for the detector axis tower driver

This commit is contained in:
2025-03-04 16:38:00 +01:00
parent 8b185c6260
commit 747d08c52a
8 changed files with 718 additions and 308 deletions
+130 -68
View File
@@ -1,6 +1,8 @@
#include "detectorTowerController.h"
#include "detectorTowerAxis.h"
#include "turboPmacController.h"
#include <epicsExport.h>
#include <errlog.h>
#include <iocsh.h>
/**
@@ -38,6 +40,17 @@ detectorTowerController::detectorTowerController(
exit(-1);
}
status =
createParam("LIFT_OFFSET_MOVE", asynParamFloat64, &liftOffsetMove_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
status = createParam("LIFT_OFFSET_LOW_LIMIT", asynParamFloat64,
&liftOffsetLowLimit_);
if (status != asynSuccess) {
@@ -70,6 +83,17 @@ detectorTowerController::detectorTowerController(
exit(-1);
}
status =
createParam("TILT_OFFSET_MOVE", asynParamFloat64, &tiltOffsetMove_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
status = createParam("TILT_OFFSET_LOW_LIMIT", asynParamFloat64,
&tiltOffsetLowLimit_);
if (status != asynSuccess) {
@@ -92,6 +116,16 @@ detectorTowerController::detectorTowerController(
exit(-1);
}
status = createParam("BEAM_ANGLE", asynParamFloat64, &beamAngle_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
status = createParam("POSITION_STATE", asynParamInt32, &positionState_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
@@ -102,7 +136,28 @@ detectorTowerController::detectorTowerController(
exit(-1);
}
status = createParam("RESET", asynParamInt32, &reset_);
status = createParam("START", asynParamInt32, &start_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
status = createParam("MOVE_TO_WORKING_POSITION", asynParamInt32,
&moveToWorkingPosition_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
status = createParam("RESET_ERROR", asynParamInt32, &resetError_);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
@@ -115,12 +170,20 @@ detectorTowerController::detectorTowerController(
asynStatus detectorTowerController::readInt32(asynUser *pasynUser,
epicsInt32 *value) {
// The detector tower cannot be disabled
if (pasynUser->reason == motorCanDisable_) {
*value = 0;
return asynSuccess;
} else {
// Check if the axis is a detectorTowerAxis
detectorTowerAxis *axis = getDetectorTowerAxis(pasynUser);
if (axis == nullptr) {
// This is apparently a "normal" turboPmacAxis
return turboPmacController::readInt32(pasynUser, value);
} else {
// The detector tower cannot be disabled
if (pasynUser->reason == motorCanDisable_) {
*value = 0;
return asynSuccess;
} else {
return turboPmacController::readInt32(pasynUser, value);
}
}
}
@@ -130,22 +193,40 @@ asynStatus detectorTowerController::writeInt32(asynUser *pasynUser,
// =====================================================================
detectorTowerAxis *axis = getVirtualAxis(pasynUser);
if (axis == nullptr) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d:\nAxis is not an "
"instance of sinqAxis",
portName, axis->axisNo_, __PRETTY_FUNCTION__, __LINE__);
return asynError;
}
detectorTowerAxis *axis = getDetectorTowerAxis(pasynUser);
// Handle custom PVs
if (function == motorEnable_) {
return axis->enable(value);
} else if (function == reset_) {
return axis->reset();
} else {
if (axis == nullptr) {
// This is apparently a "normal" turboPmacAxis
return turboPmacController::writeInt32(pasynUser, value);
} else {
// Handle custom PVs
if (function == start_) {
// Start the movement, if the axis is not already moving.
// Otherwise stop it and schedule a movement.
int done = 0;
asynStatus status =
getIntegerParam(axis->axisNo_, motorStatusDone_, &done);
if (status != asynSuccess) {
return paramLibAccessFailed(status, "motorStatusDone_",
axis->axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
if (done == 1) {
return axis->moveFromParamLib();
} else {
axis->scheduleMoveFromParamLib_ = true;
return axis->stop(0.0);
}
} else if (function == moveToWorkingPosition_) {
return axis->moveToWorkingPosition(value != 0);
} else if (function == resetError_) {
return axis->reset();
} else {
return turboPmacController::writeInt32(pasynUser, value);
}
}
}
@@ -153,30 +234,33 @@ asynStatus detectorTowerController::writeFloat64(asynUser *pasynUser,
epicsFloat64 value) {
int function = pasynUser->reason;
// =====================================================================
detectorTowerAxis *axis = getDetectorTowerAxis(pasynUser);
detectorTowerAxis *axis = getVirtualAxis(pasynUser);
if (axis == nullptr) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d:\nAxis is not an "
"instance of sinqAxis",
portName, axis->axisNo_, __PRETTY_FUNCTION__, __LINE__);
return asynError;
}
if (function == motorTargetPosition_) {
// Start the movement, if the axis is not already moving. Otherwise stop
// it and schedule a movement.
bool moving = false;
axis->poll(&moving);
if (moving) {
axis->scheduleMoveFromParamLib_ = true;
return axis->stop(0.0);
} else {
return axis->moveFromParamLib();
}
} else {
// This is apparently a "normal" turboPmacAxis
return turboPmacController::writeFloat64(pasynUser, value);
} else {
if (function == liftOffsetMove_) {
asynStatus status =
setDoubleParam(axis->axisNo_, liftOffset_, value);
if (status != asynSuccess) {
return paramLibAccessFailed(status, "liftOffset_",
axis->axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return axis->moveFromParamLib();
} else if (function == tiltOffsetMove_) {
asynStatus status =
setDoubleParam(axis->axisNo_, tiltOffset_, value);
if (status != asynSuccess) {
return paramLibAccessFailed(status, "tiltOffset_",
axis->axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return axis->moveFromParamLib();
} else {
return turboPmacController::writeFloat64(pasynUser, value);
}
}
}
@@ -186,40 +270,18 @@ If the axis does not exist or is not a Axis, a nullptr is returned and an
error is emitted.
*/
detectorTowerAxis *
detectorTowerController::getVirtualAxis(asynUser *pasynUser) {
detectorTowerController::getDetectorTowerAxis(asynUser *pasynUser) {
asynMotorAxis *asynAxis = asynMotorController::getAxis(pasynUser);
return detectorTowerController::castToVirtualAxis(asynAxis);
return dynamic_cast<detectorTowerAxis *>(asynAxis);
}
/*
Access one of the axes of the controller via the axis index.
If the axis does not exist or is not a Axis, the function must return Null
*/
detectorTowerAxis *detectorTowerController::getVirtualAxis(int axisNo) {
detectorTowerAxis *detectorTowerController::getDetectorTowerAxis(int axisNo) {
asynMotorAxis *asynAxis = asynMotorController::getAxis(axisNo);
return detectorTowerController::castToVirtualAxis(asynAxis);
}
detectorTowerAxis *
detectorTowerController::castToVirtualAxis(asynMotorAxis *asynAxis) {
// =========================================================================
// If the axis slot of the pAxes_ array is empty, a nullptr must be returned
if (asynAxis == nullptr) {
return nullptr;
}
// Here, an error is emitted since asyn_axis is not a nullptr but also not
// an instance of Axis
detectorTowerAxis *axis = dynamic_cast<detectorTowerAxis *>(asynAxis);
if (axis == nullptr) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
"an instance of turboPmacAxis",
portName, axis->axisNo_, __PRETTY_FUNCTION__, __LINE__);
}
return axis;
return dynamic_cast<detectorTowerAxis *>(asynAxis);
}
/*************************************************************************************/
@@ -292,4 +354,4 @@ static void detectorTowerControllerRegister(void) {
}
epicsExportRegistrar(detectorTowerControllerRegister);
} // extern "C"
} // extern "C"