These changes process the AdjustOrigin record during initialization to make sure its .STAT field does not show "UDF" anymore before the first processing. The gate record makes sure that no command is send to the underlying hardware during initial processing.
144 lines
5.6 KiB
Plaintext
144 lines
5.6 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")
|
|
}
|
|
|
|
# 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, "YES")
|
|
field(FLNK, "$(INSTR)$(M):ResetAO")
|
|
field(VAL, "0")
|
|
field(UDF, "FALSE")
|
|
field(SCAN, "Passive")
|
|
}
|
|
|
|
# Only forward nonzero inputs for the origin adjustment
|
|
record(calc, "$(INSTR)$(M):GateOrigin") {
|
|
field(CALC, "A!=0?A:VAL")
|
|
field(INPA, "$(INSTR)$(M):AdjustOrigin")
|
|
field(OUT, "$(INSTR)$(M):WriteAO.VAL PP") # Forward the value to the driver
|
|
field(PINI, "NO")
|
|
field(SCAN, "Passive")
|
|
}
|
|
|
|
# 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, "1") # Dummy value which is only here to trigger processing of LNK1
|
|
field(LNK1, "$(INSTR)$(M):GateOrigin.PROC PP")
|
|
field(DOL2, "0.0")
|
|
field(LNK2, "$(INSTR)$(M):AdjustOrigin.VAL PP") # Reset to zero
|
|
field(UDF, "FALSE")
|
|
}
|
|
|
|
# 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")
|
|
}
|