Commit 912a7fba authored by Franksen, Benjamin's avatar Franksen, Benjamin
Browse files

fixed performance problem: move all link parsing from process to init_record

Also added new fields IAOM and IAOV to facilitate this.
parent 461970fc
......@@ -130,7 +130,7 @@ typedef double cvt_subroutine(double,double,void**);
#define DRTY_Y 0x20
static void csm_alarm(struct cvtRecord *pcvt);
static long readInputs(struct cvtRecord *pcvt, short *pinactive);
static long readInputs(struct cvtRecord *pcvt);
static long convert(struct cvtRecord *pcvt);
static void monitor(struct cvtRecord *pcvt);
static long checkInit(struct cvtRecord *pcvt);
......@@ -168,8 +168,18 @@ static long init_record(struct cvtRecord *pcvt, int pass)
}
/* initialize input links */
recGblInitConstantLink(&pcvt->inpx, DBF_DOUBLE, &pcvt->x);
recGblInitConstantLink(&pcvt->inpy, DBF_DOUBLE, &pcvt->y);
if (pcvt->inpx.type == CONSTANT) {
recGblInitConstantLink(&pcvt->inpx, DBF_DOUBLE, &pcvt->x);
}
if (pcvt->inpy.type == CONSTANT) {
recGblInitConstantLink(&pcvt->inpy, DBF_DOUBLE, &pcvt->y);
}
if (pcvt->iaml.type == CONSTANT) {
recGblInitConstantLink(&pcvt->iaml, DBF_UCHAR, &pcvt->iaom);
}
if (pcvt->iavl.type == CONSTANT) {
recGblInitConstantLink(&pcvt->iavl, DBF_DOUBLE, &pcvt->iaov);
}
/* try to initialize conversion as specified */
if (initConversion(pcvt->name, pcvt->ntdi, pcvt->nmet, pcvt->nspe, &sub)) {
......@@ -184,7 +194,6 @@ static long init_record(struct cvtRecord *pcvt, int pass)
static long process(struct cvtRecord *pcvt)
{
long status = 0;
short inactive;
pcvt->pact = TRUE;
status = dbGetLink(&pcvt->inil, DBR_UCHAR, &pcvt->init, 0, 0);
......@@ -203,16 +212,14 @@ static long process(struct cvtRecord *pcvt)
}
pcvt->pact = TRUE;
status = readInputs(pcvt, &inactive);
status = readInputs(pcvt);
pcvt->pact = FALSE;
if (status) {
goto error;
}
if (!inactive) {
status = convert(pcvt);
}
status = convert(pcvt);
error:
csm_alarm(pcvt);
......@@ -448,7 +455,7 @@ static void csm_alarm(struct cvtRecord *pcvt)
pcvt->lalm = val;
}
static long readInputs(struct cvtRecord *pcvt, short *pinactive)
static long readInputs(struct cvtRecord *pcvt)
{
long status;
double old;
......@@ -475,39 +482,21 @@ static long readInputs(struct cvtRecord *pcvt, short *pinactive)
pcvt->drty |= DRTY_Y;
}
/* get inactive mode specifier via inlink */
if (pcvt->iaml.type == CONSTANT) {
if (sscanf(pcvt->iaml.value.constantStr,"%hi",pinactive)!=1) {
recGblSetSevr(pcvt, LINK_ALARM, INVALID_ALARM);
errmsg("invalid constant link IAML");
return -1;
}
status = dbGetLink(&pcvt->iaml, DBR_ENUM, &pcvt->iaom, 0, 0);
if (status) {
recGblSetSevr(pcvt, LINK_ALARM, INVALID_ALARM);
errmsg("invalid pv link IAML");
return status;
}
else {
status = dbGetLink(&pcvt->iaml, DBR_SHORT, pinactive, 0, 0);
if (pcvt->iaom) {
status = dbGetLink(&pcvt->iavl, DBR_DOUBLE, &pcvt->iaov, 0, 0);
if (status) {
recGblSetSevr(pcvt, LINK_ALARM, INVALID_ALARM);
errmsg("invalid pv link IAML");
errmsg("invalid pv link IAVL");
return status;
}
}
if (*pinactive) {
if (pcvt->iavl.type == CONSTANT) {
if (epicsScanDouble(pcvt->iavl.value.constantStr, &pcvt->val)!=1) {
recGblSetSevr(pcvt, LINK_ALARM, INVALID_ALARM);
errmsg("invalid constant link IAVL");
return -1;
}
}
else {
status = dbGetLink(&pcvt->iavl, DBR_DOUBLE, &pcvt->val, 0, 0);
if (status) {
recGblSetSevr(pcvt, LINK_ALARM, INVALID_ALARM);
errmsg("invalid pv link IAVL");
return status;
}
}
pcvt->val = pcvt->iaov;
}
return 0;
......@@ -595,47 +584,50 @@ static long convert(struct cvtRecord *pcvt)
{
double value;
/* convert */
switch (pcvt->meth) {
case menuCvtMethodLinear: {
value = pcvt->x * pcvt->xslo + pcvt->y * pcvt->yslo + pcvt->voff;
break;
}
case menuCvtMethodSubroutine: {
cvt_subroutine *csub = (cvt_subroutine *)pcvt->csub;
if (!csub) {
goto error;
if (pcvt->iaom) {
value = pcvt->iaov;
} else {
switch (pcvt->meth) {
case menuCvtMethodLinear: {
value = pcvt->x * pcvt->xslo + pcvt->y * pcvt->yslo + pcvt->voff;
break;
}
value = csub(pcvt->x, pcvt->y, &pcvt->dpvt);
break;
}
case menuCvtMethod1DTable: {
csm_function *csub = (csm_function *)pcvt->csub;
if (!csub) {
goto error;
case menuCvtMethodSubroutine: {
cvt_subroutine *csub = (cvt_subroutine *)pcvt->csub;
if (!csub) {
goto error;
}
value = csub(pcvt->x, pcvt->y, &pcvt->dpvt);
break;
}
value = csm_y(csub, pcvt->x);
break;
}
case menuCvtMethod1DTableInverted: {
csm_function *csub = (csm_function *)pcvt->csub;
if (!csub) {
goto error;
case menuCvtMethod1DTable: {
csm_function *csub = (csm_function *)pcvt->csub;
if (!csub) {
goto error;
}
value = csm_y(csub, pcvt->x);
break;
}
value = csm_x(csub, pcvt->y);
break;
}
case menuCvtMethod2DTable: {
csm_function *csub = (csm_function *)pcvt->csub;
if (!csub) {
case menuCvtMethod1DTableInverted: {
csm_function *csub = (csm_function *)pcvt->csub;
if (!csub) {
goto error;
}
value = csm_x(csub, pcvt->y);
break;
}
case menuCvtMethod2DTable: {
csm_function *csub = (csm_function *)pcvt->csub;
if (!csub) {
goto error;
}
value = csm_z(csub, pcvt->x, pcvt->y);
break;
}
default: {
errmsg("internal error: METH is not a member of menuCvtMethod");
goto error;
}
value = csm_z(csub, pcvt->x, pcvt->y);
break;
}
default: {
errmsg("internal error: METH is not a member of menuCvtMethod");
goto error;
}
}
......
......@@ -87,7 +87,6 @@ recordtype(cvt) {
prompt("Re-Initialize Conversion Location")
promptgroup(GUI_CONVERT)
interest(2)
initial("0")
}
field(CSUB,DBF_NOACCESS) {
prompt("Conversion Subroutine")
......@@ -245,12 +244,23 @@ recordtype(cvt) {
prompt("Inactive Mode Location")
promptgroup(GUI_INPUTS)
interest(1)
initial("0")
}
field(IAVL,DBF_INLINK) {
prompt("Inactive Value Location")
promptgroup(GUI_INPUTS)
interest(1)
initial("0")
}
field(IAOV,DBF_DOUBLE) {
prompt("Inactive Value")
promptgroup(GUI_CONVERT)
interest(1)
pp(TRUE)
}
field(IAOM,DBF_MENU) {
prompt("Inactive Mode")
promptgroup(GUI_CONVERT)
interest(1)
menu(menuYesNo)
pp(TRUE)
}
}
......@@ -274,18 +274,19 @@ Inactive Mode Parameters
========================
The convert record is either in active or inactive mode, depending on the
value retrieved from the input link field IAML, which may be a constant link.
If the value is non-zero, the record will be inactive, otherwise it will be
active. An inactive record does not perform any conversion. Instead VAL is
set to the value retrieved from the link IAVL, which may also be a constant
link directly specifying the value.
IAOM field. If the value is non-zero, the record will be inactive, otherwise
it will be active. The IAML link field can be used to input this value. An
inactive record does not perform any conversion. Instead VAL is set to the
value of the IAOV field. The IAVL link field can be used to input this value.
===== ======================= ======== === ======= ====== ====== ================ ===
Field Summary Type DCT Initial Access Modify Rec Proc Monitor PP
===== ======================= ======== === ======= ====== ====== ================ ===
IAML Inactive Mode Location INLINK Yes Yes Yes No No
IAVL Inactive Value Location INLINK Yes Yes Yes No No
===== ======================= ======== === ======= ====== ====== ================ ===
===== ======================= ============== === ======= ====== ====== ================ ===
Field Summary Type DCT Initial Access Modify Rec Proc Monitor PP
===== ======================= ============== === ======= ====== ====== ================ ===
IAML Inactive Mode Location INLINK Yes Yes Yes No No
IAOM Inactive Mode `menuYesNo`_ Yes 0 Yes Yes No Yes
IAVL Inactive Value Location INLINK Yes Yes Yes No No
IAOV Inactive Value DOUBLE Yes 0 Yes Yes No Yes
===== ======================= ============== === ======= ====== ====== ================ ===
Record Support Routines
......@@ -348,7 +349,11 @@ Routine process implements the following algorithm:
2. Get value of INIT from input link INIL and proceed as in `special`_.
3. Get values of X and Y from INPX and INPY.
3. Read inputs:
- Get values of X and Y from INPX and INPY.
- Get inactive mode IAOM from IAML.
- If inactive, get inactive value IAOV from IAVL.
4. Convert and write result to VAL.
......@@ -361,18 +366,17 @@ Routine process implements the following algorithm:
6. Check severity and write the new value. See
`Record Reference Manual, Invalid Alarm Output Action`_,
for details on how
invalid alarms affect output records.
for details on how invalid alarms affect output records.
7. Check to see if monitors should be invoked:
- Alarm monitors are invoked if the alarm status or severity has
changed.
- Archive and value change monitors are invoked if ADEL and MDEL
conditions are met.
- Monitors for RVAL and for RBV are checked whenever other monitors
are invoked.
- NSEV and NSTA are reset to 0.
- Alarm monitors are invoked if the alarm status or severity has
changed.
- Archive and value change monitors are invoked if ADEL and MDEL
conditions are met.
- Monitors for RVAL and for RBV are checked whenever other monitors
are invoked.
- NSEV and NSTA are reset to 0.
8. Scan forward link if necessary, set PACT to 0, and return.
......@@ -423,4 +427,5 @@ menuCvtInitStateError Error
.. _csm_z: csmApp/html/csmbase_8c.html#c0e3dcd535ce486f004128f9c270cb2b
.. _menuAlarmSevr: http://www.aps.anl.gov/epics/wiki/index.php/RRM_3-14_Menu_Choices#menuAlarmSevr
.. _menuIvoa: http://www.aps.anl.gov/epics/wiki/index.php/RRM_3-14_Menu_Choices#menuIvoa
.. _menuYesNo: http://www.aps.anl.gov/epics/wiki/index.php/RRM_3-14_Menu_Choices#menuYesNo
.. _sub: http://www.aps.anl.gov/epics/wiki/index.php/RRM_3-14_Subroutine
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment