From 3b660ca560bafec92f21f1708badab885af6cbad Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Wed, 13 Nov 2024 12:29:24 +0100 Subject: [PATCH 1/9] SINQSW-107 makes some changes to better cooperate with Nicos --- db/channels.db | 27 +++++++++++++++++++++ db/counterbox.proto | 34 +++++++++++++++++++++------ db/counterbox_4ch.db | 4 +++- db/counterbox_8ch.db | 4 +++- db/counterbox_common.db | 48 +++++++++++++------------------------- db/counterbox_v2.db | 2 ++ scripts/counterbox_4ch.cmd | 8 +++---- scripts/counterbox_8ch.cmd | 16 ++++++------- scripts/counterbox_v2.cmd | 22 ++++++++--------- 9 files changed, 101 insertions(+), 64 deletions(-) diff --git a/db/channels.db b/db/channels.db index e12ceaa..2a63f54 100644 --- a/db/channels.db +++ b/db/channels.db @@ -11,6 +11,25 @@ ################################################################################ # Count Commands +# record(ao,"$(P):$(NAME):THRESHOLD_$(CHANNEL)") +# { +# field(DESC, "Minimum rate for counting to proceed") +# field(VAL, "0") # Rate +# field(DRVL, "0") # Minimum Rate +# field(OMSL, "supervisory") +# field(OROC, "0") +# field(OUT, "@$(PROTO) setMinRate($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") +# field(DTYP, "stream") +# } +# +# record(ai,"$(P):$(NAME):THRESHOLD_$(CHANNEL)_RBV") +# { +# field(DESC, "Minimum rate for counting to proceed") +# field(INP, "@$(PROTO) readMinRate($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") +# field(DTYP, "stream") +# field(SCAN, "1 second") +# } + ################################################################################ # Read all monitors values @@ -18,3 +37,11 @@ record(longin, "$(P):$(NAME):M$(CHANNEL)") { field(DESC, "Counterbox CH$(CHANNEL)") } + +record(ai, "$(P):$(NAME):R$(CHANNEL)") +{ + field(DESC, "Counterbox Rate CH$(CHANNEL)") + field(INP, "@$(PROTO) readRate($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") + field(DTYP, "stream") + field(SCAN, "1 second") +} diff --git a/db/counterbox.proto b/db/counterbox.proto index b933334..fda8ec0 100644 --- a/db/counterbox.proto +++ b/db/counterbox.proto @@ -76,19 +76,39 @@ stopCount { @mismatch{in "%(\$1MsgTxt)s";} } +# setMinRate{ +# out "DL \$2 %.3f"; +# in; +# @mismatch{in "%(\$1MsgTxt)s";} +# } +# +# readMinRate{ +# out "DL \$2"; +# in "%f"; +# @mismatch{in "%(\$1MsgTxt)s";} +# } + setMinRate{ - out "DL %(\$1THRESHOLD-MONITOR)d %(\$1THRESHOLD)d"; - in; - out "DR %(\$1THRESHOLD-MONITOR)d"; + out "DL %(\$1THRESHOLD-MONITOR_RBV)d %.3f"; in; @mismatch{in "%(\$1MsgTxt)s";} } readMinRate{ - out "DR"; - in "%(\$1THRESHOLD-MONITOR_RBV)d"; out "DL %(\$1THRESHOLD-MONITOR_RBV)d"; - in "%(\$1THRESHOLD_RBV)d"; + in "%f"; + @mismatch{in "%(\$1MsgTxt)s";} +} + +setRateMonitor{ + out "DR %d"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +readRateMonitor{ + out "DR"; + in "%d"; @mismatch{in "%(\$1MsgTxt)s";} } @@ -115,7 +135,7 @@ readAll10 { readRate { out "RR \$2"; - in "%(\$1R\$2)f"; + in "%f"; @mismatch{in "%(\$1MsgTxt)s";} } diff --git a/db/counterbox_4ch.db b/db/counterbox_4ch.db index e5703d1..1a47aaf 100644 --- a/db/counterbox_4ch.db +++ b/db/counterbox_4ch.db @@ -8,10 +8,12 @@ ################################################################################ # Status Variables -record(longin, "$(P):$(NAME):MONITOR-CHANNEL") +record(longout, "$(P):$(NAME):MONITOR-CHANNEL") { field(DESC, "PRESET-COUNT Monitors this channel") field(VAL, 1) + field(DRVL, "1") # Smallest Monitor Channel + field(DRVH, "1") # Largest Monitor Channel field(DISP, 1) } diff --git a/db/counterbox_8ch.db b/db/counterbox_8ch.db index 8f0dfc0..a44d5c2 100644 --- a/db/counterbox_8ch.db +++ b/db/counterbox_8ch.db @@ -8,10 +8,12 @@ ################################################################################ # Status Variables -record(longin, "$(P):$(NAME):MONITOR-CHANNEL") +record(longout, "$(P):$(NAME):MONITOR-CHANNEL") { field(DESC, "PRESET-COUNT Monitors this channel") field(VAL, 1) + field(DRVL, "1") # Smallest Monitor Channel + field(DRVH, "1") # Largest Monitor Channel field(DISP, 1) } diff --git a/db/counterbox_common.db b/db/counterbox_common.db index 09aaf5d..21e9cea 100644 --- a/db/counterbox_common.db +++ b/db/counterbox_common.db @@ -12,19 +12,6 @@ record(bo, "$(P):$(NAME):INIT-CONF") 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") @@ -71,7 +58,7 @@ record(longin, "$(P):$(NAME):RAW-STATUS") { field(DESC, "Raw returned status value") field(DTYP, "stream") - field(SCAN, ".1 second") + field(SCAN, ".5 second") field(INP, "@$(PROTO) readStatus($(P):$(NAME):) $(ASYN_PORT)") field(FLNK, "$(P):$(NAME):READALL") } @@ -156,23 +143,24 @@ record(bo, "$(P):$(NAME):STOP") 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") +record(ao,"$(P):$(NAME):THRESHOLD") { field(DESC, "Minimum rate for counting to proceed") field(VAL, "0") # Rate - field(DRVL, "0") # Minimum Rate - field(DTYP, "stream") + field(DRVL, "0.000001") # Minimum Rate + field(DRVH, "100000") # Maximum Rate + field(OMSL, "supervisory") + field(OROC, "0") field(OUT, "@$(PROTO) setMinRate($(P):$(NAME):) $(ASYN_PORT)") + field(DTYP, "stream") } -record(longin,"$(P):$(NAME):THRESHOLD_RBV") +record(ai,"$(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") + field(DTYP, "stream") + field(SCAN, "1 second") } record(longout,"$(P):$(NAME):THRESHOLD-MONITOR") @@ -180,12 +168,17 @@ 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 + field(DRVH, "$(CHANNELS)") # Largest Threshold Channel + field(OUT, "@$(PROTO) setRateMonitor($(P):$(NAME):) $(ASYN_PORT)") + field(DTYP, "stream") } record(longin,"$(P):$(NAME):THRESHOLD-MONITOR_RBV") { field(DESC, "Channel monitored for minimum rate") + field(INP, "@$(PROTO) readRateMonitor($(P):$(NAME):) $(ASYN_PORT)") + field(DTYP, "stream") + field(SCAN, "1 second") } ################################################################################ @@ -204,12 +197,3 @@ 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") -# } diff --git a/db/counterbox_v2.db b/db/counterbox_v2.db index 5be40f0..d69b075 100644 --- a/db/counterbox_v2.db +++ b/db/counterbox_v2.db @@ -11,6 +11,8 @@ record(longout, "$(P):$(NAME):MONITOR-CHANNEL") { field(DESC, "PRESET-COUNT Monitors this channel") + field(DRVL, "1") # Smallest Monitor Channel + field(DRVH, "$(CHANNELS)") # Largest Monitor Channel field(DTYP, "stream") field(OUT, "@$(PROTO) writePresetMonitor($(P):$(NAME):) $(ASYN_PORT)") field(FLNK, "$(P):$(NAME):MONITOR-CHANNEL_RBV") diff --git a/scripts/counterbox_4ch.cmd b/scripts/counterbox_4ch.cmd index e04fb80..729c1b0 100644 --- a/scripts/counterbox_4ch.cmd +++ b/scripts/counterbox_4ch.cmd @@ -16,7 +16,7 @@ dbLoadRecords("$(counterbox_DB)counterbox_common.db", "P=$(PREFIX), NAME=$(NAME) dbLoadRecords("$(counterbox_DB)counterbox_4ch.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") # Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=4") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") diff --git a/scripts/counterbox_8ch.cmd b/scripts/counterbox_8ch.cmd index 7dfbff2..5202377 100644 --- a/scripts/counterbox_8ch.cmd +++ b/scripts/counterbox_8ch.cmd @@ -16,11 +16,11 @@ dbLoadRecords("$(counterbox_DB)counterbox_common.db", "P=$(PREFIX), NAME=$(NAME) dbLoadRecords("$(counterbox_DB)counterbox_8ch.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") # Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=4") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=5") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=6") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=7") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=8") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") diff --git a/scripts/counterbox_v2.cmd b/scripts/counterbox_v2.cmd index da4ea6d..822d0bb 100644 --- a/scripts/counterbox_v2.cmd +++ b/scripts/counterbox_v2.cmd @@ -13,18 +13,18 @@ $(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) dbLoadRecords("$(counterbox_DB)counterbox_common.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") -dbLoadRecords("$(counterbox_DB)counterbox_v2.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") +dbLoadRecords("$(counterbox_DB)counterbox_v2.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") # Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=4") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=5") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=6") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=7") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=8") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=9") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), CHANNEL=10") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=9") +dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") $(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(counterbox_DB)counterbox_v2_test.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") -- 2.49.0 From 4bd648ea5d3d2d6f61afcfb3e8077bdafd6de60f Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Mon, 18 Nov 2024 14:43:16 +0100 Subject: [PATCH 2/9] Adds PVs for reseting the channels and timer --- db/channels.db | 7 +++++++ db/counterbox.proto | 12 ++++++++++++ db/counterbox_common.db | 7 +++++++ 3 files changed, 26 insertions(+) diff --git a/db/channels.db b/db/channels.db index 2a63f54..5675e57 100644 --- a/db/channels.db +++ b/db/channels.db @@ -30,6 +30,13 @@ # field(SCAN, "1 second") # } +record(bo, "$(P):$(NAME):C$(CHANNEL)") +{ + field(DESC, "Clear the current channel count") + field(DTYP, "stream") + field(OUT, "@$(PROTO) clearChannel($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") +} + ################################################################################ # Read all monitors values diff --git a/db/counterbox.proto b/db/counterbox.proto index fda8ec0..c51c5e5 100644 --- a/db/counterbox.proto +++ b/db/counterbox.proto @@ -112,6 +112,18 @@ readRateMonitor{ @mismatch{in "%(\$1MsgTxt)s";} } +clearTimer{ + out "CT"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +clearChannel{ + out "CC \$2"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + ################################################################################ # Read Values From Monitors diff --git a/db/counterbox_common.db b/db/counterbox_common.db index 21e9cea..729ca1d 100644 --- a/db/counterbox_common.db +++ b/db/counterbox_common.db @@ -181,6 +181,13 @@ record(longin,"$(P):$(NAME):THRESHOLD-MONITOR_RBV") field(SCAN, "1 second") } +record(bo, "$(P):$(NAME):CT") +{ + field(DESC, "Clear the timer") + field(DTYP, "stream") + field(OUT, "@$(PROTO) clearTimer($(P):$(NAME):) $(ASYN_PORT)") +} + ################################################################################ # Read all monitors values -- 2.49.0 From 65d6f681b9019118e77091c19855105b24a8bd2f Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Fri, 10 Jan 2025 10:14:11 +0100 Subject: [PATCH 3/9] Adds more functionality to the simulation --- sim/counterbox_sim.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/sim/counterbox_sim.py b/sim/counterbox_sim.py index 6f6755a..d32800e 100644 --- a/sim/counterbox_sim.py +++ b/sim/counterbox_sim.py @@ -16,6 +16,7 @@ class CounterBox: def __init__(self, total_channels): self.total_channels = total_channels self.counts = [0] * self.total_channels + self.rates = [randrange(5) for i in range(self.total_channels)] self.status = 0 self.countmode = 'time' @@ -41,7 +42,8 @@ class CounterBox: def updateCounts(self): for i in range(self.total_channels): - self.counts[i] += randrange(5) + self.rates[i] = randrange(5) + self.counts[i] += self.rates[i] def getRunTime(self): elapsed = round(time.time() - self.starttime, 3) @@ -68,6 +70,10 @@ class CounterBox: return self.elapsed + def stop(self): + self.getRunTime() + self.status = 0 + def startTimePreset(self, presettime): self.countmode = 'time' self.status = 1 @@ -79,6 +85,15 @@ class CounterBox: self.status = 1 self.presetcount = presetcount self.resetCounts() + + def setMonitorChannel(self, channel): + self.monitor = channel - 1 + + def getMonitorChannel(self): + return self.monitor + 1 + + def getRate(self, channel): + return float(self.rates[channel - 1]) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: @@ -129,6 +144,9 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: elif data == 'RS': send(str(counterbox.getStatus())) + elif data == 'S': + counterbox.stop() + elif re.fullmatch(r'TP (\d+(\.\d+)?)', data): presettime = float(re.fullmatch(r'TP (\d+(\.\d+)?)', data).group(1)) counterbox.startTimePreset(presettime) @@ -139,6 +157,17 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: counterbox.startCountPreset(counts) send('') + elif data == 'PC': + send(str(counterbox.getMonitorChannel())) + + elif re.fullmatch(r'PC (\d+)', data): + channel = int(re.fullmatch(r'PC (\d+)', data).group(1)) + counterbox.setMonitorChannel(channel) + + elif re.fullmatch(r'RR (\d+)', data): + channel = int(re.fullmatch(r'RR (\d+)', data).group(1)) + send(counterbox.getRate(channel)) + else: send('?2') # Bad command -- 2.49.0 From d4b111ce6d2a1f75f9b2e3702cc9f75382bb9594 Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Thu, 13 Feb 2025 16:06:31 +0100 Subject: [PATCH 4/9] Commiting state after implementing gating etc before cleaning and refactoring --- Makefile | 3 + db/channels.db | 19 ---- db/counterbox.proto | 175 +++++++++++++++++++++++++++-------- db/counterbox_common.db | 11 ++- db/counterbox_simcontrol.db | 26 ++++++ db/counterbox_v2.db | 73 +++++++++++++++ scripts/counterbox_8ch.cmd | 2 +- scripts/counterbox_v2.cmd | 2 + sim/counterbox_sim.py | 178 +++++++++++++++++++++++++++++++++--- 9 files changed, 419 insertions(+), 70 deletions(-) create mode 100644 db/counterbox_simcontrol.db diff --git a/Makefile b/Makefile index 19c6236..f2d3b36 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ TEMPLATES += db/counterbox_v2.db TEMPLATES += db/counterbox_v2_test.db TEMPLATES += db/counterbox.proto +# Just for simulation +TEMPLATES += db/counterbox_simcontrol.db + # DBD files to include in the release DBDS += src/counterbox.dbd diff --git a/db/channels.db b/db/channels.db index 5675e57..71c43de 100644 --- a/db/channels.db +++ b/db/channels.db @@ -11,25 +11,6 @@ ################################################################################ # Count Commands -# record(ao,"$(P):$(NAME):THRESHOLD_$(CHANNEL)") -# { -# field(DESC, "Minimum rate for counting to proceed") -# field(VAL, "0") # Rate -# field(DRVL, "0") # Minimum Rate -# field(OMSL, "supervisory") -# field(OROC, "0") -# field(OUT, "@$(PROTO) setMinRate($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") -# field(DTYP, "stream") -# } -# -# record(ai,"$(P):$(NAME):THRESHOLD_$(CHANNEL)_RBV") -# { -# field(DESC, "Minimum rate for counting to proceed") -# field(INP, "@$(PROTO) readMinRate($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") -# field(DTYP, "stream") -# field(SCAN, "1 second") -# } - record(bo, "$(P):$(NAME):C$(CHANNEL)") { field(DESC, "Clear the current channel count") diff --git a/db/counterbox.proto b/db/counterbox.proto index c51c5e5..29d78a8 100644 --- a/db/counterbox.proto +++ b/db/counterbox.proto @@ -46,18 +46,6 @@ writePresetMonitor { ################################################################################ # Count Commands -startWithCountPreset { - out "MP %d"; - in; - @mismatch{in "%(\$1MsgTxt)s";} -} - -startWithTimePreset { - out "TP %#.2f"; - in; - @mismatch{in "%(\$1MsgTxt)s";} -} - pauseCount { out "PS"; in; @@ -76,17 +64,65 @@ stopCount { @mismatch{in "%(\$1MsgTxt)s";} } -# setMinRate{ -# out "DL \$2 %.3f"; -# in; -# @mismatch{in "%(\$1MsgTxt)s";} -# } -# -# readMinRate{ -# out "DL \$2"; -# in "%f"; -# @mismatch{in "%(\$1MsgTxt)s";} -# } +clearTimer{ + # We first stop the count, as otherwise on the newest counterboxes + # it starts counting again if a time preset was set. + # Not a problem with the older boxes + stopCount; + out "CT"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +clearChannel{ + out "CC \$2"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +clearCounter4 { + out "CC 1"; + in; + out "CC 2"; + in; + out "CC 3"; + in; + out "CC 4"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +clearCounter8 { + out "CC 5"; + in; + out "CC 6"; + in; + out "CC 7"; + in; + out "CC 8"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +clearCounter10 { + out "CC 9"; + in; + out "CC 10"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +startWithCountPreset { + out "MP %d"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} + +startWithTimePreset { + out "TP %#.2f"; + in; + @mismatch{in "%(\$1MsgTxt)s";} +} setMinRate{ out "DL %(\$1THRESHOLD-MONITOR_RBV)d %.3f"; @@ -112,18 +148,6 @@ readRateMonitor{ @mismatch{in "%(\$1MsgTxt)s";} } -clearTimer{ - out "CT"; - in; - @mismatch{in "%(\$1MsgTxt)s";} -} - -clearChannel{ - out "CC \$2"; - in; - @mismatch{in "%(\$1MsgTxt)s";} -} - ################################################################################ # Read Values From Monitors @@ -141,7 +165,13 @@ readAll8 { 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"; + in "%(\$1ELAPSED-TIME)f %(\$1M1)d %(\$1M2)d %(\$1M3)d %(\$1M4)d %(\$1M5)d %(\$1M6)d %(\$1M7)d %(\$1M8)d"; + # At least on the sinqtest variant this is broken + # requiring channels 9 and 10 to be manually queried + out "RC 9"; + in "%(\$1M9)d"; + out "RC 10"; + in "%(\$1M10)d"; @mismatch{in "%(\$1MsgTxt)s";} } @@ -164,3 +194,76 @@ setTestSignal { out "TG 1 %(\$1TESTGEN-HIGHRATE)d %(\$1TESTGEN-LOWRATE)d"; @mismatch{in "%(\$1MsgTxt)s";} } + +################################################################################ +# Gating Settings + +getGateStatus { + out "GT \$2"; + in "%d %(\$1GATE-ON-\$2_RBV)d"; + @mismatch{in "%(\$1MsgTxt)s";} +} + +setGateStatus { + extrainput = ignore; + out "GT \$2 %(\$1GATE-\$2)d %(\$1GATE-ON-\$2)d"; + in "Gate \$2"; + @mismatch{in "%(\$1MsgTxt)s";} +} + +setGate { + out "GATE \$2 %d"; + in ""; + @mismatch{in "%(\$1MsgTxt)s";} +} + +################################################################################ +# To clean + +startWithCountPreset4 { + clearTimer; + clearCounter4; + readAll4; + startWithCountPreset; +} + +startWithCountPreset8 { + clearTimer; + clearCounter4; + clearCounter8; + readAll8; + startWithCountPreset; +} + +startWithCountPreset10 { + clearTimer; + clearCounter4; + clearCounter8; + clearCounter10; + readAll10; + startWithCountPreset; +} + +startWithTimePreset4 { + clearTimer; + clearCounter4; + readAll4; + startWithTimePreset; +} + +startWithTimePreset8 { + clearTimer; + clearCounter4; + clearCounter8; + readAll8; + startWithTimePreset; +} + +startWithTimePreset10 { + clearTimer; + clearCounter4; + clearCounter8; + clearCounter10; + readAll10; + startWithTimePreset; +} diff --git a/db/counterbox_common.db b/db/counterbox_common.db index 729ca1d..ec2e88b 100644 --- a/db/counterbox_common.db +++ b/db/counterbox_common.db @@ -105,19 +105,21 @@ record(ao,"$(P):$(NAME):PRESET-COUNT") { field(DESC, "Count until preset reached") field(DTYP, "stream") - field(OUT, "@$(PROTO) startWithCountPreset($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) startWithCountPreset$(CHANNELS)($(P):$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(PREC, 2) + field(FLNK, "$(P):$(NAME):RAW-STATUS") } record(ao,"$(P):$(NAME):PRESET-TIME") { field(DESC, "Count for specified time") field(DTYP, "stream") - field(OUT, "@$(PROTO) startWithTimePreset($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) startWithTimePreset$(CHANNELS)($(P):$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(PREC, 2) field(EGU, "seconds") + field(FLNK, "$(P):$(NAME):RAW-STATUS") } record(bo,"$(P):$(NAME):PAUSE") @@ -126,6 +128,7 @@ record(bo,"$(P):$(NAME):PAUSE") field(DTYP, "stream") field(OUT, "@$(PROTO) pauseCount($(P):$(NAME):) $(ASYN_PORT)") field(VAL, "0") + field(FLNK, "$(P):$(NAME):RAW-STATUS") } record(bo,"$(P):$(NAME):CONTINUE") @@ -134,6 +137,7 @@ record(bo,"$(P):$(NAME):CONTINUE") field(DTYP, "stream") field(OUT, "@$(PROTO) continueCount($(P):$(NAME):) $(ASYN_PORT)") field(VAL, "0") + field(FLNK, "$(P):$(NAME):RAW-STATUS") } record(bo, "$(P):$(NAME):STOP") @@ -141,6 +145,7 @@ record(bo, "$(P):$(NAME):STOP") field(DESC, "Stop the current counting operation") field(DTYP, "stream") field(OUT, "@$(PROTO) stopCount($(P):$(NAME):) $(ASYN_PORT)") + field(FLNK, "$(P):$(NAME):RAW-STATUS") } record(ao,"$(P):$(NAME):THRESHOLD") @@ -167,7 +172,7 @@ 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, "0") # Smallest Threshold Channel (0 is off) field(DRVH, "$(CHANNELS)") # Largest Threshold Channel field(OUT, "@$(PROTO) setRateMonitor($(P):$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") diff --git a/db/counterbox_simcontrol.db b/db/counterbox_simcontrol.db new file mode 100644 index 0000000..c1c2a54 --- /dev/null +++ b/db/counterbox_simcontrol.db @@ -0,0 +1,26 @@ +# Sinq Counterbox EPICS Database for StreamDevice Communication with Simulation +# Macros +# P - Prefix +# NAME - just a name, e.g. EL737 +# PROTO - Stream device protocol file +# ASYN_PORT - Low level Asyn IP Port to EL737 + +################################################################################ + +record(bo, "$(P):$(NAME):G1") +{ + field(DESC, "Set Gate 1 Low/High") + field(ZNAM, "Low") + field(ONAM, "High") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGate($(P):$(NAME):, 1) $(ASYN_PORT)") +} + +record(bo, "$(P):$(NAME):G2") +{ + field(DESC, "Set Gate 2 Low/High") + field(ZNAM, "Low") + field(ONAM, "High") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGate($(P):$(NAME):, 2) $(ASYN_PORT)") +} diff --git a/db/counterbox_v2.db b/db/counterbox_v2.db index d69b075..1b210e3 100644 --- a/db/counterbox_v2.db +++ b/db/counterbox_v2.db @@ -31,3 +31,76 @@ record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV") ################################################################################ # Read all monitors values + +################################################################################ +# Gating Settings + +record(bo, "$(P):$(NAME):GATE-1") +{ + field(DESC, "First Gating Channel") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 1) $(ASYN_PORT)") +} + +record(bo, "$(P):$(NAME):GATE-ON-1") +{ + field(DESC, "Count when first Gate high/low") + field(ZNAM, "Low") + field(ONAM, "High") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 1) $(ASYN_PORT)") +} + +record(bi, "$(P):$(NAME):GATE-1_RBV") +{ + field(DESC, "First Gating Channel") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(DTYP, "stream") + field(INP, "@$(PROTO) getGateStatus($(P):$(NAME):, 1) $(ASYN_PORT)") + field(SCAN, "2 second") +} + +record(bi, "$(P):$(NAME):GATE-ON-1_RBV") +{ + field(DESC, "Count when first Gate high/low") + field(ZNAM, "Low") + field(ONAM, "High") +} + +record(bo, "$(P):$(NAME):GATE-2") +{ + field(DESC, "First Gating Channel") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 2) $(ASYN_PORT)") +} + +record(bo, "$(P):$(NAME):GATE-ON-2") +{ + field(DESC, "Count when first Gate high/low") + field(ZNAM, "Low") + field(ONAM, "High") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 2) $(ASYN_PORT)") +} + +record(bi, "$(P):$(NAME):GATE-2_RBV") +{ + field(DESC, "Second Gating Channel") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(DTYP, "stream") + field(INP, "@$(PROTO) getGateStatus($(P):$(NAME):, 2) $(ASYN_PORT)") + field(SCAN, "2 second") +} + +record(bi, "$(P):$(NAME):GATE-ON-2_RBV") +{ + field(DESC, "Count when second Gate high/low") + field(ZNAM, "Low") + field(ONAM, "High") +} diff --git a/scripts/counterbox_8ch.cmd b/scripts/counterbox_8ch.cmd index 5202377..3576da3 100644 --- a/scripts/counterbox_8ch.cmd +++ b/scripts/counterbox_8ch.cmd @@ -5,7 +5,7 @@ epicsEnvSet("$(NAME)_CNTBOX_HOST", "$(CNTBOX_IP):$(CNTBOX_PORT)") $(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc $(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_CNTBOX_HOST", "127.0.0.1:$(CNTBOX_PORT)") -$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(counterbox_DIR)counterbox_sim.py $(CNTBOX_PORT) 10 &" +$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(counterbox_DIR)counterbox_sim.py $(CNTBOX_PORT) 8 &" # starting the python socket seems to take a while # and need misc to use built in sleep command $(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 diff --git a/scripts/counterbox_v2.cmd b/scripts/counterbox_v2.cmd index 822d0bb..90d27d0 100644 --- a/scripts/counterbox_v2.cmd +++ b/scripts/counterbox_v2.cmd @@ -28,3 +28,5 @@ dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$ dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") $(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(counterbox_DB)counterbox_v2_test.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") + +$(SET_SIM_MODE=#) $(SET_SIM_MODE) dbLoadRecords("$(counterbox_DB)counterbox_simcontrol.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") diff --git a/sim/counterbox_sim.py b/sim/counterbox_sim.py index d32800e..578925a 100644 --- a/sim/counterbox_sim.py +++ b/sim/counterbox_sim.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +import os import re import socket import sys @@ -10,6 +11,13 @@ from random import randrange HOST = "127.0.0.1" # Localhost PORT = int(sys.argv[1]) # Port to listen on TOTAL_CH = int(sys.argv[2]) # Number of Channels +LOG2FILE = False if len(sys.argv) < 4 else bool(int(sys.argv[3])) + +import logging +logger = logging.getLogger('counterbox') + +if LOG2FILE: + logging.basicConfig(filename=os.path.join(os.getcwd(), 'counterbox_sim.log'), level=logging.INFO) class CounterBox: @@ -26,43 +34,106 @@ class CounterBox: self.elapsed = 0 self.monitor = 0 - def resetCounts(self): + self.minratechannel = 0 + self.minrates = [2] * self.total_channels + + self.gate_config = [ + #(enabled, count high/low), + ( False, True), + ( False, True), + ] + + self.gate = [ + # high/low + False, + False, + ] + + def clearCount(self, counter): + self.counts[counter-1] = 0 + + def clearCounts(self): self.counts = [0] * self.total_channels - self.starttime = time.time() + + def clearTime(self): self.elapsed = 0 + self.starttime = time.time() def getStatus(self): return self.status + def getCount(self, channel): + return self.counts[channel - 1] + def getCounts(self): - return self.counts + # The sinqtest box returns a maximum of 8 + return self.counts[0:min(len(self.counts), 8)] def getMonitorCount(self): return self.counts[self.monitor] - def updateCounts(self): + def updateRates(self): for i in range(self.total_channels): self.rates[i] = randrange(5) + + def updateCounts(self): + for i in range(self.total_channels): self.counts[i] += self.rates[i] def getRunTime(self): elapsed = round(time.time() - self.starttime, 3) + self.updateRates() + + # If gating and a low rate threshold are enabled, then the threshold + # seems to have precedence and sets the status to 5. + # If we are waiting on the gate, then the status is just 1 as normal + # after having started a count. if self.countmode == 'time': if elapsed < self.presettime: + + if self.minratechannel >= 0 and self.rates[self.minratechannel] < self.minrates[self.minratechannel]: + # adjust the starttime, so that it is as if this polling period didn't happen + self.starttime += elapsed - self.elapsed + self.status = 5 + return self.elapsed + + self.status = 1 + + for i in range(len(self.gate)): + # If the gating is enabled and the signal is in the active position + if self.gate_config[i][0] and self.gate_config[i][1] != self.gate[i]: + self.starttime += elapsed - self.elapsed + return self.elapsed + self.updateCounts() self.elapsed = elapsed else: - self.elapsed = self.presettime + self.elapsed = self.presettime if self.presettime > 0 else self.elapsed self.status = 0 elif self.countmode == 'count': if self.getMonitorCount() < self.presetcount: + + if self.minratechannel >= 0 and self.rates[self.minratechannel] < self.minrates[self.minratechannel]: + # adjust the starttime, so that it is as if this polling period didn't happen + self.starttime += elapsed - self.elapsed + self.status = 5 + return self.elapsed + + self.status = 1 + + for i in range(len(self.gate)): + # If the gating is enabled and the signal is in the active position + if self.gate_config[i][0] and self.gate_config[i][1] != self.gate[i]: + self.starttime += elapsed - self.elapsed + return self.elapsed + self.updateCounts() self.elapsed = elapsed if self.getMonitorCount() >= self.presetcount: - self.counts[self.monitor] = self.presetcount + self.counts[self.monitor] = self.presetcount if self.presetcount > 0 else self.counts[self.monitor] self.status = 0 else: @@ -73,18 +144,22 @@ class CounterBox: def stop(self): self.getRunTime() self.status = 0 + self.presettime = 0 + self.presetcount = 0 def startTimePreset(self, presettime): self.countmode = 'time' self.status = 1 self.presettime = round(presettime, 3) - self.resetCounts() + self.clearTime() + self.clearCounts() def startCountPreset(self, presetcount): self.countmode = 'count' self.status = 1 self.presetcount = presetcount - self.resetCounts() + self.clearTime() + self.clearCounts() def setMonitorChannel(self, channel): self.monitor = channel - 1 @@ -94,6 +169,28 @@ class CounterBox: def getRate(self, channel): return float(self.rates[channel - 1]) + + def getMinRateChannel(self): + return self.minratechannel + 1 + + def setMinRateChannel(self, channel): + self.minratechannel = channel - 1 + + def getMinRate(self, channel): + return self.minrates[channel - 1] + + def setMinRate(self, channel, rate): + self.minrates[channel - 1] = rate + + def getGateStatus(self, channel): + return self.gate_config[channel - 1] + + def setGateStatus(self, channel, enable, highlow): + self.gate_config[channel - 1] = (enable, highlow) + + def setGate(self, channel, highlow): + self.gate[channel - 1] = highlow + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: @@ -104,17 +201,21 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: def send(data: str): if data: + logger.info(f'SENDING: "{data}"') return conn.sendall(f'{data}\r'.encode()) else: + logger.info(f'SENDING: ""') return conn.sendall(b'\r') def receive(): data = conn.recv(1024) if data: # also removes terminator - return data.decode('ascii').rstrip() + received = data.decode('ascii').rstrip() else: - return '' + received = '' + logger.info(f'RECEIVED: "{received}"') + return received counterbox = CounterBox(TOTAL_CH) @@ -141,11 +242,26 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: )) ) + elif re.fullmatch(r'RC (\d+)', data): + channel = int(re.fullmatch(r'RC (\d+)', data).group(1)) + count = counterbox.getCount(channel) + send(f'{count}') + elif data == 'RS': send(str(counterbox.getStatus())) elif data == 'S': counterbox.stop() + send('') + + elif data == 'CT': + counterbox.clearTime() + send('') + + elif re.fullmatch(r'CC (\d+)', data): + counter = int(re.fullmatch(r'CC (\d+)', data).group(1)) + counterbox.clearCount(counter) + send('') elif re.fullmatch(r'TP (\d+(\.\d+)?)', data): presettime = float(re.fullmatch(r'TP (\d+(\.\d+)?)', data).group(1)) @@ -163,13 +279,53 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: elif re.fullmatch(r'PC (\d+)', data): channel = int(re.fullmatch(r'PC (\d+)', data).group(1)) counterbox.setMonitorChannel(channel) + send('') + + elif data == 'DR': + send(str(counterbox.getMinRateChannel())) + + elif re.fullmatch(r'DR (\d+)', data): + channel = int(re.fullmatch(r'DR (\d+)', data).group(1)) + counterbox.setMinRateChannel(channel) + send('') + + elif re.fullmatch(r'DL (\d+)', data): + channel = int(re.fullmatch(r'DL (\d+)', data).group(1)) + send('{:.3f}'.format(counterbox.getMinRate(channel))) + + elif re.fullmatch(r'DL (\d+) (\d+(?:.\d+)?)', data): + channel, rate = re.fullmatch(r'DL (\d+) (\d+(?:.\d+)?)', data).groups() + counterbox.setMinRate(int(channel), float(rate)) + send('') elif re.fullmatch(r'RR (\d+)', data): channel = int(re.fullmatch(r'RR (\d+)', data).group(1)) send(counterbox.getRate(channel)) + elif re.fullmatch(r'GT (\d+)', data): + channel = int(re.fullmatch(r'GT (\d+)', data).group(1)) + enabled, highlow = counterbox.getGateStatus(channel) + send(f'{int(enabled)} {int(highlow)}') + + elif re.fullmatch(r'GT (\d+) (\d+) (\d+)', data): + channel, enable, highlow = re.fullmatch(r'GT (\d+) (\d+) (\d+)', data).groups() + channel, enable, highlow = int(channel), bool(int(enable)), bool(int(highlow)) + counterbox.setGateStatus(channel, enable, highlow) + if enable: + send(f'Gate {channel} enabled, counting when input = {"high" if highlow else "low"}') + else: + send(f'Gate {channel} disabled') + + # Only for the simulation + elif re.fullmatch(r'GATE (\d+) (\d+)', data): + channel, highlow = re.fullmatch(r'GATE (\d+) (\d+)', data).groups() + channel, highlow = int(channel), bool(int(highlow)) + counterbox.setGate(channel, highlow) + send('') + else: send('?2') # Bad command - except: + except Exception as e: + logger.exception('Simulation Broke') send('?OV') -- 2.49.0 From d81105551d2ad455eac22479ed74ec0c6ee06254 Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Tue, 29 Apr 2025 15:58:32 +0200 Subject: [PATCH 5/9] use the INSTR environment variable instead of PREFIX --- README.md | 35 +++++------ db/channels.db | 20 ++++--- db/counterbox_4ch.db | 13 ++-- db/counterbox_8ch.db | 13 ++-- db/counterbox_common.db | 115 ++++++++++++++++++------------------ db/counterbox_simcontrol.db | 11 ++-- db/counterbox_v2.db | 46 ++++++++------- db/counterbox_v2_test.db | 21 +++++-- scripts/counterbox_4ch.cmd | 12 ++-- scripts/counterbox_8ch.cmd | 20 +++---- scripts/counterbox_v2.cmd | 28 ++++----- test/st.cmd | 2 +- test/test.py | 50 ++++++++-------- 13 files changed, 202 insertions(+), 184 deletions(-) diff --git a/README.md b/README.md index 575c9b0..2e1be67 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -Counterbox Epics Module +SINQDAQ Epics Module ----------------------- -A Stream and Asyn based driver for configuring the Counterboxes at SINQ. +A Stream and Asyn based driver for configuring the Data Acquisition Systems at +SINQ. This supports the older 4 and 8 channel EL737 models and the new 10CH 2nd generation systems. @@ -15,7 +16,7 @@ Required Variables | Environment Variable | Purpose | |----------------------|-----------------------------------------| -| PREFIX | Prefix of all device specific PVs | +| INSTR | Prefix of all device specific PVs | | NAME | First field in all PVs after Prefix | | CNTBOX\_IP | Network IP of device | | CNTBOX\_PORT | Network Port of device | @@ -23,7 +24,7 @@ Required Variables All PVs take the form ``` -$(PREFIX):$(NAME):* +$(INSTR)$(NAME):* ``` Available device startup scripts @@ -35,25 +36,25 @@ Available device startup scripts A device can be configured using one of the startup scripts as follows ``` -epicsEnvSet("PREFIX", "SQ:INSTRUMENT") # can also be set in runScript call +epicsEnvSet("INSTR", "SQ:INSTRUMENT:") # can also be set in runScript call runScript "$(counterbox_DIR)counterbox_v2.cmd" "NAME=COUNTERBOX, CNTBOX_IP=TestInst-DAQ1, CNTBOX_PORT=2000" ``` ## PVs of Interest -| PV | Description | -|---------------------------------------|----------------------------------------------------------------------| -| \$(PREFIX):\$(NAME):MsgTxt | Contains unexpected response to executed command | -| \$(PREFIX):\$(NAME):STATUS | 0: Idle, 1: Counting, 2: Low rate, 3: Paused, 4: Error | -| \$(PREFIX):\$(NAME):MONITOR-CHANNEL | Channel that PRESET-COUNT monitors (has RBV, only v2 can be changed) | -| \$(PREFIX):\$(NAME):PRESET-COUNT | Run count until specified pv value reached | -| \$(PREFIX):\$(NAME):PRESET-TIME | Run count until specified pv value in seconds reached | -| \$(PREFIX):\$(NAME):THRESHOLD | Minimum rate for counting to preceed. (has RBV) | -| \$(PREFIX):\$(NAME):THRESHOLD-MONITOR | Channel monitored for minimum rate (has RBV) | -| \$(PREFIX):\$(NAME):ELAPSED-TIME | Time Counterbox has been measuring for | -| \$(PREFIX):\$(NAME):M_ | Current count on channel. (1-10 depending on box) | -| \$(PREFIX):\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) | +| PV | Description | +|-------------------------------------|----------------------------------------------------------------------| +| \$(INSTR)\$(NAME):MsgTxt | Contains unexpected response to executed command | +| \$(INSTR)\$(NAME):STATUS | 0: Idle, 1: Counting, 2: Low rate, 3: Paused, 4: Error | +| \$(INSTR)\$(NAME):MONITOR-CHANNEL | Channel that PRESET-COUNT monitors (has RBV, only v2 can be changed) | +| \$(INSTR)\$(NAME):PRESET-COUNT | Run count until specified pv value reached | +| \$(INSTR)\$(NAME):PRESET-TIME | Run count until specified pv value in seconds reached | +| \$(INSTR)\$(NAME):THRESHOLD | Minimum rate for counting to preceed. (has RBV) | +| \$(INSTR)\$(NAME):THRESHOLD-MONITOR | Channel monitored for minimum rate (has RBV) | +| \$(INSTR)\$(NAME):ELAPSED-TIME | Time Counterbox has been measuring for | +| \$(INSTR)\$(NAME):M_ | Current count on channel. (1-10 depending on box) | +| \$(INSTR)\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) | ## Generating Test Signals diff --git a/db/channels.db b/db/channels.db index 71c43de..4f0fb54 100644 --- a/db/channels.db +++ b/db/channels.db @@ -1,9 +1,11 @@ -# EL737 EPICS Database for streamdevice support +# EPICS Database for streamdevice specific to measurement channels +# # Macros -# P - Prefix -# NAME - just a name, e.g. EL737 +# INSTR - Prefix +# NAME - the device name, e.g. EL737 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to EL737 +# ASYN_PORT - Low level Asyn IP Port to Counterbox +# CHANNEL - the number associated with the measurment channel ################################################################################ # Status Variables @@ -11,25 +13,25 @@ ################################################################################ # Count Commands -record(bo, "$(P):$(NAME):C$(CHANNEL)") +record(bo, "$(INSTR)$(NAME):C$(CHANNEL)") { field(DESC, "Clear the current channel count") field(DTYP, "stream") - field(OUT, "@$(PROTO) clearChannel($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") + field(OUT, "@$(PROTO) clearChannel($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") } ################################################################################ # Read all monitors values -record(longin, "$(P):$(NAME):M$(CHANNEL)") +record(longin, "$(INSTR)$(NAME):M$(CHANNEL)") { field(DESC, "Counterbox CH$(CHANNEL)") } -record(ai, "$(P):$(NAME):R$(CHANNEL)") +record(ai, "$(INSTR)$(NAME):R$(CHANNEL)") { field(DESC, "Counterbox Rate CH$(CHANNEL)") - field(INP, "@$(PROTO) readRate($(P):$(NAME):, $(CHANNEL)) $(ASYN_PORT)") + field(INP, "@$(PROTO) readRate($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") field(DTYP, "stream") field(SCAN, "1 second") } diff --git a/db/counterbox_4ch.db b/db/counterbox_4ch.db index 1a47aaf..4cb7dd3 100644 --- a/db/counterbox_4ch.db +++ b/db/counterbox_4ch.db @@ -1,14 +1,15 @@ -# Counterbox EPICS Database +# EPICS Database for streamdevice support 1st gen systems with 4 channels +# # Macros -# P - Prefix -# NAME - just a name, e.g. EL737 +# INSTR - Prefix +# NAME - the device name, e.g. EL737 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to EL737 +# ASYN_PORT - Low level Asyn IP Port to Counterbox ################################################################################ # Status Variables -record(longout, "$(P):$(NAME):MONITOR-CHANNEL") +record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL") { field(DESC, "PRESET-COUNT Monitors this channel") field(VAL, 1) @@ -17,7 +18,7 @@ record(longout, "$(P):$(NAME):MONITOR-CHANNEL") field(DISP, 1) } -record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV") +record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") { field(DESC, "PRESET-COUNT Monitors this channel") field(VAL, 1) diff --git a/db/counterbox_8ch.db b/db/counterbox_8ch.db index a44d5c2..3fd8a33 100644 --- a/db/counterbox_8ch.db +++ b/db/counterbox_8ch.db @@ -1,14 +1,15 @@ -# EL737 EPICS Database for streamdevice support +# EPICS Database for streamdevice support 1st gen systems with 8 channels +# # Macros -# P - Prefix -# NAME - just a name, e.g. EL737 +# INSTR - Prefix +# NAME - the device name, e.g. EL737 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to EL737 +# ASYN_PORT - Low level Asyn IP Port to Counterbox ################################################################################ # Status Variables -record(longout, "$(P):$(NAME):MONITOR-CHANNEL") +record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL") { field(DESC, "PRESET-COUNT Monitors this channel") field(VAL, 1) @@ -17,7 +18,7 @@ record(longout, "$(P):$(NAME):MONITOR-CHANNEL") field(DISP, 1) } -record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV") +record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") { field(DESC, "PRESET-COUNT Monitors this channel") field(VAL, 1) diff --git a/db/counterbox_common.db b/db/counterbox_common.db index ec2e88b..201fecf 100644 --- a/db/counterbox_common.db +++ b/db/counterbox_common.db @@ -1,82 +1,83 @@ -# EL737 EPICS Database for streamdevice support +# EPICS Database for streamdevice support with SinqDAQ Systems +# # Macros -# P - Prefix -# NAME - just a name, e.g. EL737 +# INSTR - Prefix +# NAME - the device 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") +record(bo, "$(INSTR)$(NAME):INIT-CONF") { field(DESC, "Initialises the Counterbox") - field(OUT, "@$(PROTO) initialise($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) initialise($(INSTR)$(NAME):) $(ASYN_PORT)") field(PINI, "YES") # Run at init field(DTYP, "stream") } -record(longout, "$(P):$(NAME):FULL-RESET") +record(longout, "$(INSTR)$(NAME):FULL-RESET") { field(DESC, "Reset the Counterbox") - field(OUT, "@$(PROTO) fullReset($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) fullReset($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") } ################################################################################ # Status Variables -record(stringin, "$(P):$(NAME):MsgTxt") +record(stringin, "$(INSTR)$(NAME):MsgTxt") { field(DESC, "Unexpected received response") field(DTYP, "devCounterBoxStringError") - field(FLNK, "$(P):$(NAME):INVALID-CONFIG") + field(FLNK, "$(INSTR)$(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") +record(scalcout, "$(INSTR)$(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") + field(INAA, "$(INSTR)$(NAME):MsgTxt") + field(FLNK, "$(INSTR)$(NAME):REINIT-CONF") } -record(seq, "$(P):$(NAME):REINIT-CONF") +record(seq, "$(INSTR)$(NAME):REINIT-CONF") { - field(LNK1, "$(P):$(NAME):INIT-CONF PP") + field(LNK1, "$(INSTR)$(NAME):INIT-CONF PP") field(DO1, 1) field(SELM, "Specified") - field(SELL, "$(P):$(NAME):INVALID-CONFIG.VAL") + field(SELL, "$(INSTR)$(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 +# Important! The "$(INSTR)$(NAME):READALL" isn't configure with a SCAN. Instead, +# it must always be triggered after the value of $(INSTR)$(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") +record(longin, "$(INSTR)$(NAME):RAW-STATUS") { field(DESC, "Raw returned status value") field(DTYP, "stream") field(SCAN, ".5 second") - field(INP, "@$(PROTO) readStatus($(P):$(NAME):) $(ASYN_PORT)") - field(FLNK, "$(P):$(NAME):READALL") + field(INP, "@$(PROTO) readStatus($(INSTR)$(NAME):) $(ASYN_PORT)") + field(FLNK, "$(INSTR)$(NAME):READALL") } -record(calc, "$(P):$(NAME):MAP-STATUS") +record(calc, "$(INSTR)$(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(INPA, "$(INSTR)$(NAME):RAW-STATUS NPP") + field(INPB, "$(INSTR)$(NAME):INVALID-CONFIG NPP") + field(INPC, "$(INSTR)$(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") + field(FLNK, "$(INSTR)$(NAME):STATUS") } -record(mbbi, "$(P):$(NAME):STATUS") +record(mbbi, "$(INSTR)$(NAME):STATUS") { field(DESC, "Counterbox Status") - field(INP, "$(P):$(NAME):MAP-STATUS NPP") + field(INP, "$(INSTR)$(NAME):MAP-STATUS NPP") field(ZRVL, "0") field(ZRST, "Idle") field(ONVL, "1") @@ -90,7 +91,7 @@ record(mbbi, "$(P):$(NAME):STATUS") field(FRST, "INVALID") } -record(longin, "$(P):$(NAME):CHANNELS") +record(longin, "$(INSTR)$(NAME):CHANNELS") { field(DESC, "Total Supported Channels") field(VAL, $(CHANNELS)) @@ -101,54 +102,54 @@ record(longin, "$(P):$(NAME):CHANNELS") ################################################################################ # Count Commands -record(ao,"$(P):$(NAME):PRESET-COUNT") +record(ao,"$(INSTR)$(NAME):PRESET-COUNT") { field(DESC, "Count until preset reached") field(DTYP, "stream") - field(OUT, "@$(PROTO) startWithCountPreset$(CHANNELS)($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) startWithCountPreset$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(PREC, 2) - field(FLNK, "$(P):$(NAME):RAW-STATUS") + field(FLNK, "$(INSTR)$(NAME):RAW-STATUS") } -record(ao,"$(P):$(NAME):PRESET-TIME") +record(ao,"$(INSTR)$(NAME):PRESET-TIME") { field(DESC, "Count for specified time") field(DTYP, "stream") - field(OUT, "@$(PROTO) startWithTimePreset$(CHANNELS)($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) startWithTimePreset$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(PREC, 2) field(EGU, "seconds") - field(FLNK, "$(P):$(NAME):RAW-STATUS") + field(FLNK, "$(INSTR)$(NAME):RAW-STATUS") } -record(bo,"$(P):$(NAME):PAUSE") +record(bo,"$(INSTR)$(NAME):PAUSE") { field(DESC, "Pause the current count") field(DTYP, "stream") - field(OUT, "@$(PROTO) pauseCount($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) pauseCount($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, "0") - field(FLNK, "$(P):$(NAME):RAW-STATUS") + field(FLNK, "$(INSTR)$(NAME):RAW-STATUS") } -record(bo,"$(P):$(NAME):CONTINUE") +record(bo,"$(INSTR)$(NAME):CONTINUE") { field(DESC, "Continue with a count that was paused") field(DTYP, "stream") - field(OUT, "@$(PROTO) continueCount($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) continueCount($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, "0") - field(FLNK, "$(P):$(NAME):RAW-STATUS") + field(FLNK, "$(INSTR)$(NAME):RAW-STATUS") } -record(bo, "$(P):$(NAME):STOP") +record(bo, "$(INSTR)$(NAME):STOP") { field(DESC, "Stop the current counting operation") field(DTYP, "stream") - field(OUT, "@$(PROTO) stopCount($(P):$(NAME):) $(ASYN_PORT)") - field(FLNK, "$(P):$(NAME):RAW-STATUS") + field(OUT, "@$(PROTO) stopCount($(INSTR)$(NAME):) $(ASYN_PORT)") + field(FLNK, "$(INSTR)$(NAME):RAW-STATUS") } -record(ao,"$(P):$(NAME):THRESHOLD") +record(ao,"$(INSTR)$(NAME):THRESHOLD") { field(DESC, "Minimum rate for counting to proceed") field(VAL, "0") # Rate @@ -156,55 +157,55 @@ record(ao,"$(P):$(NAME):THRESHOLD") field(DRVH, "100000") # Maximum Rate field(OMSL, "supervisory") field(OROC, "0") - field(OUT, "@$(PROTO) setMinRate($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setMinRate($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") } -record(ai,"$(P):$(NAME):THRESHOLD_RBV") +record(ai,"$(INSTR)$(NAME):THRESHOLD_RBV") { field(DESC, "Minimum rate for counting to proceed") - field(INP, "@$(PROTO) readMinRate($(P):$(NAME):) $(ASYN_PORT)") + field(INP, "@$(PROTO) readMinRate($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") field(SCAN, "1 second") } -record(longout,"$(P):$(NAME):THRESHOLD-MONITOR") +record(longout,"$(INSTR)$(NAME):THRESHOLD-MONITOR") { field(DESC, "Channel monitored for minimum rate") field(VAL, "1") # Monitor field(DRVL, "0") # Smallest Threshold Channel (0 is off) field(DRVH, "$(CHANNELS)") # Largest Threshold Channel - field(OUT, "@$(PROTO) setRateMonitor($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setRateMonitor($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") } -record(longin,"$(P):$(NAME):THRESHOLD-MONITOR_RBV") +record(longin,"$(INSTR)$(NAME):THRESHOLD-MONITOR_RBV") { field(DESC, "Channel monitored for minimum rate") - field(INP, "@$(PROTO) readRateMonitor($(P):$(NAME):) $(ASYN_PORT)") + field(INP, "@$(PROTO) readRateMonitor($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") field(SCAN, "1 second") } -record(bo, "$(P):$(NAME):CT") +record(bo, "$(INSTR)$(NAME):CT") { field(DESC, "Clear the timer") field(DTYP, "stream") - field(OUT, "@$(PROTO) clearTimer($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) clearTimer($(INSTR)$(NAME):) $(ASYN_PORT)") } ################################################################################ # Read all monitors values -record(ai, "$(P):$(NAME):READALL") +record(ai, "$(INSTR)$(NAME):READALL") { field(DESC, "Reads monitors and elapsed time") - field(INP, "@$(PROTO) readAll$(CHANNELS)($(P):$(NAME):) $(ASYN_PORT)") + field(INP, "@$(PROTO) readAll$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") - field(FLNK, "$(P):$(NAME):MAP-STATUS") + field(FLNK, "$(INSTR)$(NAME):MAP-STATUS") } -record(ai,"$(P):$(NAME):ELAPSED-TIME") +record(ai,"$(INSTR)$(NAME):ELAPSED-TIME") { field(DESC, "Counterbox Measured Time") field(EGU, "seconds") diff --git a/db/counterbox_simcontrol.db b/db/counterbox_simcontrol.db index c1c2a54..36e5128 100644 --- a/db/counterbox_simcontrol.db +++ b/db/counterbox_simcontrol.db @@ -1,26 +1,27 @@ # Sinq Counterbox EPICS Database for StreamDevice Communication with Simulation # Macros -# P - Prefix +# +# INSTR - Prefix # NAME - just a name, e.g. EL737 # PROTO - Stream device protocol file # ASYN_PORT - Low level Asyn IP Port to EL737 ################################################################################ -record(bo, "$(P):$(NAME):G1") +record(bo, "$(INSTR)$(NAME):G1") { field(DESC, "Set Gate 1 Low/High") field(ZNAM, "Low") field(ONAM, "High") field(DTYP, "stream") - field(OUT, "@$(PROTO) setGate($(P):$(NAME):, 1) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setGate($(INSTR)$(NAME):, 1) $(ASYN_PORT)") } -record(bo, "$(P):$(NAME):G2") +record(bo, "$(INSTR)$(NAME):G2") { field(DESC, "Set Gate 2 Low/High") field(ZNAM, "Low") field(ONAM, "High") field(DTYP, "stream") - field(OUT, "@$(PROTO) setGate($(P):$(NAME):, 2) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setGate($(INSTR)$(NAME):, 2) $(ASYN_PORT)") } diff --git a/db/counterbox_v2.db b/db/counterbox_v2.db index 1b210e3..ea81465 100644 --- a/db/counterbox_v2.db +++ b/db/counterbox_v2.db @@ -1,28 +1,30 @@ -# EL737 EPICS Database for streamdevice support +# EPICS Database for streamdevice support for functionality specific to the 2nd +# Generation Systems +# # Macros -# P - Prefix -# NAME - just a name, e.g. DAQV2 +# INSTR - Prefix +# NAME - the device 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") +record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL") { field(DESC, "PRESET-COUNT Monitors this channel") field(DRVL, "1") # Smallest Monitor Channel field(DRVH, "$(CHANNELS)") # Largest Monitor Channel field(DTYP, "stream") - field(OUT, "@$(PROTO) writePresetMonitor($(P):$(NAME):) $(ASYN_PORT)") - field(FLNK, "$(P):$(NAME):MONITOR-CHANNEL_RBV") + field(OUT, "@$(PROTO) writePresetMonitor($(INSTR)$(NAME):) $(ASYN_PORT)") + field(FLNK, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") } -record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV") +record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") { field(DESC, "PRESET-COUNT Monitors this channel") field(DTYP, "stream") - field(INP, "@$(PROTO) readPresetMonitor($(P):$(NAME):) $(ASYN_PORT)") + field(INP, "@$(PROTO) readPresetMonitor($(INSTR)$(NAME):) $(ASYN_PORT)") field(SCAN, "5 second") } @@ -35,70 +37,70 @@ record(longin, "$(P):$(NAME):MONITOR-CHANNEL_RBV") ################################################################################ # Gating Settings -record(bo, "$(P):$(NAME):GATE-1") +record(bo, "$(INSTR)$(NAME):GATE-1") { field(DESC, "First Gating Channel") field(ZNAM, "Disabled") field(ONAM, "Enabled") field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 1) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 1) $(ASYN_PORT)") } -record(bo, "$(P):$(NAME):GATE-ON-1") +record(bo, "$(INSTR)$(NAME):GATE-ON-1") { field(DESC, "Count when first Gate high/low") field(ZNAM, "Low") field(ONAM, "High") field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 1) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 1) $(ASYN_PORT)") } -record(bi, "$(P):$(NAME):GATE-1_RBV") +record(bi, "$(INSTR)$(NAME):GATE-1_RBV") { field(DESC, "First Gating Channel") field(ZNAM, "Disabled") field(ONAM, "Enabled") field(DTYP, "stream") - field(INP, "@$(PROTO) getGateStatus($(P):$(NAME):, 1) $(ASYN_PORT)") + field(INP, "@$(PROTO) getGateStatus($(INSTR)$(NAME):, 1) $(ASYN_PORT)") field(SCAN, "2 second") } -record(bi, "$(P):$(NAME):GATE-ON-1_RBV") +record(bi, "$(INSTR)$(NAME):GATE-ON-1_RBV") { field(DESC, "Count when first Gate high/low") field(ZNAM, "Low") field(ONAM, "High") } -record(bo, "$(P):$(NAME):GATE-2") +record(bo, "$(INSTR)$(NAME):GATE-2") { field(DESC, "First Gating Channel") field(ZNAM, "Disabled") field(ONAM, "Enabled") field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 2) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 2) $(ASYN_PORT)") } -record(bo, "$(P):$(NAME):GATE-ON-2") +record(bo, "$(INSTR)$(NAME):GATE-ON-2") { field(DESC, "Count when first Gate high/low") field(ZNAM, "Low") field(ONAM, "High") field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(P):$(NAME):, 2) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 2) $(ASYN_PORT)") } -record(bi, "$(P):$(NAME):GATE-2_RBV") +record(bi, "$(INSTR)$(NAME):GATE-2_RBV") { field(DESC, "Second Gating Channel") field(ZNAM, "Disabled") field(ONAM, "Enabled") field(DTYP, "stream") - field(INP, "@$(PROTO) getGateStatus($(P):$(NAME):, 2) $(ASYN_PORT)") + field(INP, "@$(PROTO) getGateStatus($(INSTR)$(NAME):, 2) $(ASYN_PORT)") field(SCAN, "2 second") } -record(bi, "$(P):$(NAME):GATE-ON-2_RBV") +record(bi, "$(INSTR)$(NAME):GATE-ON-2_RBV") { field(DESC, "Count when second Gate high/low") field(ZNAM, "Low") diff --git a/db/counterbox_v2_test.db b/db/counterbox_v2_test.db index 07b0f65..3a9ace7 100644 --- a/db/counterbox_v2_test.db +++ b/db/counterbox_v2_test.db @@ -1,31 +1,40 @@ +# EPICS Database for streamdevice support for testing functionality specific to +# the 2nd Generation Systems +# +# Macros +# INSTR - Prefix +# NAME - the device name, e.g. DAQV2 +# PROTO - Stream device protocol file +# ASYN_PORT - Low level Asyn IP Port to Counterbox + ################################################################################ # 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") +record(bo, "$(INSTR)$(NAME):TESTGEN") { field(DESC, "Turn on/off Testgen Signal") field(DTYP, "stream") - field(OUT, "@$(PROTO) switchTestgenOnOff($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) switchTestgenOnOff($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, 0) field(ZNAM, "OFF") field(ONAM, "ON") } -record(longout, "$(P):$(NAME):TESTGEN-LOWRATE") +record(longout, "$(INSTR)$(NAME):TESTGEN-LOWRATE") { field(DESC, "Set Minimum Testgen Rate") field(DTYP, "stream") - field(OUT, "@$(PROTO) setTestSignal($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setTestSignal($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, 1000) } -record(longout, "$(P):$(NAME):TESTGEN-HIGHRATE") +record(longout, "$(INSTR)$(NAME):TESTGEN-HIGHRATE") { field(DESC, "Set Maximum Testgen Rate") field(DTYP, "stream") - field(OUT, "@$(PROTO) setTestSignal($(P):$(NAME):) $(ASYN_PORT)") + field(OUT, "@$(PROTO) setTestSignal($(INSTR)$(NAME):) $(ASYN_PORT)") field(VAL, 1000) } diff --git a/scripts/counterbox_4ch.cmd b/scripts/counterbox_4ch.cmd index 729c1b0..28fb81c 100644 --- a/scripts/counterbox_4ch.cmd +++ b/scripts/counterbox_4ch.cmd @@ -12,11 +12,11 @@ $(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) -dbLoadRecords("$(counterbox_DB)counterbox_common.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=4") -dbLoadRecords("$(counterbox_DB)counterbox_4ch.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") +dbLoadRecords("$(counterbox_DB)counterbox_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=4") +dbLoadRecords("$(counterbox_DB)counterbox_4ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") # Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") diff --git a/scripts/counterbox_8ch.cmd b/scripts/counterbox_8ch.cmd index 3576da3..c82c9a2 100644 --- a/scripts/counterbox_8ch.cmd +++ b/scripts/counterbox_8ch.cmd @@ -12,15 +12,15 @@ $(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) -dbLoadRecords("$(counterbox_DB)counterbox_common.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=8") -dbLoadRecords("$(counterbox_DB)counterbox_8ch.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") +dbLoadRecords("$(counterbox_DB)counterbox_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=8") +dbLoadRecords("$(counterbox_DB)counterbox_8ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") # Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") diff --git a/scripts/counterbox_v2.cmd b/scripts/counterbox_v2.cmd index 90d27d0..8d2a2d2 100644 --- a/scripts/counterbox_v2.cmd +++ b/scripts/counterbox_v2.cmd @@ -12,21 +12,21 @@ $(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) -dbLoadRecords("$(counterbox_DB)counterbox_common.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") -dbLoadRecords("$(counterbox_DB)counterbox_v2.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") +dbLoadRecords("$(counterbox_DB)counterbox_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") +dbLoadRecords("$(counterbox_DB)counterbox_v2.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") # Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=9") -dbLoadRecords("$(counterbox_DB)channels.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=9") +dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") -$(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(counterbox_DB)counterbox_v2_test.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") +$(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(counterbox_DB)counterbox_v2_test.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") -$(SET_SIM_MODE=#) $(SET_SIM_MODE) dbLoadRecords("$(counterbox_DB)counterbox_simcontrol.db", "P=$(PREFIX), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") +$(SET_SIM_MODE=#) $(SET_SIM_MODE) dbLoadRecords("$(counterbox_DB)counterbox_simcontrol.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") diff --git a/test/st.cmd b/test/st.cmd index afb4067..73fe2fb 100755 --- a/test/st.cmd +++ b/test/st.cmd @@ -5,7 +5,7 @@ on error break require counterbox epicsEnvSet("STREAM_PROTOCOL_PATH","./db") -epicsEnvSet("PREFIX","SQ:TEST") +epicsEnvSet("INSTR","SQ:TEST:") epicsEnvSet("NAME","CB_TEST") epicsEnvSet("SET_SIM_MODE","") # Run Counterbox Simulation Instead of Actual Box diff --git a/test/test.py b/test/test.py index 36626cc..c7d45ff 100755 --- a/test/test.py +++ b/test/test.py @@ -40,53 +40,53 @@ def get_piped_output(proc): return stdqueue, errqueue -def getState(prefix, name): - result = run(['caget', f'{prefix}:{name}:STATUS'], stdout=PIPE) +def getState(instr, name): + result = run(['caget', f'{instr}{name}:STATUS'], stdout=PIPE) state = result.stdout.decode('ascii').rstrip().split()[1] print(f'Currently in state {state}') return state -def getCount(prefix, name, ch): - result = run(['caget', f'{prefix}:{name}:M{ch}'], stdout=PIPE) +def getCount(instr, name, ch): + result = run(['caget', f'{instr}{name}:M{ch}'], stdout=PIPE) count = int(result.stdout.decode('ascii').rstrip().split()[1]) print(f'M{ch} == {count}') return count -def presetTime(prefix, name, time): +def presetTime(instr, name, time): print(f'Starting count for {time} seconds') - run(['caput', f'{prefix}:{name}:PRESET-TIME', f'{time}']) + run(['caput', f'{instr}{name}:PRESET-TIME', f'{time}']) -def presetCount(prefix, name, count): +def presetCount(instr, name, count): print(f'Starting count until channel 1 reaches {count}') - run(['caput', f'{prefix}:{name}:PRESET-COUNT', f'{count}']) + run(['caput', f'{instr}{name}:PRESET-COUNT', f'{count}']) -def testCanCount(prefix, name): +def testCanCount(instr, name): # Check in Idle State - assert getState(prefix, name) == 'Idle', 'Not in valid state' + assert getState(instr, name) == 'Idle', 'Not in valid state' # Start Time Based Count and Check that Status Changes - assert getCount(prefix, name, 1) == 0, "Erroneous nonzero starting count value" - presetTime(prefix, name, 5) + assert getCount(instr, name, 1) == 0, "Erroneous nonzero starting count value" + presetTime(instr, name, 5) time.sleep(1) - assert getState(prefix, name) == 'Counting', 'Didn\'t start counting' + assert getState(instr, name) == 'Counting', 'Didn\'t start counting' time.sleep(5) - assert getState(prefix, name) == 'Idle', 'Didn\'t finish counting' - assert getCount(prefix, name, 1) > 0, 'No events were counted' + assert getState(instr, name) == 'Idle', 'Didn\'t finish counting' + assert getCount(instr, name, 1) > 0, 'No events were counted' # Start Monitor Based Count and Check that Status Changes presetAmount = 100 - presetCount(prefix, name, presetAmount) + presetCount(instr, name, presetAmount) time.sleep(1) - assert getState(prefix, name) == 'Counting', 'Didn\'t start counting' - assert getCount(prefix, name, 1) < presetAmount - while getState(prefix, name) != 'Idle': + assert getState(instr, name) == 'Counting', 'Didn\'t start counting' + assert getCount(instr, name, 1) < presetAmount + while getState(instr, name) != 'Idle': time.sleep(1) - assert getCount(prefix, name, 1) == presetAmount, 'Counted events not equal to preset' - assert getCount(prefix, name, 2) > 0 + assert getCount(instr, name, 1) == presetAmount, 'Counted events not equal to preset' + assert getCount(instr, name, 2) > 0 -def test(prefix, name): +def test(instr, name): - # TODO pass prefix and name to script + # TODO pass instr and name to script proc = Popen([f'{os.environ["PARENT_PATH"]}/ioc.sh'], stdout=PIPE, stderr=PIPE, shell=False) try: @@ -104,7 +104,7 @@ def test(prefix, name): print("IOC Initialisation Complete") print("Starting Tests") - testCanCount(prefix, name) + testCanCount(instr, name) print("Success") proc.kill() @@ -123,7 +123,7 @@ if __name__ == '__main__': print("Starting Test") # Test V2 - if test('SQ:TEST', 'CB_TEST'): + if test('SQ:TEST:', 'CB_TEST'): exit(0) else: exit(1) -- 2.49.0 From 5066cafc07d70fcff59a237611da41d08641f33e Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Tue, 29 Apr 2025 17:22:31 +0200 Subject: [PATCH 6/9] rename from counterbox to daq --- Makefile | 28 +++++------ README.md | 37 +++++++------- db/channels.db | 6 +-- db/{counterbox.proto => daq.proto} | 9 ++-- db/{counterbox_v2.db => daq_2nd_gen.db} | 2 +- ...nterbox_v2_test.db => daq_2nd_gen_test.db} | 2 +- db/{counterbox_4ch.db => daq_4ch.db} | 2 +- db/{counterbox_8ch.db => daq_8ch.db} | 2 +- db/{counterbox_common.db => daq_common.db} | 16 +++--- ...terbox_simcontrol.db => daq_simcontrol.db} | 2 +- scripts/counterbox_4ch.cmd | 22 -------- scripts/counterbox_8ch.cmd | 26 ---------- scripts/counterbox_v2.cmd | 32 ------------ scripts/daq_2nd_gen.cmd | 32 ++++++++++++ scripts/daq_4ch.cmd | 22 ++++++++ scripts/daq_8ch.cmd | 26 ++++++++++ sim/{counterbox_sim.py => daq_sim.py} | 50 +++++++++---------- src/counterbox.dbd | 5 -- src/{counterbox.cpp => daq.cpp} | 4 +- src/daq.dbd | 5 ++ test/st.cmd | 6 +-- 21 files changed, 168 insertions(+), 168 deletions(-) rename db/{counterbox.proto => daq.proto} (94%) rename db/{counterbox_v2.db => daq_2nd_gen.db} (98%) rename db/{counterbox_v2_test.db => daq_2nd_gen_test.db} (95%) rename db/{counterbox_4ch.db => daq_4ch.db} (94%) rename db/{counterbox_8ch.db => daq_8ch.db} (94%) rename db/{counterbox_common.db => daq_common.db} (94%) rename db/{counterbox_simcontrol.db => daq_simcontrol.db} (88%) delete mode 100644 scripts/counterbox_4ch.cmd delete mode 100644 scripts/counterbox_8ch.cmd delete mode 100644 scripts/counterbox_v2.cmd create mode 100644 scripts/daq_2nd_gen.cmd create mode 100644 scripts/daq_4ch.cmd create mode 100644 scripts/daq_8ch.cmd rename sim/{counterbox_sim.py => daq_sim.py} (87%) delete mode 100644 src/counterbox.dbd rename src/{counterbox.cpp => daq.cpp} (96%) create mode 100644 src/daq.dbd diff --git a/Makefile b/Makefile index f2d3b36..e0e4c88 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # This build the sinq extensions for the PSI EPICS setup include /ioc/tools/driver.makefile -MODULE=counterbox +MODULE=sinqDAQ BUILDCLASSES=Linux EPICS_VERSIONS=7.0.7 ARCH_FILTER=RHEL% @@ -13,26 +13,26 @@ REQUIRED+=stream # DB files to include in the release TEMPLATES += db/channels.db -TEMPLATES += db/counterbox_4ch.db -TEMPLATES += db/counterbox_8ch.db -TEMPLATES += db/counterbox_common.db -TEMPLATES += db/counterbox_v2.db -TEMPLATES += db/counterbox_v2_test.db -TEMPLATES += db/counterbox.proto +TEMPLATES += db/daq_4ch.db +TEMPLATES += db/daq_8ch.db +TEMPLATES += db/daq_common.db +TEMPLATES += db/daq_2nd_gen.db +TEMPLATES += db/daq_2nd_gen_test.db +TEMPLATES += db/daq.proto # Just for simulation -TEMPLATES += db/counterbox_simcontrol.db +TEMPLATES += db/daq_simcontrol.db # DBD files to include in the release -DBDS += src/counterbox.dbd +DBDS += src/daq.dbd # Source files to build -SOURCES += src/counterbox.cpp +SOURCES += src/daq.cpp -SCRIPTS += scripts/counterbox_4ch.cmd -SCRIPTS += scripts/counterbox_8ch.cmd -SCRIPTS += scripts/counterbox_v2.cmd -SCRIPTS += sim/counterbox_sim.py +SCRIPTS += scripts/daq_4ch.cmd +SCRIPTS += scripts/daq_8ch.cmd +SCRIPTS += scripts/daq_2nd_gen.cmd +SCRIPTS += sim/daq_sim.py CXXFLAGS += -std=c++17 USR_CFLAGS += -Wall -Wextra #-Werror diff --git a/README.md b/README.md index 2e1be67..c22f0aa 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ generation systems. ## How to Use Unless a custom database is needed, a device can be configure simply by setting -the required environment variables when calling the correct counterbox script. +the required environment variables when calling the correct DAQ interface +script. Required Variables @@ -18,8 +19,8 @@ Required Variables |----------------------|-----------------------------------------| | INSTR | Prefix of all device specific PVs | | NAME | First field in all PVs after Prefix | -| CNTBOX\_IP | Network IP of device | -| CNTBOX\_PORT | Network Port of device | +| DAQ\_IP | Network IP of device | +| DAQ\_PORT | Network Port of device | All PVs take the form @@ -29,16 +30,16 @@ $(INSTR)$(NAME):* Available device startup scripts -* scripts/counterbox\_4ch.cmd -* scripts/counterbox\_8ch.cmd -* scripts/counterbox\_v2.cmd +* scripts/daq\_4ch.cmd +* scripts/daq\_8ch.cmd +* scripts/daq\_2nd\_gen.cmd A device can be configured using one of the startup scripts as follows ``` epicsEnvSet("INSTR", "SQ:INSTRUMENT:") # can also be set in runScript call -runScript "$(counterbox_DIR)counterbox_v2.cmd" "NAME=COUNTERBOX, CNTBOX_IP=TestInst-DAQ1, CNTBOX_PORT=2000" +runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_PORT=2000" ``` ## PVs of Interest @@ -52,8 +53,8 @@ runScript "$(counterbox_DIR)counterbox_v2.cmd" "NAME=COUNTERBOX, CNTBOX_IP=TestI | \$(INSTR)\$(NAME):PRESET-TIME | Run count until specified pv value in seconds reached | | \$(INSTR)\$(NAME):THRESHOLD | Minimum rate for counting to preceed. (has RBV) | | \$(INSTR)\$(NAME):THRESHOLD-MONITOR | Channel monitored for minimum rate (has RBV) | -| \$(INSTR)\$(NAME):ELAPSED-TIME | Time Counterbox has been measuring for | -| \$(INSTR)\$(NAME):M_ | Current count on channel. (1-10 depending on box) | +| \$(INSTR)\$(NAME):ELAPSED-TIME | Time DAQ has been measuring for | +| \$(INSTR)\$(NAME):M_ | Current count on channel. (1-10 depending on DAQ system) | | \$(INSTR)\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) | ## Generating Test Signals @@ -65,34 +66,34 @@ runtime via the following ``` epicsEnvSet("LOAD_TEST_PVS","") -runScript "$(counterbox_DIR)counterbox_v2.cmd" "NAME=COUNTERBOX, CNTBOX_IP=TestInst-DAQ1, CNTBOX_PORT=2000" +runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_PORT=2000" ``` -See the file [counterbox\_v2\_test.db](./db/counterbox_v2_test.db) +See the file [daq\_2nd\_gen\_test.db](./db/daq_2nd_gen_test.db) ## Simulation Simulation of the Hardware can be toggled on as follows: ``` -epicsEnvSet("SET_SIM_MODE","") # run counterbox simulation instead of connecting to actual box -runScript "$(counterbox_DIR)counterbox_v2.cmd" "NAME=CB_TEST, CNTBOX_IP=localhost, CNTBOX_PORT=2000" +epicsEnvSet("SET_SIM_MODE","") # run DAQ simulation instead of connecting to actual system +runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=CB_TEST, DAQ_IP=localhost, DAQ_PORT=2000" ``` -In such a case, the provided `CNTBOX_IP` is ignored, and a python program +In such a case, the provided `DAQ_IP` is ignored, and a python program simulating the hardware is started in the background, listening at the -specified `CNTBOX_PORT`. So, if you have multiple devices listening on the same +specified `DAQ_PORT`. So, if you have multiple devices listening on the same port, you might have to change this port value of one of the devices when simulating hardware. You can then interact with the PVs as with the normal hardware. Keep in mind, however, that not all functionality has been implemented. -See [sim/counterbox\_sim.py](sim/counterbox_sim.py). +See [sim/daq\_sim.py](sim/daq_sim.py). ## Testing -An IOC with the counterbox\_v2 started in simulation mode can be started via -the [test/ioc.sh](test/ioc.sh) script. +An IOC with the 2nd generation DAQ started in simulation mode can be started +via the [test/ioc.sh](test/ioc.sh) script. There is also a simple automated test that can be run for a simple check of functionality and that the PVs load [test/test.py](test/test.py). diff --git a/db/channels.db b/db/channels.db index 4f0fb54..11753b5 100644 --- a/db/channels.db +++ b/db/channels.db @@ -4,7 +4,7 @@ # INSTR - Prefix # NAME - the device name, e.g. EL737 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to Counterbox +# ASYN_PORT - Low level Asyn IP Port to DAQ # CHANNEL - the number associated with the measurment channel ################################################################################ @@ -25,12 +25,12 @@ record(bo, "$(INSTR)$(NAME):C$(CHANNEL)") record(longin, "$(INSTR)$(NAME):M$(CHANNEL)") { - field(DESC, "Counterbox CH$(CHANNEL)") + field(DESC, "DAQ CH$(CHANNEL)") } record(ai, "$(INSTR)$(NAME):R$(CHANNEL)") { - field(DESC, "Counterbox Rate CH$(CHANNEL)") + field(DESC, "Rate of DAQ CH$(CHANNEL)") field(INP, "@$(PROTO) readRate($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") field(DTYP, "stream") field(SCAN, "1 second") diff --git a/db/counterbox.proto b/db/daq.proto similarity index 94% rename from db/counterbox.proto rename to db/daq.proto index 29d78a8..6a0ba2f 100644 --- a/db/counterbox.proto +++ b/db/daq.proto @@ -1,5 +1,5 @@ # -# Counterbox Protocol File +# SinqDAQ Protocol File # OutTerminator = CR; InTerminator = CR; @@ -14,7 +14,7 @@ initialise { out "ECHO 2"; # Ask for reponses in "%(\$1MsgTxt)s"; # Clear MsgTxt on Init @mismatch{ - exec 'echo "Failed to configure counterbox" && exit(1)'; + exec 'echo "Failed to configure DAQ" && exit(1)'; } } @@ -65,9 +65,8 @@ stopCount { } clearTimer{ - # We first stop the count, as otherwise on the newest counterboxes - # it starts counting again if a time preset was set. - # Not a problem with the older boxes + # We first stop the count, as otherwise the 2nd Gen Data Acquisition starts + # counting again if a time preset was set. Not a problem with the older boxes stopCount; out "CT"; in; diff --git a/db/counterbox_v2.db b/db/daq_2nd_gen.db similarity index 98% rename from db/counterbox_v2.db rename to db/daq_2nd_gen.db index ea81465..f3cb0f8 100644 --- a/db/counterbox_v2.db +++ b/db/daq_2nd_gen.db @@ -5,7 +5,7 @@ # INSTR - Prefix # NAME - the device name, e.g. DAQV2 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to Counterbox +# ASYN_PORT - Low level Asyn IP Port to DAQ ################################################################################ # Status Variables diff --git a/db/counterbox_v2_test.db b/db/daq_2nd_gen_test.db similarity index 95% rename from db/counterbox_v2_test.db rename to db/daq_2nd_gen_test.db index 3a9ace7..68d3a7c 100644 --- a/db/counterbox_v2_test.db +++ b/db/daq_2nd_gen_test.db @@ -5,7 +5,7 @@ # INSTR - Prefix # NAME - the device name, e.g. DAQV2 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to Counterbox +# ASYN_PORT - Low level Asyn IP Port to DAQ ################################################################################ # Testing Commands diff --git a/db/counterbox_4ch.db b/db/daq_4ch.db similarity index 94% rename from db/counterbox_4ch.db rename to db/daq_4ch.db index 4cb7dd3..1e2c1ac 100644 --- a/db/counterbox_4ch.db +++ b/db/daq_4ch.db @@ -4,7 +4,7 @@ # INSTR - Prefix # NAME - the device name, e.g. EL737 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to Counterbox +# ASYN_PORT - Low level Asyn IP Port to DAQ ################################################################################ # Status Variables diff --git a/db/counterbox_8ch.db b/db/daq_8ch.db similarity index 94% rename from db/counterbox_8ch.db rename to db/daq_8ch.db index 3fd8a33..d1893b0 100644 --- a/db/counterbox_8ch.db +++ b/db/daq_8ch.db @@ -4,7 +4,7 @@ # INSTR - Prefix # NAME - the device name, e.g. EL737 # PROTO - Stream device protocol file -# ASYN_PORT - Low level Asyn IP Port to Counterbox +# ASYN_PORT - Low level Asyn IP Port to DAQ ################################################################################ # Status Variables diff --git a/db/counterbox_common.db b/db/daq_common.db similarity index 94% rename from db/counterbox_common.db rename to db/daq_common.db index 201fecf..7cfc1f3 100644 --- a/db/counterbox_common.db +++ b/db/daq_common.db @@ -9,7 +9,7 @@ # Send initial initialisation commands record(bo, "$(INSTR)$(NAME):INIT-CONF") { - field(DESC, "Initialises the Counterbox") + field(DESC, "Initialises the DAQ") field(OUT, "@$(PROTO) initialise($(INSTR)$(NAME):) $(ASYN_PORT)") field(PINI, "YES") # Run at init field(DTYP, "stream") @@ -17,7 +17,7 @@ record(bo, "$(INSTR)$(NAME):INIT-CONF") record(longout, "$(INSTR)$(NAME):FULL-RESET") { - field(DESC, "Reset the Counterbox") + field(DESC, "Reset the DAQ") field(OUT, "@$(PROTO) fullReset($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") } @@ -28,16 +28,16 @@ record(longout, "$(INSTR)$(NAME):FULL-RESET") record(stringin, "$(INSTR)$(NAME):MsgTxt") { field(DESC, "Unexpected received response") - field(DTYP, "devCounterBoxStringError") + field(DTYP, "devDAQStringError") field(FLNK, "$(INSTR)$(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 +# the init if it occurs. This should only happen after turning the DAQ off and # on again or running a full reset record(scalcout, "$(INSTR)$(NAME):INVALID-CONFIG") { - field(DESC, "Has the counterbox been configured?") + field(DESC, "Has the DAQ been configured?") field(CALC, "AA[0,2] == '?OF'") field(INAA, "$(INSTR)$(NAME):MsgTxt") field(FLNK, "$(INSTR)$(NAME):REINIT-CONF") @@ -76,7 +76,7 @@ record(calc, "$(INSTR)$(NAME):MAP-STATUS") record(mbbi, "$(INSTR)$(NAME):STATUS") { - field(DESC, "Counterbox Status") + field(DESC, "DAQ Status") field(INP, "$(INSTR)$(NAME):MAP-STATUS NPP") field(ZRVL, "0") field(ZRST, "Idle") @@ -86,7 +86,7 @@ record(mbbi, "$(INSTR)$(NAME):STATUS") 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 + # 4 should never happen, if it does it means the DAQ reports undocumented statusbits field(FRVL, "4") field(FRST, "INVALID") } @@ -207,6 +207,6 @@ record(ai, "$(INSTR)$(NAME):READALL") record(ai,"$(INSTR)$(NAME):ELAPSED-TIME") { - field(DESC, "Counterbox Measured Time") + field(DESC, "DAQ Measured Time") field(EGU, "seconds") } diff --git a/db/counterbox_simcontrol.db b/db/daq_simcontrol.db similarity index 88% rename from db/counterbox_simcontrol.db rename to db/daq_simcontrol.db index 36e5128..53e5ca0 100644 --- a/db/counterbox_simcontrol.db +++ b/db/daq_simcontrol.db @@ -1,4 +1,4 @@ -# Sinq Counterbox EPICS Database for StreamDevice Communication with Simulation +# Sinq DAQ EPICS Database for StreamDevice Communication with Simulation # Macros # # INSTR - Prefix diff --git a/scripts/counterbox_4ch.cmd b/scripts/counterbox_4ch.cmd deleted file mode 100644 index 28fb81c..0000000 --- a/scripts/counterbox_4ch.cmd +++ /dev/null @@ -1,22 +0,0 @@ -require asyn -require stream - -epicsEnvSet("$(NAME)_CNTBOX_HOST", "$(CNTBOX_IP):$(CNTBOX_PORT)") - -$(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc -$(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_CNTBOX_HOST", "127.0.0.1:$(CNTBOX_PORT)") -$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(counterbox_DIR)counterbox_sim.py $(CNTBOX_PORT) 4 &" -# starting the python socket seems to take a while -# and need misc to use built in sleep command -$(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 - -epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") -drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) -dbLoadRecords("$(counterbox_DB)counterbox_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=4") -dbLoadRecords("$(counterbox_DB)counterbox_4ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") - -# Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") diff --git a/scripts/counterbox_8ch.cmd b/scripts/counterbox_8ch.cmd deleted file mode 100644 index c82c9a2..0000000 --- a/scripts/counterbox_8ch.cmd +++ /dev/null @@ -1,26 +0,0 @@ -require asyn -require stream - -epicsEnvSet("$(NAME)_CNTBOX_HOST", "$(CNTBOX_IP):$(CNTBOX_PORT)") - -$(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc -$(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_CNTBOX_HOST", "127.0.0.1:$(CNTBOX_PORT)") -$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(counterbox_DIR)counterbox_sim.py $(CNTBOX_PORT) 8 &" -# starting the python socket seems to take a while -# and need misc to use built in sleep command -$(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 - -epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") -drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) -dbLoadRecords("$(counterbox_DB)counterbox_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=8") -dbLoadRecords("$(counterbox_DB)counterbox_8ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") - -# Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") diff --git a/scripts/counterbox_v2.cmd b/scripts/counterbox_v2.cmd deleted file mode 100644 index 8d2a2d2..0000000 --- a/scripts/counterbox_v2.cmd +++ /dev/null @@ -1,32 +0,0 @@ -require asyn -require stream - -epicsEnvSet("$(NAME)_CNTBOX_HOST", "$(CNTBOX_IP):$(CNTBOX_PORT=2000)") - -$(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc -$(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_CNTBOX_HOST", "127.0.0.1:$(CNTBOX_PORT=2000)") -$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(counterbox_DIR)counterbox_sim.py $(CNTBOX_PORT=2000) 10 &" -# starting the python socket seems to take a while -# and need misc to use built in sleep command -$(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 - -epicsEnvSet("PROTO", "$(counterbox_DB)counterbox.proto") -drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_CNTBOX_HOST)", 0, 0, 0) -dbLoadRecords("$(counterbox_DB)counterbox_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") -dbLoadRecords("$(counterbox_DB)counterbox_v2.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") - -# Could also use substitions instead. -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=9") -dbLoadRecords("$(counterbox_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") - -$(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(counterbox_DB)counterbox_v2_test.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") - -$(SET_SIM_MODE=#) $(SET_SIM_MODE) dbLoadRecords("$(counterbox_DB)counterbox_simcontrol.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") diff --git a/scripts/daq_2nd_gen.cmd b/scripts/daq_2nd_gen.cmd new file mode 100644 index 0000000..cdcf852 --- /dev/null +++ b/scripts/daq_2nd_gen.cmd @@ -0,0 +1,32 @@ +require asyn +require stream + +epicsEnvSet("$(NAME)_DAQ_HOST", "$(DAQ_IP):$(DAQ_PORT=2000)") + +$(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc +$(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_DAQ_HOST", "127.0.0.1:$(DAQ_PORT=2000)") +$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(sinqDAQ_DIR)daq_sim.py $(DAQ_PORT=2000) 10 &" +# starting the python socket seems to take a while +# and need misc to use built in sleep command +$(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 + +epicsEnvSet("PROTO", "$(sinqDAQ_DB)daq.proto") +drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_DAQ_HOST)", 0, 0, 0) +dbLoadRecords("$(sinqDAQ_DB)daq_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") +dbLoadRecords("$(sinqDAQ_DB)daq_2nd_gen.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10") + +# Could also use substitions instead. +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=9") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") + +$(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(sinqDAQ_DB)daq_2nd_gen_test.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") + +$(SET_SIM_MODE=#) $(SET_SIM_MODE) dbLoadRecords("$(sinqDAQ_DB)daq_simcontrol.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") diff --git a/scripts/daq_4ch.cmd b/scripts/daq_4ch.cmd new file mode 100644 index 0000000..6c43c94 --- /dev/null +++ b/scripts/daq_4ch.cmd @@ -0,0 +1,22 @@ +require asyn +require stream + +epicsEnvSet("$(NAME)_DAQ_HOST", "$(DAQ_IP):$(DAQ_PORT)") + +$(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc +$(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_DAQ_HOST", "127.0.0.1:$(DAQ_PORT)") +$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(sinqDAQ_DIR)daq_sim.py $(DAQ_PORT) 4 &" +# starting the python socket seems to take a while +# and need misc to use built in sleep command +$(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 + +epicsEnvSet("PROTO", "$(sinqDAQ_DB)daq.proto") +drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_DAQ_HOST)", 0, 0, 0) +dbLoadRecords("$(sinqDAQ_DB)daq_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=4") +dbLoadRecords("$(sinqDAQ_DB)daq_4ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") + +# Could also use substitions instead. +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") diff --git a/scripts/daq_8ch.cmd b/scripts/daq_8ch.cmd new file mode 100644 index 0000000..1ac5187 --- /dev/null +++ b/scripts/daq_8ch.cmd @@ -0,0 +1,26 @@ +require asyn +require stream + +epicsEnvSet("$(NAME)_DAQ_HOST", "$(DAQ_IP):$(DAQ_PORT)") + +$(SET_SIM_MODE=#) $(SET_SIM_MODE) require misc +$(SET_SIM_MODE=#) $(SET_SIM_MODE) epicsEnvSet("$(NAME)_DAQ_HOST", "127.0.0.1:$(DAQ_PORT)") +$(SET_SIM_MODE=#) $(SET_SIM_MODE) system "$(sinqDAQ_DIR)daq_sim.py $(DAQ_PORT) 8 &" +# starting the python socket seems to take a while +# and need misc to use built in sleep command +$(SET_SIM_MODE=#) $(SET_SIM_MODE) sleep 3 + +epicsEnvSet("PROTO", "$(sinqDAQ_DB)daq.proto") +drvAsynIPPortConfigure("ASYN_$(NAME)", "$($(NAME)_DAQ_HOST)", 0, 0, 0) +dbLoadRecords("$(sinqDAQ_DB)daq_common.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=8") +dbLoadRecords("$(sinqDAQ_DB)daq_8ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") + +# Could also use substitions instead. +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=3") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=4") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=5") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=6") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=7") +dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=8") diff --git a/sim/counterbox_sim.py b/sim/daq_sim.py similarity index 87% rename from sim/counterbox_sim.py rename to sim/daq_sim.py index 578925a..627a1c6 100644 --- a/sim/counterbox_sim.py +++ b/sim/daq_sim.py @@ -14,13 +14,13 @@ TOTAL_CH = int(sys.argv[2]) # Number of Channels LOG2FILE = False if len(sys.argv) < 4 else bool(int(sys.argv[3])) import logging -logger = logging.getLogger('counterbox') +logger = logging.getLogger('daq') if LOG2FILE: - logging.basicConfig(filename=os.path.join(os.getcwd(), 'counterbox_sim.log'), level=logging.INFO) + logging.basicConfig(filename=os.path.join(os.getcwd(), 'daq_sim.log'), level=logging.INFO) -class CounterBox: +class DAQ: def __init__(self, total_channels): self.total_channels = total_channels self.counts = [0] * self.total_channels @@ -66,7 +66,7 @@ class CounterBox: return self.counts[channel - 1] def getCounts(self): - # The sinqtest box returns a maximum of 8 + # The sinqtest daq returns a maximum of 8 return self.counts[0:min(len(self.counts), 8)] def getMonitorCount(self): @@ -217,7 +217,7 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.info(f'RECEIVED: "{received}"') return received - counterbox = CounterBox(TOTAL_CH) + daq = DAQ(TOTAL_CH) while True: @@ -232,85 +232,85 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: send('') elif data == 'ECHO 2': - send('Counterbox') # Sends some sort of info command + send('DAQ System Version Simulation') # Sends some sort of info command elif data == 'RA': send( ' '.join(map(str, - [counterbox.getRunTime()] + \ - counterbox.getCounts() + [daq.getRunTime()] + \ + daq.getCounts() )) ) elif re.fullmatch(r'RC (\d+)', data): channel = int(re.fullmatch(r'RC (\d+)', data).group(1)) - count = counterbox.getCount(channel) + count = daq.getCount(channel) send(f'{count}') elif data == 'RS': - send(str(counterbox.getStatus())) + send(str(daq.getStatus())) elif data == 'S': - counterbox.stop() + daq.stop() send('') elif data == 'CT': - counterbox.clearTime() + daq.clearTime() send('') elif re.fullmatch(r'CC (\d+)', data): counter = int(re.fullmatch(r'CC (\d+)', data).group(1)) - counterbox.clearCount(counter) + daq.clearCount(counter) send('') elif re.fullmatch(r'TP (\d+(\.\d+)?)', data): presettime = float(re.fullmatch(r'TP (\d+(\.\d+)?)', data).group(1)) - counterbox.startTimePreset(presettime) + daq.startTimePreset(presettime) send('') elif re.fullmatch(r'MP (\d+)', data): counts = int(re.fullmatch(r'MP (\d+)', data).group(1)) - counterbox.startCountPreset(counts) + daq.startCountPreset(counts) send('') elif data == 'PC': - send(str(counterbox.getMonitorChannel())) + send(str(daq.getMonitorChannel())) elif re.fullmatch(r'PC (\d+)', data): channel = int(re.fullmatch(r'PC (\d+)', data).group(1)) - counterbox.setMonitorChannel(channel) + daq.setMonitorChannel(channel) send('') elif data == 'DR': - send(str(counterbox.getMinRateChannel())) + send(str(daq.getMinRateChannel())) elif re.fullmatch(r'DR (\d+)', data): channel = int(re.fullmatch(r'DR (\d+)', data).group(1)) - counterbox.setMinRateChannel(channel) + daq.setMinRateChannel(channel) send('') elif re.fullmatch(r'DL (\d+)', data): channel = int(re.fullmatch(r'DL (\d+)', data).group(1)) - send('{:.3f}'.format(counterbox.getMinRate(channel))) + send('{:.3f}'.format(daq.getMinRate(channel))) elif re.fullmatch(r'DL (\d+) (\d+(?:.\d+)?)', data): channel, rate = re.fullmatch(r'DL (\d+) (\d+(?:.\d+)?)', data).groups() - counterbox.setMinRate(int(channel), float(rate)) + daq.setMinRate(int(channel), float(rate)) send('') elif re.fullmatch(r'RR (\d+)', data): channel = int(re.fullmatch(r'RR (\d+)', data).group(1)) - send(counterbox.getRate(channel)) + send(daq.getRate(channel)) elif re.fullmatch(r'GT (\d+)', data): channel = int(re.fullmatch(r'GT (\d+)', data).group(1)) - enabled, highlow = counterbox.getGateStatus(channel) + enabled, highlow = daq.getGateStatus(channel) send(f'{int(enabled)} {int(highlow)}') elif re.fullmatch(r'GT (\d+) (\d+) (\d+)', data): channel, enable, highlow = re.fullmatch(r'GT (\d+) (\d+) (\d+)', data).groups() channel, enable, highlow = int(channel), bool(int(enable)), bool(int(highlow)) - counterbox.setGateStatus(channel, enable, highlow) + daq.setGateStatus(channel, enable, highlow) if enable: send(f'Gate {channel} enabled, counting when input = {"high" if highlow else "low"}') else: @@ -320,7 +320,7 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: elif re.fullmatch(r'GATE (\d+) (\d+)', data): channel, highlow = re.fullmatch(r'GATE (\d+) (\d+)', data).groups() channel, highlow = int(channel), bool(int(highlow)) - counterbox.setGate(channel, highlow) + daq.setGate(channel, highlow) send('') else: diff --git a/src/counterbox.dbd b/src/counterbox.dbd deleted file mode 100644 index 4ef690d..0000000 --- a/src/counterbox.dbd +++ /dev/null @@ -1,5 +0,0 @@ -#--------------------------------------------- -# Counterbox specific DB definitions -#--------------------------------------------- - -device(stringin,INST_IO,devCounterBoxStringError,"devCounterBoxStringError") diff --git a/src/counterbox.cpp b/src/daq.cpp similarity index 96% rename from src/counterbox.cpp rename to src/daq.cpp index 591fea3..02d2bf0 100644 --- a/src/counterbox.cpp +++ b/src/daq.cpp @@ -54,7 +54,7 @@ struct { DEVSUPFUN get_ioint_info; DEVSUPFUN read_ai; DEVSUPFUN special_linconv; -} devCounterBoxStringError = { +} devDAQStringError = { 6, NULL, NULL, NULL, NULL, (DEVSUPFUN)map_raw_failure_message, NULL}; -epicsExportAddress(dset, devCounterBoxStringError); +epicsExportAddress(dset, devDAQStringError); diff --git a/src/daq.dbd b/src/daq.dbd new file mode 100644 index 0000000..3bfdf32 --- /dev/null +++ b/src/daq.dbd @@ -0,0 +1,5 @@ +#--------------------------------------------- +# DAQ specific DB definitions +#--------------------------------------------- + +device(stringin, INST_IO, devDAQStringError, "devDAQStringError") diff --git a/test/st.cmd b/test/st.cmd index 73fe2fb..7f55320 100755 --- a/test/st.cmd +++ b/test/st.cmd @@ -2,13 +2,13 @@ on error break -require counterbox +require sinqDAQ epicsEnvSet("STREAM_PROTOCOL_PATH","./db") epicsEnvSet("INSTR","SQ:TEST:") epicsEnvSet("NAME","CB_TEST") -epicsEnvSet("SET_SIM_MODE","") # Run Counterbox Simulation Instead of Actual Box -runScript "$(counterbox_DIR)counterbox_v2.cmd" "CNTBOX_IP=127.0.0.1, CNTBOX_PORT=2000" +epicsEnvSet("SET_SIM_MODE","") # Run Simulation Instead of Actual Interface +runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "DAQ_IP=127.0.0.1, DAQ_PORT=2000" iocInit() -- 2.49.0 From f31e7c1e23a979113093af91fcc67dad30951f57 Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Fri, 23 May 2025 11:51:57 +0200 Subject: [PATCH 7/9] changes to play nicer with the nicos detector interface and with caproto --- db/channels.db | 33 ++++++++++++++++++++++++++++++++- db/daq_common.db | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/db/channels.db b/db/channels.db index 11753b5..c136ec8 100644 --- a/db/channels.db +++ b/db/channels.db @@ -10,14 +10,42 @@ ################################################################################ # Status Variables +# Trigger a change in status as clearing +record(bo, "$(INSTR)$(NAME):T$(CHANNEL)") +{ + field(DESC, "Trigger Clearing Status") + field(VAL, 1) + field(OUT, "$(INSTR)$(NAME):S$(CHANNEL) PP") +} + +# Trigger a change in status as value returned to 0 +record(seq, "$(INSTR)$(NAME):O$(CHANNEL)") +{ + field(DESC, "Trigger Returned to 0 Status") + field(LNK0, "$(INSTR)$(NAME):S$(CHANNEL) PP") + field(DO0, 0) + field(SELM, "Specified") + field(SELL, "$(INSTR)$(NAME):M$(CHANNEL).VAL") +} + +# Current Status of Channel, i.e. is it ready to count? +record(bi, "$(INSTR)$(NAME):S$(CHANNEL)") +{ + field(DESC, "Channel Status") + field(VAL, 0) + field(ZNAM, "OK") + field(ONAM, "CLEARING") +} + ################################################################################ # Count Commands -record(bo, "$(INSTR)$(NAME):C$(CHANNEL)") +record(longout, "$(INSTR)$(NAME):C$(CHANNEL)") { field(DESC, "Clear the current channel count") field(DTYP, "stream") field(OUT, "@$(PROTO) clearChannel($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") + field(FLNK, "$(INSTR)$(NAME):T$(CHANNEL)") } ################################################################################ @@ -26,6 +54,8 @@ record(bo, "$(INSTR)$(NAME):C$(CHANNEL)") record(longin, "$(INSTR)$(NAME):M$(CHANNEL)") { field(DESC, "DAQ CH$(CHANNEL)") + field(EGU, "cts") + field(FLNK, "$(INSTR)$(NAME):O$(CHANNEL)") } record(ai, "$(INSTR)$(NAME):R$(CHANNEL)") @@ -33,5 +63,6 @@ record(ai, "$(INSTR)$(NAME):R$(CHANNEL)") field(DESC, "Rate of DAQ CH$(CHANNEL)") field(INP, "@$(PROTO) readRate($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") field(DTYP, "stream") + field(EGU, "cts/sec") field(SCAN, "1 second") } diff --git a/db/daq_common.db b/db/daq_common.db index 7cfc1f3..763aea3 100644 --- a/db/daq_common.db +++ b/db/daq_common.db @@ -98,6 +98,32 @@ record(longin, "$(INSTR)$(NAME):CHANNELS") field(DISP, 1) } +# Trigger a change in status as clearing +record(bo, "$(INSTR)$(NAME):ETT") +{ + field(DESC, "Trigger Clearing Status") + field(VAL, 1) + field(OUT, "$(INSTR)$(NAME):ETS PP") +} + +# Trigger a change in status as value returned to 0 +record(seq, "$(INSTR)$(NAME):ETO") +{ + field(DESC, "Trigger Returned to 0 Status") + field(LNK0, "$(INSTR)$(NAME):ETS PP") + field(DO0, 0) + field(SELM, "Specified") + field(SELL, "$(INSTR)$(NAME):ELAPSED-TIME.VAL") +} + +# Current Status of Channel, i.e. is it ready to count? +record(bi, "$(INSTR)$(NAME):ETS") +{ + field(DESC, "Channel Status") + field(VAL, 0) + field(ZNAM, "OK") + field(ONAM, "CLEARING") +} ################################################################################ # Count Commands @@ -167,6 +193,7 @@ record(ai,"$(INSTR)$(NAME):THRESHOLD_RBV") field(INP, "@$(PROTO) readMinRate($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") field(SCAN, "1 second") + field(EGU, "cts/sec") } record(longout,"$(INSTR)$(NAME):THRESHOLD-MONITOR") @@ -185,13 +212,15 @@ record(longin,"$(INSTR)$(NAME):THRESHOLD-MONITOR_RBV") field(INP, "@$(PROTO) readRateMonitor($(INSTR)$(NAME):) $(ASYN_PORT)") field(DTYP, "stream") field(SCAN, "1 second") + field(EGU, "CH") } -record(bo, "$(INSTR)$(NAME):CT") +record(longout, "$(INSTR)$(NAME):CT") { field(DESC, "Clear the timer") field(DTYP, "stream") field(OUT, "@$(PROTO) clearTimer($(INSTR)$(NAME):) $(ASYN_PORT)") + field(FLNK, "$(INSTR)$(NAME):ETT") } ################################################################################ @@ -208,5 +237,6 @@ record(ai, "$(INSTR)$(NAME):READALL") record(ai,"$(INSTR)$(NAME):ELAPSED-TIME") { field(DESC, "DAQ Measured Time") - field(EGU, "seconds") + field(EGU, "sec") + field(FLNK, "$(INSTR)$(NAME):ETO") } -- 2.49.0 From 3dd7c5a1d96a7c11802d959768367865b14425c4 Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Mon, 16 Jun 2025 17:38:48 +0200 Subject: [PATCH 8/9] moves the gating configuration logic to epics --- Makefile | 1 + db/daq.proto | 6 +-- db/daq_2nd_gen.db | 85 ++++++----------------------------------- db/daq_common.db | 6 ++- scripts/daq_2nd_gen.cmd | 3 ++ 5 files changed, 22 insertions(+), 79 deletions(-) diff --git a/Makefile b/Makefile index e0e4c88..56ca12a 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ REQUIRED+=stream # DB files to include in the release TEMPLATES += db/channels.db +TEMPLATES += db/gating_channels.db TEMPLATES += db/daq_4ch.db TEMPLATES += db/daq_8ch.db TEMPLATES += db/daq_common.db diff --git a/db/daq.proto b/db/daq.proto index 6a0ba2f..4b4e2fb 100644 --- a/db/daq.proto +++ b/db/daq.proto @@ -199,13 +199,13 @@ setTestSignal { getGateStatus { out "GT \$2"; - in "%d %(\$1GATE-ON-\$2_RBV)d"; + in "%d %(\$1GATE-\$2-TRIG_RBV)d"; @mismatch{in "%(\$1MsgTxt)s";} } setGateStatus { extrainput = ignore; - out "GT \$2 %(\$1GATE-\$2)d %(\$1GATE-ON-\$2)d"; + out "GT \$2 %(\$1GATE-\$2-ENABLE)d %(\$1GATE-\$2-TRIG)d"; in "Gate \$2"; @mismatch{in "%(\$1MsgTxt)s";} } @@ -217,7 +217,7 @@ setGate { } ################################################################################ -# To clean +# TODO To clean startWithCountPreset4 { clearTimer; diff --git a/db/daq_2nd_gen.db b/db/daq_2nd_gen.db index f3cb0f8..2c06596 100644 --- a/db/daq_2nd_gen.db +++ b/db/daq_2nd_gen.db @@ -25,7 +25,17 @@ record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") field(DESC, "PRESET-COUNT Monitors this channel") field(DTYP, "stream") field(INP, "@$(PROTO) readPresetMonitor($(INSTR)$(NAME):) $(ASYN_PORT)") - field(SCAN, "5 second") + field(SCAN, "1 second") +} + +# Force back to 1 if it is 0, as 0 has no meaning... +record(seq, "$(INSTR)$(NAME):CORRECT-MONITOR-CHANNEL") +{ + field(SELM, "Specified") + field(SELL, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV.VAL NPP") + field(DO0, 1) + field(LNK0, "$(INSTR)$(NAME):MONITOR-CHANNEL PP") + field(SCAN, ".5 second") } ################################################################################ @@ -33,76 +43,3 @@ record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") ################################################################################ # Read all monitors values - -################################################################################ -# Gating Settings - -record(bo, "$(INSTR)$(NAME):GATE-1") -{ - field(DESC, "First Gating Channel") - field(ZNAM, "Disabled") - field(ONAM, "Enabled") - field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 1) $(ASYN_PORT)") -} - -record(bo, "$(INSTR)$(NAME):GATE-ON-1") -{ - field(DESC, "Count when first Gate high/low") - field(ZNAM, "Low") - field(ONAM, "High") - field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 1) $(ASYN_PORT)") -} - -record(bi, "$(INSTR)$(NAME):GATE-1_RBV") -{ - field(DESC, "First Gating Channel") - field(ZNAM, "Disabled") - field(ONAM, "Enabled") - field(DTYP, "stream") - field(INP, "@$(PROTO) getGateStatus($(INSTR)$(NAME):, 1) $(ASYN_PORT)") - field(SCAN, "2 second") -} - -record(bi, "$(INSTR)$(NAME):GATE-ON-1_RBV") -{ - field(DESC, "Count when first Gate high/low") - field(ZNAM, "Low") - field(ONAM, "High") -} - -record(bo, "$(INSTR)$(NAME):GATE-2") -{ - field(DESC, "First Gating Channel") - field(ZNAM, "Disabled") - field(ONAM, "Enabled") - field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 2) $(ASYN_PORT)") -} - -record(bo, "$(INSTR)$(NAME):GATE-ON-2") -{ - field(DESC, "Count when first Gate high/low") - field(ZNAM, "Low") - field(ONAM, "High") - field(DTYP, "stream") - field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, 2) $(ASYN_PORT)") -} - -record(bi, "$(INSTR)$(NAME):GATE-2_RBV") -{ - field(DESC, "Second Gating Channel") - field(ZNAM, "Disabled") - field(ONAM, "Enabled") - field(DTYP, "stream") - field(INP, "@$(PROTO) getGateStatus($(INSTR)$(NAME):, 2) $(ASYN_PORT)") - field(SCAN, "2 second") -} - -record(bi, "$(INSTR)$(NAME):GATE-ON-2_RBV") -{ - field(DESC, "Count when second Gate high/low") - field(ZNAM, "Low") - field(ONAM, "High") -} diff --git a/db/daq_common.db b/db/daq_common.db index 763aea3..f898bf1 100644 --- a/db/daq_common.db +++ b/db/daq_common.db @@ -167,7 +167,7 @@ record(bo,"$(INSTR)$(NAME):CONTINUE") field(FLNK, "$(INSTR)$(NAME):RAW-STATUS") } -record(bo, "$(INSTR)$(NAME):STOP") +record(longout, "$(INSTR)$(NAME):STOP") { field(DESC, "Stop the current counting operation") field(DTYP, "stream") @@ -179,7 +179,9 @@ record(ao,"$(INSTR)$(NAME):THRESHOLD") { field(DESC, "Minimum rate for counting to proceed") field(VAL, "0") # Rate - field(DRVL, "0.000001") # Minimum Rate + # Could perhaps still be improved. + # It seems to only accept whole counts? + field(DRVL, "1") # Minimum Rate field(DRVH, "100000") # Maximum Rate field(OMSL, "supervisory") field(OROC, "0") diff --git a/scripts/daq_2nd_gen.cmd b/scripts/daq_2nd_gen.cmd index cdcf852..25f576b 100644 --- a/scripts/daq_2nd_gen.cmd +++ b/scripts/daq_2nd_gen.cmd @@ -27,6 +27,9 @@ dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$ dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=9") dbLoadRecords("$(sinqDAQ_DB)channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=10") +dbLoadRecords("$(sinqDAQ_DB)gating_channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=1") +dbLoadRecords("$(sinqDAQ_DB)gating_channels.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNEL=2") + $(LOAD_TEST_PVS=#) $(LOAD_TEST_PVS) dbLoadRecords("$(sinqDAQ_DB)daq_2nd_gen_test.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") $(SET_SIM_MODE=#) $(SET_SIM_MODE) dbLoadRecords("$(sinqDAQ_DB)daq_simcontrol.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)") -- 2.49.0 From 65ad13d1142925465ac5f7d135b2e8f824d5425e Mon Sep 17 00:00:00 2001 From: Edward Wall Date: Tue, 17 Jun 2025 10:12:52 +0200 Subject: [PATCH 9/9] adds gating stuff, writes all thresholds simultaneously, updates readme with example --- README.md | 100 +++++++++++++++++++++++++++++++++++++++++ db/channels.db | 9 ++++ db/daq.proto | 2 +- db/daq_2nd_gen.db | 33 ++++++++++++++ db/daq_4ch.db | 13 ++++++ db/daq_8ch.db | 17 +++++++ db/daq_common.db | 5 +-- db/gating_channels.db | 102 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 db/gating_channels.db diff --git a/README.md b/README.md index c22f0aa..5a76d62 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_P | \$(INSTR)\$(NAME):ELAPSED-TIME | Time DAQ has been measuring for | | \$(INSTR)\$(NAME):M_ | Current count on channel. (1-10 depending on DAQ system) | | \$(INSTR)\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) | +| \$(INSTR)\$(NAME):GATE-_ | Configuration for Gating in newer hardware | ## Generating Test Signals @@ -71,6 +72,105 @@ runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_P See the file [daq\_2nd\_gen\_test.db](./db/daq_2nd_gen_test.db) +## Nicos Interface + +A set of Nicos devices have been developed which allow control of the Detector +Hardware via this Epics Driver. The corresponding code can be found in +[sinqdaq.py](https://gitea.psi.ch/lin-instrument-computers/Nicos/src/branch/release-3.12/nicos_sinq/devices/epics/sinqdaq.py). + +## Full Example + +Include the following snippet in your IOC + +``` +# st.cmd at SINQTEST + +epicsEnvSet("STREAM_PROTOCOL_PATH","./db") +epicsEnvSet("INSTR","SQ:SINQTEST:") + +require sinqDAQ +runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_PORT=2000" +``` + +What follows is an example Nicos setup file. The "channels" are created in the loop +at the bottom. + +``` +# DAQDetector.py +description = 'Devices for the detectors' + +countprefix = 'SQ:SINQTEST:DAQ' + +devices = dict( + ElapsedTime = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQTime', + daqpvprefix = countprefix, + ), + DAQPreset = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQPreset', + description = '2nd Generation Data Acquisition', + daqpvprefix = countprefix, + channels = [], + time_channel = ['ElapsedTime'], + ), + DAQV2 = device( + 'nicos_sinq.devices.epics.sinqdaq.SinqDetector', + description = 'Detector Interface', + timers = ['ElapsedTime'], + counters = [], + monitors = ['DAQPreset'], + images = [], + others = [], + liveinterval = 2, + saveintervals = [2] + ), + ThresholdChannel = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQMinThresholdChannel', + daqpvprefix = countprefix, + channels = [], + visibility = {'metadata', 'namespace'}, + ), + Threshold = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQMinThreshold', + daqpvprefix = countprefix, + min_rate_channel = 'ThresholdChannel', + visibility = {'metadata', 'namespace'}, + ), + Gate1 = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQGate', + daqpvprefix = countprefix, + channel = 1, + visibility = {'metadata', 'namespace'}, + ), + Gate2 = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQGate', + daqpvprefix = countprefix, + channel = 2, + visibility = {'metadata', 'namespace'}, + ), + TestGen = device('nicos_sinq.devices.epics.sinqdaq.DAQTestGen', + daqpvprefix = countprefix, + visibility = {'metadata', 'namespace'}, + ), +) + +for i in range(10): + devices[f'monitor{i+1}'] = device( + 'nicos_sinq.devices.epics.sinqdaq.DAQChannel', + description = f'Monitor {i + 1}', + daqpvprefix = countprefix, + channel = i + 1, + type = 'monitor', + ) + devices['DAQPreset'][1]['channels'].append(f'monitor{i+1}') + devices['ThresholdChannel'][1]['channels'].append(f'monitor{i+1}') + devices['DAQV2'][1]['monitors'].append(f'monitor{i+1}') + +startupcode = ''' +SetDetectors(DAQV2) +''' +``` + ## Simulation Simulation of the Hardware can be toggled on as follows: diff --git a/db/channels.db b/db/channels.db index c136ec8..48dae2a 100644 --- a/db/channels.db +++ b/db/channels.db @@ -48,6 +48,15 @@ record(longout, "$(INSTR)$(NAME):C$(CHANNEL)") field(FLNK, "$(INSTR)$(NAME):T$(CHANNEL)") } +record(ao,"$(INSTR)$(NAME):THRESH$(CHANNEL)") +{ + field(DESC, "Sets minimum rate for counting to proceed") + field(OMSL, "supervisory") + field(OROC, "0") + field(OUT, "@$(PROTO) setMinRate($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") + field(DTYP, "stream") +} + ################################################################################ # Read all monitors values diff --git a/db/daq.proto b/db/daq.proto index 4b4e2fb..6d5fbec 100644 --- a/db/daq.proto +++ b/db/daq.proto @@ -124,7 +124,7 @@ startWithTimePreset { } setMinRate{ - out "DL %(\$1THRESHOLD-MONITOR_RBV)d %.3f"; + out "DL \$2 %.3f"; in; @mismatch{in "%(\$1MsgTxt)s";} } diff --git a/db/daq_2nd_gen.db b/db/daq_2nd_gen.db index 2c06596..f5f2af9 100644 --- a/db/daq_2nd_gen.db +++ b/db/daq_2nd_gen.db @@ -41,5 +41,38 @@ record(seq, "$(INSTR)$(NAME):CORRECT-MONITOR-CHANNEL") ################################################################################ # Count Commands +# The hardware stores a separate threshold for each channel, which is somewhat +# unintuitive for the user, as only one can actually be made use of at a time. +# So, we just write the threshold value to all channels when it is changed. +record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F") +{ + field(OMSL, "supervisory") + field(SELM, "All") + field(OUTA, "$(INSTR)$(NAME):THRESHOLD-F1 PP") + field(OUTB, "$(INSTR)$(NAME):THRESHOLD-F2 PP") +} + +record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F1") +{ + field(OMSL, "supervisory") + field(SELM, "All") + field(OUTA, "$(INSTR)$(NAME):THRESH1 PP") + field(OUTB, "$(INSTR)$(NAME):THRESH2 PP") + field(OUTC, "$(INSTR)$(NAME):THRESH3 PP") + field(OUTD, "$(INSTR)$(NAME):THRESH4 PP") + field(OUTE, "$(INSTR)$(NAME):THRESH5 PP") + field(OUTF, "$(INSTR)$(NAME):THRESH6 PP") + field(OUTG, "$(INSTR)$(NAME):THRESH7 PP") + field(OUTH, "$(INSTR)$(NAME):THRESH8 PP") +} + +record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F2") +{ + field(OMSL, "supervisory") + field(SELM, "All") + field(OUTA, "$(INSTR)$(NAME):THRESH9 PP") + field(OUTB, "$(INSTR)$(NAME):THRESH10 PP") +} + ################################################################################ # Read all monitors values diff --git a/db/daq_4ch.db b/db/daq_4ch.db index 1e2c1ac..193a01a 100644 --- a/db/daq_4ch.db +++ b/db/daq_4ch.db @@ -28,5 +28,18 @@ record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") ################################################################################ # Count Commands +# The hardware stores a separate threshold for each channel, which is somewhat +# unintuitive for the user, as only one can actually be made use of at a time. +# So, we just write the threshold value to all channels when it is changed. +record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F") +{ + field(OMSL, "supervisory") + field(SELM, "All") + field(OUTA, "$(INSTR)$(NAME):THRESH1 PP") + field(OUTB, "$(INSTR)$(NAME):THRESH2 PP") + field(OUTC, "$(INSTR)$(NAME):THRESH3 PP") + field(OUTD, "$(INSTR)$(NAME):THRESH4 PP") +} + ################################################################################ # Read all monitors values diff --git a/db/daq_8ch.db b/db/daq_8ch.db index d1893b0..c770a7d 100644 --- a/db/daq_8ch.db +++ b/db/daq_8ch.db @@ -28,5 +28,22 @@ record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV") ################################################################################ # Count Commands +# The hardware stores a separate threshold for each channel, which is somewhat +# unintuitive for the user, as only one can actually be made use of at a time. +# So, we just write the threshold value to all channels when it is changed. +record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F") +{ + field(OMSL, "supervisory") + field(SELM, "All") + field(OUTA, "$(INSTR)$(NAME):THRESH1 PP") + field(OUTB, "$(INSTR)$(NAME):THRESH2 PP") + field(OUTC, "$(INSTR)$(NAME):THRESH3 PP") + field(OUTD, "$(INSTR)$(NAME):THRESH4 PP") + field(OUTE, "$(INSTR)$(NAME):THRESH5 PP") + field(OUTF, "$(INSTR)$(NAME):THRESH6 PP") + field(OUTG, "$(INSTR)$(NAME):THRESH7 PP") + field(OUTH, "$(INSTR)$(NAME):THRESH8 PP") +} + ################################################################################ # Read all monitors values diff --git a/db/daq_common.db b/db/daq_common.db index f898bf1..fa86c65 100644 --- a/db/daq_common.db +++ b/db/daq_common.db @@ -178,15 +178,14 @@ record(longout, "$(INSTR)$(NAME):STOP") record(ao,"$(INSTR)$(NAME):THRESHOLD") { field(DESC, "Minimum rate for counting to proceed") - field(VAL, "0") # Rate + field(VAL, "1") # Default Rate # Could perhaps still be improved. # It seems to only accept whole counts? field(DRVL, "1") # Minimum Rate field(DRVH, "100000") # Maximum Rate field(OMSL, "supervisory") field(OROC, "0") - field(OUT, "@$(PROTO) setMinRate($(INSTR)$(NAME):) $(ASYN_PORT)") - field(DTYP, "stream") + field(OUT, "$(INSTR)$(NAME):THRESHOLD-F PP") } record(ai,"$(INSTR)$(NAME):THRESHOLD_RBV") diff --git a/db/gating_channels.db b/db/gating_channels.db new file mode 100644 index 0000000..248e609 --- /dev/null +++ b/db/gating_channels.db @@ -0,0 +1,102 @@ +# EPICS Database for streamdevice specific to gating channels +# +# Macros +# INSTR - Prefix +# NAME - the device name, e.g. EL737 +# PROTO - Stream device protocol file +# ASYN_PORT - Low level Asyn IP Port to DAQ +# CHANNEL - the number associated with the measurment channel + +################################################################################ + +# Records for configuring gating settings +record(mbbo, "$(INSTR)$(NAME):GATE-$(CHANNEL)") +{ + field(DESC, "Sets the current gate state") + field(DTYP, "Soft Channel") + field(OUT, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SET PP") + field(ZRST, "Disabled") + field(ONST, "Trigger Low") + field(TWST, "Trigger High") +} + +record(dfanout, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SET") +{ + field(OUTA, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL.SELN PP") + field(OUTB, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL2.SELN PP") +} + +record(seq, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL") +{ + field(SELM, "Specified") + field(DO0, 0) + field(LNK0, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE PP") + field(DO1, 1) + field(LNK1, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE PP") + field(DO2, 1) + field(LNK2, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE PP") +} + +record(bo, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE") +{ + field(DESC, "Enable Gating Channel") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") +} + +record(seq, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL2") +{ + field(SELM, "Specified") + field(DO1, 0) + field(LNK1, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG PP") + field(DO2, 1) + field(LNK2, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG PP") +} + +record(bo, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG") +{ + field(DESC, "Set Count when first Gate high/low") + field(ZNAM, "Low") + field(ONAM, "High") + field(DTYP, "stream") + field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") +} + +# Records for reading configured gating settings +record(mbbi, "$(INSTR)$(NAME):GATE-$(CHANNEL)_RBV") +{ + field(DESC, "The current gate state") + field(ZRST, "Disabled") + field(ONST, "Trigger Low") + field(TWST, "Trigger High") +} + +record(calcout, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL_RBV") +{ + field(INPA, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE_RBV NPP") + field(INPB, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG_RBV NPP") + field(CALC, "A=0?0:B=0?1:2") + field(OOPT, "On Change") + field(OUT, "$(INSTR)$(NAME):GATE-$(CHANNEL)_RBV PP") + field(FLNK, "$(INSTR)$(NAME):GATE-$(CHANNEL)_RBV") +} + +record(bi, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE_RBV") +{ + field(DESC, "Is Gating Channel Enabled") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(DTYP, "stream") + field(INP, "@$(PROTO) getGateStatus($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)") + field(SCAN, "2 second") + field(FLNK, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL_RBV") +} + +record(bi, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG_RBV") +{ + field(DESC, "Count when first Gate high/low") + field(ZNAM, "Low") + field(ONAM, "High") +} -- 2.49.0