cleanup mbboDirect bit field handling

B0 -> BF shall always follow the corresponding bit in VAL.

Remove special handling for OMSL.
This commit is contained in:
Michael Davidsaver
2021-09-01 11:18:28 -07:00
parent 7ce69155a9
commit 9c1340d7d5
2 changed files with 63 additions and 74 deletions

View File

@@ -88,6 +88,14 @@ static long writeValue(mbboDirectRecord *);
#define NUM_BITS 32
static
void bitsFromVAL(mbboDirectRecord *prec)
{
unsigned i;
for(i=0; i<NUM_BITS; i++)
(&prec->b0)[i] = !!(prec->val&(1u<<i));
}
static long init_record(struct dbCommon *pcommon, int pass)
{
struct mbboDirectRecord *prec = (struct mbboDirectRecord *)pcommon;
@@ -131,19 +139,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
status = 0;
}
if (!prec->udf &&
prec->omsl == menuOmslsupervisory) {
/* Set initial B0 - B1F from VAL */
epicsUInt32 val = prec->val;
epicsUInt8 *pBn = &prec->b0;
int i;
for (i = 0; i < NUM_BITS; i++) {
*pBn++ = !! (val & 1);
val >>= 1;
}
}
bitsFromVAL(prec);
prec->mlst = prec->val;
prec->oraw = prec->rval;
prec->orbv = prec->rbv;
@@ -174,24 +170,13 @@ static long process(struct dbCommon *pcommon)
}
prec->val = val;
}
else if (prec->omsl == menuOmslsupervisory) {
epicsUInt8 *pBn = &prec->b0;
epicsUInt32 val = 0;
epicsUInt32 bit = 1;
int i;
/* Construct VAL from B0 - B1F */
for (i = 0; i < NUM_BITS; i++, bit <<= 1)
if (*pBn++)
val |= bit;
prec->val = val;
}
else if (prec->udf) {
recGblSetSevr(prec, UDF_ALARM, prec->udfs);
recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "UDFS");
goto CONTINUE;
}
prec->udf = FALSE;
bitsFromVAL(prec);
/* Convert VAL to RVAL */
convert(prec);
@@ -234,6 +219,9 @@ CONTINUE:
recGblGetTimeStampSimm(prec, prec->simm, NULL);
}
/* update bits to reflect any change made by dset */
bitsFromVAL(prec);
monitor(prec);
/* Wrap up */
@@ -255,60 +243,41 @@ static long special(DBADDR *paddr, int after)
return 0;
}
if (!after)
return 0;
switch (paddr->special) {
case SPC_MOD: /* Bn field modified */
if (prec->omsl == menuOmslsupervisory) {
/* Adjust VAL corresponding to the bit changed */
epicsUInt8 *pBn = (epicsUInt8 *) paddr->pfield;
epicsUInt32 bit = 1 << (pBn - &prec->b0);
if (*pBn)
prec->val |= bit;
else
prec->val &= ~bit;
prec->udf = FALSE;
convert(prec);
if(after==0 && fieldIndex >= mbboDirectRecordB0 && fieldIndex <= mbboDirectRecordB1F) {
if(prec->omsl == menuOmslclosed_loop) {
/* To avoid confusion, reject changes to bit fields while in closed loop.
* Not a 100% solution as confusion can still arise if dset overwrites VAL.
*/
return S_db_noMod;
}
break;
case SPC_RESET: /* OMSL field modified */
if (prec->omsl == menuOmslclosed_loop) {
/* Construct VAL from B0 - B1F */
epicsUInt8 *pBn = &prec->b0;
epicsUInt32 val = 0, bit = 1;
int i;
} else if(after==1 && fieldIndex >= mbboDirectRecordB0 && fieldIndex <= mbboDirectRecordB1F) {
/* Adjust VAL corresponding to the bit changed */
epicsUInt8 *pBn = (epicsUInt8 *) paddr->pfield;
epicsUInt32 bit = 1 << (pBn - &prec->b0);
epicsUInt32 oobit = prec->obit;
for (i = 0; i < NUM_BITS; i++, bit <<= 1)
if (*pBn++)
val |= bit;
prec->val = val;
/* Because this is !(VAL and PP), dbPut() will always post a monitor on this B* field
* after we return. We must keep track of this change separately from MLST to handle
* situations where VAL and B* are changed prior to next monitor(). eg. by dset to
* reflect bits actually written. This is the role of OBIT.
*/
if (*pBn) {
prec->val |= bit;
prec->obit |= bit;
} else {
prec->val &= ~bit;
prec->obit &= ~bit;
}
else if (prec->omsl == menuOmslsupervisory) {
/* Set B0 - B1F from VAL and post monitors */
epicsUInt32 val = prec->val;
epicsUInt8 *pBn = &prec->b0;
int i;
if(oobit!=prec->obit)
db_post_events(prec, &prec->obit, DBE_VALUE|DBE_LOG);
for (i = 0; i < NUM_BITS; i++, pBn++, val >>= 1) {
epicsUInt8 oBn = *pBn;
prec->udf = FALSE;
convert(prec);
*pBn = !! (val & 1);
if (oBn != *pBn)
db_post_events(prec, pBn, DBE_VALUE | DBE_LOG);
}
}
break;
default:
recGblDbaddrError(S_db_badChoice, paddr, "mbboDirect: special");
return S_db_badChoice;
}
prec->udf = FALSE;
return 0;
}
@@ -329,9 +298,24 @@ static void monitor(mbboDirectRecord *prec)
if (prec->mlst != prec->val) {
events |= DBE_VALUE | DBE_LOG;
prec->mlst = prec->val;
db_post_events(prec, &prec->mlst, events);
}
if (events)
if (events) {
db_post_events(prec, &prec->val, events);
}
{
unsigned i;
epicsUInt32 bitsChanged = prec->obit ^ (epicsUInt32)prec->val;
for(i=0; i<NUM_BITS; i++) {
/* post bit when value or alarm severity changes */
if((events&~(DBE_VALUE|DBE_LOG)) || (bitsChanged&(1u<<i))) {
db_post_events(prec, (&prec->b0)+i, events | DBE_VALUE | DBE_LOG);
}
}
prec->obit = prec->val;
db_post_events(prec, &prec->obit, events);
}
events |= DBE_VALUE | DBE_LOG;
if (prec->oraw != prec->rval) {

View File

@@ -104,7 +104,6 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
field(OMSL,DBF_MENU) {
prompt("Output Mode Select")
promptgroup("50 - Output")
special(SPC_RESET)
pp(TRUE)
interest(1)
menu(menuOmsl)
@@ -154,6 +153,11 @@ Parameters> for more on the record name (NAME) and description (DESC) fields.
special(SPC_NOMOD)
interest(3)
}
field(OBIT,DBF_LONG) {
prompt("Last Bit mask Monitored")
special(SPC_NOMOD)
interest(3)
}
field(SHFT,DBF_USHORT) {
prompt("Shift")
promptgroup("50 - Output")
@@ -169,6 +173,7 @@ MASK is used by device support routine to read the hardware register. Record
support sets low order NOBT bits. Device support can shift this value.
MLST holds the value when the last monitor for value change was triggered.
OBIT has similar role wrt. the B* fields.
=fields NOBT, ORAW, MASK, MLST