Merge PR #63, longout.OOPT

This commit is contained in:
Andrew Johnson
2022-12-29 16:31:42 -06:00
6 changed files with 451 additions and 4 deletions
+68 -2
View File
@@ -81,10 +81,14 @@ rset longoutRSET={
};
epicsExportAddress(rset,longoutRSET);
#define DONT_EXEC_OUTPUT 0
#define EXEC_OUTPUT 1
static void checkAlarms(longoutRecord *prec);
static void monitor(longoutRecord *prec);
static long writeValue(longoutRecord *prec);
static void convert(longoutRecord *prec, epicsInt32 value);
static long conditional_write(longoutRecord *prec);
static long init_record(struct dbCommon *pcommon, int pass)
{
@@ -119,6 +123,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
prec->mlst = prec->val;
prec->alst = prec->val;
prec->lalm = prec->val;
prec->pval = prec->val;
prec->outpvt = EXEC_OUTPUT;
return 0;
}
@@ -210,6 +217,14 @@ static long special(DBADDR *paddr, int after)
recGblCheckSimm((dbCommon *)prec, &prec->sscn, prec->oldsimm, prec->simm);
return(0);
}
/* Detect an output link re-direction (change) */
if (dbGetFieldIndex(paddr) == longoutRecordOUT) {
if ((after) && (prec->ooch == menuYesNoYES))
prec->outpvt = EXEC_OUTPUT;
return(0);
}
default:
recGblDbaddrError(S_db_badChoice, paddr, "longout: special");
return(S_db_badChoice);
@@ -391,7 +406,7 @@ static long writeValue(longoutRecord *prec)
switch (prec->simm) {
case menuYesNoNO:
status = pdset->write_longout(prec);
status = conditional_write(prec);
break;
case menuYesNoYES: {
@@ -421,10 +436,61 @@ static long writeValue(longoutRecord *prec)
static void convert(longoutRecord *prec, epicsInt32 value)
{
/* check drive limits */
/* check drive limits */
if(prec->drvh > prec->drvl) {
if (value > prec->drvh) value = prec->drvh;
else if (value < prec->drvl) value = prec->drvl;
}
prec->val = value;
}
/* Evaluate OOPT field to perform the write operation */
static long conditional_write(longoutRecord *prec)
{
struct longoutdset *pdset = (struct longoutdset *) prec->dset;
long status = 0;
int doDevSupWrite = 0;
switch (prec->oopt)
{
case longoutOOPT_On_Change:
/* Forces a write op if a change in the OUT field is detected OR is first process */
if (prec->outpvt == EXEC_OUTPUT) {
doDevSupWrite = 1;
} else {
/* Only write if value is different from the previous one */
doDevSupWrite = (prec->val != prec->pval);
}
break;
case longoutOOPT_Every_Time:
doDevSupWrite = 1;
break;
case longoutOOPT_When_Zero:
doDevSupWrite = (prec->val == 0);
break;
case longoutOOPT_When_Non_zero:
doDevSupWrite = (prec->val != 0);
break;
case longoutOOPT_Transition_To_Zero:
doDevSupWrite = ((prec->val == 0)&&(prec->pval != 0));
break;
case longoutOOPT_Transition_To_Non_zero:
doDevSupWrite = ((prec->val != 0)&&(prec->pval == 0));
break;
default:
break;
}
if (doDevSupWrite)
status = pdset->write_longout(prec);
prec->pval = prec->val;
prec->outpvt = DONT_EXEC_OUTPUT; /* reset status */
return status;
}
@@ -20,6 +20,15 @@ limits.
=cut
menu(longoutOOPT) {
choice(longoutOOPT_Every_Time,"Every Time")
choice(longoutOOPT_On_Change,"On Change")
choice(longoutOOPT_When_Zero,"When Zero")
choice(longoutOOPT_When_Non_zero,"When Non-zero")
choice(longoutOOPT_Transition_To_Zero,"Transition To Zero")
choice(longoutOOPT_Transition_To_Non_zero,"Transition To Non-zero")
}
recordtype(longout) {
=head2 Parameter Fields
@@ -72,7 +81,46 @@ See L<Address
Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html#address-specification>
for information on the format of hardware addresses and database links.
=fields OUT, DTYP
=fields OUT, DTYP, OOPT, OOCH
=head4 Menu longoutOOPT
The OOPT field determines the condition that causes the output link to be
written to. It's a menu field that has six choices:
=menu longoutOOPT
=over
=item *
C<Every Time> -- write output every time record is processed. (DEFAULT)
=item *
C<On Change> -- write output every time VAL changes.
=item *
C<When Zero> -- when record is processed, write output if VAL is zero.
=item *
C<When Non-zero> -- when record is processed, write output if VAL is
non-zero.
=item *
C<Transition To Zero> -- when record is processed, write output only if VAL
is zero and the last value was non-zero.
=item *
C<Transition To Non-zero> -- when record is processed, write output only if
VAL is non-zero and last value was zero.
=back
=head4 Changes in OUT field when OOPT = On Change
If OOCH is C<YES> (its default value) and the OOPT field is C<On Change>,
the record will write to the device support the first time the record gets
processed after its OUT link is modified, even when the output value has
not actually changed.
=cut
@@ -94,6 +142,7 @@ for information on the format of hardware addresses and database links.
}
field(OUT,DBF_OUTLINK) {
prompt("Output Specification")
special(SPC_MOD)
promptgroup("50 - Output")
interest(1)
}
@@ -365,7 +414,7 @@ for more information on simulation mode and its fields.
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
extra("epicsCallback *simpvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID output action")
@@ -378,6 +427,29 @@ for more information on simulation mode and its fields.
promptgroup("50 - Output")
interest(2)
}
field(PVAL,DBF_LONG) {
prompt("Previous Value")
}
field(OUTPVT,DBF_NOACCESS) {
prompt("Output Write Control Private")
special(SPC_NOMOD)
interest(4)
extra("epicsEnum16 outpvt")
}
field(OOCH,DBF_MENU) {
prompt("Output Exec. On Change (Opt)")
promptgroup("50 - Output")
interest(1)
menu(menuYesNo)
initial("1")
}
field(OOPT,DBF_MENU) {
prompt("Output Execute Opt")
promptgroup("50 - Output")
interest(1)
menu(longoutOOPT)
initial("0")
}
=begin html