# EL737 EPICS Database for streamdevice support # Macros # P - Prefix # NAME - just a name, e.g. EL737 # PROTO - Stream device protocol file # ASYN_PORT - Low level Asyn IP Port to EL737 # Send initial initialisation commands record(bo, "$(P):$(NAME):INIT-CONF") { field(DESC, "Initialises the Counterbox") field(OUT, "@$(PROTO) initialise($(P):$(NAME):) $(ASYN_PORT)") field(PINI, "YES") # Run at init field(DTYP, "stream") field(FLNK, "$(P):$(NAME):INIT-BOX") } # As we aren't certain of the order that PINI exectutes PVs, we only set it to # true on INIT-CONF to make sure the box is ready to receive commands, and then # let INIT-CONF trigger the initialisation of other necessary records record(fanout, "$(P):$(NAME):INIT-BOX") { field(DESC, "Rewrite PVs to Box") field(SELM, "All") field(LNK0, "$(P):$(NAME):MONITOR-CHANNEL_RBV PP") field(LNK1, "$(P):$(NAME):RAW-STATUS PP") field(LNK2, "$(P):$(NAME):THRESHOLD_RBV PP") } record(longout, "$(P):$(NAME):FULL-RESET") { field(DESC, "Reset the Counterbox") field(OUT, "@$(PROTO) fullReset($(P):$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") } ################################################################################ # Status Variables record(stringin, "$(P):$(NAME):MsgTxt") { field(DESC, "Unexpected received response") field(DTYP, "devCounterBoxStringError") field(FLNK, "$(P):$(NAME):INVALID-CONFIG") } # We want to recognise the invalid config error message, so that we can rerun # the init if it occurs. This should only happen after turning the box off and # on again or running a full reset record(scalcout, "$(P):$(NAME):INVALID-CONFIG") { field(DESC, "Has the counterbox been configured?") field(CALC, "AA[0,2] == '?OF'") field(INAA, "$(P):$(NAME):MsgTxt") field(FLNK, "$(P):$(NAME):REINIT-CONF") } record(seq, "$(P):$(NAME):REINIT-CONF") { field(LNK1, "$(P):$(NAME):INIT-CONF PP") field(DO1, 1) field(SELM, "Specified") field(SELL, "$(P):$(NAME):INVALID-CONFIG.VAL") } # Important! The "$(P):$(NAME):READALL" isn't configure with a SCAN. Instead, # it must always be triggered after the value of $(P):$(NAME):RAW-STATUS is # updated, so that it can't be the case that the status changes back from # counting to idle, without having updated the time and count values. record(longin, "$(P):$(NAME):RAW-STATUS") { field(DESC, "Raw returned status value") field(DTYP, "stream") field(SCAN, ".1 second") field(INP, "@$(PROTO) readStatus($(P):$(NAME):) $(ASYN_PORT)") field(FLNK, "$(P):$(NAME):READALL") } record(calc, "$(P):$(NAME):MAP-STATUS") { field(DESC, "Maps Raw Status to State") field(INPA, "$(P):$(NAME):RAW-STATUS NPP") field(INPB, "$(P):$(NAME):INVALID-CONFIG NPP") field(INPC, "$(P):$(NAME):RAW-STATUS.UDF NPP") # should also be invalid if can't read the status field(CALC, "(B=1||C==1)?4:A=0?0:(A=1||A=2)?1:(A=5||A=6)?2:(A=9||A=13||A=10||A=14)?3:4") field(FLNK, "$(P):$(NAME):STATUS") } record(mbbi, "$(P):$(NAME):STATUS") { field(DESC, "Counterbox Status") field(INP, "$(P):$(NAME):MAP-STATUS NPP") field(ZRVL, "0") field(ZRST, "Idle") field(ONVL, "1") field(ONST, "Counting") field(TWVL, "2") field(TWST, "Low rate") field(THVL, "3") field(THST, "Paused") # 4 should never happen, if it does it means the counter box reports undocumented statusbits field(FRVL, "4") field(FRST, "INVALID") } record(longin, "$(P):$(NAME):CHANNELS") { field(DESC, "Total Supported Channels") field(VAL, $(CHANNELS)) field(DISP, 1) } ################################################################################ # Count Commands record(ao,"$(P):$(NAME):PRESET-COUNT") { field(DESC, "Count until preset reached") field(DTYP, "stream") field(OUT, "@$(PROTO) startWithCountPreset($(P):$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(PREC, 2) } record(ao,"$(P):$(NAME):PRESET-TIME") { field(DESC, "Count for specified time") field(DTYP, "stream") field(OUT, "@$(PROTO) startWithTimePreset($(P):$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(PREC, 2) field(EGU, "seconds") } record(bo,"$(P):$(NAME):PAUSE") { field(DESC, "Pause the current count") field(DTYP, "stream") field(OUT, "@$(PROTO) pauseCount($(P):$(NAME):) $(ASYN_PORT)") field(VAL, "0") } record(bo,"$(P):$(NAME):CONTINUE") { field(DESC, "Continue with a count that was paused") field(DTYP, "stream") field(OUT, "@$(PROTO) continueCount($(P):$(NAME):) $(ASYN_PORT)") field(VAL, "0") } record(bo, "$(P):$(NAME):STOP") { field(DESC, "Stop the current counting operation") field(DTYP, "stream") field(OUT, "@$(PROTO) stopCount($(P):$(NAME):) $(ASYN_PORT)") } # TODO should changing the monitor also set things? # or only when actually setting a threshold? record(longout,"$(P):$(NAME):THRESHOLD") { field(DESC, "Minimum rate for counting to proceed") field(VAL, "0") # Rate field(DRVL, "0") # Minimum Rate field(DTYP, "stream") field(OUT, "@$(PROTO) setMinRate($(P):$(NAME):) $(ASYN_PORT)") } record(longin,"$(P):$(NAME):THRESHOLD_RBV") { field(DESC, "Minimum rate for counting to proceed") field(DTYP, "stream") field(INP, "@$(PROTO) readMinRate($(P):$(NAME):) $(ASYN_PORT)") field(SCAN, "2 second") } record(longout,"$(P):$(NAME):THRESHOLD-MONITOR") { field(DESC, "Channel monitored for minimum rate") field(VAL, "1") # Monitor field(DRVL, "1") # Smallest Threshold Channel field(DRVL, "$(CHANNELS)") # Largest Threshold Channel } record(longin,"$(P):$(NAME):THRESHOLD-MONITOR_RBV") { field(DESC, "Channel monitored for minimum rate") } ################################################################################ # Read all monitors values record(ai, "$(P):$(NAME):READALL") { field(DESC, "Reads monitors and elapsed time") field(INP, "@$(PROTO) readAll$(CHANNELS)($(P):$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") field(FLNK, "$(P):$(NAME):MAP-STATUS") } record(ai,"$(P):$(NAME):ELAPSED-TIME") { field(DESC, "Counterbox Measured Time") field(EGU, "seconds") } # Not yet sure whether we want to support this # record(longin, "$(P):$(NAME):R1") # { # field(DESC, "Counterbox Rate CH1") # field(INP, "@$(PROTO) readRate($(P):$(NAME):, 1) $(ASYN_PORT)") # field(SCAN, ".2 second") # field(DTYP, "stream") # }