EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Tips for doing conditional logic in EPICS records
From: Mark Davis via Tech-talk <tech-talk at aps.anl.gov>
To: tech-talk at aps.anl.gov
Date: Thu, 30 Apr 2020 09:54:37 -0400
On 4/27/2020 12:16 PM, Ralph Lange via Tech-talk wrote:
On Mon, 27 Apr 2020 at 18:04, Mooney, Tim M. via Tech-talk <tech-talk at aps.anl.gov> wrote:
One way to do conditional execution in an EPICS database is by using the SELM and SELN fields of a seq record.  Set SELM to "Specified", and write a number to the SELN field. If you want more than one of several things to happen, you can write "Mask" to SELM, and write a bitmap value to SELN, specifying which things to do.

+1
The combination of a calcout record (evaluating conditions) writing to a seq record in "Mask" mode (executing actions) is extremely powerful. As actions can include delays and changing the calcout's fields, that setup is good enough for a small state machine. (You will also win any district level obfuscation contest.)

Cheers,
~Ralph


The above comments by Tim and Ralph were the inspiration for the solution I decided on:

NOTE:  Some of the PP/NPP/CP/MS/NMS/etc values may need tweaking yet...)
record(ai, "I_RSET")  {
  field(DESC, "current set readback")
  field(PREC, "3")
  field(ADEL, "0.01")
}

record(bi, "_updateRSET")  {
  field(VAL,  "1")
  field(PINI, "YES")
}

record(scalcout, "_psInReset")  {
  field(DESC, "Is PS in reset state?")
  field(INAA, "CMD_STAT CP MSS")
  field(CALC, "AA = 'R'")
}


# Compute value for seq record bit-mask to specify which actions to perform
record(transform, "_RSET_UpdateLogic")
{
  field(INPA, "_psInReset CP MSS")
  field(INPB, "_updateRSET CP MSS")
  field(INPC, "ON_RSTS CP MSS")

  # if (psInReset == 1)  { I_RSET = 0;  updateRSET = 0; }  (actions 1 and 2: Mask=0x03)
  field(CLCJ, "(A=1) ? 3 : 0")

  # else  if (_ON_RSTS_ == 1)  { I_RSET = I_CSET;  updateRSET = 0; }  (actions 3 and 2: Mask=0x06)
  field(CLCK, "(J!=0) ? 0 : (C=1) ? 6 : 0")

  # else  if (updateRSET)  I_RSET = 0;  (action 1: Mask=0x01)
  field(CLCL, "(K!=0) ? 0 : (B=1) ? 1 : 0")

  # Write the resulting bitmask and trigger the desired actions
  field(CLCM, "J | K | L")
  field(OUTM, "_RSET_UpdateActions.SELN")
  field(FLNK, "_RSET_UpdateActions")
}


# The list of actions used by the RSET_UpdateLogic record which determines
# what (if any) change needs to be made to the RSET value.  Which actions to
# performed is specified by writing a bitmapped value to the SELN field (1 bit
# for each action).

record(seq, "_RSET_UpdateActions")  {
  field(SELM, "Mask")

  # Mask bit 0x01:  Set I_RSET = 0
  field(DOL1, "0")
  field(LNK1, "I_RSET PP")

  # Mask bit 0x02:  Set updateRSET = 0
  field(DOL2, "0")
  field(LNK2, "_updateRSET PP")

  # Mask bit 0x04:  Set I_RSET = I_CSET
  field(DOL3, "I_CSET NPP")
  field(LNK3, "I_RSET PP")
}


The above approach is modeled on the more procedural approach typically used in high level languages (given a set of conditions, perform all the necessary actions):

if (expression1)
   do a bunch of stuff ...
else
   if (expression2)
     do a different bunch of stuff ...
  else
    do yet a different bunch of stuff ...


However, a more data-driven approach (compute the next state for each variable) could produce the same effect with just a transform record:

   A = (set of nested if/else conditions and expressions)
   B = (possibly overlapping set of nested if/else conditions and expressions)

Having (very successfully) used the later approach heavily in most the embedded controller code I wrote for years, this approach definitely has some advantages.  However, given the vast difference in the tools used to express it in this case  (EPICS records rather than C code), I think the more verbose approach is easier to comprehend, debug, and maintain.  But your mileage may vary.


Mark



Mark Davis NSCL/FRIB Control Systems Software Engineer davism50 at msu.edu
On 4/27/2020 12:16 PM, Ralph Lange via Tech-talk wrote:
On Mon, 27 Apr 2020 at 18:04, Mooney, Tim M. via Tech-talk <tech-talk at aps.anl.gov> wrote:
One way to do conditional execution in an EPICS database is by using the SELM and SELN fields of a seq record.  Set SELM to "Specified", and write a number to the SELN field. If you want more than one of several things to happen, you can write "Mask" to SELM, and write a bitmap value to SELN, specifying which things to do.

+1
The combination of a calcout record (evaluating conditions) writing to a seq record in "Mask" mode (executing actions) is extremely powerful. As actions can include delays and changing the calcout's fields, that setup is good enough for a small state machine. (You will also win any district level obfuscation contest.)

Cheers,
~Ralph



References:
Tips for doing conditional logic in EPICS records Mark Davis via Tech-talk
Re: Tips for doing conditional logic in EPICS records Mooney, Tim M. via Tech-talk
Re: Tips for doing conditional logic in EPICS records Ralph Lange via Tech-talk

Navigate by Date:
Prev: releases of devlib2 and mrfioc2 Michael Davidsaver via Tech-talk
Next: Motor record: ACS support Mark Vigder via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
Navigate by Thread:
Prev: Re: Tips for doing conditional logic in EPICS records Ralph Lange via Tech-talk
Next: StreamDevice question Mark Davis via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
ANJ, 30 Apr 2020 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·