133 lines
5.3 KiB
Plaintext
133 lines
5.3 KiB
Plaintext
# Read the position state of the axis:
|
|
# 0 = not ready
|
|
# 1 = ready (in working position)
|
|
# 2 = Moving from working to changer position or in changer position
|
|
# 3 = Moving from changer to working state
|
|
record(longin, "$(INSTR)$(M):PositionStateRBV")
|
|
{
|
|
field(DTYP, "asynInt32")
|
|
field(INP, "@asyn($(CONTROLLER),$(AXIS)) POSITION_STATE_RBV")
|
|
field(SCAN, "I/O Intr")
|
|
field(PINI, "NO")
|
|
}
|
|
|
|
# Set to 0 to move the tower into working state and to 1 to move into changer position.
|
|
# The PV "$(INSTR)$(M):ChangeStateRBV" can be used to check if starting the corresponding
|
|
# movement was successfull.
|
|
record(longout, "$(INSTR)$(M):ChangeState") {
|
|
field(DTYP, "asynInt32")
|
|
field(OUT, "@asyn($(CONTROLLER),$(AXIS),1) CHANGE_STATE")
|
|
field(PINI, "NO")
|
|
field(DRVH, "1")
|
|
field(DRVL, "0")
|
|
}
|
|
|
|
# When a value is written to the PV "$(INSTR)$(M):ChangeState", the tower needs to be
|
|
# idle (PositionState = 0), otherwise the state will not be changed. If the value
|
|
# of this PV is equal to "$(INSTR)$(M):ChangeState", starting a state change was
|
|
# successfull, otherwise not.
|
|
record(longin, "$(INSTR)$(M):ChangeStateRBV")
|
|
{
|
|
field(DTYP, "asynInt32")
|
|
field(INP, "@asyn($(CONTROLLER),$(AXIS)) CHANGE_STATE_RBV")
|
|
field(SCAN, "I/O Intr")
|
|
field(PINI, "NO")
|
|
}
|
|
|
|
# This PV combines the position state and the movement readback value from the
|
|
# motor record:
|
|
# - 0, if the tower is in working state or transitioning to change position
|
|
# - 1, If the tower is in change position or transitioning to working state
|
|
record(calc, "$(INSTR)$(M):ChangingStateRBV")
|
|
{
|
|
field(INPA, "$(INSTR)$(M):PositionStateRBV CP")
|
|
field(INPB, "$(INSTR)$(M).MOVN CP")
|
|
field(CALC, "((A == 2 && B == 0) || A == 3) ? 1 : 0")
|
|
}
|
|
|
|
# Convert the double value from the calc record to an integer value.
|
|
record(longout, "$(INSTR)$(M):ChangingStateRBV_int") {
|
|
field(DOL, "$(INSTR)$(M):ChangingStateRBV CP")
|
|
field(OMSL, "closed_loop")
|
|
}
|
|
|
|
# Read out the origin of the corresponding axis by the given value.
|
|
# This PV does nothing for "normal" Turbo PMAC axes.
|
|
record(ai, "$(INSTR)$(M):Origin") {
|
|
field(DTYP, "asynFloat64")
|
|
field(INP, "@asyn($(CONTROLLER),$(AXIS)) MOTOR_ORIGIN")
|
|
field(SCAN, "I/O Intr")
|
|
field(PINI, "NO")
|
|
field(VAL, "0")
|
|
}
|
|
|
|
# Shift the origin of the corresponding axis by the given value. The axis will move to this
|
|
# position and the hardware controller will internally set this position as the
|
|
# new "0" value. This PV does nothing for "normal" Turbo PMAC axes.
|
|
record(ao, "$(INSTR)$(M):AdjustOrigin") {
|
|
field(DTYP, "Raw Soft Channel")
|
|
field(PINI, "NO")
|
|
field(FLNK, "$(INSTR)$(M):ResetAO")
|
|
field(VAL, "0")
|
|
}
|
|
|
|
# Reset the PV $(INSTR)$(M):AdjustOrigin to zero after it has been written to and
|
|
# forward the value to $(INSTR)$(M):WriteAO which does the actual writing.
|
|
record(seq, "$(INSTR)$(M):ResetAO") {
|
|
field(DESC, "Write value to hardware then reset to 0")
|
|
field(DOL1, "$(INSTR)$(M):AdjustOrigin")
|
|
field(LNK1, "$(INSTR)$(M):WriteAO.VAL PP") # Perform write to hardware
|
|
field(DOL2, "0.0")
|
|
field(LNK2, "$(INSTR)$(M):AdjustOrigin.VAL PP") # Reset to zero
|
|
}
|
|
|
|
# This record forwards the adjustment of the origin to the asyn driver.
|
|
record(ao, "$(INSTR)$(M):WriteAO") {
|
|
field(DTYP, "asynFloat64")
|
|
field(OUT, "@asyn($(CONTROLLER),$(AXIS),1) MOTOR_ADJUST_ORIGIN")
|
|
field(PINI, "NO")
|
|
field(VAL, "0")
|
|
}
|
|
|
|
# This record pair reads the parameter library value for "AdjustOriginHighLimitFromDriver_"
|
|
# and pushes it to the high limit field of the "$(INSTR)$(M):AdjustOrigin" PV.
|
|
# This can be used to read limits from the hardware and correspondingly update the motor record from the driver.
|
|
# The implementation strategy is taken from https://epics.anl.gov/tech-talk/2022/msg00464.php.
|
|
# This record is coupled to the parameter library via AdjustOriginHighLimitFromDriver_ -> MOTOR_AOHL_FROM_DRIVER.
|
|
record(ai, "$(INSTR)$(M):AOHL_RBV")
|
|
{
|
|
field(DTYP, "asynFloat64")
|
|
field(INP, "@asyn($(CONTROLLER),$(AXIS)) MOTOR_AOHL_FROM_DRIVER")
|
|
field(SCAN, "I/O Intr")
|
|
field(FLNK, "$(INSTR)$(M):PushAOHL2Field")
|
|
field(PINI, "NO")
|
|
}
|
|
# Abbreviated name because EPICS apparently has a maximum record name length
|
|
record(ao, "$(INSTR)$(M):PushAOHL2Field") {
|
|
field(DOL, "$(INSTR)$(M):AOHL_RBV NPP")
|
|
field(OUT, "$(INSTR)$(M):AdjustOrigin.DRVH")
|
|
field(OMSL, "closed_loop")
|
|
field(PINI, "NO")
|
|
}
|
|
|
|
# This record pair reads the parameter library value for "motorLowLimitFromDriver_"
|
|
# and pushes it to the low limit field of the "$(INSTR)$(M):AdjustOrigin" PV.
|
|
# This can be used to read limits from the hardware and correspondingly update the motor record from the driver.
|
|
# The implementation strategy is taken from https://epics.anl.gov/tech-talk/2022/msg00464.php.
|
|
# This record is coupled to the parameter library via AdjustOriginLowLimitFromDriver_ -> MOTOR_AOLL_FROM_DRIVER.
|
|
record(ai, "$(INSTR)$(M):AOLL_RBV")
|
|
{
|
|
field(DTYP, "asynFloat64")
|
|
field(INP, "@asyn($(CONTROLLER),$(AXIS)) MOTOR_AOLL_FROM_DRIVER")
|
|
field(SCAN, "I/O Intr")
|
|
field(FLNK, "$(INSTR)$(M):PushAOLL2Field")
|
|
field(PINI, "NO")
|
|
}
|
|
# Abbreviated name because EPICS apparently has a maximum record name length
|
|
record(ao, "$(INSTR)$(M):PushAOLL2Field") {
|
|
field(DOL, "$(INSTR)$(M):AOLL_RBV NPP")
|
|
field(OUT, "$(INSTR)$(M):AdjustOrigin.DRVL")
|
|
field(OMSL, "closed_loop")
|
|
field(PINI, "NO")
|
|
}
|