Draft Stream Device Rewrite of Counterbox Driver
This commit is contained in:
46
db/counterbox.db
Normal file
46
db/counterbox.db
Normal file
@ -0,0 +1,46 @@
|
||||
# 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
|
||||
|
||||
################################################################################
|
||||
# Status Variables
|
||||
|
||||
record(longin, "$(P):$(NAME):MONITOR-CHANNEL")
|
||||
{
|
||||
field(DESC, "PRESET-COUNT Monitors this channel")
|
||||
field(VAL, 1)
|
||||
field(DISP, 1)
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV")
|
||||
{
|
||||
field(DESC, "PRESET-COUNT Monitors this channel")
|
||||
field(VAL, 1)
|
||||
field(DISP, 1)
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Count Commands
|
||||
|
||||
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, "8") # Largest Threshold Channel
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Read all monitors values
|
||||
|
||||
record(ai, "$(P):$(NAME):READALL")
|
||||
{
|
||||
field(DESC, "Reads monitors and elapsed time")
|
||||
field(INP, "@$(PROTO) readAll8($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(SCAN, ".2 second")
|
||||
field(DTYP, "stream")
|
||||
field(FLNK, "$(P):$(NAME):UNSET-COUNTING")
|
||||
}
|
128
db/counterbox.proto
Normal file
128
db/counterbox.proto
Normal file
@ -0,0 +1,128 @@
|
||||
#
|
||||
# Counterbox Protocol File
|
||||
#
|
||||
OutTerminator = CR;
|
||||
InTerminator = CR;
|
||||
ReadTimeout = 100;
|
||||
WriteTimeout = 100;
|
||||
ReplyTimeout = 200;
|
||||
LockTimeout = 450;
|
||||
|
||||
initialise {
|
||||
out "RMT 1";
|
||||
in;
|
||||
out "ECHO 2";
|
||||
in "%(\$1MsgTxt)s"; # Clear MsgTxt on Init
|
||||
@mismatch{
|
||||
exec 'echo "Failed to configure counterbox" && exit(1)';
|
||||
}
|
||||
}
|
||||
|
||||
fullReset {
|
||||
out "\%";
|
||||
wait 5000;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Status Variables
|
||||
|
||||
readStatus {
|
||||
out "RS";
|
||||
in "%d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
readPresetMonitor {
|
||||
out "PC";
|
||||
in "%d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
writePresetMonitor {
|
||||
out "PC %d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Count Commands
|
||||
|
||||
startWithCountPreset {
|
||||
out "MP %d";
|
||||
in;
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
startWithTimePreset {
|
||||
out "TP %#.2f";
|
||||
in;
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
pauseCount {
|
||||
out "PS";
|
||||
in;
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
continueCount {
|
||||
out "CO";
|
||||
in;
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
stopCount {
|
||||
out "S";
|
||||
in;
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
setMinRate{
|
||||
out "DL %(\$1THRESHOLD-MONITOR)d %(\$1THRESHOLD)d";
|
||||
in;
|
||||
out "DR %(\$1THRESHOLD-MONITOR)d";
|
||||
in;
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
readMinRate{
|
||||
out "DR";
|
||||
in "%(\$1THRESHOLD-MONITOR_RBV)d";
|
||||
out "DL %(\$1THRESHOLD-MONITOR_RBV)d";
|
||||
in "%(\$1THRESHOLD_RBV)d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Read Values From Monitors
|
||||
|
||||
readAll8 {
|
||||
out "RA";
|
||||
in "%(\$1ELAPSED-TIME)f %(\$1M1)d %(\$1M2)d %(\$1M3)d %(\$1M4)d %(\$1M5)d %(\$1M6)d %(\$1M7)d %(\$1M8)d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
readAll10 {
|
||||
out "RA";
|
||||
in "%(\$1ELAPSED-TIME)f %(\$1M1)d %(\$1M2)d %(\$1M3)d %(\$1M4)d %(\$1M5)d %(\$1M6)d %(\$1M7)d %(\$1M8)d %(\$1M9)d %(\$1M10)d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
readRate {
|
||||
out "RR \$2";
|
||||
in "%(\$1R\$2)f";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Testing Commands
|
||||
|
||||
switchTestgenOnOff {
|
||||
out "TG %{off|on}";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
||||
|
||||
# Only suppporting test channel 1 at the moment. (The first argument to TG)
|
||||
setTestSignal {
|
||||
out "TG 1 %(\$1TESTGEN-HIGHRATE)d %(\$1TESTGEN-LOWRATE)d";
|
||||
@mismatch{in "%(\$1MsgTxt)s";}
|
||||
}
|
259
db/counterbox_common.db
Normal file
259
db/counterbox_common.db
Normal file
@ -0,0 +1,259 @@
|
||||
# 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):READALL 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")
|
||||
}
|
||||
|
||||
# The COUNTING PV stays True until Counterbox has switched back to idle mode
|
||||
# and the monitor counts have been read. Therefore, we know that the monitor
|
||||
# values have been updated to represent their final values, when this switches
|
||||
# back to False.
|
||||
#
|
||||
# This is accomplished via the explicit SET-COUNTING and UNSET-COUNTING seq
|
||||
# records, that are triggered by a switch to the counting status
|
||||
# (RAW-STATUS == 1 || 2) and a read of the monitors respectively.
|
||||
record(bi, "$(P):$(NAME):COUNTING")
|
||||
{
|
||||
field(DESC, "Counterbox is Counting")
|
||||
field(VAL, 0)
|
||||
}
|
||||
|
||||
record(seq, "$(P):$(NAME):SET-COUNTING")
|
||||
{
|
||||
field(LNK1, "$(P):$(NAME):COUNTING PP")
|
||||
field(DO1, 1)
|
||||
field(SELM, "Specified")
|
||||
field(SELL, "$(P):$(NAME):MAP-STATUS.VAL")
|
||||
field(FLNK, "$(P):$(NAME):STATUS")
|
||||
}
|
||||
|
||||
record(seq, "$(P):$(NAME):UNSET-COUNTING")
|
||||
{
|
||||
field(LNK0, "$(P):$(NAME):COUNTING PP")
|
||||
field(DO0, 0)
|
||||
field(SELM, "Specified")
|
||||
field(SELL, "$(P):$(NAME):RAW-STATUS.VAL")
|
||||
field(FLNK, "$(P):$(NAME):MAP-STATUS")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):RAW-STATUS")
|
||||
{
|
||||
field(DESC, "Raw returned status value")
|
||||
field(DTYP, "stream")
|
||||
field(SCAN, ".2 second")
|
||||
field(INP, "@$(PROTO) readStatus($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(FLNK, "$(P):$(NAME):MAP-STATUS")
|
||||
}
|
||||
|
||||
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):COUNTING NPP")
|
||||
field(CALC, "B=1?4:(C=1&&A=0)||A=1||A=2?1:A=0?0:A=5||A=6?2:A=9||A=13||A=10||A=14?3:4")
|
||||
field(FLNK, "$(P):$(NAME):SET-COUNTING")
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# 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(longin,"$(P):$(NAME):THRESHOLD-MONITOR_RBV")
|
||||
{
|
||||
field(DESC, "Channel monitored for minimum rate")
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Read all monitors values
|
||||
|
||||
record(ai,"$(P):$(NAME):ELAPSED-TIME")
|
||||
{
|
||||
field(DESC, "Counterbox Measured Time")
|
||||
field(EGU, "seconds")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M1")
|
||||
{
|
||||
field(DESC, "Counterbox CH1")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M2")
|
||||
{
|
||||
field(DESC, "Counterbox CH2")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M3")
|
||||
{
|
||||
field(DESC, "Counterbox CH3")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M4")
|
||||
{
|
||||
field(DESC, "Counterbox CH4")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M5")
|
||||
{
|
||||
field(DESC, "Counterbox CH5")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M6")
|
||||
{
|
||||
field(DESC, "Counterbox CH6")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M7")
|
||||
{
|
||||
field(DESC, "Counterbox CH7")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M8")
|
||||
{
|
||||
field(DESC, "Counterbox CH8")
|
||||
}
|
||||
|
||||
# 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")
|
||||
# }
|
88
db/counterbox_v2.db
Normal file
88
db/counterbox_v2.db
Normal file
@ -0,0 +1,88 @@
|
||||
# EL737 EPICS Database for streamdevice support
|
||||
# Macros
|
||||
# P - Prefix
|
||||
# NAME - just a name, e.g. DAQV2
|
||||
# PROTO - Stream device protocol file
|
||||
# ASYN_PORT - Low level Asyn IP Port to Counterbox
|
||||
|
||||
################################################################################
|
||||
# Status Variables
|
||||
|
||||
record(longout, "$(P):$(NAME):MONITOR-CHANNEL")
|
||||
{
|
||||
field(DESC, "PRESET-COUNT Monitors this channel")
|
||||
field(DTYP, "stream")
|
||||
field(OUT, "@$(PROTO) writePresetMonitor($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(FLNK, "$(P):$(NAME):MONITOR-CHANNEL_RBV")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV")
|
||||
{
|
||||
field(DESC, "PRESET-COUNT Monitors this channel")
|
||||
field(DTYP, "stream")
|
||||
field(INP, "@$(PROTO) readPresetMonitor($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(SCAN, "5 second")
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Count Commands
|
||||
|
||||
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, "10") # Largest Threshold Channel
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Read all monitors values
|
||||
|
||||
record(ai, "$(P):$(NAME):READALL")
|
||||
{
|
||||
field(DESC, "Reads monitors and elapsed time")
|
||||
field(INP, "@$(PROTO) readAll10($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(SCAN, ".2 second")
|
||||
field(DTYP, "stream")
|
||||
field(FLNK, "$(P):$(NAME):UNSET-COUNTING")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M9")
|
||||
{
|
||||
field(DESC, "Counterbox CH9")
|
||||
}
|
||||
|
||||
record(longin, "$(P):$(NAME):M10")
|
||||
{
|
||||
field(DESC, "Counterbox CH10")
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Testing Commands
|
||||
|
||||
# These won't match the values on the machine after a full restart But I chose
|
||||
# not to force their intialisation as they are only important for testing
|
||||
|
||||
record(bo, "$(P):$(NAME):TESTGEN")
|
||||
{
|
||||
field(DESC, "Turn on/off Testgen Signal")
|
||||
field(DTYP, "stream")
|
||||
field(OUT, "@$(PROTO) switchTestgenOnOff($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(VAL, 0)
|
||||
}
|
||||
|
||||
record(longout, "$(P):$(NAME):TESTGEN-LOWRATE")
|
||||
{
|
||||
field(DESC, "Set Minimum Testgen Rate")
|
||||
field(DTYP, "stream")
|
||||
field(OUT, "@$(PROTO) setTestSignal($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(VAL, 1000)
|
||||
}
|
||||
|
||||
record(longout, "$(P):$(NAME):TESTGEN-HIGHRATE")
|
||||
{
|
||||
field(DESC, "Set Maximum Testgen Rate")
|
||||
field(DTYP, "stream")
|
||||
field(OUT, "@$(PROTO) setTestSignal($(P):$(NAME):) $(ASYN_PORT)")
|
||||
field(VAL, 1000)
|
||||
}
|
Reference in New Issue
Block a user