presets all managed on epics side, separates presets from starting #10

Open
wall_e wants to merge 8 commits from moving_more_logic_to_epics_cleanup into master
13 changed files with 795 additions and 268 deletions
+1
View File
@@ -13,6 +13,7 @@ REQUIRED+=stream
# DB files to include in the release
TEMPLATES += db/channels.db
TEMPLATES += db/time.db
TEMPLATES += db/gating_channels.db
TEMPLATES += db/daq_4ch.db
TEMPLATES += db/daq_8ch.db
+189 -60
View File
@@ -8,38 +8,206 @@
# CHANNEL - the number associated with the measurment channel
################################################################################
# Status Variables
# Channel Specific
# Trigger a change in status as clearing
record(bo, "$(INSTR)$(NAME):T$(CHANNEL)")
# Updated by READALL, at POLL_FREQ frequency
record(int64in, "$(INSTR)$(NAME):CH$(CHANNEL)")
{
field(DESC, "Trigger Clearing Status")
field(VAL, 1)
field(OUT, "$(INSTR)$(NAME):S$(CHANNEL) PP")
field(DESC, "DAQ CH$(CHANNEL) Counts")
field(EGU, "cts")
field(FLNK, "$(INSTR)$(NAME):CH$(CHANNEL)_POLL")
}
# Trigger a change in status as value returned to 0
record(seq, "$(INSTR)$(NAME):O$(CHANNEL)")
record(ai, "$(INSTR)$(NAME):CH$(CHANNEL)_RATE")
{
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")
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")
}
# Current Status of Channel, i.e. is it ready to count?
record(bi, "$(INSTR)$(NAME):S$(CHANNEL)")
record(ao, "$(INSTR)$(NAME):CH$(CHANNEL)_THRESH")
{
field(DESC, "Channel Status")
field(VAL, 0)
field(ZNAM, "OK")
field(ONAM, "CLEARING")
# Rate for this channel only applies, if
# $(INSTR)$(NAME):THRESHOLD-MONITOR == $(CHANNEL)
field(DESC, "Sets min rate for counting to proceed")
field(OMSL, "supervisory")
field(OROC, "0")
field(OUT, "@$(PROTO) setMinRate($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)")
field(DTYP, "stream")
field(EGU, "cts/sec")
}
################################################################################
# Count Commands
# Poll Loop
record(dfanout, "$(INSTR)$(NAME):CH$(CHANNEL)_POLL")
{
field(DESC, "Channel $(CHANNEL) poll sequence")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH$(CHANNEL)_HWCS.PROC")
field(OUTB, "$(INSTR)$(NAME):CH$(CHANNEL)_STS_RAW.PROC")
field(OUTC, "$(INSTR)$(NAME):CH$(CHANNEL)_REACHED.PROC")
}
################################################################################
# Clearing Channel Counts
record(bi, "$(INSTR)$(NAME):CH$(CHANNEL)_CLEARED")
{
field(DESC, "are hw counts being cleared")
field(VAL, 0)
field(ZNAM, "Cleared")
field(ONAM, "Clearing")
}
# Trigger a change in status as value returned to 0
record(seq, "$(INSTR)$(NAME):CH$(CHANNEL)_HWCS")
{
field(DESC, "Trigger returned to 0 status")
field(SELM, "Specified")
field(SELL, "$(INSTR)$(NAME):CH$(CHANNEL).VAL")
field(DO0, 0)
field(LNK0, "$(INSTR)$(NAME):CH$(CHANNEL)_CLEARED PP")
}
record(dfanout, "$(INSTR)$(NAME):CH$(CHANNEL)_CLEAR")
{
field(DESC, "Clears the current channel count")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH$(CHANNEL)_CLEARED PP PP")
field(OUTB, "$(INSTR)$(NAME):CH$(CHANNEL)_HWC.PROC PP")
}
record(longout, "$(INSTR)$(NAME):CH$(CHANNEL)_HWC")
{
field(DESC, "Clear in Hardware")
field(DTYP, "stream")
field(OMSL, "closed_loop")
field(DOL, "$(INSTR)$(NAME):CH$(CHANNEL)_BM NPP")
field(OUT, "@$(PROTO) clearChannel($(INSTR)$(NAME):) $(ASYN_PORT)")
}
################################################################################
# Determining Channel Status
record(calc, "$(INSTR)$(NAME):CH$(CHANNEL)_STS_RAW")
{
field(DESC, "Raw Channel Status")
field(INPA, "$(INSTR)$(NAME):STATUS NPP")
field(INPB, "$(INSTR)$(NAME):CH$(CHANNEL)_CLEARED NPP")
field(INPC, "$(INSTR)$(NAME):CH$(CHANNEL)_SET NPP")
field(CALC, "A == 1 || B || C")
field(FLNK, "$(INSTR)$(NAME):CH$(CHANNEL)_STS")
}
# Current Status of Channel, i.e. is it ready for a new operation?
record(mbbi, "$(INSTR)$(NAME):CH$(CHANNEL)_STS")
{
field(DESC, "Channel Status")
field(INP, "$(INSTR)$(NAME):CH$(CHANNEL)_STS_RAW NPP MS")
field(ZRVL, "0")
field(ZRST, "Idle")
field(ONVL, "1")
field(ONST, "Busy")
}
################################################################################
# Channel Preset
# If set, stop count once preset reached
record(int64in, "$(INSTR)$(NAME):CH$(CHANNEL)_PRESET")
{
field(DESC, "Monitor Count Preset")
field(VAL, 0)
field(FLNK, "$(INSTR)$(NAME):CH$(CHANNEL)_SETTING")
}
record(calcout, "$(INSTR)$(NAME):CH$(CHANNEL)_REACHED")
{
field(DESC, "Stop if preset reached")
field(INPA, "$(INSTR)$(NAME):CH$(CHANNEL) NPP")
field(INPB, "$(INSTR)$(NAME):CH$(CHANNEL)_PRESET NPP")
field(CALC, "B > 0 && A >= B")
field(OOPT, "When Non-zero")
field(OUT, "$(INSTR)$(NAME):STOP.PROC")
}
################################################################################
# Setting Channel Preset
record(bi, "$(INSTR)$(NAME):CH$(CHANNEL)_SET")
{
field(DESC, "is preset being configured")
field(VAL, 0)
field(ZNAM, "Set")
field(ONAM, "Setting")
}
record(calcout, "$(INSTR)$(NAME):CH$(CHANNEL)_CHECK_SET")
{
field(DESC, "Was preset fully configured")
field(SCAN, ".1 second")
field(INPA, "$(INSTR)$(NAME):CH$(CHANNEL)_SET NPP")
field(INPB, "$(INSTR)$(NAME):MONITOR-CHANNEL NPP")
field(INPC, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV NPP")
field(CALC, "A && ( ($(CHANNEL) # B) || (B = C) )")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "0")
# This is just a delay, as otherwise, Nicos will not see
# the $(INSTR)$(NAME):CH$(CHANNEL)_SET state change
# when not changing which monitor channel the preset
# applies to. Is there a better way?
field(ODLY, .5)
field(OUT, "$(INSTR)$(NAME):CH$(CHANNEL)_SET PP")
}
record(dfanout, "$(INSTR)$(NAME):CH$(CHANNEL)_SETTING")
{
field(DESC, "Trigger setting HW preset")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH$(CHANNEL)_SET PP")
field(OUTB, "$(INSTR)$(NAME):CH$(CHANNEL)_IN_HW.PROC PP")
}
record(calcout, "$(INSTR)$(NAME):CH$(CHANNEL)_IN_HW")
{
field(DESC, "Possible to configure in HW")
field(INPA, "$(INSTR)$(NAME):PRESET_TYPE NPP")
field(INPB, "$(INSTR)$(NAME):CH$(CHANNEL)_PRESET NPP")
field(INPC, "$(INSTR)$(NAME):MONITOR-CHANNEL.DRVH NPP")
field(CALC, "A=0 && B>0 && $(CHANNEL)<=C")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "1")
field(OUT, "$(INSTR)$(NAME):CH$(CHANNEL)_HW_CONF.PROC")
}
record(ao, "$(INSTR)$(NAME):CH$(CHANNEL)_HW_CONF")
{
field(DESC, "Configure in HW")
field(OMSL, "closed_loop")
field(DOL, $(CHANNEL))
field(OUT, "$(INSTR)$(NAME):MONITOR-CHANNEL PP")
field(FLNK, "$(INSTR)$(NAME):CH$(CHANNEL)_SET_PTYPE PP")
}
record(ao, "$(INSTR)$(NAME):CH$(CHANNEL)_SET_PTYPE")
{
field(OMSL, "closed_loop")
field(DOL, 2)
field(OUT, "$(INSTR)$(NAME):PRESET_TYPE PP")
}
################################################################################
# Unfortunately, clearing the channels is somewhat complicated as a result of
# the addition of more channels over time and minimal changes to the underlying interface
#
@@ -63,49 +231,10 @@ record(bi, "$(INSTR)$(NAME):S$(CHANNEL)")
# CC 5 setzt gleichzeitig die Zähler der Channels 1 und 3 zurück
# CC 16 ist gleichbedeutend wie CT (Timer zurücksetzen)
# CC 511 setzt gleichzeitig die Zähler aller Kanäle (auch des Timers) zurück.
record(calc, "$(INSTR)$(NAME):BM$(CHANNEL)")
record(calc, "$(INSTR)$(NAME):CH$(CHANNEL)_BM")
{
field(DESC, "Bit Mask for Channel")
field(INPA, $(CHANNEL))
field(CALC, "A > 4 ? 2 ^ A : 2 ^ (A-1)")
field(PINI, "YES")
}
record(longout, "$(INSTR)$(NAME):C$(CHANNEL)")
{
field(DESC, "Clear the current channel count")
field(DTYP, "stream")
field(OMSL, "closed_loop")
field(DOL, "$(INSTR)$(NAME):BM$(CHANNEL) NPP")
field(OUT, "@$(PROTO) clearChannel($(INSTR)$(NAME):) $(ASYN_PORT)")
field(FLNK, "$(INSTR)$(NAME):T$(CHANNEL)")
}
record(ao,"$(INSTR)$(NAME):THRESH$(CHANNEL)")
{
field(DESC, "Sets min 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
record(int64in, "$(INSTR)$(NAME):M$(CHANNEL)")
{
field(DESC, "DAQ CH$(CHANNEL)")
field(EGU, "cts")
field(FLNK, "$(INSTR)$(NAME):O$(CHANNEL)")
}
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")
}
+10 -10
View File
@@ -1,12 +1,12 @@
#
# SinqDAQ Protocol File
#
#
OutTerminator = CR;
InTerminator = CR;
ReadTimeout = 100;
WriteTimeout = 100;
ReplyTimeout = 1000;
LockTimeout = 500;
ReadTimeout = 100;
WriteTimeout = 100;
ReplyTimeout = 1000;
LockTimeout = 500;
initialise {
out "RMT 1"; # Turn on Remote Control
@@ -141,25 +141,25 @@ readRateMonitor{
readAll4 {
out "RA";
in "%(\$1ELAPSED-TIME)f %(\$1M1)d %(\$1M2)d %(\$1M3)d %(\$1M4)d";
in "%(\$1T)f %(\$1CH1)d %(\$1CH2)d %(\$1CH3)d %(\$1CH4)d";
@mismatch{in "%(\$1MsgTxt)s";}
}
readAll8 {
out "RA";
in "%(\$1ELAPSED-TIME)f %(\$1M1)d %(\$1M2)d %(\$1M3)d %(\$1M4)d %(\$1M5)d %(\$1M6)d %(\$1M7)d %(\$1M8)d";
in "%(\$1T)f %(\$1CH1)d %(\$1CH2)d %(\$1CH3)d %(\$1CH4)d %(\$1CH5)d %(\$1CH6)d %(\$1CH7)d %(\$1CH8)d";
@mismatch{in "%(\$1MsgTxt)s";}
}
readAll10 {
out "RA";
in "%(\$1ELAPSED-TIME)f %(\$1M1)d %(\$1M2)d %(\$1M3)d %(\$1M4)d %(\$1M5)d %(\$1M6)d %(\$1M7)d %(\$1M8)d";
in "%(\$1T)f %(\$1CH1)d %(\$1CH2)d %(\$1CH3)d %(\$1CH4)d %(\$1CH5)d %(\$1CH6)d %(\$1CH7)d %(\$1CH8)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";
in "%(\$1CH9)d";
out "RC 10";
in "%(\$1M10)d";
in "%(\$1CH10)d";
@mismatch{in "%(\$1MsgTxt)s";}
}
+112 -30
View File
@@ -12,7 +12,7 @@
record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL")
{
field(DESC, "PRESET-COUNT Monitors this channel")
field(DESC, "PRESET_COUNT Monitors this channel")
field(DRVL, "1") # Smallest Monitor Channel
field(DRVH, "$(CHANNELS)") # Largest Monitor Channel
field(DTYP, "stream")
@@ -22,15 +22,15 @@ record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL")
record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV")
{
field(DESC, "PRESET-COUNT Monitors this channel")
field(DESC, "PRESET_COUNT Monitors this channel")
field(DTYP, "stream")
field(INP, "@$(PROTO) readPresetMonitor($(INSTR)$(NAME):) $(ASYN_PORT)")
field(SCAN, "1 second")
field(FLNK, "$(INSTR)$(NAME):CORRECT-MONITOR-CHANNEL.PROC")
field(SCAN, ".5 second")
field(FLNK, "$(INSTR)$(NAME):CORRECT_MONITOR_CHANNEL.PROC")
}
# Force back to 1 if it is 0, as 0 has no meaning...
record(seq, "$(INSTR)$(NAME):CORRECT-MONITOR-CHANNEL")
record(seq, "$(INSTR)$(NAME):CORRECT_MONITOR_CHANNEL")
{
field(SELM, "Specified")
field(SELL, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV.VAL NPP")
@@ -38,41 +38,123 @@ record(seq, "$(INSTR)$(NAME):CORRECT-MONITOR-CHANNEL")
field(LNK0, "$(INSTR)$(NAME):MONITOR-CHANNEL PP")
}
################################################################################
# Count Commands
record(sel, "$(INSTR)$(NAME):CH_PRESET")
{
field(DESC, "Monitor threshold to actually use")
field(SELM, "Specified")
field(NVL, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV.VAL NPP")
# Skip A as it corresponds to 0
field(INPB, "$(INSTR)$(NAME):CH1_PRESET NPP")
field(INPC, "$(INSTR)$(NAME):CH2_PRESET NPP")
field(INPD, "$(INSTR)$(NAME):CH3_PRESET NPP")
field(INPE, "$(INSTR)$(NAME):CH4_PRESET NPP")
field(INPF, "$(INSTR)$(NAME):CH5_PRESET NPP")
field(INPG, "$(INSTR)$(NAME):CH6_PRESET NPP")
field(INPH, "$(INSTR)$(NAME):CH7_PRESET NPP")
field(INPI, "$(INSTR)$(NAME):CH8_PRESET NPP")
field(INPJ, "$(INSTR)$(NAME):CH9_PRESET NPP")
field(INPK, "$(INSTR)$(NAME):CH10_PRESET NPP")
}
record(dfanout,"$(INSTR)$(NAME):CH_PRESET_CLEAR")
{
field(DESC, "Clears all channel presets")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH_PRESET_CLEAR1.PROC")
field(OUTB, "$(INSTR)$(NAME):CH_PRESET_CLEAR2.PROC")
}
record(dfanout,"$(INSTR)$(NAME):CH_PRESET_CLEAR1")
{
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 0)
field(OUTA, "$(INSTR)$(NAME):CH1_PRESET PP")
field(OUTB, "$(INSTR)$(NAME):CH2_PRESET PP")
field(OUTC, "$(INSTR)$(NAME):CH3_PRESET PP")
field(OUTD, "$(INSTR)$(NAME):CH4_PRESET PP")
field(OUTE, "$(INSTR)$(NAME):CH5_PRESET PP")
field(OUTF, "$(INSTR)$(NAME):CH6_PRESET PP")
field(OUTG, "$(INSTR)$(NAME):CH7_PRESET PP")
field(OUTH, "$(INSTR)$(NAME):CH8_PRESET PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_PRESET_CLEAR2")
{
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 0)
field(OUTA, "$(INSTR)$(NAME):CH9_PRESET PP")
field(OUTB, "$(INSTR)$(NAME):CH10_PRESET PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_CLEAR")
{
field(DESC, "Clears all channel counts")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH_CLEAR1.PROC PP")
field(OUTB, "$(INSTR)$(NAME):CH_CLEAR2.PROC PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_CLEAR1")
{
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH1_CLEAR.PROC PP")
field(OUTB, "$(INSTR)$(NAME):CH2_CLEAR.PROC PP")
field(OUTC, "$(INSTR)$(NAME):CH3_CLEAR.PROC PP")
field(OUTD, "$(INSTR)$(NAME):CH4_CLEAR.PROC PP")
field(OUTE, "$(INSTR)$(NAME):CH5_CLEAR.PROC PP")
field(OUTF, "$(INSTR)$(NAME):CH6_CLEAR.PROC PP")
field(OUTG, "$(INSTR)$(NAME):CH7_CLEAR.PROC PP")
field(OUTH, "$(INSTR)$(NAME):CH8_CLEAR.PROC PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_CLEAR2")
{
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH9_CLEAR.PROC PP")
field(OUTB, "$(INSTR)$(NAME):CH10_CLEAR.PROC PP")
}
################################################################################
# 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")
record(dfanout,"$(INSTR)$(NAME):CH_THRESHOLD")
{
field(DESC, "Sets Channel Lowrate Thresholds")
field(OMSL, "supervisory")
field(SELM, "All")
field(OUTA, "$(INSTR)$(NAME):CH_THRESHOLD1 PP")
field(OUTB, "$(INSTR)$(NAME):CH_THRESHOLD2 PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_THRESHOLD1")
{
field(OMSL, "supervisory")
field(SELM, "All")
field(OUTA, "$(INSTR)$(NAME):THRESHOLD-F1 PP")
field(OUTB, "$(INSTR)$(NAME):THRESHOLD-F2 PP")
field(OUTA, "$(INSTR)$(NAME):CH1_THRESH PP")
field(OUTB, "$(INSTR)$(NAME):CH2_THRESH PP")
field(OUTC, "$(INSTR)$(NAME):CH3_THRESH PP")
field(OUTD, "$(INSTR)$(NAME):CH4_THRESH PP")
field(OUTE, "$(INSTR)$(NAME):CH5_THRESH PP")
field(OUTF, "$(INSTR)$(NAME):CH6_THRESH PP")
field(OUTG, "$(INSTR)$(NAME):CH7_THRESH PP")
field(OUTH, "$(INSTR)$(NAME):CH8_THRESH PP")
}
record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F1")
record(dfanout,"$(INSTR)$(NAME):CH_THRESHOLD2")
{
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")
field(OUTA, "$(INSTR)$(NAME):CH9_THRESH PP")
field(OUTB, "$(INSTR)$(NAME):CH10_THRESH 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
+41 -15
View File
@@ -11,7 +11,7 @@
record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL")
{
field(DESC, "PRESET-COUNT Monitors this channel")
field(DESC, "PRESET_COUNT Monitors this channel")
field(VAL, 1)
field(DRVL, 0) # Smallest Monitor Channel (should really be 1)
field(DRVH, 1) # Largest Monitor Channel
@@ -20,26 +20,52 @@ record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL")
record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV")
{
field(DESC, "PRESET-COUNT Monitors this channel")
field(DESC, "PRESET_COUNT Monitors this channel")
field(VAL, 1)
field(DISP, 1)
}
################################################################################
# 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")
record(ai, "$(INSTR)$(NAME):CH_PRESET")
{
field(OMSL, "supervisory")
field(DESC, "Monitor threshold to actually use")
field(INP, "$(INSTR)$(NAME):CH1_PRESET NPP")
}
record(dfanout,"$(INSTR)$(NAME):CH_PRESET_CLEAR")
{
field(DESC, "Clears all channel presets")
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(OMSL, "closed_loop")
field(DOL, 0)
field(OUTA, "$(INSTR)$(NAME):CH1_PRESET PP")
field(OUTB, "$(INSTR)$(NAME):CH2_PRESET PP")
field(OUTC, "$(INSTR)$(NAME):CH3_PRESET PP")
field(OUTD, "$(INSTR)$(NAME):CH4_PRESET PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_CLEAR")
{
field(DESC, "Clears all channel counts")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH1_CLEAR.PROC PP")
field(OUTB, "$(INSTR)$(NAME):CH2_CLEAR.PROC PP")
field(OUTC, "$(INSTR)$(NAME):CH3_CLEAR.PROC PP")
field(OUTD, "$(INSTR)$(NAME):CH4_CLEAR.PROC PP")
}
################################################################################
# Read all monitors values
# 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):CH_THRESHOLD")
{
field(DESC, "Sets Channel Lowrate Thresholds")
field(OMSL, "supervisory")
field(SELM, "All")
field(OUTA, "$(INSTR)$(NAME):CH1_THRESH PP")
field(OUTB, "$(INSTR)$(NAME):CH2_THRESH PP")
field(OUTC, "$(INSTR)$(NAME):CH3_THRESH PP")
field(OUTD, "$(INSTR)$(NAME):CH4_THRESH PP")
}
+53 -19
View File
@@ -11,7 +11,7 @@
record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL")
{
field(DESC, "PRESET-COUNT Monitors this channel")
field(DESC, "PRESET_COUNT Monitors this channel")
field(VAL, 1)
field(DRVL, 0) # Smallest Monitor Channel (should really be 1)
field(DRVH, 1) # Largest Monitor Channel
@@ -20,30 +20,64 @@ record(longout, "$(INSTR)$(NAME):MONITOR-CHANNEL")
record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV")
{
field(DESC, "PRESET-COUNT Monitors this channel")
field(DESC, "PRESET_COUNT Monitors this channel")
field(VAL, 1)
field(DISP, 1)
}
################################################################################
# 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")
record(ai, "$(INSTR)$(NAME):CH_PRESET")
{
field(OMSL, "supervisory")
field(DESC, "Monitor threshold to actually use")
field(INP, "$(INSTR)$(NAME):CH1_PRESET NPP")
}
record(dfanout,"$(INSTR)$(NAME):CH_PRESET_CLEAR")
{
field(DESC, "Clears all channel presets")
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")
field(OMSL, "closed_loop")
field(DOL, 0)
field(OUTA, "$(INSTR)$(NAME):CH1_PRESET PP")
field(OUTB, "$(INSTR)$(NAME):CH2_PRESET PP")
field(OUTC, "$(INSTR)$(NAME):CH3_PRESET PP")
field(OUTD, "$(INSTR)$(NAME):CH4_PRESET PP")
field(OUTE, "$(INSTR)$(NAME):CH5_PRESET PP")
field(OUTF, "$(INSTR)$(NAME):CH6_PRESET PP")
field(OUTG, "$(INSTR)$(NAME):CH7_PRESET PP")
field(OUTH, "$(INSTR)$(NAME):CH8_PRESET PP")
}
record(dfanout,"$(INSTR)$(NAME):CH_CLEAR")
{
field(DESC, "Clears all channel counts")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):CH1_CLEAR.PROC PP")
field(OUTB, "$(INSTR)$(NAME):CH2_CLEAR.PROC PP")
field(OUTC, "$(INSTR)$(NAME):CH3_CLEAR.PROC PP")
field(OUTD, "$(INSTR)$(NAME):CH4_CLEAR.PROC PP")
field(OUTE, "$(INSTR)$(NAME):CH5_CLEAR.PROC PP")
field(OUTF, "$(INSTR)$(NAME):CH6_CLEAR.PROC PP")
field(OUTG, "$(INSTR)$(NAME):CH7_CLEAR.PROC PP")
field(OUTH, "$(INSTR)$(NAME):CH8_CLEAR.PROC PP")
}
################################################################################
# Read all monitors values
# 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):CH_THRESHOLD")
{
field(DESC, "Sets Channel Lowrate Thresholds")
field(OMSL, "supervisory")
field(SELM, "All")
field(OUTA, "$(INSTR)$(NAME):CH1_THRESH PP")
field(OUTB, "$(INSTR)$(NAME):CH2_THRESH PP")
field(OUTC, "$(INSTR)$(NAME):CH3_THRESH PP")
field(OUTD, "$(INSTR)$(NAME):CH4_THRESH PP")
field(OUTE, "$(INSTR)$(NAME):CH5_THRESH PP")
field(OUTF, "$(INSTR)$(NAME):CH6_THRESH PP")
field(OUTG, "$(INSTR)$(NAME):CH7_THRESH PP")
field(OUTH, "$(INSTR)$(NAME):CH8_THRESH PP")
}
+231 -119
View File
@@ -5,6 +5,10 @@
# NAME - the device name, e.g. EL737
# PROTO - Stream device protocol file
# ASYN_PORT - Low level Asyn IP Port to EL737
# POLL_FREQ - Scan string defining main status-loop polling frequency (default .5 second)
################################################################################
# Hardware Initialisation
# Send initial initialisation commands
record(bo, "$(INSTR)$(NAME):INIT-CONF")
@@ -22,14 +26,22 @@ record(longout, "$(INSTR)$(NAME):FULL-RESET")
field(DTYP, "stream")
}
################################################################################
# Status Variables
record(stringin, "$(INSTR)$(NAME):MsgTxt")
record(dfanout, "$(INSTR)$(NAME):RESET")
{
field(DESC, "Unexpected received response")
field(DTYP, "devDAQStringError")
field(FLNK, "$(INSTR)$(NAME):INVALID-CONFIG")
field(DESC, "Reset internal state")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, "0")
# Internal Count Timer
field(OUTA, "$(INSTR)$(NAME):WAIT_HW PP")
# Time Preset
# field(OUTB, "$(INSTR)$(NAME):T_PRESET PP")
# field(OUTC, "$(INSTR)$(NAME):T_CLEARED PP")
# Monitor Presets
# field(OUTD, "$(INSTR)$(NAME):CH_PRESET_CLEAR PP")
# field(OUTE, "$(INSTR)$(NAME):RESET_MT PP")
# HW Preset Type
# field(OUTF, "$(INSTR)$(NAME):PRESET_TYPE PP")
}
# We want to recognise the invalid config error message, so that we can rerun
@@ -51,37 +63,52 @@ record(seq, "$(INSTR)$(NAME):REINIT-CONF")
field(SELL, "$(INSTR)$(NAME):INVALID-CONFIG.VAL")
}
# 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.
#
# The status can be interpreted as follows
#
# Bit 0: NC_STAT_P_TIME_C
# Bit 1: NC_STAT_P_COUNT_C
# Bit 2: NC_STAT_RATE_OK_C It appears this should be ignored unless counting
# Bit 3: NC_STAT_PAUSE_C
#
record(mbbiDirect, "$(INSTR)$(NAME):RAW-STATUS")
################################################################################
# Hardware Box Specific
record(longin, "$(INSTR)$(NAME):CHANNELS")
{
field(DESC, "Raw returned status value")
field(DTYP, "stream")
field(SCAN, ".5 second")
field(INP, "@$(PROTO) readStatus($(INSTR)$(NAME):) $(ASYN_PORT)")
field(FLNK, "$(INSTR)$(NAME):READALL")
field(DESC, "Total Supported Channels")
field(VAL, $(CHANNELS))
field(DISP, 1)
}
record(mbbi, "$(INSTR)$(NAME):PRESET_TYPE")
{
field(DESC, "Type of Hardware Preset")
field(ZRVL, "0")
field(ZRST, "Unset")
field(ONVL, "1")
field(ONST, "Time")
field(TWVL, "2")
field(TWST, "Monitor")
}
record(longin, "$(INSTR)$(NAME):WAIT_HW")
{
field(DESC, "Internal Sent Start Count")
}
record(stringin, "$(INSTR)$(NAME):MsgTxt")
{
field(DESC, "Unexpected received response")
field(DTYP, "devDAQStringError")
field(FLNK, "$(INSTR)$(NAME):INVALID-CONFIG")
}
################################################################################
# System Status
record(bi, "$(INSTR)$(NAME):COUNTING_TIME")
{
field(INP, "$(INSTR)$(NAME):RAW-STATUS.B0 NPP MS")
field(INP, "$(INSTR)$(NAME):RAW_STATUS.B0 NPP MS")
field(ZNAM, "DISABLED")
field(ONAM, "COUNTING")
}
record(bi, "$(INSTR)$(NAME):COUNTING_PRESET")
{
field(INP, "$(INSTR)$(NAME):RAW-STATUS.B1 NPP MS")
field(INP, "$(INSTR)$(NAME):RAW_STATUS.B1 NPP MS")
field(ZNAM, "DISABLED")
field(ONAM, "COUNTING")
}
@@ -89,7 +116,7 @@ record(bi, "$(INSTR)$(NAME):COUNTING_PRESET")
record(calc, "$(INSTR)$(NAME):RATE_MAP")
{
field(DESC, "This bit is not consistent across DAQs")
field(INPA, "$(INSTR)$(NAME):RAW-STATUS.B2 NPP MS")
field(INPA, "$(INSTR)$(NAME):RAW_STATUS.B2 NPP MS")
field(CALC, "(A=$(RATE_OKAY_BIT))?0:1")
}
@@ -102,28 +129,15 @@ record(bi, "$(INSTR)$(NAME):IS_LOWRATE")
record(bi, "$(INSTR)$(NAME):IS_PAUSED")
{
field(INP, "$(INSTR)$(NAME):RAW-STATUS.B3 NPP MS")
field(INP, "$(INSTR)$(NAME):RAW_STATUS.B3 NPP MS")
field(ZNAM, "RUNNING")
field(ONAM, "PAUSED")
}
record(calc, "$(INSTR)$(NAME):MAP-STATUS")
{
field(DESC, "Maps Raw Status to State")
field(INPA, "$(INSTR)$(NAME):INVALID-CONFIG NPP MS")
field(INPB, "$(INSTR)$(NAME):RAW-STATUS.UDF NPP MS") # should also be invalid if can't read the status
field(INPC, "$(INSTR)$(NAME):COUNTING_TIME PP MS")
field(INPD, "$(INSTR)$(NAME):COUNTING_PRESET PP MS")
field(INPE, "$(INSTR)$(NAME):IS_LOWRATE PP MS")
field(INPF, "$(INSTR)$(NAME):IS_PAUSED PP MS")
field(CALC, "(A=1||B=1)?4:(F=1)?3:(C=0&&D=0)?0:(E=1)?2:1")
field(FLNK, "$(INSTR)$(NAME):STATUS")
}
record(mbbi, "$(INSTR)$(NAME):STATUS")
{
field(DESC, "DAQ Status")
field(INP, "$(INSTR)$(NAME):MAP-STATUS NPP MS")
field(INP, "$(INSTR)$(NAME):MAP_STATUS NPP MS")
field(ZRVL, "0")
field(ZRST, "Idle")
field(ONVL, "1")
@@ -137,62 +151,18 @@ record(mbbi, "$(INSTR)$(NAME):STATUS")
field(FRST, "INVALID")
}
record(longin, "$(INSTR)$(NAME):CHANNELS")
{
field(DESC, "Total Supported Channels")
field(VAL, $(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
# HW Commands
record(ao,"$(INSTR)$(NAME):PRESET-COUNT")
record(dfanout,"$(INSTR)$(NAME):START")
{
field(DESC, "Count until preset reached")
field(DTYP, "stream")
field(OUT, "@$(PROTO) startWithCountPreset$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)")
field(VAL, 0)
field(PREC, 2)
field(FLNK, "$(INSTR)$(NAME):RAW-STATUS")
}
record(ao,"$(INSTR)$(NAME):PRESET-TIME")
{
field(DESC, "Count for specified time")
field(DTYP, "stream")
field(OUT, "@$(PROTO) startWithTimePreset$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)")
field(VAL, 0)
field(PREC, 2)
field(EGU, "seconds")
field(FLNK, "$(INSTR)$(NAME):RAW-STATUS")
field(DESC, "clear, then trigger count")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):T_HWC.PROC PP")
field(OUTB, "$(INSTR)$(NAME):CH_CLEAR.PROC PP")
field(FLNK, "$(INSTR)$(NAME):TRIGGER")
}
record(bo,"$(INSTR)$(NAME):PAUSE")
@@ -201,7 +171,7 @@ record(bo,"$(INSTR)$(NAME):PAUSE")
field(DTYP, "stream")
field(OUT, "@$(PROTO) pauseCount($(INSTR)$(NAME):) $(ASYN_PORT)")
field(VAL, "0")
field(FLNK, "$(INSTR)$(NAME):RAW-STATUS")
field(FLNK, "$(INSTR)$(NAME):HW_POLL_SEQ")
}
record(bo,"$(INSTR)$(NAME):CONTINUE")
@@ -210,7 +180,7 @@ record(bo,"$(INSTR)$(NAME):CONTINUE")
field(DTYP, "stream")
field(OUT, "@$(PROTO) continueCount($(INSTR)$(NAME):) $(ASYN_PORT)")
field(VAL, "0")
field(FLNK, "$(INSTR)$(NAME):RAW-STATUS")
field(FLNK, "$(INSTR)$(NAME):HW_POLL_SEQ")
}
record(longout, "$(INSTR)$(NAME):STOP")
@@ -218,9 +188,167 @@ record(longout, "$(INSTR)$(NAME):STOP")
field(DESC, "Stop the current counting operation")
field(DTYP, "stream")
field(OUT, "@$(PROTO) stopCount($(INSTR)$(NAME):) $(ASYN_PORT)")
field(FLNK, "$(INSTR)$(NAME):RAW-STATUS")
field(FLNK, "$(INSTR)$(NAME):HW_POLL_SEQ")
}
################################################################################
# Poll Loop
record(bo, "$(INSTR)$(NAME):HW_POLL")
{
field(OMSL, "closed_loop")
field(DOL, 1)
field(SCAN, "$(POLL_FREQ=.5 second)")
field(OUT, "$(INSTR)$(NAME):HW_POLL_SEQ.PROC")
}
record(dfanout, "$(INSTR)$(NAME):HW_POLL_SEQ")
{
field(DESC, "Time channel poll sequence")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
# This order is important, to ensure that the status
# can't change whichout having first updated the time
# and count records to their final values
field(OUTA, "$(INSTR)$(NAME):RAW_STATUS.PROC")
field(OUTB, "$(INSTR)$(NAME):READALL.PROC")
field(OUTC, "$(INSTR)$(NAME):MAP_STATUS.PROC")
field(OUTD, "$(INSTR)$(NAME):STATUS.PROC")
field(OUTE, "$(INSTR)$(NAME):PRESET_TYPE_CLEAR.PROC")
field(OUTF, "$(INSTR)$(NAME):T_PRESET_CLEAR.PROC")
field(OUTG, "$(INSTR)$(NAME):PRESET_CLEAR.PROC")
field(OUTH, "$(INSTR)$(NAME):CLEAR_WAIT_HW.PROC")
}
# The status can be interpreted as follows
#
# Bit 0: NC_STAT_P_TIME_C
# Bit 1: NC_STAT_P_COUNT_C
# Bit 2: NC_STAT_RATE_OK_C It appears this should be ignored unless counting
# Bit 3: NC_STAT_PAUSE_C
#
record(mbbiDirect, "$(INSTR)$(NAME):RAW_STATUS")
{
field(DESC, "Raw returned status value")
field(DTYP, "stream")
field(INP, "@$(PROTO) readStatus($(INSTR)$(NAME):) $(ASYN_PORT)")
}
record(calc, "$(INSTR)$(NAME):MAP_STATUS")
{
field(DESC, "Maps Raw Status to State")
field(INPA, "$(INSTR)$(NAME):INVALID-CONFIG NPP MS")
field(INPB, "$(INSTR)$(NAME):RAW_STATUS.UDF NPP MS") # should also be invalid if can't read the status
field(INPC, "$(INSTR)$(NAME):COUNTING_TIME PP MS")
field(INPD, "$(INSTR)$(NAME):COUNTING_PRESET PP MS")
field(INPE, "$(INSTR)$(NAME):IS_LOWRATE PP MS")
field(INPF, "$(INSTR)$(NAME):IS_PAUSED PP MS")
field(INPG, "$(INSTR)$(NAME):WAIT_HW NPP MS")
field(CALC, "(A=1||B=1)?4:(F=1)?3:(C=0&&D=0&&G<=0)?0:(E=1)?2:1")
}
record(calcout, "$(INSTR)$(NAME):PRESET_TYPE_CLEAR")
{
field(INPA, "$(INSTR)$(NAME):STATUS NPP")
field(CALC, "A")
field(OOPT, "Transition To Zero")
field(DOPT, "Use OCAL")
field(OCAL, "0")
field(OUT, "$(INSTR)$(NAME):PRESET_TYPE PP")
}
record(calcout, "$(INSTR)$(NAME):T_PRESET_CLEAR")
{
field(INPA, "$(INSTR)$(NAME):STATUS NPP")
field(CALC, "A")
field(OOPT, "Transition To Zero")
field(DOPT, "Use OCAL")
field(OCAL, "0")
field(OUT, "$(INSTR)$(NAME):T_PRESET PP")
}
record(calcout, "$(INSTR)$(NAME):PRESET_CLEAR")
{
field(INPA, "$(INSTR)$(NAME):STATUS NPP")
field(CALC, "A")
field(OOPT, "Transition To Zero")
field(DOPT, "Use OCAL")
field(OCAL, "0")
field(OUT, "$(INSTR)$(NAME):CH_PRESET_CLEAR PP")
}
record(calcout, "$(INSTR)$(NAME):CLEAR_WAIT_HW")
{
field(INPA, "$(INSTR)$(NAME):WAIT_HW NPP")
field(INPB, "$(INSTR)$(NAME):COUNTING_TIME NPP MS")
field(INPC, "$(INSTR)$(NAME):COUNTING_PRESET NPP MS")
field(CALC, "A")
field(DOPT, "Use OCAL")
field(OCAL, "(B||C)?0:A-1")
field(OOPT, "When Non-zero")
field(OUT, "$(INSTR)$(NAME):WAIT_HW PP")
}
################################################################################
# Count Startup
record(seq,"$(INSTR)$(NAME):TRIGGER")
{
field(DESC, "Start count according to PRESET_TYPE")
field(SELM, "Specified")
field(SELL, "$(INSTR)$(NAME):PRESET_TYPE NPP")
field(DO0, 1)
field(LNK0, "$(INSTR)$(NAME):PRESET_SOFT.PROC")
field(DO1, 1)
field(LNK1, "$(INSTR)$(NAME):PRESET_TIME.PROC")
field(DO2, 1)
field(LNK2, "$(INSTR)$(NAME):PRESET_COUNT.PROC")
field(FLNK, "$(INSTR)$(NAME):SET_WAIT_HW")
}
record(ao, "$(INSTR)$(NAME):PRESET_SOFT")
{
field(DESC, "Count forever :)")
field(OMSL, "closed_loop")
field(DOL, "15768000") # Half a year :)
field(OUT, "$(INSTR)$(NAME):T_PRESET")
field(FLNK, "$(INSTR)$(NAME):PRESET_TIME")
}
record(ao,"$(INSTR)$(NAME):PRESET_TIME")
{
field(DESC, "Count for specified time")
field(DTYP, "stream")
field(OMSL, "closed_loop")
field(DOL, "$(INSTR)$(NAME):T_PRESET NPP")
field(OUT, "@$(PROTO) startWithTimePreset$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)")
field(PREC, 2)
field(EGU, "seconds")
field(FLNK, "$(INSTR)$(NAME):HW_POLL_SEQ")
}
record(ao,"$(INSTR)$(NAME):PRESET_COUNT")
{
field(DESC, "Count until preset reached")
field(DTYP, "stream")
field(OMSL, "closed_loop")
field(DOL, "$(INSTR)$(NAME):CH_PRESET PP")
field(OUT, "@$(PROTO) startWithCountPreset$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)")
field(PREC, 0)
field(FLNK, "$(INSTR)$(NAME):HW_POLL_SEQ")
}
record(longout, "$(INSTR)$(NAME):SET_WAIT_HW")
{
field(OMSL, "closed_loop")
field(DOL, 5)
field(OUT, "$(INSTR)$(NAME):WAIT_HW PP")
}
################################################################################
# Hardware Lowrate Threshold
record(ao,"$(INSTR)$(NAME):THRESHOLD")
{
field(DESC, "Minimum rate for counting to proceed")
@@ -231,7 +359,7 @@ record(ao,"$(INSTR)$(NAME):THRESHOLD")
field(DRVH, "100000") # Maximum Rate
field(OMSL, "supervisory")
field(OROC, "0")
field(OUT, "$(INSTR)$(NAME):THRESHOLD-F PP")
field(OUT, "$(INSTR)$(NAME):CH_THRESHOLD PP")
}
record(ai,"$(INSTR)$(NAME):THRESHOLD_RBV")
@@ -260,26 +388,18 @@ record(longin,"$(INSTR)$(NAME):THRESHOLD-MONITOR_RBV")
field(DTYP, "stream")
field(SCAN, "1 second")
field(EGU, "CH")
field(FLNK, "$(INSTR)$(NAME):THRESHOLD-MONITOR-FLNK")
field(FLNK, "$(INSTR)$(NAME):THR_MONITOR_PROCESS")
}
record(calcout, "$(INSTR)$(NAME):THRESHOLD-MONITOR-FLNK")
record(calcout, "$(INSTR)$(NAME):THR_MONITOR_PROCESS")
{
field(DESC, "Only process Threshold when Non-Zero")
field(CALC, "A")
field(INPA, "$(INSTR)$(NAME):THRESHOLD-MONITOR_RBV")
field(CALC, "A")
field(OOPT, "When Non-zero")
field(OUT, "$(INSTR)$(NAME):THRESHOLD_RBV.PROC PP")
}
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")
}
################################################################################
# Read all monitors values
@@ -288,12 +408,4 @@ record(ai, "$(INSTR)$(NAME):READALL")
field(DESC, "Reads monitors and elapsed time")
field(INP, "@$(PROTO) readAll$(CHANNELS)($(INSTR)$(NAME):) $(ASYN_PORT)")
field(DTYP, "stream")
field(FLNK, "$(INSTR)$(NAME):MAP-STATUS")
}
record(ai,"$(INSTR)$(NAME):ELAPSED-TIME")
{
field(DESC, "DAQ Measured Time")
field(EGU, "sec")
field(FLNK, "$(INSTR)$(NAME):ETO")
}
+132
View File
@@ -0,0 +1,132 @@
# EPICS Database for streamdevice specific to time channel
#
# Macros
# INSTR - Prefix
# NAME - the device name, e.g. EL737
# PROTO - Stream device protocol file
# ASYN_PORT - Low level Asyn IP Port to DAQ
################################################################################
# Time Channel Specific
# Updated by READALL, at POLL_FREQ frequency
record(ai,"$(INSTR)$(NAME):T")
{
field(DESC, "DAQ Measured Time")
field(EGU, "sec")
field(FLNK, "$(INSTR)$(NAME):T_POLL")
}
################################################################################
# Poll Loop
record(dfanout, "$(INSTR)$(NAME):T_POLL")
{
field(DESC, "Time channel poll sequence")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):T_HWCS.PROC")
field(OUTB, "$(INSTR)$(NAME):T_STS_RAW.PROC")
field(OUTC, "$(INSTR)$(NAME):TIME_REACHED.PROC")
}
################################################################################
# Clearing Time
# Current Status of Channel, i.e. is it ready to count?
record(bi, "$(INSTR)$(NAME):T_CLEARED")
{
field(DESC, "is hw time being cleared")
field(VAL, 0)
field(ZNAM, "Cleared")
field(ONAM, "Clearing")
}
# Trigger a change in status as value returned to 0
record(seq, "$(INSTR)$(NAME):T_HWCS")
{
field(DESC, "Trigger returned to 0 status")
field(LNK0, "$(INSTR)$(NAME):T_CLEARED PP")
field(DO0, 0)
field(SELM, "Specified")
field(SELL, "$(INSTR)$(NAME):T.VAL")
}
# Trigger a change in status as clearing
record(dfanout, "$(INSTR)$(NAME):T_CLEAR")
{
field(DESC, "Clears the time channel count")
field(SELM, "All")
field(OMSL, "closed_loop")
field(DOL, 1)
field(OUTA, "$(INSTR)$(NAME):T_CLEARED PP")
field(OUTB, "$(INSTR)$(NAME):T_HWC.PROC PP")
}
record(longout, "$(INSTR)$(NAME):T_HWC")
{
field(DESC, "Clear in Hardware")
field(DTYP, "stream")
field(OMSL, "closed_loop")
field(DOL, "1")
field(OUT, "@$(PROTO) clearTimer($(INSTR)$(NAME):) $(ASYN_PORT)")
}
################################################################################
# Determining Time Channel Status
record(calc, "$(INSTR)$(NAME):T_STS_RAW")
{
field(DESC, "Raw time channel status")
field(INPA, "$(INSTR)$(NAME):STATUS NPP MS")
field(INPB, "$(INSTR)$(NAME):T_CLEARED NPP")
field(CALC, "A == 1 || B")
field(FLNK, "$(INSTR)$(NAME):T_STS")
}
# Current Status of Channel, i.e. is it ready for a new operation?
record(mbbi, "$(INSTR)$(NAME):T_STS")
{
field(DESC, "Time channel status")
field(INP, "$(INSTR)$(NAME):T_STS_RAW NPP MS")
field(ZRVL, "0")
field(ZRST, "Idle")
field(ONVL, "1")
field(ONST, "Busy")
}
################################################################################
# Time Channel Preset
# If set, stop count once preset reached
record(int64in, "$(INSTR)$(NAME):T_PRESET")
{
field(DESC, "Time Preset")
field(VAL, 0)
field(FLNK, "$(INSTR)$(NAME):TIME_SET_PTYPE")
}
record(calcout, "$(INSTR)$(NAME):TIME_REACHED")
{
field(DESC, "Stop if preset reached")
field(INPA, "$(INSTR)$(NAME):T NPP")
field(INPB, "$(INSTR)$(NAME):T_PRESET NPP")
field(CALC, "B > 0 && A >= B")
field(OOPT, "When Non-zero")
field(OUT, "$(INSTR)$(NAME):STOP.PROC")
}
################################################################################
# Setting Time Channel Preset
record(calcout, "$(INSTR)$(NAME):TIME_SET_PTYPE")
{
field(INPA, "$(INSTR)$(NAME):PRESET_TYPE NPP")
field(INPB, "$(INSTR)$(NAME):T_PRESET NPP")
field(CALC, "A=0 && B>0")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "1")
field(OUT, "$(INSTR)$(NAME):PRESET_TYPE PP")
}
+2
View File
@@ -15,6 +15,8 @@ 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, RATE_OKAY_BIT=$(RATE_OKAY_BIT=0)")
dbLoadRecords("$(sinqDAQ_DB)daq_2nd_gen.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME), CHANNELS=10")
dbLoadRecords("$(sinqDAQ_DB)time.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")
+2
View File
@@ -15,6 +15,8 @@ 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, RATE_OKAY_BIT=$(RATE_OKAY_BIT=0)")
dbLoadRecords("$(sinqDAQ_DB)daq_4ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)")
dbLoadRecords("$(sinqDAQ_DB)time.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")
+2
View File
@@ -15,6 +15,8 @@ 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, RATE_OKAY_BIT=$(RATE_OKAY_BIT=0)")
dbLoadRecords("$(sinqDAQ_DB)daq_8ch.db", "INSTR=$(INSTR), NAME=$(NAME), PROTO=$(PROTO), ASYN_PORT=ASYN_$(NAME)")
dbLoadRecords("$(sinqDAQ_DB)time.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")
+3 -3
View File
@@ -134,7 +134,7 @@ class DAQ:
if self.getMonitorCount() >= self.presetcount:
self.counts[self.monitor] = self.presetcount if self.presetcount > 0 else self.counts[self.monitor]
self.status = 0
self.status = 0
else:
raise Exception("Invalid State")
@@ -191,7 +191,7 @@ class DAQ:
def setGate(self, channel, highlow):
self.gate[channel - 1] = highlow
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
@@ -216,7 +216,7 @@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
received = ''
logger.info(f'RECEIVED: "{received}"')
return received
daq = DAQ(TOTAL_CH)
while True:
+17 -12
View File
@@ -42,31 +42,36 @@ def get_piped_output(proc):
def getState(instr, name):
result = run(['caget', f'{instr}{name}:STATUS'], stdout=PIPE)
state = result.stdout.decode('ascii').rstrip().split()[1]
state = result.stdout.decode('ascii').rstrip().split()[1]
print(f'Currently in state {state}')
return state
def getCount(instr, name, ch):
result = run(['caget', f'{instr}{name}:M{ch}'], stdout=PIPE)
result = run(['caget', f'{instr}{name}:CH{ch}'], stdout=PIPE)
count = int(result.stdout.decode('ascii').rstrip().split()[1])
print(f'M{ch} == {count}')
print(f'CH{ch} == {count}')
return count
def presetTime(instr, name, time):
print(f'Starting count for {time} seconds')
run(['caput', f'{instr}{name}:PRESET-TIME', f'{time}'])
print(f'Setting preset on time channel of {time} seconds')
run(['caput', f'{instr}{name}:T_PRESET', f'{time}'])
def presetCount(instr, name, count):
print(f'Starting count until channel 1 reaches {count}')
run(['caput', f'{instr}{name}:PRESET-COUNT', f'{count}'])
def presetCount(instr, name, channel, count):
print(f'Setting preset on channel {channel} of {count} counts')
run(['caput', f'{instr}{name}:CH{channel}_PRESET', f'{count}'])
def startCount(instr, name):
print('Starting Count')
run(['caput', f'{instr}{name}:START', '1'])
def testCanCount(instr, name):
# Check in Idle State
assert getState(instr, name) == 'Idle', 'Not in valid state'
# Start Time Based Count and Check that Status Changes
assert getCount(instr, name, 1) == 0, "Erroneous nonzero starting count value"
presetTime(instr, name, 5)
startCount(instr, name)
time.sleep(1)
assert getState(instr, name) == 'Counting', 'Didn\'t start counting'
time.sleep(5)
@@ -74,8 +79,10 @@ def testCanCount(instr, name):
assert getCount(instr, name, 1) > 0, 'No events were counted'
# Start Monitor Based Count and Check that Status Changes
presetChannel = 1
presetAmount = 100
presetCount(instr, name, presetAmount)
presetCount(instr, name, presetChannel, presetAmount)
startCount(instr, name)
time.sleep(1)
assert getState(instr, name) == 'Counting', 'Didn\'t start counting'
assert getCount(instr, name, 1) < presetAmount
@@ -99,8 +106,6 @@ def test(instr, name):
if 'iocRun: All initialization complete' in line:
break # IOC is now running
#time.sleep(20)
print("IOC Initialisation Complete")
print("Starting Tests")