Adjusted driver with auxiliary axes offsets
This commit is contained in:
246
.clang-format
Normal file
246
.clang-format
Normal file
@ -0,0 +1,246 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
...
|
||||
|
9
Makefile
9
Makefile
@ -13,15 +13,18 @@ REQUIRED+=motorBase
|
||||
motorBase_VERSION=7.2.2
|
||||
|
||||
# Specify the version of turboPmac we want to build against
|
||||
turboPmac_VERSION=0.10.0
|
||||
sinqMotor_VERSION=mathis_s
|
||||
|
||||
# Specify the version of turboPmac we want to build against
|
||||
turboPmac_VERSION=mathis_s
|
||||
|
||||
# These headers allow to depend on this library for derived drivers.
|
||||
HEADERS += src/auxiliaryAxis.h
|
||||
HEADERS += src/detectorTowerAuxiliaryAxis.h
|
||||
HEADERS += src/detectorTowerAxis.h
|
||||
HEADERS += src/detectorTowerController.h
|
||||
|
||||
# Source files to build
|
||||
SOURCES += src/auxiliaryAxis.cpp
|
||||
SOURCES += src/detectorTowerAuxiliaryAxis.cpp
|
||||
SOURCES += src/detectorTowerAxis.cpp
|
||||
SOURCES += src/detectorTowerController.cpp
|
||||
|
||||
|
@ -7,15 +7,17 @@
|
||||
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 three objects:
|
||||
- `detectorTowerAxis`: This is a virtual axis which controls multiple physical motors in order to provide a synchronized movement.
|
||||
- `detectorTowerController`: This is an expanded variant of `turboPmacController` provided by the Turbo PMAC library linked above.It is needed to operate a `detectorTowerAxis`, but it can also be used to operate a "normal" `turboPmacAxis`.
|
||||
- `auxiliaryAxis`: This is an auxiliary axis type attached to the main detector axis. Multiple instances of these axes are constructed automatically when creating a `detectorTowerAxis`.
|
||||
- `detectorTowerAuxiliaryAxis`: This is an auxiliary axis type attached to the main detector axis. Multiple instances of these axes are constructed automatically when creating a `detectorTowerAxis`.
|
||||
The header files contain detailed documentation for all public functions. The headers themselves are exported when building the library to allow other drivers to depend on this one.
|
||||
|
||||
## User guide
|
||||
|
||||
The centerpiece of this driver is the `detectorTowerAxis`, which controls the angle of the detector flight tube. Creating an instance of this axis type also creates multiple so-called `auxiliaryAxis`, which are used to perform secondary movements.
|
||||
The centerpiece of this driver is the `detectorTowerAxis`, which controls the angle of the detector flight tube. Creating an instance of this axis type also creates multiple so-called `detectorTowerAuxiliaryAxis`, which are used to perform secondary movements.
|
||||
|
||||
The utilities provided in the `utils` folder of https://git.psi.ch/sinq-epics-modules/turboPmac work with this driver as well.
|
||||
|
||||
TODO: How to start combined movement
|
||||
|
||||
### Usage in IOC shell
|
||||
|
||||
detectorTower exports the following IOC shell functions:
|
||||
@ -99,7 +101,7 @@ Note that the speed of the detector tower axes 1, 2 and 3 cannot be set. Setting
|
||||
|
||||
The code is designed around the `detectorTowerAxis`, which controls the angle of the beam guide and acts as a "master" axis. Other movements are realized as auxiliary axes (e.g. for the vertical lift offset and the tilt offset). The `detectorTowerAxis` has pointers to all associated auxiliary axes and (as described above) its IOC shell constructor also builds the associated auxiliary axes.
|
||||
|
||||
The `doPoll` implementation for `detectorTowerAxis` queries the status of both the `detectorTowerAxis` itself and all associated auxiliary axes. If any of the axes is moving, the `detectorTowerAxis` is set to "moving" as well. In turn, the `doPoll` implementation of a `auxiliaryAxis` checks if its associated `detectorTowerAxis` is moving and sets its own movement status accordingly.
|
||||
The `doPoll` implementation for `detectorTowerAxis` queries the status of both the `detectorTowerAxis` itself and all associated auxiliary axes. If any of the axes is moving, the `detectorTowerAxis` is set to "moving" as well. In turn, the `doPoll` implementation of a `detectorTowerAuxiliaryAxis` checks if its associated `detectorTowerAxis` is moving and sets its own movement status accordingly.
|
||||
|
||||
The `detectorTowerController` is a thin wrapper around a `turboPmacController` which overwrites the `readInt32` and `writeInt32` in order to support the PVs "$(INSTR)$(M):ChangeState", "$(INSTR)$(M):PositionStateRBV" and "$(INSTR)$(M):ChangingStateRBV". Any calls to these two methods not concerning the aforementioned PVs are directly forwarded to `turboPmacController::readInt32` / `turboPmacController::writeInt32`.
|
||||
|
||||
|
@ -36,3 +36,12 @@ record(longout, "$(INSTR)$(M):ChangingStateRBV_int") {
|
||||
field(DOL, "$(INSTR)$(M):ChangingStateRBV CP")
|
||||
field(OMSL, "closed_loop")
|
||||
}
|
||||
|
||||
# Set an additional offset to the target position of an auxiliary axis
|
||||
# For all other axis types, writing to this parameter does nothing.
|
||||
record(ao, "$(INSTR)$(M):TargetOffset") {
|
||||
field(DTYP, "asynFloat64")
|
||||
field(OUT, "@asyn($(CONTROLLER),$(AXIS),1) MOTOR_TARGET_OFFSET")
|
||||
field(PINI, "YES")
|
||||
field(VAL, "0")
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
#include "auxiliaryAxis.h"
|
||||
#include "detectorTowerAuxiliaryAxis.h"
|
||||
#include "detectorTowerAxis.h"
|
||||
#include "detectorTowerController.h"
|
||||
#include "turboPmacController.h"
|
||||
@ -7,10 +7,10 @@
|
||||
#include <iocsh.h>
|
||||
|
||||
/*
|
||||
Contains all instances of auxiliaryAxis which have been created and is used
|
||||
in the initialization hook function.
|
||||
Contains all instances of detectorTowerAuxiliaryAxis which have been created and
|
||||
is used in the initialization hook function.
|
||||
*/
|
||||
static std::vector<auxiliaryAxis *> axes;
|
||||
static std::vector<detectorTowerAuxiliaryAxis *> axes;
|
||||
|
||||
/**
|
||||
* @brief Hook function to perform certain actions during the IOC initialization
|
||||
@ -21,15 +21,17 @@ static void epicsInithookFunction(initHookState iState) {
|
||||
if (iState == initHookAfterDatabaseRunning) {
|
||||
// Iterate through all axes of each and call the initialization method
|
||||
// on each one of them.
|
||||
for (std::vector<auxiliaryAxis *>::iterator itA = axes.begin();
|
||||
for (std::vector<detectorTowerAuxiliaryAxis *>::iterator itA =
|
||||
axes.begin();
|
||||
itA != axes.end(); ++itA) {
|
||||
auxiliaryAxis *axis = *itA;
|
||||
detectorTowerAuxiliaryAxis *axis = *itA;
|
||||
axis->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auxiliaryAxis::auxiliaryAxis(detectorTowerController *pC, int axisNo)
|
||||
detectorTowerAuxiliaryAxis::detectorTowerAuxiliaryAxis(
|
||||
detectorTowerController *pC, int axisNo)
|
||||
: turboPmacAxis(pC, axisNo, false), pC_(pC) {
|
||||
|
||||
/*
|
||||
@ -46,7 +48,7 @@ auxiliaryAxis::auxiliaryAxis(detectorTowerController *pC, int axisNo)
|
||||
is a configuration error.
|
||||
*/
|
||||
if (axisNo >= pC->numAxes()) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d: FATAL ERROR: "
|
||||
"Axis index %d must be smaller than the total number of axes "
|
||||
"%d",
|
||||
@ -65,12 +67,12 @@ auxiliaryAxis::auxiliaryAxis(detectorTowerController *pC, int axisNo)
|
||||
axes.push_back(this);
|
||||
}
|
||||
|
||||
auxiliaryAxis::~auxiliaryAxis(void) {
|
||||
detectorTowerAuxiliaryAxis::~detectorTowerAuxiliaryAxis(void) {
|
||||
// Since the controller memory is managed somewhere else, we don't need to
|
||||
// clean up the pointer pC here.
|
||||
}
|
||||
|
||||
asynStatus auxiliaryAxis::init() {
|
||||
asynStatus detectorTowerAuxiliaryAxis::init() {
|
||||
|
||||
// Local variable declaration
|
||||
asynStatus status = asynSuccess;
|
||||
@ -85,7 +87,7 @@ asynStatus auxiliaryAxis::init() {
|
||||
&motorRecResolution);
|
||||
if (status == asynParamUndefined) {
|
||||
if (now + maxInitTime < time(NULL)) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line "
|
||||
"%d\nInitializing the parameter library failed.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__,
|
||||
@ -104,7 +106,7 @@ asynStatus auxiliaryAxis::init() {
|
||||
}
|
||||
|
||||
// Perform the actual poll
|
||||
asynStatus auxiliaryAxis::doPoll(bool *moving) {
|
||||
asynStatus detectorTowerAuxiliaryAxis::doPoll(bool *moving) {
|
||||
|
||||
// Return value for the poll
|
||||
asynStatus poll_status = asynSuccess;
|
||||
@ -167,8 +169,8 @@ asynStatus auxiliaryAxis::doPoll(bool *moving) {
|
||||
bool wantToPrint = pl_status != asynSuccess;
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, wantToPrint,
|
||||
pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line "
|
||||
"%d:\ncallParamCallbacks failed with %s.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -184,8 +186,9 @@ asynStatus auxiliaryAxis::doPoll(bool *moving) {
|
||||
return poll_status;
|
||||
}
|
||||
|
||||
asynStatus auxiliaryAxis::doMove(double position, int relative,
|
||||
double min_velocity, double max_velocity,
|
||||
asynStatus detectorTowerAuxiliaryAxis::doMove(double position, int relative,
|
||||
double min_velocity,
|
||||
double max_velocity,
|
||||
double acceleration) {
|
||||
|
||||
double motorRecResolution = 0.0;
|
||||
@ -205,7 +208,7 @@ asynStatus auxiliaryAxis::doMove(double position, int relative,
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus auxiliaryAxis::stop(double acceleration) {
|
||||
asynStatus detectorTowerAuxiliaryAxis::stop(double acceleration) {
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
@ -213,7 +216,7 @@ asynStatus auxiliaryAxis::stop(double acceleration) {
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
|
||||
char response[pC_->MAXBUF_];
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@ -221,7 +224,7 @@ asynStatus auxiliaryAxis::stop(double acceleration) {
|
||||
|
||||
if (rw_status != asynSuccess) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nStopping the movement "
|
||||
"failed.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||
@ -238,4 +241,4 @@ asynStatus auxiliaryAxis::stop(double acceleration) {
|
||||
return rw_status;
|
||||
}
|
||||
|
||||
asynStatus auxiliaryAxis::reset() { return dTA_->reset(); };
|
||||
asynStatus detectorTowerAuxiliaryAxis::reset() { return dTA_->reset(); };
|
@ -1,5 +1,5 @@
|
||||
#ifndef auxiliaryAxis_H
|
||||
#define auxiliaryAxis_H
|
||||
#ifndef detectorTowerAuxiliaryAxis_H
|
||||
#define detectorTowerAuxiliaryAxis_H
|
||||
#include "turboPmacAxis.h"
|
||||
|
||||
// Forward declaration of the controller class to resolve the cyclic dependency
|
||||
@ -8,7 +8,7 @@
|
||||
class detectorTowerController;
|
||||
class detectorTowerAxis;
|
||||
|
||||
class auxiliaryAxis : public turboPmacAxis {
|
||||
class detectorTowerAuxiliaryAxis : public turboPmacAxis {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new detectorTowerAxis
|
||||
@ -16,13 +16,14 @@ class auxiliaryAxis : public turboPmacAxis {
|
||||
* @param pController Pointer to the associated controller
|
||||
* @param axisNo Index of the axis
|
||||
*/
|
||||
auxiliaryAxis(detectorTowerController *pController, int axisNo);
|
||||
detectorTowerAuxiliaryAxis(detectorTowerController *pController,
|
||||
int axisNo);
|
||||
|
||||
/**
|
||||
* @brief Destroy the turboPmacAxis
|
||||
*
|
||||
*/
|
||||
virtual ~auxiliaryAxis();
|
||||
virtual ~detectorTowerAuxiliaryAxis();
|
||||
|
||||
/**
|
||||
* @brief Readout of some values from the controller at IOC startup
|
@ -47,9 +47,10 @@ static void deferredMovementCollectorLoop(void *drvPvt) {
|
||||
}
|
||||
}
|
||||
|
||||
detectorTowerAxis::detectorTowerAxis(detectorTowerController *pC, int axisNo,
|
||||
auxiliaryAxis *liftOffsetAxis,
|
||||
auxiliaryAxis *tiltOffsetAxis)
|
||||
detectorTowerAxis::detectorTowerAxis(
|
||||
detectorTowerController *pC, int axisNo,
|
||||
detectorTowerAuxiliaryAxis *liftZeroCorrAxis,
|
||||
detectorTowerAuxiliaryAxis *tiltZeroCorrAxis)
|
||||
: turboPmacAxis(pC, axisNo, false), pC_(pC) {
|
||||
|
||||
/*
|
||||
@ -66,7 +67,7 @@ detectorTowerAxis::detectorTowerAxis(detectorTowerController *pC, int axisNo,
|
||||
is a configuration error.
|
||||
*/
|
||||
if (axisNo >= pC->numAxes()) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d: FATAL ERROR: "
|
||||
"Axis index %d must be smaller than the total number of axes "
|
||||
"%d",
|
||||
@ -81,10 +82,13 @@ detectorTowerAxis::detectorTowerAxis(detectorTowerController *pC, int axisNo,
|
||||
receivedTarget_ = false;
|
||||
startingDeferredMovement_ = false;
|
||||
deferredMovementWait_ = 0.1; // seconds
|
||||
liftOffsetAxis_ = liftOffsetAxis;
|
||||
tiltOffsetAxis_ = tiltOffsetAxis;
|
||||
liftOffsetAxis->dTA_ = this;
|
||||
tiltOffsetAxis->dTA_ = this;
|
||||
liftZeroCorrAxis_ = liftZeroCorrAxis;
|
||||
tiltZeroCorrAxis_ = tiltZeroCorrAxis;
|
||||
liftZeroCorrAxis->dTA_ = this;
|
||||
tiltZeroCorrAxis->dTA_ = this;
|
||||
|
||||
// Will be populated in the init() method
|
||||
beamRadius_ = 0.0;
|
||||
|
||||
// Register the hook function during construction of the first axis object
|
||||
if (axes.empty()) {
|
||||
@ -116,6 +120,8 @@ asynStatus detectorTowerAxis::init() {
|
||||
// Local variable declaration
|
||||
asynStatus status = asynSuccess;
|
||||
double motorRecResolution = 0.0;
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
int nvals = 0;
|
||||
|
||||
// The parameter library takes some time to be initialized. Therefore we
|
||||
// wait until the status is not asynParamUndefined anymore.
|
||||
@ -126,7 +132,7 @@ asynStatus detectorTowerAxis::init() {
|
||||
&motorRecResolution);
|
||||
if (status == asynParamUndefined) {
|
||||
if (now + maxInitTime < time(NULL)) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis "
|
||||
"%ddeferredMovementCollectorLoop => %s, line "
|
||||
"%d\nInitializing the parameter library failed.\n",
|
||||
@ -143,10 +149,22 @@ asynStatus detectorTowerAxis::init() {
|
||||
}
|
||||
}
|
||||
|
||||
// Read the detector radius
|
||||
const char *command = "RADIUS";
|
||||
status = pC_->writeRead(axisNo_, command, response, 10);
|
||||
if (status != asynSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
nvals = sscanf(response, "%lf", &beamRadius_);
|
||||
if (nvals != 1) {
|
||||
return pC_->couldNotParseResponse(command, response, axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Perform the actual poll
|
||||
asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
// Return value for the poll
|
||||
@ -158,7 +176,8 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
|
||||
char response[pC_->MAXBUF_], userMessage[pC_->MAXBUF_];
|
||||
char userMessage[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
int nvals = 0;
|
||||
|
||||
int direction = 0;
|
||||
@ -172,11 +191,10 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
double highLimit = 0.0;
|
||||
double lowLimit = 0.0;
|
||||
double detectorHeight = 0.0;
|
||||
double detectorRadius = 0.0;
|
||||
double liftOffsetHighLimit = 0.0;
|
||||
double liftOffsetLowLimit = 0.0;
|
||||
double tiltOffsetHighLimit = 0.0;
|
||||
double tiltOffsetLowLimit = 0.0;
|
||||
double liftZeroCorrHighLimit = 0.0;
|
||||
double liftZeroCorrLowLimit = 0.0;
|
||||
double tiltZeroCorrHighLimit = 0.0;
|
||||
double tiltZeroCorrLowLimit = 0.0;
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@ -202,20 +220,22 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
- Axis error
|
||||
- Beam tilt angle
|
||||
- Beam tilt angle limits
|
||||
- Beam lift position
|
||||
- Beam lift offset limits
|
||||
- Detector tilt offset limits
|
||||
*/
|
||||
const char *command = "P354 P358 P359 Q510 Q513 Q514 Q353 Q354 Q553 Q554";
|
||||
const char *command =
|
||||
"P354 P358 P359 Q510 Q513 Q514 Q310 Q353 Q354 Q553 Q554";
|
||||
rw_status = pC_->writeRead(axisNo_, command, response, 10);
|
||||
if (rw_status != asynSuccess) {
|
||||
return rw_status;
|
||||
}
|
||||
|
||||
nvals =
|
||||
sscanf(response, "%d %d %d %lf %lf %lf %lf %lf %lf %lf", &inPosition,
|
||||
&positionState, &error, &beamTiltAngle, &highLimit, &lowLimit,
|
||||
&liftOffsetHighLimit, &liftOffsetLowLimit, &tiltOffsetHighLimit,
|
||||
&tiltOffsetLowLimit);
|
||||
nvals = sscanf(response, "%d %d %d %lf %lf %lf %lf %lf %lf %lf %lf",
|
||||
&inPosition, &positionState, &error, &beamTiltAngle,
|
||||
&highLimit, &lowLimit, &detectorHeight,
|
||||
&liftZeroCorrHighLimit, &liftZeroCorrLowLimit,
|
||||
&tiltZeroCorrHighLimit, &tiltZeroCorrLowLimit);
|
||||
if (nvals != 10) {
|
||||
return pC_->couldNotParseResponse(command, response, axisNo_,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
@ -300,9 +320,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
default:
|
||||
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyPosState, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nReached unknown "
|
||||
"state P354 = %d.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -323,7 +343,7 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
}
|
||||
|
||||
if (resetCountPosState) {
|
||||
pC_->getMsgPrintControl().resetCount(keyPosState, pC_->asynUserSelf());
|
||||
pC_->getMsgPrintControl().resetCount(keyPosState, pC_->pasynUser());
|
||||
}
|
||||
|
||||
if (*moving) {
|
||||
@ -348,9 +368,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
break;
|
||||
case 1:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nBrake COZ not "
|
||||
"released (P359=1).%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -373,9 +393,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 2:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nMove command "
|
||||
"rejected because axis is already moving.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -397,8 +417,8 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 3:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nError motor "
|
||||
"FTZ.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -421,9 +441,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 4:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis stopped "
|
||||
"unexpectedly.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -447,9 +467,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 5:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nRelease removed "
|
||||
"while moving.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -473,9 +493,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 6:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nEmergency stop "
|
||||
"activated.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -496,8 +516,8 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 7:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nError motor "
|
||||
"COZ.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -520,8 +540,8 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 8:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nError motor "
|
||||
"COM.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -544,8 +564,8 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 9:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nError motor "
|
||||
"COX.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -568,8 +588,8 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
case 10:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nHit end "
|
||||
"switch FTZ.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -591,9 +611,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
case 11:
|
||||
// Following error
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
|
||||
"following error FTZ exceeded.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -618,9 +638,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
|
||||
default:
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
|
||||
pC_->asynUserSelf())) {
|
||||
pC_->pasynUser())) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nUnknown error "
|
||||
"P359 = %d.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, error,
|
||||
@ -642,7 +662,7 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
}
|
||||
|
||||
if (resetError) {
|
||||
pC_->getMsgPrintControl().resetCount(keyError, pC_->asynUserSelf());
|
||||
pC_->getMsgPrintControl().resetCount(keyError, pC_->pasynUser());
|
||||
}
|
||||
|
||||
// Update the parameter library
|
||||
@ -701,46 +721,46 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
||||
}
|
||||
|
||||
// Set the values for the offset axes
|
||||
int liftAxisNo = liftOffsetAxis_->axisNo_;
|
||||
double liftOffsetPosition =
|
||||
detectorHeight + detectorRadius * sin(beamTiltAngle);
|
||||
int liftAxisNo = liftZeroCorrAxis_->axisNo_;
|
||||
double liftZeroCorrPosition =
|
||||
detectorHeight + beamRadius_ * sin(beamTiltAngle);
|
||||
|
||||
pl_status = setMotorPosition(liftOffsetPosition);
|
||||
pl_status = setMotorPosition(liftZeroCorrPosition);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pl_status;
|
||||
}
|
||||
pl_status = pC_->setDoubleParam(liftAxisNo, pC_->motorHighLimitFromDriver(),
|
||||
liftOffsetHighLimit);
|
||||
liftZeroCorrHighLimit);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorHighLimitFromDriver_",
|
||||
liftAxisNo, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
pl_status = pC_->setDoubleParam(liftAxisNo, pC_->motorLowLimitFromDriver(),
|
||||
liftOffsetLowLimit);
|
||||
liftZeroCorrLowLimit);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorLowLimitFromDriver_",
|
||||
liftAxisNo, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
int tiltAxisNo = tiltOffsetAxis_->axisNo_;
|
||||
int tiltAxisNo = tiltZeroCorrAxis_->axisNo_;
|
||||
|
||||
// There exists no readback value for tiltOffsetAxis_, hence we just set the
|
||||
// current position to the target position.
|
||||
tiltOffsetAxis_->setMotorPosition(tiltOffsetAxis_->targetPosition_);
|
||||
// There exists no readback value for tiltZeroCorrAxis_, hence we just set
|
||||
// the current position to the target position.
|
||||
tiltZeroCorrAxis_->setMotorPosition(tiltZeroCorrAxis_->targetPosition_);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pl_status;
|
||||
}
|
||||
pl_status = pC_->setDoubleParam(tiltAxisNo, pC_->motorHighLimitFromDriver(),
|
||||
tiltOffsetHighLimit);
|
||||
tiltZeroCorrHighLimit);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorHighLimitFromDriver_",
|
||||
tiltAxisNo, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
pl_status = pC_->setDoubleParam(tiltAxisNo, pC_->motorLowLimitFromDriver(),
|
||||
tiltOffsetLowLimit);
|
||||
tiltZeroCorrLowLimit);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorLowLimitFromDriver_",
|
||||
tiltAxisNo, __PRETTY_FUNCTION__,
|
||||
@ -792,8 +812,11 @@ asynStatus detectorTowerAxis::startCombinedMove() {
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
|
||||
char command[pC_->MAXBUF_], response[pC_->MAXBUF_];
|
||||
char command[pC_->MAXBUF_] = {0};
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
double motorCoordinatesPosition = 0.0;
|
||||
double offsetliftZeroCorr = 0.0;
|
||||
double offsettiltZeroCorr = 0.0;
|
||||
int positionState = 0;
|
||||
|
||||
// =========================================================================
|
||||
@ -803,8 +826,8 @@ asynStatus detectorTowerAxis::startCombinedMove() {
|
||||
bool isInChangerPos = positionState == 2 || positionState == 3;
|
||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
isInChangerPos, pC_->asynUserSelf())) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
isInChangerPos, pC_->pasynUser())) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis cannot be "
|
||||
"moved because it is moving from working to changer "
|
||||
"position, is in changer position or is moving from changer "
|
||||
@ -817,11 +840,30 @@ asynStatus detectorTowerAxis::startCombinedMove() {
|
||||
return asynError;
|
||||
}
|
||||
|
||||
// Read out any offsets for the zero correction axes
|
||||
pl_status =
|
||||
pC_->getDoubleParam(tiltZeroCorrAxis_->axisNo(),
|
||||
pC_->motorTargetOffset(), &offsettiltZeroCorr);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorTargetOffset",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
pl_status =
|
||||
pC_->getDoubleParam(liftZeroCorrAxis_->axisNo(),
|
||||
pC_->motorTargetOffset(), &offsetliftZeroCorr);
|
||||
if (pl_status != asynSuccess) {
|
||||
return pC_->paramLibAccessFailed(pl_status, "motorTargetOffset",
|
||||
axisNo_, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
// Set the target positions for beam tilt, detector tilt offset and lift
|
||||
// offset
|
||||
snprintf(command, sizeof(command), "Q451=%lf Q454=%lf Q456=%lf P350=1",
|
||||
targetPosition_, liftOffsetAxis_->targetPosition_,
|
||||
tiltOffsetAxis_->targetPosition_);
|
||||
targetPosition_,
|
||||
liftZeroCorrAxis_->targetPosition_ + offsetliftZeroCorr,
|
||||
tiltZeroCorrAxis_->targetPosition_ + offsettiltZeroCorr);
|
||||
|
||||
// Lock the access to the controller since this function runs in another
|
||||
// thread than the poll method.
|
||||
@ -835,7 +877,7 @@ asynStatus detectorTowerAxis::startCombinedMove() {
|
||||
|
||||
if (rw_status != asynSuccess) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
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__,
|
||||
@ -859,7 +901,7 @@ asynStatus detectorTowerAxis::stop(double acceleration) {
|
||||
// Status of parameter library operations
|
||||
asynStatus pl_status = asynSuccess;
|
||||
|
||||
char response[pC_->MAXBUF_];
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@ -867,7 +909,7 @@ asynStatus detectorTowerAxis::stop(double acceleration) {
|
||||
|
||||
if (rw_status != asynSuccess) {
|
||||
asynPrint(
|
||||
pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nStopping the movement "
|
||||
"failed.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||
@ -897,7 +939,7 @@ asynStatus detectorTowerAxis::readEncoderType() {
|
||||
asynStatus
|
||||
detectorTowerAxis::toggleWorkingChangerState(bool toChangingPosition) {
|
||||
|
||||
char response[pC_->MAXBUF_];
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
|
||||
// Status of read-write-operations of ASCII commands to the controller
|
||||
asynStatus rw_status = asynSuccess;
|
||||
@ -921,7 +963,7 @@ detectorTowerAxis::toggleWorkingChangerState(bool toChangingPosition) {
|
||||
}
|
||||
|
||||
if (moving) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_ERROR,
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
||||
"idle and can therefore not be moved to %s state.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -944,7 +986,7 @@ detectorTowerAxis::toggleWorkingChangerState(bool toChangingPosition) {
|
||||
(toChangingPosition == true && positionState == 2);
|
||||
|
||||
if (isAlreadyThere) {
|
||||
asynPrint(pC_->asynUserSelf(), ASYN_TRACE_WARNING,
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_WARNING,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is already "
|
||||
"in %s position.%s\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
@ -973,7 +1015,7 @@ detectorTowerAxis::toggleWorkingChangerState(bool toChangingPosition) {
|
||||
|
||||
asynStatus detectorTowerAxis::doReset() {
|
||||
|
||||
char response[pC_->MAXBUF_];
|
||||
char response[pC_->MAXBUF_] = {0};
|
||||
asynStatus pl_status = asynSuccess;
|
||||
int positionState = 0;
|
||||
|
||||
@ -1014,7 +1056,8 @@ C wrapper for the axis constructor. Please refer to the detectorTower
|
||||
constructor documentation. The controller is read from the portName.
|
||||
*/
|
||||
asynStatus detectorTowerCreateAxis(const char *portName, int axisDetectorTower,
|
||||
int liftOffsetaxisNo, int tiltOffsetaxisNo) {
|
||||
int liftZeroCorraxisNo,
|
||||
int tiltZeroCorraxisNo) {
|
||||
|
||||
/*
|
||||
findAsynPortDriver is a asyn library FFI function which uses the C ABI.
|
||||
@ -1053,9 +1096,9 @@ asynStatus detectorTowerCreateAxis(const char *portName, int axisDetectorTower,
|
||||
}
|
||||
|
||||
// Assert that the three indices are different from each other
|
||||
if (axisDetectorTower == liftOffsetaxisNo ||
|
||||
axisDetectorTower == tiltOffsetaxisNo ||
|
||||
tiltOffsetaxisNo == liftOffsetaxisNo) {
|
||||
if (axisDetectorTower == liftZeroCorraxisNo ||
|
||||
axisDetectorTower == tiltZeroCorraxisNo ||
|
||||
tiltZeroCorraxisNo == liftZeroCorraxisNo) {
|
||||
errlogPrintf("Controller \"%s\" => %s, line %d\nAll three axis indices "
|
||||
"must be unique.",
|
||||
portName, __PRETTY_FUNCTION__, __LINE__);
|
||||
@ -1076,13 +1119,15 @@ asynStatus detectorTowerCreateAxis(const char *portName, int axisDetectorTower,
|
||||
be "leaked" here.
|
||||
*/
|
||||
|
||||
auxiliaryAxis *liftOffsetAxis = new auxiliaryAxis(pC, liftOffsetaxisNo);
|
||||
auxiliaryAxis *tiltOffsetAxis = new auxiliaryAxis(pC, tiltOffsetaxisNo);
|
||||
detectorTowerAuxiliaryAxis *liftZeroCorrAxis =
|
||||
new detectorTowerAuxiliaryAxis(pC, liftZeroCorraxisNo);
|
||||
detectorTowerAuxiliaryAxis *tiltZeroCorrAxis =
|
||||
new detectorTowerAuxiliaryAxis(pC, tiltZeroCorraxisNo);
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
detectorTowerAxis *pAxis = new detectorTowerAxis(
|
||||
pC, axisDetectorTower, liftOffsetAxis, tiltOffsetAxis);
|
||||
pC, axisDetectorTower, liftZeroCorrAxis, tiltZeroCorrAxis);
|
||||
|
||||
// Allow manipulation of the controller again
|
||||
pC->unlock();
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef detectorTowerAxis_H
|
||||
#define detectorTowerAxis_H
|
||||
#include "auxiliaryAxis.h"
|
||||
#include "detectorTowerAuxiliaryAxis.h"
|
||||
#include "turboPmacAxis.h"
|
||||
|
||||
// Forward declaration of the controller class to resolve the cyclic dependency
|
||||
@ -15,14 +15,14 @@ class detectorTowerAxis : public turboPmacAxis {
|
||||
*
|
||||
* @param pController Pointer to the associated controller
|
||||
* @param axisNo Index of the axis
|
||||
* @param liftOffsetAxis Pointer to the attached axis which controls
|
||||
* @param liftZeroCorrAxis Pointer to the attached axis which controls
|
||||
* the lift offset
|
||||
* @param tiltOffsetAxis Pointer to the attached axis which controls
|
||||
* @param tiltZeroCorrAxis Pointer to the attached axis which controls
|
||||
* the tilt offset
|
||||
*/
|
||||
detectorTowerAxis(detectorTowerController *pController, int axisNo,
|
||||
auxiliaryAxis *liftOffsetAxis,
|
||||
auxiliaryAxis *tiltOffsetAxis);
|
||||
detectorTowerAuxiliaryAxis *liftZeroCorrAxis,
|
||||
detectorTowerAuxiliaryAxis *tiltZeroCorrAxis);
|
||||
|
||||
/**
|
||||
* @brief Destroy the detectorTowerAxis
|
||||
@ -100,8 +100,8 @@ class detectorTowerAxis : public turboPmacAxis {
|
||||
*/
|
||||
asynStatus doReset();
|
||||
|
||||
// If true, either this axis or one of the auxiliaryAxis attached to it
|
||||
// received a movement command.
|
||||
// If true, either this axis or one of the detectorTowerAuxiliaryAxis
|
||||
// attached to it received a movement command.
|
||||
bool receivedTarget_;
|
||||
|
||||
// If set to true, the virtual axis is about to start a deferred movement
|
||||
@ -118,11 +118,12 @@ class detectorTowerAxis : public turboPmacAxis {
|
||||
protected:
|
||||
detectorTowerController *pC_;
|
||||
int error_;
|
||||
auxiliaryAxis *tiltOffsetAxis_;
|
||||
auxiliaryAxis *liftOffsetAxis_;
|
||||
detectorTowerAuxiliaryAxis *tiltZeroCorrAxis_;
|
||||
detectorTowerAuxiliaryAxis *liftZeroCorrAxis_;
|
||||
double beamRadius_;
|
||||
|
||||
private:
|
||||
friend class auxiliaryAxis;
|
||||
friend class detectorTowerAuxiliaryAxis;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -47,45 +47,73 @@ detectorTowerController::detectorTowerController(
|
||||
stringifyAsynStatus(status));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = createParam("MOTOR_OFFSET", asynParamFloat64, &motorTargetOffset_);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
asynStatus detectorTowerController::readInt32(asynUser *pasynUser,
|
||||
epicsInt32 *value) {
|
||||
|
||||
// Check if the axis is a detectorTowerAxis
|
||||
detectorTowerAxis *axis = getDetectorTowerAxis(pasynUser);
|
||||
if (axis == nullptr) {
|
||||
// This is apparently a "normal" turboPmacAxis or an auxiliaryAxis
|
||||
return turboPmacController::readInt32(pasynUser, value);
|
||||
} else {
|
||||
// The detector tower cannot be disabled
|
||||
// The detector tower or its auxiliary axes cannot be disabled
|
||||
if (pasynUser->reason == motorCanDisable_) {
|
||||
detectorTowerAxis *dTAxis = getDetectorTowerAxis(pasynUser);
|
||||
if (dTAxis != nullptr) {
|
||||
*value = 0;
|
||||
return asynSuccess;
|
||||
} else {
|
||||
}
|
||||
detectorTowerAuxiliaryAxis *dTAAxis =
|
||||
getDetectorTowerAuxiliaryAxis(pasynUser);
|
||||
if (dTAAxis != nullptr) {
|
||||
*value = 0;
|
||||
return asynSuccess;
|
||||
}
|
||||
}
|
||||
return turboPmacController::readInt32(pasynUser, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asynStatus detectorTowerController::writeInt32(asynUser *pasynUser,
|
||||
epicsInt32 value) {
|
||||
|
||||
// =====================================================================
|
||||
|
||||
if (pasynUser->reason == motorCanDisable_) {
|
||||
detectorTowerAxis *dTAxis = getDetectorTowerAxis(pasynUser);
|
||||
if (dTAxis != nullptr) {
|
||||
return dTAxis->toggleWorkingChangerState(value);
|
||||
}
|
||||
}
|
||||
return turboPmacController::writeInt32(pasynUser, value);
|
||||
}
|
||||
|
||||
asynStatus detectorTowerController::writeFloat64(asynUser *pasynUser,
|
||||
epicsFloat64 value) {
|
||||
int function = pasynUser->reason;
|
||||
|
||||
// =====================================================================
|
||||
|
||||
detectorTowerAxis *axis = getDetectorTowerAxis(pasynUser);
|
||||
if (function == motorTargetOffset_) {
|
||||
|
||||
if (axis == nullptr) {
|
||||
// This is apparently a "normal" turboPmacAxis or an auxiliaryAxis
|
||||
return turboPmacController::writeInt32(pasynUser, value);
|
||||
} else {
|
||||
if (function == changeState_) {
|
||||
return axis->toggleWorkingChangerState(value);
|
||||
} else {
|
||||
return turboPmacController::writeInt32(pasynUser, value);
|
||||
// Write into the parameter library and trigger a movement cycle, if the
|
||||
// writing succeeded
|
||||
asynStatus status = turboPmacController::writeFloat64(pasynUser, value);
|
||||
if (status == asynSuccess) {
|
||||
detectorTowerAxis *dTAxis = getDetectorTowerAxis(pasynUser);
|
||||
if (dTAxis != nullptr) {
|
||||
dTAxis->receivedTarget_ = true;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
return turboPmacController::writeFloat64(pasynUser, value);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -108,6 +136,27 @@ detectorTowerAxis *detectorTowerController::getDetectorTowerAxis(int axisNo) {
|
||||
return dynamic_cast<detectorTowerAxis *>(asynAxis);
|
||||
}
|
||||
|
||||
/*
|
||||
Access one of the axes of the controller via the axis adress stored in asynUser.
|
||||
If the axis does not exist or is not a Axis, a nullptr is returned and an
|
||||
error is emitted.
|
||||
*/
|
||||
detectorTowerAuxiliaryAxis *
|
||||
detectorTowerController::getDetectorTowerAuxiliaryAxis(asynUser *pasynUser) {
|
||||
asynMotorAxis *asynAxis = asynMotorController::getAxis(pasynUser);
|
||||
return dynamic_cast<detectorTowerAuxiliaryAxis *>(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
|
||||
*/
|
||||
detectorTowerAuxiliaryAxis *
|
||||
detectorTowerController::getDetectorTowerAuxiliaryAxis(int axisNo) {
|
||||
asynMotorAxis *asynAxis = asynMotorController::getAxis(axisNo);
|
||||
return dynamic_cast<detectorTowerAuxiliaryAxis *>(asynAxis);
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/** The following functions are C-wrappers, and can be called directly from
|
||||
* iocsh */
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#ifndef detectorTowerController_H
|
||||
#define detectorTowerController_H
|
||||
#include "auxiliaryAxis.h"
|
||||
#include "detectorTowerAuxiliaryAxis.h"
|
||||
#include "detectorTowerAxis.h"
|
||||
#include "turboPmacController.h"
|
||||
|
||||
@ -52,6 +52,15 @@ class detectorTowerController : public turboPmacController {
|
||||
*/
|
||||
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||
|
||||
/**
|
||||
* @brief Overloaded function of turboPmacController
|
||||
*
|
||||
* @param pasynUser Specify the axis via the asynUser
|
||||
* @param value New value
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
|
||||
|
||||
/**
|
||||
* @brief Get the axis object
|
||||
*
|
||||
@ -70,16 +79,37 @@ class detectorTowerController : public turboPmacController {
|
||||
*/
|
||||
detectorTowerAxis *getDetectorTowerAxis(int axisNo);
|
||||
|
||||
/**
|
||||
* @brief Get the axis object
|
||||
*
|
||||
* @param pasynUser Specify the axis via the asynUser
|
||||
* @return detectorTowerAuxiliaryAxis* If no axis could be found,
|
||||
* this is a nullptr
|
||||
*/
|
||||
detectorTowerAuxiliaryAxis *
|
||||
getDetectorTowerAuxiliaryAxis(asynUser *pasynUser);
|
||||
|
||||
/**
|
||||
* @brief Get the axis object
|
||||
*
|
||||
* @param axisNo Specify the axis via its index
|
||||
* @return detectorTowerAuxiliaryAxis* If no axis could be found,
|
||||
* this is a nullptr
|
||||
*/
|
||||
detectorTowerAuxiliaryAxis *getDetectorTowerAuxiliaryAxis(int axisNo);
|
||||
|
||||
// Accessors for additional PVs
|
||||
int positionStateRBV() { return positionStateRBV_; }
|
||||
int changeState() { return changeState_; }
|
||||
int motorTargetOffset() { return motorTargetOffset_; }
|
||||
|
||||
private:
|
||||
// Indices of additional PVs
|
||||
#define FIRST_detectorTower_PARAM positionStateRBV_
|
||||
int positionStateRBV_;
|
||||
int changeState_;
|
||||
#define LAST_detectorTower_PARAM changeState_
|
||||
int motorTargetOffset_;
|
||||
#define LAST_detectorTower_PARAM motorTargetOffset_
|
||||
};
|
||||
#define NUM_detectorTower_DRIVER_PARAMS \
|
||||
(&LAST_detectorTower_PARAM - &FIRST_detectorTower_PARAM + 1)
|
||||
|
Reference in New Issue
Block a user