14 Commits
0.2.0 ... 1.1.0

Author SHA1 Message Date
bc8561c299 Updated turboPmac version 2025-06-18 08:33:04 +02:00
cf6f836416 Updated turboPmac version 2025-06-17 16:51:08 +02:00
6e99b37ed2 Updated turboPmac version 2025-06-17 13:26:13 +02:00
f745af48fe Added destructor for detectorTowerController 2025-06-10 15:04:34 +02:00
0fd312b672 Updated dependency turboPmac to 1.1.1 2025-06-10 15:01:42 +02:00
c15e513b2e Updated turboPmac to 1.1.1 2025-06-10 15:00:33 +02:00
6f9b890374 Updated turboPmac to 1.1 2025-06-10 14:44:59 +02:00
fbbe8c4553 Updated turboPmac to 1.1 2025-06-10 14:22:15 +02:00
675819741b Updated turboPmac version 2025-06-10 13:57:57 +02:00
eb3826ec35 Stop or reset now also resets the deferred movement flags 2025-06-10 11:15:40 +02:00
5dd5a26243 Removed unnecessary code (bug in sinqMotor has been found) 2025-05-16 16:33:49 +02:00
832884179c Updated dependencies sinqMotor and turboPmac both to 0.15.2 2025-05-16 16:17:36 +02:00
94edef6cd8 New error message always results in status problem
Previously, a new error message did not automatically result in a status
problem being shown. This patch fixes that.
2025-05-16 11:29:38 +02:00
afdd66a648 Adjusted link to turboPmac repository 2025-05-15 17:18:39 +02:00
10 changed files with 160 additions and 586 deletions

View File

