diff --git a/Makefile b/Makefile index 56ca12a..e7eb256 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ DBDS += src/daq.dbd # Source files to build SOURCES += src/daq.cpp +SOURCES += src/daq_soft_proton.c SCRIPTS += scripts/daq_4ch.cmd SCRIPTS += scripts/daq_8ch.cmd @@ -36,6 +37,6 @@ SCRIPTS += scripts/daq_2nd_gen.cmd SCRIPTS += sim/daq_sim.py 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 diff --git a/src/daq_soft_proton.c b/src/daq_soft_proton.c index 60f2e84..5a27bd2 100644 --- a/src/daq_soft_proton.c +++ b/src/daq_soft_proton.c @@ -5,12 +5,13 @@ * Typically it is sampling the proton rate from HIPA via * channel access. */ -#include +#include + #include #include - #include #include +#include #include #include @@ -32,6 +33,7 @@ struct spc_internal { epicsUInt32 count_type; epicsInt64 preset_count; epicsFloat64 preset_time; + epicsFloat64 average_rate; }; /* Enum with values for all commands @@ -41,7 +43,7 @@ enum commands { COUNT_PRESET = 1, TIME_PRESET = 2, PAUSE = 3, - CONTINUE = 4 + CONTINUE = 4, STOP = 5, FULL_RESET = 6 }; @@ -57,45 +59,44 @@ enum status { }; -int handleNoop(struct spc_internal* spc_int, epicsChar** msg_text) { - const char[] funcstr = "handleNoop"; +int handleNoop(struct spc_internal* spc, epicsOldString* msg_text) { + const char* funcstr = "handleNoop"; /* This shouldn't happen, but let's handle it just in case */ - if (spc_int->status >= INVALID || spc->command_trig > FULL_RESET) { - *msg_text = "INVALID STATE!"; + if (spc->status >= INVALID || spc->command_trig > FULL_RESET) { + strcpy(*msg_text, "INVALID STATE!"); errlogPrintf("%s: Status and/or command triggers are invalid \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; } /* Determine if we are idle and have received a noop command */ - if (spc_int->status == IDLE) { - switch (spc_int->command_trig) { + if (spc->status == IDLE) { + switch (spc->command_trig) { case PAUSE: case CONTINUE: 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" "Status has value %d, \n" - "Command trigger has value %d\n", - funcstr, spc_int->status, spc_int->command_trig); - *exit_status = 1; /* Positive value: No alarm and no output processing */ + "Command trigger has value %d\n", *msg_text, + funcstr, spc->status, spc->command_trig); return 1; } } /* Determine if we are counting, low_rate or paused; * and have received a noop command */ - if (spc_int->status == COUNTING || spc_int->status == LOW_RATE || - spc_int -> PAUSED) { - switch (spc_int->command_trig) { + if (spc->status == COUNTING || spc->status == LOW_RATE || + spc->status == PAUSED) { + switch (spc->command_trig) { case COUNT_PRESET: case TIME_PRESET: + strcpy(*msg_text, "Already counting"); printf("%s: Already counting can not start a new count\n" "Status has value %d, \n" "Command trigger has value %d\n", - funcstr, spc_int->status, spc_int->command_trig); - *exit_status = 0; + funcstr, spc->status, spc->command_trig); /* This case could be seen as OK. * Nothing is keeping us from continuing, so let's do that. */ 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 */ - if (spc_int->status == PAUSED && spc_int->command_trig == PAUSE) { + if (spc->status == PAUSED && spc->command_trig == PAUSE) { errlogPrintf("%s: Already paused\n" "Status has value %d, \n" "Command trigger has value %d\n", - funcstr, spc_int->status, spc_int->command_trig); - *exit_status = 1; /* Positive value: No alarm and no output processing */ + funcstr, spc->status, spc->command_trig); return 1; } /* 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. - * Even though this record can process arrays, we only use it with scalars, - * hence all the [0]'s. + * Even though this record can process arrays, we only use it with scalars. */ static long processEmulatedCounter(struct aSubRecord *psub) { - const char[] funcstr = "processEmulatedCounter"; + const char* funcstr = "processEmulatedCounter"; if (softProtonDebug) printf("%s was called\n", funcstr); /* Declare internal variable */ struct spc_internal spc_int; - struct spc_internal spc = &spc_int; - int exit_status = 0; + struct spc_internal* spc = &spc_int; /* Copy input values to a struct on the stack * to simplify creation of functions */ - spc->status = psub->a[0]; - spc->monitor_count = psub->b[0]; - spc->elapsed_time = psub->c[0]; - spc->command_trig = psub->d[0]; - spc->threshold = psub->e[0]; - spc->count_type = psub->f[0]; - spc->preset_count = psub->g[0]; - spc->preset_time = psub->h[0]; - spc->prev_proton_rate = psub->j[0]; - spc->proton_rate = psub->l[0]; + spc->status = *(epicsUInt32*)psub->a; + 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 = *(epicsInt64*)psub->g; + spc->preset_time = *(epicsFloat64*)psub->h; + spc->prev_proton_rate = *(epicsFloat64*)psub->j; + spc->proton_rate = *(epicsFloat64*)psub->l; /* Get the pointer to output values only to increase readability. */ - epicsUInt32* status_out = psub->vala; - epicsInt64* monitor_count_out = psub->valb; - epicsFloat64* elaped_time_out = psub->valc; - epicsUInt32* command_trig_out = psub->vald; - epicsFloat64* prev_proton_rate_out = psub->vale; - epicsUInt32* is_low_rate_out = psub->valf; - epicsChar* msg_txt_out = &psub->valg; + epicsUInt32* status_out = (epicsUInt32*)psub->vala; + epicsInt64* monitor_count_out = (epicsInt64*)psub->valb; + epicsFloat64* elapsed_time_out = (epicsFloat64*)psub->valc; + epicsUInt32* command_trig_out = (epicsUInt32*)psub->vald; + epicsFloat64* prev_proton_rate_out = (epicsFloat64*)psub->vale; + epicsUInt32* is_low_rate_out = (epicsUInt32*)psub->valf; + epicsOldString* msg_txt_out = (epicsOldString*)psub->valg; /* Always no matter what, handle the 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 */ - *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 */ } else { *is_low_rate_out = 1; /* Illogical but 0 is low_rate, 1 high rate */ } /* 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 */ - return 0; + return 0; /* Commands with priority always yielding IDLE status first */ if (spc->command_trig == FULL_RESET) { - msg_txt_out = "Full reset!"; + strcpy(*msg_txt_out, "Full reset!"); /* Reset everything, done! */ *status_out = IDLE; *monitor_count_out = 0; @@ -192,7 +190,7 @@ static long processEmulatedCounter(struct aSubRecord *psub) } else if (((spc->status == COUNTING || spc->status == LOW_RATE) && spc->command_trig == PAUSE) || (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. * Also we are paused but have received no command, this * 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 */ if (softProtonDebug) printf("%s: Starting Count!\n", funcstr); /* 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); return -1; } @@ -215,22 +213,22 @@ static long processEmulatedCounter(struct aSubRecord *psub) *monitor_count_out = 0; *elapsed_time_out = 0; *command_trig_out = NONE; - if (is_low_rate_out == 1) { + if (*is_low_rate_out == 1) { *status_out = LOW_RATE; } else { *status_out = COUNTING; } return 0; - } else if ((((spc_int->status == LOW_RATE && spc_int->command_trig == NONE) || - (spc_int->status == LOW_RATE && spc_int->command_trig == CONTINUE))) - && is_low_rate_out == 1) { + } else if ((((spc->status == LOW_RATE && spc->command_trig == NONE) || + (spc->status == LOW_RATE && spc->command_trig == CONTINUE))) + && *is_low_rate_out == 1) { *status_out = LOW_RATE; /* LOW_RATE or resuming from PAUSE */ *command_trig_out = NONE; /* Maintain same counter and time*/ - *monitor_count_out = spc_int->monitor_count; - *elapsed_time_out = spc_int->elapsed_time; - return 0 + *monitor_count_out = spc->monitor_count; + *elapsed_time_out = spc->elapsed_time; + return 0; } /* Ending up here means: @@ -247,12 +245,12 @@ static long processEmulatedCounter(struct aSubRecord *psub) *status_out = COUNTING; /* Increament counter and time */ - *monitor_count_out = spc_int->monitor_count + - average_rate * SOFT_PROTON_SAMPLE_RATE; - *elapsed_time_out = spc_int->elapsed_time + SOFT_PROTON_SAMPLE_RATE; + *monitor_count_out = spc->monitor_count + + spc->average_rate * SOFT_PROTON_SAMPLE_RATE; + *elapsed_time_out = spc->elapsed_time + SOFT_PROTON_SAMPLE_RATE; /* Check if we are below threshold */ - if (is_low_rate_out == 1) { + if (*is_low_rate_out == 1) { *status_out = LOW_RATE; } else { *status_out = COUNTING; @@ -261,11 +259,11 @@ static long processEmulatedCounter(struct aSubRecord *psub) /* Check if count is finished normally. * Higher priority than low rate */ if (/* Time based count finished */ - (*elapsed_time_out >= spc_int->preset_time && - spc_int->count_type = TIME_PRESET) || + (*elapsed_time_out >= spc->preset_time && + spc->count_type == TIME_PRESET) || /* Monitor based count finished */ - (*monitor_count_out >= spc_int->preset_time && - spc_int->count_type = COUNT_PRESET)) { + (*monitor_count_out >= spc->preset_time && + spc->count_type == COUNT_PRESET)) { *status_out = IDLE; }