Last big things:

* Implemented support for diabling theshold channel
* Separate proton current simulation db.
* Separate startup snippet with support for simulation mode.
* Short readme entry
This commit is contained in:
2026-02-05 14:08:33 +01:00
parent 4e42eab39b
commit 6cf24254e3
6 changed files with 51 additions and 29 deletions

View File

@@ -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

View File

@@ -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'
```

View File

@@ -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")
}

12
db/sim_proton_current.db Normal file
View File

@@ -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")
}

View File

@@ -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

View File

@@ -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 */