compiled soft_proton

This commit is contained in:
2026-01-19 09:48:07 +01:00
parent 025e985b75
commit 45b01bf4c4
2 changed files with 67 additions and 68 deletions

View File

@@ -29,6 +29,7 @@ DBDS += src/daq.dbd
# Source files to build # Source files to build
SOURCES += src/daq.cpp SOURCES += src/daq.cpp
SOURCES += src/daq_soft_proton.c
SCRIPTS += scripts/daq_4ch.cmd SCRIPTS += scripts/daq_4ch.cmd
SCRIPTS += scripts/daq_8ch.cmd SCRIPTS += scripts/daq_8ch.cmd
@@ -36,6 +37,6 @@ SCRIPTS += scripts/daq_2nd_gen.cmd
SCRIPTS += sim/daq_sim.py SCRIPTS += sim/daq_sim.py
CXXFLAGS += -std=c++17 CXXFLAGS += -std=c++17
USR_CFLAGS += -Wall -Wextra #-Werror USR_CFLAGS += -std=c11 -Wall -Wextra #-Werror
# MISCS would be the place to keep the stream device template files # MISCS would be the place to keep the stream device template files

View File

@@ -5,12 +5,13 @@
* Typically it is sampling the proton rate from HIPA via * Typically it is sampling the proton rate from HIPA via
* channel access. * channel access.
*/ */
#include <stdio.h> #include <string.h>
#include <dbDefs.h> #include <dbDefs.h>
#include <errlog.h> #include <errlog.h>
#include <aSubRecord.h> #include <aSubRecord.h>
#include <epicsTypes.h> #include <epicsTypes.h>
#include <epicsString.h>
#include <registryFunction.h> #include <registryFunction.h>
#include <epicsExport.h> #include <epicsExport.h>
@@ -32,6 +33,7 @@ struct spc_internal {
epicsUInt32 count_type; epicsUInt32 count_type;
epicsInt64 preset_count; epicsInt64 preset_count;
epicsFloat64 preset_time; epicsFloat64 preset_time;
epicsFloat64 average_rate;
}; };
/* Enum with values for all commands /* Enum with values for all commands
@@ -41,7 +43,7 @@ enum commands {
COUNT_PRESET = 1, COUNT_PRESET = 1,
TIME_PRESET = 2, TIME_PRESET = 2,
PAUSE = 3, PAUSE = 3,
CONTINUE = 4 CONTINUE = 4,
STOP = 5, STOP = 5,
FULL_RESET = 6 FULL_RESET = 6
}; };
@@ -57,45 +59,44 @@ enum status {
}; };
int handleNoop(struct spc_internal* spc_int, epicsChar** msg_text) { int handleNoop(struct spc_internal* spc, epicsOldString* msg_text) {
const char[] funcstr = "handleNoop"; const char* funcstr = "handleNoop";
/* This shouldn't happen, but let's handle it just in case */ /* This shouldn't happen, but let's handle it just in case */
if (spc_int->status >= INVALID || spc->command_trig > FULL_RESET) { if (spc->status >= INVALID || spc->command_trig > FULL_RESET) {
*msg_text = "INVALID STATE!"; strcpy(*msg_text, "INVALID STATE!");
errlogPrintf("%s: Status and/or command triggers are invalid \n" errlogPrintf("%s: Status and/or command triggers are invalid \n"
"Status has value %d, \n Command trigger has value %d\n", "Status has value %d, \n Command trigger has value %d\n",
funcstr, spc_int->status, spc_int->command_trig); funcstr, spc->status, spc->command_trig);
return 1; return 1;
} }
/* Determine if we are idle and have received a noop command */ /* Determine if we are idle and have received a noop command */
if (spc_int->status == IDLE) { if (spc->status == IDLE) {
switch (spc_int->command_trig) { switch (spc->command_trig) {
case PAUSE: case PAUSE:
case CONTINUE: case CONTINUE:
case STOP: case STOP:
*msg_text = "Can not PAUSE/CONTINUE/STOP during IDLE."; strcpy(*msg_text, "Can not PAUSE/CONTINUE/STOP during IDLE.");
printf("%s: %s\n" printf("%s: %s\n"
"Status has value %d, \n" "Status has value %d, \n"
"Command trigger has value %d\n", "Command trigger has value %d\n", *msg_text,
funcstr, spc_int->status, spc_int->command_trig); funcstr, spc->status, spc->command_trig);
*exit_status = 1; /* Positive value: No alarm and no output processing */
return 1; return 1;
} }
} }
/* Determine if we are counting, low_rate or paused; /* Determine if we are counting, low_rate or paused;
* and have received a noop command */ * and have received a noop command */
if (spc_int->status == COUNTING || spc_int->status == LOW_RATE || if (spc->status == COUNTING || spc->status == LOW_RATE ||
spc_int -> PAUSED) { spc->status == PAUSED) {
switch (spc_int->command_trig) { switch (spc->command_trig) {
case COUNT_PRESET: case COUNT_PRESET:
case TIME_PRESET: case TIME_PRESET:
strcpy(*msg_text, "Already counting");
printf("%s: Already counting can not start a new count\n" printf("%s: Already counting can not start a new count\n"
"Status has value %d, \n" "Status has value %d, \n"
"Command trigger has value %d\n", "Command trigger has value %d\n",
funcstr, spc_int->status, spc_int->command_trig); funcstr, spc->status, spc->command_trig);
*exit_status = 0;
/* This case could be seen as OK. /* This case could be seen as OK.
* Nothing is keeping us from continuing, so let's do that. */ * Nothing is keeping us from continuing, so let's do that. */
return 0; return 0;
@@ -103,12 +104,11 @@ int handleNoop(struct spc_internal* spc_int, epicsChar** msg_text) {
} }
/* Determine if we are paused and a pause command */ /* Determine if we are paused and a pause command */
if (spc_int->status == PAUSED && spc_int->command_trig == PAUSE) { if (spc->status == PAUSED && spc->command_trig == PAUSE) {
errlogPrintf("%s: Already paused\n" errlogPrintf("%s: Already paused\n"
"Status has value %d, \n" "Status has value %d, \n"
"Command trigger has value %d\n", "Command trigger has value %d\n",
funcstr, spc_int->status, spc_int->command_trig); funcstr, spc->status, spc->command_trig);
*exit_status = 1; /* Positive value: No alarm and no output processing */
return 1; return 1;
} }
/* None of the noop cases detected */ /* None of the noop cases detected */
@@ -117,62 +117,60 @@ int handleNoop(struct spc_internal* spc_int, epicsChar** msg_text) {
/* /*
* This function is called everytime the record processes. * This function is called everytime the record processes.
* Even though this record can process arrays, we only use it with scalars, * Even though this record can process arrays, we only use it with scalars.
* hence all the [0]'s.
*/ */
static long processEmulatedCounter(struct aSubRecord *psub) static long processEmulatedCounter(struct aSubRecord *psub)
{ {
const char[] funcstr = "processEmulatedCounter"; const char* funcstr = "processEmulatedCounter";
if (softProtonDebug) printf("%s was called\n", funcstr); if (softProtonDebug) printf("%s was called\n", funcstr);
/* Declare internal variable */ /* Declare internal variable */
struct spc_internal spc_int; struct spc_internal spc_int;
struct spc_internal spc = &spc_int; struct spc_internal* spc = &spc_int;
int exit_status = 0;
/* Copy input values to a struct on the stack /* Copy input values to a struct on the stack
* to simplify creation of functions */ * to simplify creation of functions */
spc->status = psub->a[0]; spc->status = *(epicsUInt32*)psub->a;
spc->monitor_count = psub->b[0]; spc->monitor_count = *(epicsInt64*)psub->b;
spc->elapsed_time = psub->c[0]; spc->elapsed_time = *(epicsFloat64*)psub->c;
spc->command_trig = psub->d[0]; spc->command_trig = *(epicsUInt32*)psub->d;
spc->threshold = psub->e[0]; spc->threshold = *(epicsFloat64*)psub->e;
spc->count_type = psub->f[0]; spc->count_type = *(epicsUInt32*)psub->f;
spc->preset_count = psub->g[0]; spc->preset_count = *(epicsInt64*)psub->g;
spc->preset_time = psub->h[0]; spc->preset_time = *(epicsFloat64*)psub->h;
spc->prev_proton_rate = psub->j[0]; spc->prev_proton_rate = *(epicsFloat64*)psub->j;
spc->proton_rate = psub->l[0]; spc->proton_rate = *(epicsFloat64*)psub->l;
/* Get the pointer to output values only to increase readability. */ /* Get the pointer to output values only to increase readability. */
epicsUInt32* status_out = psub->vala; epicsUInt32* status_out = (epicsUInt32*)psub->vala;
epicsInt64* monitor_count_out = psub->valb; epicsInt64* monitor_count_out = (epicsInt64*)psub->valb;
epicsFloat64* elaped_time_out = psub->valc; epicsFloat64* elapsed_time_out = (epicsFloat64*)psub->valc;
epicsUInt32* command_trig_out = psub->vald; epicsUInt32* command_trig_out = (epicsUInt32*)psub->vald;
epicsFloat64* prev_proton_rate_out = psub->vale; epicsFloat64* prev_proton_rate_out = (epicsFloat64*)psub->vale;
epicsUInt32* is_low_rate_out = psub->valf; epicsUInt32* is_low_rate_out = (epicsUInt32*)psub->valf;
epicsChar* msg_txt_out = &psub->valg; epicsOldString* msg_txt_out = (epicsOldString*)psub->valg;
/* Always no matter what, handle the rate */ /* Always no matter what, handle the rate */
/* - Calculate average rate */ /* - Calculate average rate */
average_rate = (spc->proton_rate + spc->prev_proton_rate) / 2; spc->average_rate = (spc->proton_rate + spc->prev_proton_rate) / 2;
/* - Store current rate as previous rate */ /* - Store current rate as previous rate */
*prev_proton_rate_out = spc_int->proton_rate; *prev_proton_rate_out = spc->proton_rate;
if (average_rate < spc->threshold) { if (spc->average_rate < spc->threshold) {
*is_low_rate_out = 0; /* Illogical but 0 is low_rate, 1 high rate */ *is_low_rate_out = 0; /* Illogical but 0 is low_rate, 1 high rate */
} else { } else {
*is_low_rate_out = 1; /* Illogical but 0 is low_rate, 1 high rate */ *is_low_rate_out = 1; /* Illogical but 0 is low_rate, 1 high rate */
} }
/* Handle noop situations both valid and invalid */ /* Handle noop situations both valid and invalid */
if (handle_noop(spc, &msg_txt_out)) if (handleNoop(spc, msg_txt_out))
/* We have state that prohibits further processing */ /* We have state that prohibits further processing */
return 0; return 0;
/* Commands with priority always yielding IDLE status first */ /* Commands with priority always yielding IDLE status first */
if (spc->command_trig == FULL_RESET) { if (spc->command_trig == FULL_RESET) {
msg_txt_out = "Full reset!"; strcpy(*msg_txt_out, "Full reset!");
/* Reset everything, done! */ /* Reset everything, done! */
*status_out = IDLE; *status_out = IDLE;
*monitor_count_out = 0; *monitor_count_out = 0;
@@ -192,7 +190,7 @@ static long processEmulatedCounter(struct aSubRecord *psub)
} else if (((spc->status == COUNTING || spc->status == LOW_RATE) } else if (((spc->status == COUNTING || spc->status == LOW_RATE)
&& spc->command_trig == PAUSE) || && spc->command_trig == PAUSE) ||
(spc->status == PAUSED && spc->command_trig == NONE)) { (spc->status == PAUSED && spc->command_trig == NONE)) {
msg_txt_out = "Stopping!"; strcpy(*msg_txt_out, "Stopping!");
/* We are counting or at low rate and received pause. /* We are counting or at low rate and received pause.
* Also we are paused but have received no command, this * Also we are paused but have received no command, this
* is probably slightly inaccurate but simplifies things.*/ * is probably slightly inaccurate but simplifies things.*/
@@ -206,7 +204,7 @@ static long processEmulatedCounter(struct aSubRecord *psub)
/* Determine if we are idle but received a count command */ /* Determine if we are idle but received a count command */
if (softProtonDebug) printf("%s: Starting Count!\n", funcstr); if (softProtonDebug) printf("%s: Starting Count!\n", funcstr);
/* Sanity check that count type is properly stored */ /* Sanity check that count type is properly stored */
if (command_trig != count_type) { if (spc->command_trig != spc->count_type) {
if (softProtonDebug) printf("%s: Count type not stored!\n", funcstr); if (softProtonDebug) printf("%s: Count type not stored!\n", funcstr);
return -1; return -1;
} }
@@ -215,22 +213,22 @@ static long processEmulatedCounter(struct aSubRecord *psub)
*monitor_count_out = 0; *monitor_count_out = 0;
*elapsed_time_out = 0; *elapsed_time_out = 0;
*command_trig_out = NONE; *command_trig_out = NONE;
if (is_low_rate_out == 1) { if (*is_low_rate_out == 1) {
*status_out = LOW_RATE; *status_out = LOW_RATE;
} else { } else {
*status_out = COUNTING; *status_out = COUNTING;
} }
return 0; return 0;
} else if ((((spc_int->status == LOW_RATE && spc_int->command_trig == NONE) || } else if ((((spc->status == LOW_RATE && spc->command_trig == NONE) ||
(spc_int->status == LOW_RATE && spc_int->command_trig == CONTINUE))) (spc->status == LOW_RATE && spc->command_trig == CONTINUE)))
&& is_low_rate_out == 1) { && *is_low_rate_out == 1) {
*status_out = LOW_RATE; *status_out = LOW_RATE;
/* LOW_RATE or resuming from PAUSE */ /* LOW_RATE or resuming from PAUSE */
*command_trig_out = NONE; *command_trig_out = NONE;
/* Maintain same counter and time*/ /* Maintain same counter and time*/
*monitor_count_out = spc_int->monitor_count; *monitor_count_out = spc->monitor_count;
*elapsed_time_out = spc_int->elapsed_time; *elapsed_time_out = spc->elapsed_time;
return 0 return 0;
} }
/* Ending up here means: /* Ending up here means:
@@ -247,12 +245,12 @@ static long processEmulatedCounter(struct aSubRecord *psub)
*status_out = COUNTING; *status_out = COUNTING;
/* Increament counter and time */ /* Increament counter and time */
*monitor_count_out = spc_int->monitor_count + *monitor_count_out = spc->monitor_count +
average_rate * SOFT_PROTON_SAMPLE_RATE; spc->average_rate * SOFT_PROTON_SAMPLE_RATE;
*elapsed_time_out = spc_int->elapsed_time + SOFT_PROTON_SAMPLE_RATE; *elapsed_time_out = spc->elapsed_time + SOFT_PROTON_SAMPLE_RATE;
/* Check if we are below threshold */ /* Check if we are below threshold */
if (is_low_rate_out == 1) { if (*is_low_rate_out == 1) {
*status_out = LOW_RATE; *status_out = LOW_RATE;
} else { } else {
*status_out = COUNTING; *status_out = COUNTING;
@@ -261,11 +259,11 @@ static long processEmulatedCounter(struct aSubRecord *psub)
/* Check if count is finished normally. /* Check if count is finished normally.
* Higher priority than low rate */ * Higher priority than low rate */
if (/* Time based count finished */ if (/* Time based count finished */
(*elapsed_time_out >= spc_int->preset_time && (*elapsed_time_out >= spc->preset_time &&
spc_int->count_type = TIME_PRESET) || spc->count_type == TIME_PRESET) ||
/* Monitor based count finished */ /* Monitor based count finished */
(*monitor_count_out >= spc_int->preset_time && (*monitor_count_out >= spc->preset_time &&
spc_int->count_type = COUNT_PRESET)) { spc->count_type == COUNT_PRESET)) {
*status_out = IDLE; *status_out = IDLE;
} }