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 <2020> 2021 2022 2023 2024 2025 | 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 <2020> 2021 2022 2023 2024 2025 |
<== 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 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
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") }
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