@ -6,7 +6,7 @@
![Coordinate systems](images/CoordinateSystems.svg)
This is a driver for the detector tower which is based on the Turbo PMAC driver (https://git.psi.ch/sinq-epics-modules/turboPmac). It consists of the following four objects:
This is a driver for the detector tower which is based on the Turbo PMAC driver (https://gitea.psi.ch/lin-epics-modules/turboPmac). It consists of the following four objects:
- `detectorTowerController`: This is an expanded variant of `turboPmacController` provided by the Turbo PMAC library linked above.It is needed to operate a `detectorTowerAngleAxis`, but it can also be used to operate a "normal" `turboPmacAxis`.
- `detectorTowerAngleAxis`: This is a virtual axis which controls multiple physical motors ($x$ and $z$) in order to provide a combined movement. Moving it results in a rotation of the entire beam around the support axis position ($\alpha$).
- `detectorTowerLiftAxis`: This is a virtual axis which controls multiple physical motors in order to provide a combined movement. Moving it results in a vertical lift ($z_{lift}$).

View File

@ -1,5 +1,7 @@
#include "detectorTowerAngleAxis.h"
#include "detectorTowerController.h"
#include "detectorTowerLiftAxis.h"
#include "detectorTowerSupportAxis.h"
#include "turboPmacController.h"
#include <epicsExport.h>
#include <errlog.h>
@ -157,17 +159,8 @@ asynStatus detectorTowerAngleAxis::init() {
}
// Initialize the motorStatusMoving flag
status = setIntegerParam(pC_->motorStatusMoving(), 0);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusMoving_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
status = setIntegerParam(pC_->changeStateRBV(), positionState == 2);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "changeStateRBV", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(this, motorStatusMoving, false);
setAxisParamChecked(this, changeStateRBV, positionState == 2);
return callParamCallbacks();
}
@ -181,15 +174,9 @@ asynStatus detectorTowerAngleAxis::poll(bool *moving) {
if (axisNo() < liftAxis()->axisNo() && axisNo() < supportAxis()->axisNo()) {
status = pC_->pollDetectorAxes(moving, this, liftAxis(), supportAxis());
} else {
status = pC_->getIntegerParam(axisNo(), pC_->motorStatusMoving(),
(int *)moving);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusMoving",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
getAxisParamChecked(this, motorStatusMoving, moving);
}
wasMoving_ = *moving;
setWasMoving(*moving);
return status;
}
@ -206,17 +193,11 @@ asynStatus detectorTowerAngleAxis::doMove(double position, int relative,
double max_velocity,
double acceleration) {
double motorRecResolution = 0.0;
asynStatus plStatus = pC_->getDoubleParam(
axisNo_, pC_->motorRecResolution(), &motorRecResolution);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorRecResolution_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
// Signal to the deferredMovementCollectorLoop that a movement should be
// started to the defined target position.
targetPosition_ = position * motorRecResolution;
setTargetPosition(position * motorRecResolution);
receivedTarget_ = true;
return asynSuccess;
@ -225,10 +206,7 @@ asynStatus detectorTowerAngleAxis::doMove(double position, int relative,
asynStatus detectorTowerAngleAxis::startCombinedMove() {
// Status of read-write-operations of ASCII commands to the controller
asynStatus rwStatus = asynSuccess;
// Status of parameter library operations
asynStatus plStatus = asynSuccess;
asynStatus status = asynSuccess;
char command[pC_->MAXBUF_] = {0};
char response[pC_->MAXBUF_] = {0};
@ -237,12 +215,7 @@ asynStatus detectorTowerAngleAxis::startCombinedMove() {
// =========================================================================
plStatus =
pC_->getIntegerParam(axisNo_, pC_->positionStateRBV(), &positionState);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "positionStateRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(this, positionStateRBV, &positionState);
// If the axis is in changer position, it must be moved into working
// position before any move can be started.
@ -259,20 +232,9 @@ asynStatus detectorTowerAngleAxis::startCombinedMove() {
pC_->getMsgPrintControl().getSuffix());
}
if (isInChangerPos) {
plStatus = setStringParam(pC_->motorMessageText(),
"Move the axis to working state first.");
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorMessageText",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
plStatus = setIntegerParam(pC_->motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, motorMessageText,
"Move the axis to working state first.");
setAxisParamChecked(this, motorStatusProblem, true);
callParamCallbacks();
startingDeferredMovement_ = false;
@ -282,77 +244,64 @@ asynStatus detectorTowerAngleAxis::startCombinedMove() {
// Set the target positions for beam tilt, detector tilt offset and lift
// offset
snprintf(command, sizeof(command), "Q451=%lf Q454=%lf P350=1",
targetPosition_, liftAxis_->targetPosition_);
targetPosition(), liftAxis_->targetPosition());
// Lock the access to the controller since this function runs in another
// thread than the poll method.
pC_->lock();
// We don't expect an answer
rwStatus = pC_->writeRead(axisNo_, command, response, 0);
status = pC_->writeRead(axisNo_, command, response, 0);
// Free the controller again
pC_->unlock();
if (rwStatus != asynSuccess) {
if (status != asynSuccess) {
asynPrint(
pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nStarting movement to "
"target position %lf failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
motorCoordinatesPosition);
plStatus = setIntegerParam(pC_->motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, motorStatusProblem, true);
callParamCallbacks();
}
return rwStatus;
return status;
}
asynStatus detectorTowerAngleAxis::stop(double acceleration) {
// Status of read-write-operations of ASCII commands to the controller
asynStatus rwStatus = asynSuccess;
// Status of parameter library operations
asynStatus plStatus = asynSuccess;
asynStatus status = asynSuccess;
char response[pC_->MAXBUF_] = {0};
// =========================================================================
rwStatus = pC_->writeRead(axisNo_, "P350=8", response, 0);
status = pC_->writeRead(axisNo_, "P350=8", response, 0);
if (rwStatus != asynSuccess) {
if (status != asynSuccess) {
asynPrint(
pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nStopping the movement "
"failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
plStatus = setIntegerParam(pC_->motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, motorStatusProblem, true);
return asynError;
}
return rwStatus;
// Reset the deferred movement flags
startingDeferredMovement_ = false;
deferredMovementWait_ = false;
return status;
}
// The detector tower axis uses absolute encoders
asynStatus detectorTowerAngleAxis::readEncoderType() {
asynStatus status = setStringParam(pC_->encoderType(), AbsoluteEncoder);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "encoderType_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(this, encoderType, AbsoluteEncoder);
return asynSuccess;
}
@ -362,27 +311,19 @@ detectorTowerAngleAxis::toggleWorkingChangerState(bool toChangingPosition) {
char response[pC_->MAXBUF_] = {0};
// Status of read-write-operations of ASCII commands to the controller
asynStatus rwStatus = asynSuccess;
// Status of parameter library operations
asynStatus plStatus = asynSuccess;
asynStatus status = asynSuccess;
bool moving = false;
int positionState = 0;
// =========================================================================
rwStatus = poll(&moving);
if (rwStatus != asynSuccess) {
return rwStatus;
status = poll(&moving);
if (status != asynSuccess) {
return status;
}
plStatus =
pC_->getIntegerParam(axisNo_, pC_->positionStateRBV(), &positionState);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "positionStateRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(this, positionStateRBV, &positionState);
if (moving) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
@ -392,21 +333,10 @@ detectorTowerAngleAxis::toggleWorkingChangerState(bool toChangingPosition) {
toChangingPosition ? "changer" : "working",
pC_->getMsgPrintControl().getSuffix());
plStatus = setStringParam(
pC_->motorMessageText(),
setAxisParamChecked(
this, motorMessageText,
"Axis cannot be moved to changer position while it is moving.");
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorMessageText_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
plStatus = setIntegerParam(pC_->changeStateRBV(), !toChangingPosition);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "changeStateRBV",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, changeStateRBV, !toChangingPosition);
return asynError;
}
@ -424,39 +354,20 @@ detectorTowerAngleAxis::toggleWorkingChangerState(bool toChangingPosition) {
pC_->getMsgPrintControl().getSuffix());
// Update the PV anyway, even though nothing changed.
plStatus = setIntegerParam(pC_->changeStateRBV(), toChangingPosition);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "changeStateRBV",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, changeStateRBV, toChangingPosition);
return asynSuccess;
}
// Move the axis into changer or working position
if (toChangingPosition) {
rwStatus = pC_->writeRead(axisNo_, "P350=2", response, 0);
status = pC_->writeRead(axisNo_, "P350=2", response, 0);
} else {
rwStatus = pC_->writeRead(axisNo_, "P350=3", response, 0);
status = pC_->writeRead(axisNo_, "P350=3", response, 0);
}
if (plStatus != asynSuccess) {
plStatus = setIntegerParam(pC_->changeStateRBV(), !toChangingPosition);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "changeStateRBV",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
}
plStatus = setIntegerParam(pC_->changeStateRBV(), toChangingPosition);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "changeStateRBV", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
return rwStatus;
setAxisParamChecked(this, changeStateRBV, toChangingPosition);
return asynSuccess;
}
asynStatus detectorTowerAngleAxis::adjustOrigin(double newOrigin) {
@ -468,12 +379,7 @@ asynStatus detectorTowerAngleAxis::adjustOrigin(double newOrigin) {
// =========================================================================
status =
pC_->getIntegerParam(axisNo_, pC_->positionStateRBV(), &positionState);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "positionStateRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(this, positionStateRBV, &positionState);
// If the axis is in changer position, it must be moved into working
// position before any move can be started.
@ -502,12 +408,7 @@ asynStatus detectorTowerAngleAxis::adjustOrigin(double newOrigin) {
"angle origin %lf failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
newOrigin);
status = setIntegerParam(pC_->motorStatusProblem(), true);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, motorStatusProblem, true);
}
return status;
@ -516,15 +417,13 @@ asynStatus detectorTowerAngleAxis::adjustOrigin(double newOrigin) {
asynStatus detectorTowerAngleAxis::doReset() {
char response[pC_->MAXBUF_] = {0};
asynStatus plStatus = asynSuccess;
int positionState = 0;
plStatus =
pC_->getIntegerParam(axisNo_, pC_->positionStateRBV(), &positionState);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "positionStateRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(this, positionStateRBV, &positionState);
// Reset the deferred movement flags
startingDeferredMovement_ = false;
deferredMovementWait_ = false;
/*
Check which action should be performed:

View File

@ -1,14 +1,7 @@
#ifndef detectorTowerAngleAxis_H
#define detectorTowerAngleAxis_H
#include "detectorTowerController.h"
#include "turboPmacAxis.h"
#include <errlog.h>
// Forward declaration of the controller class to resolve the cyclic dependency
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class detectorTowerController;
class detectorTowerLiftAxis;
class detectorTowerSupportAxis;
class detectorTowerAngleAxis : public turboPmacAxis {
public:
@ -164,6 +157,11 @@ class detectorTowerAngleAxis : public turboPmacAxis {
*/
int error_;
/**
* @brief Return a pointer to the axis controller
*/
virtual detectorTowerController *pController() override { return pC_; };
protected:
detectorTowerController *pC_;
detectorTowerLiftAxis *liftAxis_;

View File

@ -1,6 +1,7 @@
#include "detectorTowerController.h"
#include "detectorTowerAngleAxis.h"
#include "turboPmacController.h"
#include "detectorTowerLiftAxis.h"
#include "detectorTowerSupportAxis.h"
#include <epicsExport.h>
#include <errlog.h>
#include <iocsh.h>
@ -106,11 +107,13 @@ detectorTowerController::detectorTowerController(
}
}
detectorTowerController::~detectorTowerController() {}
asynStatus detectorTowerController::readInt32(asynUser *pasynUser,
epicsInt32 *value) {
// The detector axes cannot be disabled
if (pasynUser->reason == motorCanDisable_) {
if (pasynUser->reason == motorCanDisable()) {
detectorTowerAngleAxis *aAxis = getDetectorTowerAngleAxis(pasynUser);
if (aAxis != nullptr) {
*value = 0;
@ -150,31 +153,6 @@ asynStatus detectorTowerController::writeInt32(asynUser *pasynUser,
}
}
/*
Due to a bug which is currently not understood, the reset has to be handled
here rather than using the default implementation in sinqController. Piping
the motor reset request to sinqController causes segfaults. It might be due
to the fact that the default `reset` implementation of sinqAxis locks the
controller in order to perform some fast polls and that for some reason this
behaviour cannot be overwritten even by providing custom `reset` methods for
all three axes.
*/
if (pasynUser->reason == motorReset_) {
detectorTowerAngleAxis *aAxis = getDetectorTowerAngleAxis(pasynUser);
if (aAxis != nullptr) {
return aAxis->reset();
}
detectorTowerLiftAxis *lAxis = getDetectorTowerLiftAxis(pasynUser);
if (lAxis != nullptr) {
return lAxis->reset();
}
detectorTowerSupportAxis *sAxis =
getDetectorTowerSupportAxis(pasynUser);
if (sAxis != nullptr) {
return sAxis->reset();
}
}
return turboPmacController::writeInt32(pasynUser, value);
}
@ -309,7 +287,7 @@ asynStatus detectorTowerController::pollDetectorAxes(
int error = 0;
int positionState = 0;
int inPosition = 0;
int notInPosition = 0;
double angle = 0.0;
double prevAngle = 0.0;
@ -359,37 +337,13 @@ asynStatus detectorTowerController::pollDetectorAxes(
The motorStatusProblem_ field changes the motor record fields SEVR and STAT.
*/
plStatus = angleAxis->setIntegerParam(motorStatusProblem(), false);
if (plStatus != asynSuccess) {
paramLibAccessFailed(plStatus, "motorStatusProblem_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(motorStatusProblem(), false);
if (plStatus != asynSuccess) {
paramLibAccessFailed(plStatus, "motorStatusProblem_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setIntegerParam(motorStatusProblem(), false);
if (plStatus != asynSuccess) {
paramLibAccessFailed(plStatus, "motorStatusProblem_", supportAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorStatusProblem, false);
setAxisParamChecked(liftAxis, motorStatusProblem, false);
setAxisParamChecked(supportAxis, motorStatusProblem, false);
plStatus = angleAxis->setIntegerParam(motorStatusCommsError(), false);
if (plStatus != asynSuccess) {
paramLibAccessFailed(plStatus, "motorStatusCommsError_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(motorStatusCommsError(), false);
if (plStatus != asynSuccess) {
paramLibAccessFailed(plStatus, "motorStatusCommsError_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setIntegerParam(motorStatusCommsError(), false);
if (plStatus != asynSuccess) {
paramLibAccessFailed(plStatus, "motorStatusCommsError_", supportAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorStatusCommsError, false);
setAxisParamChecked(liftAxis, motorStatusCommsError, false);
setAxisParamChecked(supportAxis, motorStatusCommsError, false);
// Read the previous motor positions
plStatus = angleAxis->motorPosition(&prevAngle);
@ -426,7 +380,7 @@ asynStatus detectorTowerController::pollDetectorAxes(
nvals =
sscanf(response,
"%d %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
&inPosition, &positionState, &error, &angle, &angleHighLimit,
&notInPosition, &positionState, &error, &angle, &angleHighLimit,
&angleLowLimit, &angleOrigin, &angleAdjustOriginHighLimit,
&angleAdjustOriginLowLimit, &lift, &liftHighLimit, &liftLowLimit,
&liftOrigin, &liftAdjustOriginHighLimit,
@ -450,20 +404,12 @@ asynStatus detectorTowerController::pollDetectorAxes(
*/
// Angle
plStatus = getDoubleParam(angleAxisNo, motorLimitsOffset(), &limitsOffset);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorLimitsOffset_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(angleAxis, motorLimitsOffset, &limitsOffset);
angleHighLimit = angleHighLimit - limitsOffset;
angleLowLimit = angleLowLimit + limitsOffset;
// Lift
plStatus = getDoubleParam(liftAxisNo, motorLimitsOffset(), &limitsOffset);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorLimitsOffset_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(liftAxis, motorLimitsOffset, &limitsOffset);
liftHighLimit = liftHighLimit - limitsOffset;
liftLowLimit = liftLowLimit + limitsOffset;
@ -471,7 +417,7 @@ asynStatus detectorTowerController::pollDetectorAxes(
angleAxis->error_ = error;
// Check if the tower is moving
if (inPosition == 1 || positionState > 2) {
if (notInPosition == 1 || positionState > 2) {
// By now, the controller has actually started the movement
angleAxis->startingDeferredMovement_ = false;
*moving = true;
@ -835,257 +781,84 @@ asynStatus detectorTowerController::pollDetectorAxes(
Does the paramLib already contain an error message? If either this is the
case or if error != 0, report a status problem for all axes.
*/
getStringParam(angleAxisNo, motorMessageText(), sizeof(waitingErrorMessage),
waitingErrorMessage);
getAxisParamChecked(angleAxis, motorMessageText, &waitingErrorMessage);
if (error != 0 || waitingErrorMessage[0] != '\0') {
if (error != 0 || errorMessage[0] != '\0' ||
waitingErrorMessage[0] != '\0') {
plStatus = angleAxis->setIntegerParam(motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusProblem_",
angleAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
plStatus = liftAxis->setIntegerParam(motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusProblem_",
liftAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
plStatus = supportAxis->setIntegerParam(motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusProblem_",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(angleAxis, motorStatusProblem, true);
setAxisParamChecked(liftAxis, motorStatusProblem, true);
setAxisParamChecked(supportAxis, motorStatusProblem, true);
}
// Update the error message text with the one created in this poll (in case
// it is not empty).
if (errorMessage[0] != '\0') {
plStatus = angleAxis->setStringParam(motorMessageText(), errorMessage);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorMessageText_",
angleAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
plStatus = liftAxis->setStringParam(motorMessageText(), errorMessage);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorMessageText_",
liftAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
plStatus =
supportAxis->setStringParam(motorMessageText(), errorMessage);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorMessageText_",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(angleAxis, motorMessageText, errorMessage);
setAxisParamChecked(liftAxis, motorMessageText, errorMessage);
setAxisParamChecked(supportAxis, motorMessageText, errorMessage);
}
// Update the working position state PV
plStatus = angleAxis->setIntegerParam(positionStateRBV(), positionState);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "positionStateRBV_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(positionStateRBV(), positionState);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "positionStateRBV_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setIntegerParam(positionStateRBV(), positionState);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "positionStateRBV_",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(angleAxis, positionStateRBV, positionState);
setAxisParamChecked(liftAxis, positionStateRBV, positionState);
setAxisParamChecked(supportAxis, positionStateRBV, positionState);
// The axes are always enabled
plStatus = angleAxis->setIntegerParam(motorEnableRBV(), 1);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorEnableRBV_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(motorEnableRBV(), 1);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorEnableRBV_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setIntegerParam(motorEnableRBV(), 1);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorEnableRBV_", supportAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorEnableRBV, true);
setAxisParamChecked(liftAxis, motorEnableRBV, true);
setAxisParamChecked(supportAxis, motorEnableRBV, true);
// Are the axes currently moving?
plStatus = angleAxis->setIntegerParam(motorStatusMoving(), *moving);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusMoving_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(motorStatusMoving(), *moving);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusMoving_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setIntegerParam(motorStatusMoving(), *moving);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusMoving_",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(angleAxis, motorStatusMoving, *moving);
setAxisParamChecked(liftAxis, motorStatusMoving, *moving);
setAxisParamChecked(supportAxis, motorStatusMoving, *moving);
// Is the axis movement done?
plStatus = angleAxis->setIntegerParam(motorStatusDone(), !(*moving));
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusDone_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(motorStatusDone(), !(*moving));
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusDone_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setIntegerParam(motorStatusDone(), !(*moving));
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusDone_", supportAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorStatusDone, !(*moving));
setAxisParamChecked(liftAxis, motorStatusDone, !(*moving));
setAxisParamChecked(supportAxis, motorStatusDone, !(*moving));
// In which direction are the axes currently moving?
plStatus = angleAxis->setIntegerParam(motorStatusDirection(), angleDir);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusDirection_",
angleAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setIntegerParam(motorStatusDirection(), liftDir);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusDirection_",
liftAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorStatusDirection, angleDir);
setAxisParamChecked(liftAxis, motorStatusDirection, liftDir);
// Using the lift direction for the support axis is done on purpose!
plStatus = supportAxis->setIntegerParam(motorStatusDirection(), liftDir);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorStatusDirection_",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(supportAxis, motorStatusDirection, liftDir);
// High limits from hardware
plStatus =
setDoubleParam(angleAxisNo, motorHighLimitFromDriver(), angleHighLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorHighLimitFromDriver",
angleAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
plStatus =
setDoubleParam(liftAxisNo, motorHighLimitFromDriver(), liftHighLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorHighLimitFromDriver",
liftAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorHighLimitFromDriver, angleHighLimit);
setAxisParamChecked(liftAxis, motorHighLimitFromDriver, liftHighLimit);
// Using the lift high limit for the support axis is done on purpose!
plStatus = setDoubleParam(supportAxisNo, motorHighLimitFromDriver(),
liftHighLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorHighLimitFromDriver",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(supportAxis, motorHighLimitFromDriver, liftHighLimit);
// Low limits from hardware
plStatus =
setDoubleParam(angleAxisNo, motorLowLimitFromDriver(), angleLowLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorLowLimitFromDriver",
angleAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
plStatus =
setDoubleParam(liftAxisNo, motorLowLimitFromDriver(), liftLowLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorLowLimitFromDriver",
liftAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorLowLimitFromDriver, angleLowLimit);
setAxisParamChecked(liftAxis, motorLowLimitFromDriver, liftLowLimit);
// Using the lift low limit for the support axis is done on purpose!
plStatus =
setDoubleParam(supportAxisNo, motorLowLimitFromDriver(), liftLowLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorLowLimitFromDriver",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(supportAxis, motorLowLimitFromDriver, liftLowLimit);
// Write the motor origin
plStatus = setDoubleParam(angleAxisNo, motorOrigin(), angleOrigin);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorOrigin", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = setDoubleParam(liftAxisNo, motorOrigin(), liftOrigin);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorOrigin", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = setDoubleParam(supportAxisNo, motorOrigin(), supportOrigin);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "supportOrigin", supportAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorOrigin, angleOrigin);
setAxisParamChecked(liftAxis, motorOrigin, liftOrigin);
setAxisParamChecked(supportAxis, motorOrigin, supportOrigin);
// Origin adjustment high limit
plStatus =
setDoubleParam(angleAxisNo, motorAdjustOriginHighLimitFromDriver(),
angleAdjustOriginHighLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorOriginHighLimitFromDriver",
angleAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
plStatus =
setDoubleParam(liftAxisNo, motorAdjustOriginHighLimitFromDriver(),
liftAdjustOriginHighLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorOriginHighLimitFromDriver",
liftAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorAdjustOriginHighLimitFromDriver,
angleAdjustOriginHighLimit);
setAxisParamChecked(liftAxis, motorAdjustOriginHighLimitFromDriver,
liftAdjustOriginHighLimit);
// Using the lift high limit for the support axis is done on purpose!
plStatus =
setDoubleParam(supportAxisNo, motorAdjustOriginHighLimitFromDriver(),
liftAdjustOriginHighLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorOriginHighLimitFromDriver",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(supportAxis, motorAdjustOriginHighLimitFromDriver,
liftAdjustOriginHighLimit);
// Origin adjustment low limit
plStatus =
setDoubleParam(angleAxisNo, motorAdjustOriginLowLimitFromDriver(),
angleAdjustOriginLowLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus,
"motorAdjustOriginLowLimitFromDriver",
angleAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
plStatus = setDoubleParam(liftAxisNo, motorAdjustOriginLowLimitFromDriver(),
liftAdjustOriginLowLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus,
"motorAdjustOriginLowLimitFromDriver",
liftAxisNo, __PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(angleAxis, motorAdjustOriginLowLimitFromDriver,
angleAdjustOriginLowLimit);
setAxisParamChecked(liftAxis, motorAdjustOriginLowLimitFromDriver,
liftAdjustOriginLowLimit);
// Using the lift low limit for the support axis is done on purpose!
plStatus =
setDoubleParam(supportAxisNo, motorAdjustOriginLowLimitFromDriver(),
liftAdjustOriginLowLimit);
if (plStatus != asynSuccess) {
return paramLibAccessFailed(
plStatus, "motorAdjustOriginLowLimitFromDriver", supportAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(supportAxis, motorAdjustOriginLowLimitFromDriver,
liftAdjustOriginLowLimit);
// Axes positions
plStatus = angleAxis->setMotorPosition(angle);
@ -1159,22 +932,9 @@ asynStatus detectorTowerController::pollDetectorAxes(
one poll cycle, but are cleared afterwards. Persisting error messages will
be recreated during each poll.
*/
plStatus = angleAxis->setStringParam(motorMessageText(), "");
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorMessageText_", angleAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = liftAxis->setStringParam(motorMessageText(), "");
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorMessageText_", liftAxisNo,
__PRETTY_FUNCTION__, __LINE__);
}
plStatus = supportAxis->setStringParam(motorMessageText(), "");
if (plStatus != asynSuccess) {
return paramLibAccessFailed(plStatus, "motorMessageText_",
supportAxisNo, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(angleAxis, motorMessageText, "");
setAxisParamChecked(liftAxis, motorMessageText, "");
setAxisParamChecked(supportAxis, motorMessageText, "");
return pollStatus;
}

View File

@ -8,11 +8,15 @@
#ifndef detectorTowerController_H
#define detectorTowerController_H
#include "detectorTowerAngleAxis.h"
#include "detectorTowerLiftAxis.h"
#include "detectorTowerSupportAxis.h"
#include "turboPmacController.h"
// Forward declaration of the axis classes to resolve the cyclic dependency
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class detectorTowerAngleAxis;
class detectorTowerLiftAxis;
class detectorTowerSupportAxis;
class detectorTowerController : public turboPmacController {
public:
@ -35,6 +39,8 @@ class detectorTowerController : public turboPmacController {
int numAxes, double movingPollPeriod,
double idlePollPeriod, double comTimeout);
virtual ~detectorTowerController();
/**
* @brief Overloaded function of turboPmacController
*

View File

@ -1,6 +1,7 @@
#include "detectorTowerLiftAxis.h"
#include "detectorTowerAngleAxis.h"
#include "detectorTowerController.h"
#include "detectorTowerSupportAxis.h"
#include "turboPmacController.h"
#include <epicsExport.h>
#include <errlog.h>
@ -111,11 +112,7 @@ asynStatus detectorTowerLiftAxis::init() {
}
// Initialize the motorStatusMoving flag
status = setIntegerParam(pC_->motorStatusMoving(), 0);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusMoving_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(this, motorStatusMoving, false);
// Check if we are currently in the changer position and update the PV
// accordingly
@ -126,11 +123,7 @@ asynStatus detectorTowerLiftAxis::init() {
__PRETTY_FUNCTION__, __LINE__);
}
status = setIntegerParam(pC_->changeStateRBV(), positionState == 2);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "changeStateRBV", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(this, changeStateRBV, positionState == 2);
return callParamCallbacks();
}
@ -146,15 +139,9 @@ asynStatus detectorTowerLiftAxis::poll(bool *moving) {
status = pC_->pollDetectorAxes(moving, angleAxis(), this,
angleAxis()->supportAxis());
} else {
status = pC_->getIntegerParam(axisNo(), pC_->motorStatusMoving(),
(int *)moving);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusMoving",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
getAxisParamChecked(this, motorStatusMoving, moving);
}
wasMoving_ = *moving;
setWasMoving(*moving);
return status;
}
@ -172,18 +159,12 @@ asynStatus detectorTowerLiftAxis::doMove(double position, int relative,
double acceleration) {
double motorRecResolution = 0.0;
asynStatus plStatus = pC_->getDoubleParam(
axisNo_, pC_->motorRecResolution(), &motorRecResolution);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorRecResolution_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
// Signal to the deferredMovementCollectorLoop (of the
// detectorTowerAngleAxis) that a movement should be started to the
// defined target position.
targetPosition_ = position * motorRecResolution;
setTargetPosition(position * motorRecResolution);
angleAxis_->receivedTarget_ = true;
return asynSuccess;
@ -192,37 +173,8 @@ asynStatus detectorTowerLiftAxis::doMove(double position, int relative,
asynStatus detectorTowerLiftAxis::reset() { return angleAxis()->reset(); };
asynStatus detectorTowerLiftAxis::stop(double acceleration) {
// Status of read-write-operations of ASCII commands to the controller
asynStatus rwStatus = asynSuccess;
// Status of parameter library operations
asynStatus plStatus = asynSuccess;
char response[pC_->MAXBUF_] = {0};
// =========================================================================
rwStatus = pC_->writeRead(axisNo_, "P350=8", response, 0);
if (rwStatus != asynSuccess) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line %d\nStopping "
"the movement "
"failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
plStatus = setIntegerParam(pC_->motorStatusProblem(), true);
if (plStatus != asynSuccess) {
return pC_->paramLibAccessFailed(plStatus, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
return asynError;
}
return rwStatus;
}
return angleAxis()->stop(acceleration);
};
asynStatus detectorTowerLiftAxis::readEncoderType() {
return angleAxis()->readEncoderType();
@ -237,12 +189,7 @@ asynStatus detectorTowerLiftAxis::adjustOrigin(double newOrigin) {
// =========================================================================
status =
pC_->getIntegerParam(axisNo_, pC_->positionStateRBV(), &positionState);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "positionStateRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(this, positionStateRBV, &positionState);
// If the axis is in changer position, it must be moved into working
// position before any move can be started.
@ -271,12 +218,7 @@ asynStatus detectorTowerLiftAxis::adjustOrigin(double newOrigin) {
"lift origin %lf failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
newOrigin);
status = setIntegerParam(pC_->motorStatusProblem(), true);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, motorStatusProblem, true);
}
return status;

View File

@ -1,13 +1,8 @@
#ifndef detectorTowerLiftAxis_H
#define detectorTowerLiftAxis_H
#include "detectorTowerController.h"
#include "turboPmacAxis.h"
// Forward declaration of the controller class to resolve the cyclic dependency
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class detectorTowerController;
class detectorTowerAngleAxis;
class detectorTowerLiftAxis : public turboPmacAxis {
public:
/**
@ -19,10 +14,6 @@ class detectorTowerLiftAxis : public turboPmacAxis {
detectorTowerLiftAxis(detectorTowerController *pController, int axisNo,
detectorTowerAngleAxis *angleAxis);
/**
* @brief Destroy the turboPmacAxis
*
*/
virtual ~detectorTowerLiftAxis();
/**
@ -114,6 +105,11 @@ class detectorTowerLiftAxis : public turboPmacAxis {
*/
asynStatus readEncoderType();
/**
* @brief Return a pointer to the axis controller
*/
virtual detectorTowerController *pController() override { return pC_; };
protected:
detectorTowerController *pC_;
detectorTowerAngleAxis *angleAxis_;

View File

@ -1,6 +1,7 @@
#include "detectorTowerSupportAxis.h"
#include "detectorTowerAngleAxis.h"
#include "detectorTowerController.h"
#include "detectorTowerLiftAxis.h"
#include "turboPmacController.h"
#include <epicsExport.h>
#include <errlog.h>
@ -111,11 +112,7 @@ asynStatus detectorTowerSupportAxis::init() {
}
// Initialize the motorStatusMoving flag
status = setIntegerParam(pC_->motorStatusMoving(), 0);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusMoving_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(this, motorStatusMoving, false);
// Check if we are currently in the changer position and update the PV
// accordingly
@ -126,12 +123,7 @@ asynStatus detectorTowerSupportAxis::init() {
__PRETTY_FUNCTION__, __LINE__);
}
status = setIntegerParam(pC_->changeStateRBV(), positionState == 2);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "changeStateRBV", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
setAxisParamChecked(this, changeStateRBV, positionState == 2);
return callParamCallbacks();
}
@ -147,15 +139,9 @@ asynStatus detectorTowerSupportAxis::poll(bool *moving) {
status = pC_->pollDetectorAxes(moving, angleAxis(),
angleAxis()->liftAxis(), this);
} else {
status = pC_->getIntegerParam(axisNo(), pC_->motorStatusMoving(),
(int *)moving);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusMoving",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
getAxisParamChecked(this, motorStatusMoving, moving);
}
wasMoving_ = *moving;
setWasMoving(*moving);
return status;
}
@ -186,12 +172,7 @@ asynStatus detectorTowerSupportAxis::adjustOrigin(double newOrigin) {
// =========================================================================
status =
pC_->getIntegerParam(axisNo_, pC_->positionStateRBV(), &positionState);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "positionStateRBV_", axisNo_,
__PRETTY_FUNCTION__, __LINE__);
}
getAxisParamChecked(this, positionStateRBV, &positionState);
// If the axis is in changer position, it must be moved into working
// position before any move can be started.
@ -220,12 +201,8 @@ asynStatus detectorTowerSupportAxis::adjustOrigin(double newOrigin) {
"lift origin %lf failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
newOrigin);
status = setIntegerParam(pC_->motorStatusProblem(), true);
if (status != asynSuccess) {
return pC_->paramLibAccessFailed(status, "motorStatusProblem_",
axisNo_, __PRETTY_FUNCTION__,
__LINE__);
}
setAxisParamChecked(this, motorStatusProblem, true);
}
return status;

View File

@ -1,13 +1,8 @@
#ifndef detectorTowerSupportAxis_H
#define detectorTowerSupportAxis_H
#include "detectorTowerController.h"
#include "turboPmacAxis.h"
// Forward declaration of the controller class to resolve the cyclic dependency
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class detectorTowerController;
class detectorTowerAngleAxis;
/**
* @brief Passive axis which is mostly controlled indirectly by the hardware
*
@ -24,10 +19,6 @@ class detectorTowerSupportAxis : public turboPmacAxis {
detectorTowerSupportAxis(detectorTowerController *pController, int axisNo,
detectorTowerAngleAxis *angleAxis);
/**
* @brief Destroy the detectorTowerSupportAxis
*
*/
virtual ~detectorTowerSupportAxis();
/**
@ -116,6 +107,11 @@ class detectorTowerSupportAxis : public turboPmacAxis {
*/
asynStatus readEncoderType();
/**
* @brief Return a pointer to the axis controller
*/
virtual detectorTowerController *pController() override { return pC_; };
protected:
detectorTowerController *pC_;
detectorTowerAngleAxis *angleAxis_;