Files
sinqSPS/beamstop/sans_llb_beamstop.db
T
wall_e c2b45a91d2
Test And Build / Build (push) Successful in 4s
use internal MCU-derived state in addition to SPS
2026-05-19 15:31:31 +02:00

453 lines
14 KiB
Plaintext

################################################################################
# Beamstop Changer
################################################################################
record(longout, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP-INIT")
{
field(DESC, "Initialises BEAMSTOP PV")
field(DOL, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP_RBV NPP")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP NPP")
field(OMSL, "closed_loop")
field(PINI, "YES")
}
record(longout, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP")
{
field(DESC, "Select new Beamstop")
field(DRVL, 0)
field(DRVH, 3)
field(PINI, "NO")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):SET-BUSY.PROC PP")
}
# Reset status
record(seq, "$(INSTR)$(SPS_REGISTER_NAME):RESET")
{
field(DESC, "Try to reset status")
# Set the beamstop setpoint to same as readback
# in case they are out of sync, i.e. retry error.
field(DOL0, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP_RBV NPP")
field(LNK0, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP NPP")
field(DOL1, 0)
field(LNK1, "$(INSTR)$(SPS_REGISTER_NAME):STATUS PP")
field(SELM, "All")
}
record(bi, "$(INSTR)$(SPS_REGISTER_NAME):BUSY")
{
field(DESC, "Internal Busy State")
field(VAL, 0)
field(ZNAM, "Ready")
field(ONAM, "Busy")
}
# Make sure to disable motors before actually triggering SPS so there can be no
# chance, that they switch to a busy state in Nicos before being disabled
record(seq, "$(INSTR)$(SPS_REGISTER_NAME):SET-BUSY")
{
field(DESC, "Trigger Internal Busy Status")
field(SELM, "All")
# This determines the number of max retry ticks
field(DOL0, 5)
field(LNK0, "$(INSTR)$(SPS_REGISTER_NAME):BUSY PP")
field(DOL1, "$(INSTR)$(SPS_REGISTER_NAME):BSX-DISV PP")
field(LNK1, "$(BS_MCU):bsx.DISV PP")
field(DOL2, "$(INSTR)$(SPS_REGISTER_NAME):BSY-DISV PP")
field(LNK2, "$(BS_MCU):bsy.DISV PP")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP-OUT")
}
# Can be used to disable BSX and BSY during
# a beamstop change
record(calc, "$(INSTR)$(SPS_REGISTER_NAME):BSX-DISV")
{
field(INPA, "$(BS_MCU):bsx.DISA NPP")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):MAP-STATUS NPP")
field(INPC, "$(INSTR)$(SPS_REGISTER_NAME):BUSY NPP")
field(CALC, "(B=0)&&(C=0)?!A:A")
}
record(calc, "$(INSTR)$(SPS_REGISTER_NAME):BSY-DISV")
{
field(INPA, "$(BS_MCU):bsy.DISA NPP")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):MAP-STATUS NPP")
field(INPC, "$(INSTR)$(SPS_REGISTER_NAME):BUSY NPP")
field(CALC, "(B=0)&&(C=0)?!A:A")
}
record(longout, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP-OUT")
{
field(DESC, "Send new selection to SPS")
field(DOL, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP NPP")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP-RAW PP")
field(OMSL, "closed_loop")
field(DRVL, 0)
field(DRVH, 3)
field(PINI, "NO")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):TRIGGER-DELAY")
}
record(seq, "$(INSTR)$(SPS_REGISTER_NAME):TRIGGER-DELAY")
{
field(DESC, "Delays Internal Trigger as SPS too slow")
field(DOL0, 1)
field(LNK0, "$(INSTR)$(SPS_REGISTER_NAME):TRIGGER.PROC PP")
field(DLY0, 0.5)
field(SELM, "All")
field(PINI, "NO")
}
record(longout, "$(INSTR)$(SPS_REGISTER_NAME):TRIGGER")
{
field(DESC, "Internal Trigger")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):EXECUTE-CHANGE PP")
field(OMSL, "closed_loop")
field(DOL, 1)
field(PINI, "NO")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):MAP-STATUS PP")
}
# This is a hack, the SPS sometimes doesn't registers the beamstop
# execute command.
record(calcout, "$(INSTR)$(SPS_REGISTER_NAME):RETRY")
{
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP NPP")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP_RBV NPP")
field(INPC, "$(INSTR)$(SPS_REGISTER_NAME):BUSY")
# Can't trust the SPS, so instead monitor the MCU state
field(INPD, "$(BS_MCU):BS:TARGET_RANGE NPP")
field(CALC, "A#B&&C#0&&D=0?1:0")
field(DOPT, "Use CALC")
field(OOPT, "When Non-zero")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP-OUT.PROC PP")
field(SCAN, "2 second")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):SPS-CHANGING")
}
record(calc, "$(INSTR)$(SPS_REGISTER_NAME):SPS-CHANGING")
{
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):MOVES NPP")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):IN-POSITION NPP")
field(CALC, "A=1||B=0")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):MCU-CHANGING")
}
# Can't trust the SPS
record(calc, "$(INSTR)$(SPS_REGISTER_NAME):MCU-CHANGING")
{
field(INPA, "$(BS_MCU):BS:TARGET_RANGE NPP")
field(CALC, "A#0")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):DECREASE-BUSY-TICK")
}
record(calcout, "$(INSTR)$(SPS_REGISTER_NAME):DECREASE-BUSY-TICK")
{
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):BUSY NPP")
field(CALC, "A")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "A-1")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):BUSY PP")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):DELAY-RETRY-ERROR")
}
# Delay check for retry error, not this happens after each retry.
# But we gate the retry error wih checking if busy is 0
record(seq, "$(INSTR)$(SPS_REGISTER_NAME):DELAY-RETRY-ERROR")
{
field(DESC, "Delays checking if retry error occurred")
field(DOL0, 1)
field(LNK0, "$(INSTR)$(SPS_REGISTER_NAME):RETRY-ERROR.PROC PP")
field(DLY0, 1)
field(SELM, "All")
}
record(calc, "$(INSTR)$(SPS_REGISTER_NAME):RETRY-ERROR")
{
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP_RBV")
field(INPC, "$(INSTR)$(SPS_REGISTER_NAME):BUSY")
field(INPD, "$(INSTR)$(SPS_REGISTER_NAME):SPS-CHANGING NPP")
field(CALC, "A#B&&C=0&&D=0?1:0")
#field(OOPT, "When Non-zero")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):MAP-STATUS")
}
record(calc, "$(INSTR)$(SPS_REGISTER_NAME):MAP-STATUS")
{
field(DESC, "Maps Status Variables to singular status")
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):SERVICE-MODE NPP")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):SPS-CHANGING NPP")
field(INPD, "$(INSTR)$(SPS_REGISTER_NAME):ERROR NPP")
field(INPE, "$(INSTR)$(SPS_REGISTER_NAME):EXECUTE-POSSIBLE NPP")
field(INPF, "$(INSTR)$(SPS_REGISTER_NAME):ConnStatusFetch NPP")
field(INPG, "$(INSTR)$(SPS_REGISTER_NAME):ConnStatusWrite NPP")
field(INPH, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP NPP")
field(INPI, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP_RBV NPP")
field(INPK, "$(INSTR)$(SPS_REGISTER_NAME):RETRY-ERROR NPP")
# For the case of 0... as the SPS always has everything as 0
# during movement, meaning that we end up flicking between
# busy and not busy when switching to 0
field(INPC, "$(INSTR)$(SPS_REGISTER_NAME):LOADED NPP")
field(CALC, "(F=0||G=0||D=1||K=1)?3:(A=1)?2:(B=1||H#I||H#C)?1:0")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):UNBLOCK-MOTORS")
}
# Make sure, that motors are re-enabled before the status
# of the changer returns to "Okay".
record(seq, "$(INSTR)$(SPS_REGISTER_NAME):UNBLOCK-MOTORS")
{
field(DESC, "Trigger Internal Busy Status")
field(SELM, "All")
field(DOL1, "$(INSTR)$(SPS_REGISTER_NAME):BSX-DISV PP")
field(LNK1, "$(BS_MCU):bsx.DISV PP")
field(DOL2, "$(INSTR)$(SPS_REGISTER_NAME):BSY-DISV PP")
field(LNK2, "$(BS_MCU):bsy.DISV PP")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):STATUS PP")
}
record(mbbi, "$(INSTR)$(SPS_REGISTER_NAME):STATUS")
{
field(DESC, "Status of Beamstop Changer")
field(INP, "$(INSTR)$(SPS_REGISTER_NAME):MAP-STATUS NPP")
field(ZRVL, "0")
field(ZRST, "Okay")
field(ONVL, "1")
field(ONST, "Busy")
field(TWVL, "2")
field(TWST, "Warning")
field(THVL, "3")
field(THST, "Error")
field(FRST, "4")
field(FRST, "Unknown")
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):STATUS-Msg")
}
record(stringout, "$(INSTR)$(SPS_REGISTER_NAME):Retry-Error-Msg")
{
field(DESC, "Beamstop max retries failed message")
field(VAL, "Failed trying to change beamstop")
}
record(scalcout, "$(INSTR)$(SPS_REGISTER_NAME):STATUS-Msg")
{
field(DESC, "Status Message")
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):RETRY-ERROR NPP")
field(INAA, "$(INSTR)$(SPS_REGISTER_NAME):Retry-Error-Msg NPP")
field(INBB, "$(INSTR)$(SPS_REGISTER_NAME):BLOCKED-REASON-Msg NPP")
field(CALC, 'A=1?AA:BB')
field(FLNK, "$(INSTR)$(SPS_REGISTER_NAME):SET-READY")
}
record(calcout, "$(INSTR)$(SPS_REGISTER_NAME):SET-READY")
{
field(INPA, "$(INSTR)$(SPS_REGISTER_NAME):BUSY")
field(INPB, "$(INSTR)$(SPS_REGISTER_NAME):MCU-CHANGING NPP")
field(CALC, "A?B:0")
field(OOPT, "Transition To Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "0")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):BUSY PP")
}
################################################################################
# Beamstop Motors and Collision Detection
################################################################################
record(longin, "$(BS_MCU):BS:X_0") {
field(DESC, "X-Position of Beamstop 0")
field(DTYP, "stream")
field(INP , "@$(PROTO) pmac_get(Q453) $(BS_MCU_ASYN_PORT) 0")
field(PINI, "YES")
}
record(longin, "$(BS_MCU):BS:X_1") {
field(DESC, "X-Position of Beamstop 1")
field(DTYP, "stream")
field(INP , "@$(PROTO) pmac_get(Q454) $(BS_MCU_ASYN_PORT) 0")
field(PINI, "YES")
}
record(longin, "$(BS_MCU):BS:X_2") {
field(DESC, "X-Position of Beamstop 2")
field(DTYP, "stream")
field(INP , "@$(PROTO) pmac_get(Q455) $(BS_MCU_ASYN_PORT) 0")
field(PINI, "YES")
}
record(longin, "$(BS_MCU):BS:X_3") {
field(DESC, "X-Position of Beamstop 3")
field(DTYP, "stream")
field(INP , "@$(PROTO) pmac_get(Q456) $(BS_MCU_ASYN_PORT) 0")
field(PINI, "YES")
}
record(longin, "$(BS_MCU):BS:Y_GET") {
field(DESC, "Y Position for picking up Beamstop")
field(DTYP, "stream")
field(INP , "@$(PROTO) pmac_get(Q553) $(BS_MCU_ASYN_PORT) 0")
field(PINI, "YES")
}
record(longin, "$(BS_MCU):BS:Y_PUT") {
field(DESC, "Y Position under beamstops")
field(DTYP, "stream")
field(INP , "@$(PROTO) pmac_get(Q554) $(BS_MCU_ASYN_PORT) 0")
field(PINI, "YES")
}
record(calcout, "$(BS_MCU):BS:ST") {
field(DESC, "Monitors beamstop changing")
field(DTYP, "stream")
field(OUT , "@$(PROTO) st() $(BS_MCU_ASYN_PORT) 0")
field(CALC, "0")
field(SCAN, ".1 second")
field(FLNK, "$(BS_MCU):BS:ST_FANOUT1")
}
record(fanout, "$(BS_MCU):BS:ST_FANOUT1") {
field(LNK1, "$(BS_MCU):BS:TARGET")
field(LNK2, "$(BS_MCU):BS:TARGET_X")
field(LNK3, "$(BS_MCU):BS:TARGET_Y")
field(LNK5, "$(BS_MCU):BS:TARGET_BS_RAW")
field(LNK6, "$(BS_MCU):BS:TARGET_BS")
field(FLNK, "$(BS_MCU):BS:ST_FANOUT2")
}
record(fanout, "$(BS_MCU):BS:ST_FANOUT2") {
field(LNK1, "$(BS_MCU):BS:BSX_ACK_RBV")
field(LNK2, "$(BS_MCU):BS:BSY_ACK_RBV")
field(LNK3, "$(BS_MCU):BS:TARGET_RANGE_RAW")
field(LNK4, "$(BS_MCU):BS:TARGET_RANGE")
field(LNK5, "$(BS_MCU):BS:LOADED_RAW")
field(LNK6, "$(BS_MCU):BS:INVALID")
}
record(longin, "$(BS_MCU):BS:TARGET") {
field(DESC, "Beamstop position being driven to")
field(INP, "$(BS_MCU):BS:ST.A NPP MS")
}
record(ai, "$(BS_MCU):BS:TARGET_X") {
field(DESC, "X Position being driven to")
field(INP, "$(BS_MCU):BS:ST.B NPP MS")
}
record(ai, "$(BS_MCU):BS:TARGET_Y") {
field(DESC, "Y Position being driven to")
field(INP, "$(BS_MCU):BS:ST.C NPP MS")
}
record(longin, "$(BS_MCU):BS:BSX_ACK_RBV") {
field(DESC, "BSX ACK")
field(INP, "$(BS_MCU):BS:ST.D NPP MS")
}
record(longin, "$(BS_MCU):BS:BSY_ACK_RBV") {
field(DESC, "BSY ACK")
field(INP, "$(BS_MCU):BS:ST.E NPP MS")
}
record(calc, "$(BS_MCU):BS:TARGET_BS_RAW") {
field(DESC, "Beamstop == TARGET_X")
# Dynamic Inputs
field(INPA, "$(BS_MCU):BS:TARGET_X NPP MS")
# Static Inputs
field(INPI, "$(BS_MCU):BS:X_0 NPP MS")
field(INPJ, "$(BS_MCU):BS:X_1 NPP MS")
field(INPK, "$(BS_MCU):BS:X_2 NPP MS")
field(INPL, "$(BS_MCU):BS:X_3 NPP MS")
# Maybe having a tolerance isn't really necessary?
# they get set exactly to the value in the MCU
field(CALC, "ABS(A-I)<1?0:ABS(A-J)<1?1:ABS(A-K)<1?2:ABS(A-L)<1?3:4")
# field(CALC, "A=I?0:A=J?1:A=K?2:A=L?3:4")
}
record(mbbi, "$(BS_MCU):BS:TARGET_BS") {
field(DESC, "Target Beamstop Holder")
field(DTYP, "Soft Channel")
field(INP, "$(BS_MCU):BS:TARGET_BS_RAW NPP MS")
field(ZRST, "No Beamstop")
field(ONST, "Beamstop 1")
field(TWST, "Beamstop 2")
field(THST, "Beamstop 3")
field(FRST, "User Mode")
}
record(calc, "$(BS_MCU):BS:TARGET_RANGE_RAW") {
field(DESC, "Beamstop target y-range")
# Dynamic Inputs
field(INPA, "$(BS_MCU):BS:TARGET_Y NPP MS")
# Static Inputs
field(INPK, "$(BS_MCU):BS:Y_GET NPP MS")
field(INPL, "$(BS_MCU):BS:Y_PUT NPP MS")
# Maybe having a tolerance isn't really necessary?
# they get set exactly to the value in the MCU
field(CALC, "ABS(A-K)<1?1:ABS(A-L)<1?2:0")
}
record(mbbi, "$(BS_MCU):BS:TARGET_RANGE") {
field(DESC, "Beamstop target y-range")
field(DTYP, "Soft Channel")
field(INP, "$(BS_MCU):BS:TARGET_RANGE_RAW NPP MS")
field(ZRST, "User Mode")
field(ONST, "Level with Beamstops")
field(TWST, "Under Beamstops")
}
record(calcout, "$(BS_MCU):BS:LOADED_RAW")
{
field(INPA, "$(BS_MCU):BS:TARGET_BS NPP MS")
field(INPB, "$(BS_MCU):BS:TARGET_RANGE NPP MS")
field(CALC, "B=2")
field(OOPT, "Transition To Zero")
field(DOPT, "Use OCAL")
field(OCAL, "A")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):LOADED PP")
}
record(longout, "$(INSTR)$(SPS_REGISTER_NAME):LOADED-INIT")
{
field(DESC, "Initialises LOADED PV")
field(DOL, "$(INSTR)$(SPS_REGISTER_NAME):BEAMSTOP_RBV NPP")
field(OUT, "$(INSTR)$(SPS_REGISTER_NAME):LOADED NPP")
field(OMSL, "closed_loop")
field(PINI, "YES")
}
record(mbbi, "$(INSTR)$(SPS_REGISTER_NAME):LOADED")
{
field(DESC, "Most recently lifted beamstop")
field(ZRST, "No Beamstop")
field(ONST, "Beamstop 1")
field(TWST, "Beamstop 2")
field(THST, "Beamstop 3")
}
record(calcout, "$(BS_MCU):BS:INVALID") {
field(DESC, "Invalid Move STOP MOTORS!")
# Dynamic Inputs
field(INPA, "$(BS_MCU):BS:TARGET_BS NPP MS")
field(INPB, "$(BS_MCU):BS:TARGET_RANGE NPP MS")
field(INPC, "$(INSTR)$(SPS_REGISTER_NAME):LOADED NPP MS")
field(CALC, "(A<4) && (B=1) && (A#C)")
field(OOPT, "Transition To Non-zero")
field(OUT, "$(BS_MCU):BS:IMMEDIATE_STOP.PROC PP")
}
record(longout, "$(BS_MCU):BS:IMMEDIATE_STOP") {
field(DESC, "Invalid Move STOP MOTORS!")
# For Test
# field(OUT, "TEST_RECORD PP")
# field(OMSL, "closed_loop")
# field(DOL, "1")
# TODO not currently activated
# FOR REAL
# field(DTYP, "stream")
# field(OUT , "@$(PROTO) stop() $(BS_MCU_ASYN_PORT) 0")
}
# record(longin, "TEST_RECORD") {
# field(VAL, 0)
# }