diff --git a/Makefile b/Makefile index 926b6f1..8e7762c 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ TEMPLATES += db/daq_2nd_gen.db TEMPLATES += db/daq_2nd_gen_test.db TEMPLATES += db/daq.proto TEMPLATES += db/daq_soft_proton.db +TEMPLATES += db/sim_proton_current.db # Just for simulation TEMPLATES += db/daq_simcontrol.db @@ -35,6 +36,7 @@ SOURCES += src/daq_soft_proton.c SCRIPTS += scripts/daq_4ch.cmd SCRIPTS += scripts/daq_8ch.cmd SCRIPTS += scripts/daq_2nd_gen.cmd +SCRIPTS += scripts/daq_soft_proton.cmd SCRIPTS += sim/daq_sim.py CXXFLAGS += -std=c++17 diff --git a/README.md b/README.md index 8d6daeb..6170e29 100644 --- a/README.md +++ b/README.md @@ -299,3 +299,17 @@ require based module system. You might have to change the specified version in the [test/st.cmd](test/st.cmd) file to the version you compiled and want to test. + +## Software based proton current DAQ +This repository also contain a software based DAQ implementation that just +requires a channel access link (remote Process Variable) to a proton rate. +From that it implements the same interface as the counter boxes, and is +compatible with the sinqdaq device in Nicos, albeit with only one channel. + +### Simulated software based proton current DAQ +You can start a proton current DAQ based on a simulation with the following +command on any PC having the SINQ epics environment installed. +``` +iocsh -r sinqDAQ,0.4.0 -c 'epicsEnvSet(SET_SIM_MODE,"" )' -c 'epicsEnvSet(INSTR,SQ:TEST:)' -c 'epicsEnvSet(NAME, SPC)' -c 'runScript($(sinqDAQ_DIR)daq_soft_proton.cmd' +``` + diff --git a/db/daq_soft_proton.db b/db/daq_soft_proton.db index 77d11a5..e89addc 100644 --- a/db/daq_soft_proton.db +++ b/db/daq_soft_proton.db @@ -235,16 +235,18 @@ record(aSub, "$(INSTR)$(NAME):EMULATION") field(FTC, "DOUBLE") field(INPD, "$(INSTR)$(NAME):COMMAND-TRIG") field(FTD, "ULONG") - field(INPE, "$(INSTR)$(NAME):THRESHOLD") - field(FTE, "DOUBLE") # Address the PV which are mapped as input backwards - field(INPF, "$(INSTR)$(NAME):COUNT-TYPE") - field(FTF, "ULONG") - field(INPG, "$(INSTR)$(NAME):PRESET-COUNT") - field(FTG, "DOUBLE") - field(INPH, "$(INSTR)$(NAME):PRESET-TIME") + field(INPE, "$(INSTR)$(NAME):THRESHOLD-MONITOR") + field(FTE, "LONG") + field(INPF, "$(INSTR)$(NAME):THRESHOLD") + field(FTF, "DOUBLE") + field(INPG, "$(INSTR)$(NAME):COUNT-TYPE") + field(FTG, "ULONG") + field(INPH, "$(INSTR)$(NAME):PRESET-COUNT") field(FTH, "DOUBLE") + field(INPI, "$(INSTR)$(NAME):PRESET-TIME") + field(FTI, "DOUBLE") # L is last input before EPICS 7.0.10 field(INPJ, "$(INSTR)$(NAME):R1-PREV") field(FTJ, "DOUBLE") @@ -283,8 +285,7 @@ record(int64in, "$(INSTR)$(NAME):M1") record(calc, "$(INSTR)$(NAME):R1") { field(DESC, "Rate of DAQ CH0 proton current") - #field(INPA, "$(REMOTE_RATE_PV) CA") - field(INPA, "$(INSTR)$(NAME):PROTON_CURR") + field(INPA, "$(REMOTE_RATE_PV) CA") field(INPB, "$(SHUTTER1_PV=0)") field(INPC, "$(SHUTTER1_CLOSED_VAL=1)") field(INPD, "$(SHUTTER2_PV=0)") @@ -324,12 +325,4 @@ record(bi, "$(INSTR)$(NAME):S1") field(ONAM, "CLEARING") } -record(calc, "$(INSTR)$(NAME):PROTON_CURR") { - field(SCAN, ".1 second") - field(CALC, "1500 + 101 * SIN(A)") - field(INPA, "$(INSTR)$(NAME):PROTON_CURR_VAR PP") -} -record(calc, "$(INSTR)$(NAME):PROTON_CURR_VAR") { - field(CALC, "VAL + 0.001") -} diff --git a/db/sim_proton_current.db b/db/sim_proton_current.db new file mode 100644 index 0000000..e49a202 --- /dev/null +++ b/db/sim_proton_current.db @@ -0,0 +1,12 @@ +# This is database that provides a simulated proton current +# for testing purposes. +# +record(calc, "$(INSTR)$(NAME):SIM_PROTON_CURR") { + field(SCAN, ".1 second") + field(CALC, "1500 + 101 * SIN(A)") + field(INPA, "$(INSTR)$(NAME):PROTON_CURR_VAR PP") +} + +record(calc, "$(INSTR)$(NAME):PROTON_CURR_VAR") { + field(CALC, "VAL + 0.001") +} diff --git a/scripts/daq_soft_proton.cmd b/scripts/daq_soft_proton.cmd index b0e2617..3ab7803 100644 --- a/scripts/daq_soft_proton.cmd +++ b/scripts/daq_soft_proton.cmd @@ -1,10 +1,8 @@ -require sinqDAQ, soederqvist_a +#var softProtonDebug 1 +$(SET_SIM_MODE=#)dbLoadRecords("$(sinqDAQ_DB)sim_proton_current.db", "INSTR=$(INSTR), NAME=$(NAME), REMOTE_RATE_PV=NULL") +$(SET_SIM_MODE=#)epicsEnvSet("REMOTE_RATE_PV", "$(INSTR)$(NAME):SIM_PROTON_CURR") -var softProtonDebug 1 - -dbLoadRecords("$(sinqDAQ_DB)daq_soft_proton.db", "INSTR=$(INSTR), NAME=$(NAME), REMOTE_RATE_PV=NULL") +dbLoadRecords("$(sinqDAQ_DB)daq_soft_proton.db", "INSTR=$(INSTR), NAME=$(NAME), REMOTE_RATE_PV=$(REMOTE_RATE_PV)") iocInit - -dbpr SQ:TEST:SPC:EMULATION diff --git a/src/daq_soft_proton.c b/src/daq_soft_proton.c index 1192f84..de91fb9 100644 --- a/src/daq_soft_proton.c +++ b/src/daq_soft_proton.c @@ -27,6 +27,7 @@ struct spc_internal { epicsInt64 monitor_count; epicsFloat64 elapsed_time; epicsUInt32 command_trig; + epicsInt32 threshold_ch; epicsFloat64 threshold; epicsFloat64 proton_rate; epicsFloat64 prev_proton_rate; @@ -135,10 +136,11 @@ static long processEmulatedCounter(struct aSubRecord *psub) spc->monitor_count = *(epicsInt64*)psub->b; spc->elapsed_time = *(epicsFloat64*)psub->c; spc->command_trig = *(epicsUInt32*)psub->d; - spc->threshold = *(epicsFloat64*)psub->e; - spc->count_type = *(epicsUInt32*)psub->f; - spc->preset_count = *(epicsFloat64*)psub->g; - spc->preset_time = *(epicsFloat64*)psub->h; + spc->threshold_ch = *(epicsInt32*)psub->e; + spc->threshold = *(epicsFloat64*)psub->f; + spc->count_type = *(epicsUInt32*)psub->g; + spc->preset_count = *(epicsFloat64*)psub->h; + spc->preset_time = *(epicsFloat64*)psub->i; spc->prev_proton_rate = *(epicsFloat64*)psub->j; spc->proton_rate = *(epicsFloat64*)psub->l; @@ -157,7 +159,8 @@ static long processEmulatedCounter(struct aSubRecord *psub) /* - Store current rate as previous rate */ *prev_proton_rate_out = spc->proton_rate; - if (spc->average_rate < spc->threshold) { + if (spc->average_rate < spc->threshold && + spc->threshold_ch >= 1) { /* Channel 0 is interpreted as disabled */ *is_low_rate_out = 1; } else { *is_low_rate_out = 0; @@ -248,7 +251,7 @@ static long processEmulatedCounter(struct aSubRecord *psub) * 1. status == COUNTING && command_trig == NONE * 2. status == COUNTING && command_trig == CONTINUE * 3. status == PAUSED && command_trig == CONTINUE - * 4. status == LOW_RATE && command_trig in [ NONE, CONTINUE ] && high_rate + * 4. status == LOW_RATE && command_trig in [ NONE, CONTINUE ] && high_rate */ /* We may have had a command */