makerelease
This commit is contained in:
223
src/rec/recAi.c
223
src/rec/recAi.c
@ -112,11 +112,15 @@ struct aidset { /* analog input dset */
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ai;/*(-1,0,1)=>(failure,success,don't Continue*/
|
||||
DEVSUPFUN read_ai;/*(0,1,2)=> success and */
|
||||
/*(convert,don't continue, don't convert)*/
|
||||
/* if convert then raw value stored in rval */
|
||||
DEVSUPFUN special_linconv;
|
||||
};
|
||||
|
||||
long convert_ai();
|
||||
void convert();
|
||||
void alarm();
|
||||
void monitor();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -144,8 +148,7 @@ static long report(fp,paddr)
|
||||
if(recGblReportGblChoice(fp,pai,"LLSV",pai->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G ESLO %-12.4G\n",
|
||||
pai->hyst,pai->adel,pai->mdel,pai->eslo)) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X ACHN %d\n",
|
||||
pai->rval,pai->achn)) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X\n",pai->rval)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
pai->lalm,pai->alst,pai->mlst)) return(-1);
|
||||
if(fprintf(fp,"LBRK %d\n",pai->lbrk)) return(-1);
|
||||
@ -158,18 +161,23 @@ static long init_record(pai)
|
||||
struct aidset *pdset;
|
||||
long status;
|
||||
|
||||
/* initialize so that first alarm, archive, and monitor get generated*/
|
||||
pai->lalm = 1e30;
|
||||
pai->alst = 1e30;
|
||||
pai->mlst = 1e30;
|
||||
|
||||
if(!(pdset = (struct aidset *)(pai->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,pai,"ai: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_ai function defined */
|
||||
if( (pdset->number < 5) || (pdset->read_ai == NULL) ) {
|
||||
if( (pdset->number < 6) || (pdset->read_ai == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,pai,"ai: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
pai->init = TRUE;
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pai))) return(status);
|
||||
if((status=(*pdset->init_record)(pai,process))) return(status);
|
||||
}
|
||||
if(pai->linr >= 2) { /*must find breakpoint table*/
|
||||
if( !cvtTable || (cvtTable->number < pai->linr)
|
||||
@ -196,43 +204,19 @@ static long process(paddr)
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
/*pact must not be set true until read_ai completes*/
|
||||
status=(*pdset->read_ai)(pai); /* read the new value */
|
||||
pai->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(1);
|
||||
else if(status == -1) {
|
||||
if(pai->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
pai->stat = READ_ALARM;
|
||||
pai->sevr = MAJOR_ALARM;
|
||||
pai->achn=1;
|
||||
}
|
||||
}
|
||||
else if(status == -2) {
|
||||
if(pai->stat != HW_LIMIT_ALARM) {/* error. set alarm condition */
|
||||
pai->stat = HW_LIMIT_ALARM;
|
||||
pai->sevr = MAJOR_ALARM;
|
||||
pai->achn=1;
|
||||
}
|
||||
status=0;
|
||||
}
|
||||
else if(status!=0) return(status);
|
||||
else if(pai->stat == READ_ALARM || pai->stat == HW_LIMIT_ALARM) {
|
||||
pai->stat = NO_ALARM;
|
||||
pai->sevr = NO_ALARM;
|
||||
pai->achn=1;
|
||||
}
|
||||
if(status==0) status=convert_ai(pai);
|
||||
if(status==1) return(0);
|
||||
if(status==2) status=0; else convert(pai);
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pai);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pai->disa) status = monitor(pai);
|
||||
|
||||
monitor(pai);
|
||||
/* process the forward scan link record */
|
||||
if (pai->flnk.type==DB_LINK) dbScanPassive(&pai->flnk.value);
|
||||
if (pai->flnk.type==DB_LINK) dbScanPassive(&pai->flnk.value.db_link.pdbAddr);
|
||||
|
||||
pai->init=FALSE;
|
||||
pai->pact=FALSE;
|
||||
@ -249,7 +233,7 @@ static long special(paddr,after)
|
||||
|
||||
switch(special_type) {
|
||||
case(SPC_LINCONV):
|
||||
if(pdset->number<5 || !(pdset->special_linconv)) {
|
||||
if(pdset->number<6 || !(pdset->special_linconv)) {
|
||||
recGblDbaddrError(S_db_noMod,paddr,"ai: special");
|
||||
return(S_db_noMod);
|
||||
}
|
||||
@ -268,7 +252,7 @@ static long get_precision(paddr,precision)
|
||||
struct aiRecord *pai=(struct aiRecord *)paddr->precord;
|
||||
|
||||
*precision = pai->prec;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(pai,pvdes)
|
||||
@ -288,7 +272,7 @@ static long get_units(paddr,units)
|
||||
struct aiRecord *pai=(struct aiRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,pai->egu,sizeof(pai->egu));
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
@ -303,7 +287,7 @@ static long get_graphic_double(paddr,pgd)
|
||||
pgd->upper_warning_limit = pai->high;
|
||||
pgd->lower_warning_limit = pai->low;
|
||||
pgd->lower_alarm_limit = pai->lolo;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
@ -314,121 +298,101 @@ static long get_control_double(paddr,pcd)
|
||||
|
||||
pcd->upper_ctrl_limit = pai->hopr;
|
||||
pcd->lower_ctrl_limit = pai->lopr;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long alarm(pai)
|
||||
static void alarm(pai)
|
||||
struct aiRecord *pai;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (pai->stat == READ_ALARM) return(0);
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (pai->stat != NO_ALARM){
|
||||
ftemp = pai->lalm - pai->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < pai->hyst) return(0);
|
||||
}
|
||||
/* if difference is not > hysterisis don't bother */
|
||||
ftemp = pai->lalm - pai->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < pai->hyst) return;
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (pai->hhsv != NO_ALARM){
|
||||
if (pai->nsev<pai->hhsv){
|
||||
if (pai->val > pai->hihi){
|
||||
pai->lalm = pai->val;
|
||||
if (pai->stat != HIHI_ALARM){
|
||||
pai->stat = HIHI_ALARM;
|
||||
pai->sevr = pai->hhsv;
|
||||
pai->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
pai->nsta = HIHI_ALARM;
|
||||
pai->nsev = pai->hhsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pai->llsv != NO_ALARM){
|
||||
if (pai->nsev<pai->llsv){
|
||||
if (pai->val < pai->lolo){
|
||||
pai->lalm = pai->val;
|
||||
if (pai->stat != LOLO_ALARM){
|
||||
pai->stat = LOLO_ALARM;
|
||||
pai->sevr = pai->llsv;
|
||||
pai->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
pai->nsta = LOLO_ALARM;
|
||||
pai->nsev = pai->llsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (pai->hsv != NO_ALARM){
|
||||
if (pai->nsev<pai->hsv){
|
||||
if (pai->val > pai->high){
|
||||
pai->lalm = pai->val;
|
||||
if (pai->stat != HIGH_ALARM){
|
||||
pai->stat = HIGH_ALARM;
|
||||
pai->sevr =pai->hsv;
|
||||
pai->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
pai->nsta = HIGH_ALARM;
|
||||
pai->nsev =pai->hsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pai->lsv != NO_ALARM){
|
||||
if (pai->nsev<pai->lsv){
|
||||
if (pai->val < pai->low){
|
||||
pai->lalm = pai->val;
|
||||
if (pai->stat != LOW_ALARM){
|
||||
pai->stat = LOW_ALARM;
|
||||
pai->sevr = pai->lsv;
|
||||
pai->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
pai->nsta = LOW_ALARM;
|
||||
pai->nsev = pai->lsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (pai->stat != NO_ALARM){
|
||||
pai->stat = NO_ALARM;
|
||||
pai->sevr = NO_ALARM;
|
||||
pai->achn = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(pai)
|
||||
static void monitor(pai)
|
||||
struct aiRecord *pai;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pai->stat;
|
||||
sevr=pai->sevr;
|
||||
nsta=pai->nsta;
|
||||
nsev=pai->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pai->stat = nsta;
|
||||
pai->sevr = nsev;
|
||||
pai->nsta = 0;
|
||||
pai->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pai->mlis.count == 0) return(0L);
|
||||
if (pai->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pai->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(pai,&pai->stat,DBE_VALUE);
|
||||
db_post_events(pai,&pai->sevr,DBE_VALUE);
|
||||
|
||||
}
|
||||
/* check for value change */
|
||||
delta = pai->mlst - pai->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > pai->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
pai->mlst = pai->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = pai->mlst - pai->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > pai->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
pai->mlst = pai->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
@ -437,7 +401,6 @@ static long monitor(pai)
|
||||
if (delta > pai->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
pai->alst = pai->val;
|
||||
}
|
||||
@ -447,24 +410,22 @@ static long monitor(pai)
|
||||
db_post_events(pai,&pai->val,monitor_mask);
|
||||
db_post_events(pai,&pai->rval,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
return;
|
||||
}
|
||||
|
||||
static long convert_ai(pai)
|
||||
static void convert(pai)
|
||||
struct aiRecord *pai;
|
||||
{
|
||||
float val;
|
||||
|
||||
|
||||
val = pai->rval;
|
||||
/* adjust slope and offset */
|
||||
if(pai->aslo != 0.0)
|
||||
val = val * pai->aslo + pai->aoff;
|
||||
else if(pai->aoff != 0.0)
|
||||
val = val + pai->aoff;
|
||||
if(pai->aslo != 0.0) val = val * pai->aslo + pai->aoff;
|
||||
|
||||
/* convert raw to engineering units and signal units */
|
||||
if(pai->linr == 0) {
|
||||
val = pai->val;
|
||||
; /* do nothing*/
|
||||
}
|
||||
else if(pai->linr == 1) {
|
||||
val = (val * pai->eslo) + pai->egul;
|
||||
@ -476,16 +437,7 @@ struct aiRecord *pai;
|
||||
short lbrk;
|
||||
int number;
|
||||
|
||||
val = pai->val;
|
||||
pbrkTable = (struct brkTable *) pai->pbrk;
|
||||
if((val<pbrkTable->rawLow) || (val>pbrkTable->rawHigh)) {
|
||||
if(pai->stat != READ_ALARM) {
|
||||
pai->stat = READ_ALARM;
|
||||
pai->sevr = MAJOR_ALARM;
|
||||
pai->achn = 1;
|
||||
}
|
||||
return(0L);
|
||||
}
|
||||
number = pbrkTable->number;
|
||||
if(pai->init) lbrk = number/2; /* Just start in the middle */
|
||||
else {
|
||||
@ -493,21 +445,28 @@ struct aiRecord *pai;
|
||||
/*make sure we dont go off end of table*/
|
||||
if( (lbrk+1) >= number ) lbrk--;
|
||||
}
|
||||
pInt = (pbrkTable->papBrkInt[lbrk]);
|
||||
pnxtInt = (pbrkTable->papBrkInt[lbrk+1]);
|
||||
pInt = pbrkTable->papBrkInt[lbrk];
|
||||
pnxtInt = pbrkTable->papBrkInt[lbrk+1];
|
||||
/* find entry for increased value */
|
||||
while( (pnxtInt->raw) <= val ) {
|
||||
if( lbrk >= number-1) {
|
||||
errMessage(S_db_badField,"breakpoint table error");
|
||||
return(S_db_badField);
|
||||
if(pai->nsev < MAJOR_ALARM) {
|
||||
pai->nsta = SOFT_ALARM;
|
||||
pai->nsev = MAJOR_ALARM;
|
||||
}
|
||||
break; /* out of while */
|
||||
}
|
||||
lbrk++;
|
||||
pInt = pbrkTable->papBrkInt[lbrk];
|
||||
pnxtInt = pbrkTable->papBrkInt[lbrk+1];
|
||||
}
|
||||
while( (pInt->raw) > val) {
|
||||
if(lbrk==0) {
|
||||
errMessage(S_db_badField,"breakpoint table error");
|
||||
return(S_db_badField);
|
||||
if(pai->nsev < MAJOR_ALARM) {
|
||||
pai->nsta = SOFT_ALARM;
|
||||
pai->nsev = MAJOR_ALARM;
|
||||
}
|
||||
break; /* out of while */
|
||||
}
|
||||
lbrk--;
|
||||
pInt = pbrkTable->papBrkInt[lbrk];
|
||||
@ -517,11 +476,11 @@ struct aiRecord *pai;
|
||||
}
|
||||
|
||||
/* apply smoothing algorithm */
|
||||
if (pai->smoo != 0){
|
||||
if (pai->smoo != 0.0){
|
||||
if (pai->init == 0) pai->val = val; /* initial condition */
|
||||
pai->val = val * (1.00 - pai->smoo) + (pai->val * pai->smoo);
|
||||
}else{
|
||||
pai->val = val;
|
||||
}
|
||||
return(0L);
|
||||
return;
|
||||
}
|
||||
|
381
src/rec/recAo.c
381
src/rec/recAo.c
@ -1,4 +1,3 @@
|
||||
|
||||
/* recAo.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -57,13 +56,13 @@
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <devSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <special.h>
|
||||
#include <recSup.h>
|
||||
#include <aoRecord.h>
|
||||
|
||||
@ -108,19 +107,26 @@ struct aodset { /* analog input dset */
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_ao;
|
||||
DEVSUPFUN write_ao;
|
||||
DEVSUPFUN write_ao;/*(0,1)=>success and */
|
||||
/*(continue, don`t continue) */
|
||||
DEVSUPFUN special_linconv;
|
||||
};
|
||||
|
||||
/* the following definitions must match those in choiceGbl.ascii */
|
||||
#define OUTPUT_FULL 0
|
||||
#define SUPERVISORY 0
|
||||
#define CLOSED_LOOP 1
|
||||
|
||||
/* the following definitions must match those in choiceRec.ascii */
|
||||
#define OUTPUT_FULL 0
|
||||
#define OUTPUT_INCREMENTAL 1
|
||||
|
||||
/* The following must match the definition in choiceGbl.ascii */
|
||||
#define LINEAR 1
|
||||
|
||||
long convert_ao();
|
||||
void alarm();
|
||||
void convert();
|
||||
void monitor();
|
||||
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -148,8 +154,7 @@ static long report(fp,paddr)
|
||||
if(recGblReportGblChoice(fp,pao,"LLSV",pao->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G ESLO %-12.4G\n",
|
||||
pao->hyst,pao->adel,pao->mdel,pao->eslo)) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X ACHN %d\n",
|
||||
pao->rval,pao->achn)) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X\n", pao->rval)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
pao->lalm,pao->alst,pao->mlst)) return(-1);
|
||||
return(0);
|
||||
@ -161,18 +166,22 @@ static long init_record(pao)
|
||||
struct aodset *pdset;
|
||||
long status;
|
||||
|
||||
/* initialize so that first alarm, archive, and monitor get generated*/
|
||||
pao->lalm = 1e30;
|
||||
pao->alst = 1e30;
|
||||
pao->mlst = 1e30;
|
||||
|
||||
if(!(pdset = (struct aodset *)(pao->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,pao,"ao: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_ao and write_ao function defined */
|
||||
if( (pdset->number < 6) || (pdset->read_ao == NULL) ||(pdset->write_ao ==NULL) ) {
|
||||
/* must have write_ao function defined */
|
||||
if( (pdset->number < 6) || (pdset->write_ao ==NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,pao,"ao: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
pao->init = TRUE;
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pao))) return(status);
|
||||
if((status=(*pdset->init_record)(pao,process))) return(status);
|
||||
}
|
||||
/* get the intial value */
|
||||
if ((pao->dol.type == CONSTANT) && (pao->dol.value.value != 0)){
|
||||
@ -187,93 +196,53 @@ static long process(paddr)
|
||||
struct aoRecord *pao=(struct aoRecord *)(paddr->precord);
|
||||
struct aodset *pdset = (struct aodset *)(pao->dset);
|
||||
long status;
|
||||
long nRequest;
|
||||
float value;
|
||||
float diff;
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_ao==NULL) ) {
|
||||
pao->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pao,"write_ao");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
/* fetch the desired output if there is a database link */
|
||||
if ((pao->dol.type == DB_LINK) && (pao->omsl == CLOSED_LOOP)){
|
||||
nRequest=1;
|
||||
if (dbGetLink(&pao->dol.value,DBR_FLOAT,&value,&nRequest) < 0){
|
||||
if (pao->stat != READ_ALARM){
|
||||
pao->stat = READ_ALARM;
|
||||
pao->sevr = MAJOR_ALARM;
|
||||
pao->achn = 1;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
if (pao->oif == OUTPUT_FULL)
|
||||
pao->val = value; /* output full */
|
||||
else
|
||||
pao->val += value; /* output incremental */
|
||||
}
|
||||
|
||||
/* apply the output rate of change */
|
||||
if (pao->oroc){
|
||||
diff = pao->val - pao->oval;
|
||||
if (diff < 0){
|
||||
if (pao->oroc < -diff){
|
||||
pao->oval -= pao->oroc;
|
||||
}else{
|
||||
pao->oval = pao->val;
|
||||
}
|
||||
}else if (pao->oroc < diff){
|
||||
pao->oval += pao->oroc;
|
||||
}else{
|
||||
pao->oval = pao->val;
|
||||
}
|
||||
}else{
|
||||
pao->oval = pao->val;
|
||||
}
|
||||
/* MARTY check for HW_LIMIT*/
|
||||
if(pao->pact == 0) convert(pao);
|
||||
status=(*pdset->write_ao)(pao); /* write the new value */
|
||||
pao->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(1);
|
||||
else if(status == -1) {
|
||||
if(pao->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
pao->stat = READ_ALARM;
|
||||
pao->sevr = MAJOR_ALARM;
|
||||
pao->achn=1;
|
||||
}
|
||||
}
|
||||
else if(status!=0) return(status);
|
||||
else if(pao->stat == READ_ALARM || pao->stat == HW_LIMIT_ALARM) {
|
||||
pao->stat = NO_ALARM;
|
||||
pao->sevr = NO_ALARM;
|
||||
pao->achn=1;
|
||||
}
|
||||
if(status==0) status=convert_ao(pao);
|
||||
/* MARTY convert_ao_rb */
|
||||
|
||||
/* report no harware error if previous hardware error */
|
||||
if ((pao->stat == READ_ALARM) || (pao->stat == WRITE_ALARM)){
|
||||
pao->stat = NO_ALARM;
|
||||
pao->sevr = NO_ALARM;
|
||||
pao->achn = 1;
|
||||
}
|
||||
if(status==1) return(0);
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pao);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pao->disa) status = monitor(pao);
|
||||
monitor(pao);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pao->flnk.type==DB_LINK) dbScanPassive(&pao->flnk.value);
|
||||
if (pao->flnk.type==DB_LINK) dbScanPassive(&pao->flnk.value.db_link.pdbAddr);
|
||||
|
||||
pao->init=FALSE;
|
||||
pao->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long special(paddr,after)
|
||||
struct dbAddr *paddr;
|
||||
int after;
|
||||
{
|
||||
struct aoRecord *pao = (struct aoRecord *)(paddr->precord);
|
||||
struct aodset *pdset = (struct aodset *) (pao->dset);
|
||||
int special_type = paddr->special;
|
||||
|
||||
switch(special_type) {
|
||||
case(SPC_LINCONV):
|
||||
if(pdset->number<6 || !(pdset->special_linconv)) {
|
||||
recGblDbaddrError(S_db_noMod,paddr,"ao: special");
|
||||
return(S_db_noMod);
|
||||
}
|
||||
return((*pdset->special_linconv)(pao,after));
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"ao: special");
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
}
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
@ -282,7 +251,7 @@ static long get_precision(paddr,precision)
|
||||
struct aoRecord *pao=(struct aoRecord *)paddr->precord;
|
||||
|
||||
*precision = pao->prec;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(pao,pvdes)
|
||||
@ -302,7 +271,7 @@ static long get_units(paddr,units)
|
||||
struct aoRecord *pao=(struct aoRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,pao->egu,sizeof(pao->egu));
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
@ -317,7 +286,7 @@ static long get_graphic_double(paddr,pgd)
|
||||
pgd->upper_warning_limit = pao->high;
|
||||
pgd->lower_warning_limit = pao->low;
|
||||
pgd->lower_alarm_limit = pao->lolo;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
@ -328,162 +297,164 @@ static long get_control_double(paddr,pcd)
|
||||
|
||||
pcd->upper_ctrl_limit = pao->hopr;
|
||||
pcd->lower_ctrl_limit = pao->lopr;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long alarm(pao)
|
||||
static void alarm(pao)
|
||||
struct aoRecord *pao;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (pao->stat == READ_ALARM) return(0);
|
||||
if (pao->stat == WRITE_ALARM) return(0);
|
||||
if (pao->stat == HW_LIMIT_ALARM) return(0);
|
||||
/* if difference is not > hysterisis don't bother */
|
||||
ftemp = pao->lalm - pao->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < pao->hyst) return;
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (pao->stat != NO_ALARM){
|
||||
ftemp = pao->lalm - pao->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < pao->hyst) return(0);
|
||||
}
|
||||
/* alarm condition hihi */
|
||||
if (pao->nsev<pao->hhsv){
|
||||
if (pao->val > pao->hihi){
|
||||
pao->lalm = pao->val;
|
||||
pao->nsta = HIHI_ALARM;
|
||||
pao->nsev = pao->hhsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (pao->hhsv != NO_ALARM){
|
||||
if (pao->val > pao->hihi){
|
||||
pao->lalm = pao->val;
|
||||
if (pao->stat != HIHI_ALARM){
|
||||
pao->stat = HIHI_ALARM;
|
||||
pao->sevr = pao->hhsv;
|
||||
pao->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* alarm condition lolo */
|
||||
if (pao->nsev<pao->llsv){
|
||||
if (pao->val < pao->lolo){
|
||||
pao->lalm = pao->val;
|
||||
pao->nsta = LOLO_ALARM;
|
||||
pao->nsev = pao->llsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pao->llsv != NO_ALARM){
|
||||
if (pao->val < pao->lolo){
|
||||
pao->lalm = pao->val;
|
||||
if (pao->stat != LOLO_ALARM){
|
||||
pao->stat = LOLO_ALARM;
|
||||
pao->sevr = pao->llsv;
|
||||
pao->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* alarm condition high */
|
||||
if (pao->nsev<pao->hsv){
|
||||
if (pao->val > pao->high){
|
||||
pao->lalm = pao->val;
|
||||
pao->nsta = HIGH_ALARM;
|
||||
pao->nsev =pao->hsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (pao->hsv != NO_ALARM){
|
||||
if (pao->val > pao->high){
|
||||
pao->lalm = pao->val;
|
||||
if (pao->stat != HIGH_ALARM){
|
||||
pao->stat = HIGH_ALARM;
|
||||
pao->sevr =pao->hsv;
|
||||
pao->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pao->lsv != NO_ALARM){
|
||||
if (pao->val < pao->low){
|
||||
pao->lalm = pao->val;
|
||||
if (pao->stat != LOW_ALARM){
|
||||
pao->stat = LOW_ALARM;
|
||||
pao->sevr = pao->lsv;
|
||||
pao->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (pao->stat != NO_ALARM){
|
||||
pao->stat = NO_ALARM;
|
||||
pao->sevr = NO_ALARM;
|
||||
pao->achn = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
/* alarm condition lolo */
|
||||
if (pao->nsev<pao->lsv){
|
||||
if (pao->val < pao->low){
|
||||
pao->lalm = pao->val;
|
||||
pao->nsta = LOW_ALARM;
|
||||
pao->nsev = pao->lsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(pao)
|
||||
static void monitor(pao)
|
||||
struct aoRecord *pao;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pao->stat;
|
||||
sevr=pao->sevr;
|
||||
nsta=pao->nsta;
|
||||
nsev=pao->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pao->stat = nsta;
|
||||
pao->sevr = nsev;
|
||||
pao->nsta = 0;
|
||||
pao->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pao->mlis.count == 0) return(0L);
|
||||
if (pao->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pao->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(pao,&pao->stat,DBE_VALUE);
|
||||
db_post_events(pao,&pao->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
delta = pao->mlst - pao->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > pao->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
pao->mlst = pao->val;
|
||||
}
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pao,&pao->stat,DBE_VALUE);
|
||||
db_post_events(pao,&pao->sevr,DBE_VALUE);
|
||||
/* check for archive change */
|
||||
delta = pao->alst - pao->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > pao->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
pao->alst = pao->val;
|
||||
}
|
||||
|
||||
/* update last value monitored */
|
||||
pao->mlst = pao->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = pao->mlst - pao->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > pao->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
pao->mlst = pao->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
delta = pao->alst - pao->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > pao->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
pao->alst = pao->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pao,&pao->val,monitor_mask);
|
||||
db_post_events(pao,&pao->rval,monitor_mask);
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pao,&pao->val,monitor_mask);
|
||||
db_post_events(pao,&pao->rval,monitor_mask);
|
||||
db_post_events(pao,&pao->rbv,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
return;
|
||||
}
|
||||
|
||||
static convert_ao_rb(value,pao)
|
||||
unsigned short value; /* readback raw value */
|
||||
struct aoRecord *pao;
|
||||
{
|
||||
|
||||
switch (pao->linr){
|
||||
case (LINEAR):
|
||||
pao->rbv = (value * pao->eslo) + pao->egul;
|
||||
break;
|
||||
default:
|
||||
pao->rbv = value;
|
||||
}
|
||||
}
|
||||
|
||||
static convert_ao(pao)
|
||||
static void convert(pao)
|
||||
struct aoRecord *pao;
|
||||
{
|
||||
/* fetch the desired output if there is a database link */
|
||||
if ((pao->dol.type == DB_LINK) && (pao->omsl == CLOSED_LOOP)){
|
||||
long nRequest;
|
||||
long options;
|
||||
short save_pact;
|
||||
float value;
|
||||
|
||||
options=0;
|
||||
nRequest=1;
|
||||
save_pact = pao->pact;
|
||||
pao->pact = TRUE;
|
||||
(void)dbGetLink(&pao->dol.value,DBR_FLOAT,&value,&options,&nRequest);
|
||||
if (pao->oif == OUTPUT_FULL)
|
||||
pao->val = value; /* output full */
|
||||
else
|
||||
pao->val += value; /* output incremental */
|
||||
pao->pact = save_pact;
|
||||
}
|
||||
|
||||
/* apply the output rate of change */
|
||||
if (pao->oroc){
|
||||
float diff;
|
||||
|
||||
diff = pao->val - pao->oval;
|
||||
if (diff < 0){
|
||||
if (pao->oroc < -diff){
|
||||
pao->oval -= pao->oroc;
|
||||
}else{
|
||||
pao->oval = pao->val;
|
||||
}
|
||||
}else if (pao->oroc < diff){
|
||||
pao->oval += pao->oroc;
|
||||
}else{
|
||||
pao->oval = pao->val;
|
||||
}
|
||||
}else{
|
||||
pao->oval = pao->val;
|
||||
}
|
||||
|
||||
/* check drive limits */
|
||||
if (pao->oval > pao->drvh) pao->oval = pao->drvh;
|
||||
else if (pao->oval < pao->drvl) pao->oval = pao->drvl;
|
||||
|
123
src/rec/recBi.c
123
src/rec/recBi.c
@ -1,4 +1,3 @@
|
||||
|
||||
/* recBi.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -51,7 +50,6 @@
|
||||
#include <strLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -67,8 +65,8 @@ long report();
|
||||
#define initialize NULL
|
||||
long init_record();
|
||||
long process();
|
||||
long special();
|
||||
long get_precision();
|
||||
#define special NULL
|
||||
#define get_precision NULL
|
||||
long get_value();
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
@ -78,7 +76,6 @@ long get_enum_str();
|
||||
#define get_graphic_double NULL
|
||||
#define get_control_double NULL
|
||||
long get_enum_strs();
|
||||
|
||||
struct rset biRSET={
|
||||
RSETNUMBER,
|
||||
report,
|
||||
@ -96,7 +93,6 @@ struct rset biRSET={
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_enum_strs };
|
||||
|
||||
struct bidset { /* binary input dset */
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
@ -105,6 +101,9 @@ struct bidset { /* binary input dset */
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_bi;/*(-1,0,1)=>(failure,success,don't Continue*/
|
||||
};
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -120,7 +119,8 @@ static long report(fp,paddr)
|
||||
pbi->rval)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long init_record(pbi)
|
||||
struct biRecord *pbi;
|
||||
{
|
||||
@ -137,8 +137,10 @@ static long init_record(pbi)
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pbi))) return(status);
|
||||
if((status=(*pdset->init_record)(pbi,process))) return(status);
|
||||
}
|
||||
pbi->mlst = -1;
|
||||
pbi->lalm = -1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -160,29 +162,13 @@ static long process(paddr)
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(1);
|
||||
else if(status == -1) {
|
||||
if(pbi->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
pbi->stat = READ_ALARM;
|
||||
pbi->sevr = MAJOR_ALARM;
|
||||
pbi->achn=1;
|
||||
}
|
||||
}
|
||||
else if(status!=0) return(status);
|
||||
else if(pbi->stat == READ_ALARM) {
|
||||
pbi->stat = NO_ALARM;
|
||||
pbi->sevr = NO_ALARM;
|
||||
pbi->achn=1;
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pbi);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pbi->disa) status = monitor(pbi);
|
||||
|
||||
monitor(pbi);
|
||||
/* process the forward scan link record */
|
||||
if (pbi->flnk.type==DB_LINK) dbScanPassive(&pbi->flnk.value);
|
||||
if (pbi->flnk.type==DB_LINK) dbScanPassive(&pbi->flnk.value.db_link.pdbAddr);
|
||||
|
||||
pbi->pact=FALSE;
|
||||
return(status);
|
||||
@ -207,11 +193,11 @@ static long get_enum_str(paddr,pstring)
|
||||
if(pbi->val==0) {
|
||||
strncpy(pstring,pbi->znam,sizeof(pbi->znam));
|
||||
pstring[sizeof(pbi->znam)] = 0;
|
||||
} else if(pbi->val==0) {
|
||||
} else if(pbi->val==1) {
|
||||
strncpy(pstring,pbi->onam,sizeof(pbi->onam));
|
||||
pstring[sizeof(pbi->onam)] = 0;
|
||||
} else {
|
||||
strcpy(pstring,"Illegal Value");
|
||||
strcpy(pstring,"Illegal_Value");
|
||||
}
|
||||
return(0L);
|
||||
}
|
||||
@ -229,89 +215,72 @@ static long get_enum_strs(paddr,pes)
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long alarm(pbi)
|
||||
static void alarm(pbi)
|
||||
struct biRecord *pbi;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (pbi->stat == READ_ALARM) return(0);
|
||||
|
||||
if (pbi->val == pbi->lalm){
|
||||
/* no new message for COS alarms */
|
||||
if (pbi->stat == COS_ALARM){
|
||||
pbi->stat = NO_ALARM;
|
||||
pbi->sevr = NO_ALARM;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (pbi->val == pbi->lalm) return;
|
||||
|
||||
/* set last alarmed value */
|
||||
pbi->lalm = pbi->val;
|
||||
|
||||
/* check for state alarm */
|
||||
if (pbi->val == 0){
|
||||
if (pbi->zsv != NO_ALARM){
|
||||
pbi->stat = STATE_ALARM;
|
||||
pbi->sevr = pbi->zsv;
|
||||
pbi->achn = 1;
|
||||
return;
|
||||
if (pbi->nsev<pbi->zsv){
|
||||
pbi->nsta = STATE_ALARM;
|
||||
pbi->nsev = pbi->zsv;
|
||||
}
|
||||
}else{
|
||||
if (pbi->osv != NO_ALARM){
|
||||
pbi->stat = STATE_ALARM;
|
||||
pbi->sevr = pbi->osv;
|
||||
pbi->achn = 1;
|
||||
return;
|
||||
if (pbi->nsev<pbi->osv){
|
||||
pbi->nsta = STATE_ALARM;
|
||||
pbi->nsev = pbi->osv;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for cos alarm */
|
||||
if (pbi->cosv != NO_ALARM){
|
||||
pbi->sevr = pbi->cosv;
|
||||
pbi->stat = COS_ALARM;
|
||||
pbi->achn = 1;
|
||||
return;
|
||||
if (pbi->nsev<pbi->cosv) {
|
||||
pbi->nsta = COS_ALARM;
|
||||
pbi->nsev = pbi->cosv;
|
||||
}
|
||||
|
||||
/* check for change from alarm to no alarm */
|
||||
if (pbi->sevr != NO_ALARM){
|
||||
pbi->sevr = NO_ALARM;
|
||||
pbi->stat = NO_ALARM;
|
||||
pbi->achn = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(pbi)
|
||||
static void monitor(pbi)
|
||||
struct biRecord *pbi;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pbi->stat;
|
||||
sevr=pbi->sevr;
|
||||
nsta=pbi->nsta;
|
||||
nsev=pbi->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pbi->stat = nsta;
|
||||
pbi->sevr = nsev;
|
||||
pbi->nsta = 0;
|
||||
pbi->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pbi->mlis.count == 0) return(0L);
|
||||
if (pbi->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pbi->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
|
||||
if (stat!=nsta || sevr!=nsev){
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pbi,&pbi->stat,DBE_VALUE);
|
||||
db_post_events(pbi,&pbi->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pbi->mlst = pbi->val;
|
||||
}
|
||||
/* check for value change */
|
||||
}else if (pbi->mlst != pbi->val){
|
||||
if (pbi->mlst != pbi->val){
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
|
||||
/* update last value monitored */
|
||||
pbi->mlst = pbi->val;
|
||||
}
|
||||
@ -321,5 +290,5 @@ static long monitor(pbi)
|
||||
db_post_events(pbi,&pbi->val,monitor_mask);
|
||||
db_post_events(pbi,&pbi->rval,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
return;
|
||||
}
|
||||
|
204
src/rec/recBo.c
204
src/rec/recBo.c
@ -1,4 +1,3 @@
|
||||
|
||||
/* recBo.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -57,9 +56,9 @@
|
||||
#include <stdioLib.h>
|
||||
#include <lstLib.h>
|
||||
#include <strLib.h>
|
||||
#include <wdLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -75,8 +74,8 @@ long report();
|
||||
#define initialize NULL
|
||||
long init_record();
|
||||
long process();
|
||||
long special();
|
||||
long get_precision();
|
||||
#define special NULL
|
||||
#define get_precision NULL
|
||||
long get_value();
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
@ -111,13 +110,33 @@ struct bodset { /* binary output dset */
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_bo;/*(-1,0)=>(failure,success*/
|
||||
DEVSUPFUN write_bo;/*(-1,0,1)=>(failure,success,don't Continue*/
|
||||
};
|
||||
|
||||
/* the following definitions must match those in choiceGbl.ascii */
|
||||
#define OUTPUT_FULL 0
|
||||
#define SUPERVISORY 0
|
||||
#define CLOSED_LOOP 1
|
||||
|
||||
/* control block for callback*/
|
||||
struct callback {
|
||||
void (*callback)();
|
||||
struct dbAddr dbAddr;
|
||||
WDOG_ID wd_id;
|
||||
short completion;
|
||||
};
|
||||
|
||||
void callbackRequest();
|
||||
void alarm();
|
||||
void monitor();
|
||||
|
||||
static void myCallback(pcallback)
|
||||
struct callback *pcallback;
|
||||
{
|
||||
short value=0;
|
||||
|
||||
pcallback->completion = TRUE;
|
||||
dbPutField(&(pcallback->dbAddr),DBR_SHORT,&value,1L);
|
||||
}
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -139,13 +158,14 @@ static long init_record(pbo)
|
||||
{
|
||||
struct bodset *pdset;
|
||||
long status;
|
||||
struct callback *pcallback;
|
||||
|
||||
if(!(pdset = (struct bodset *)(pbo->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,pbo,"bo: init_record");
|
||||
return(S_dev_noDSET);
|
||||
}
|
||||
/* must have read_bo and write_bo functions defined */
|
||||
if( (pdset->number < 5) || (pdset->read_bo == NULL) || (pdset->write_bo == NULL) ) {
|
||||
/* must have write_bo functions defined */
|
||||
if( (pdset->number < 5) || (pdset->write_bo == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,pbo,"bo: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
@ -155,9 +175,15 @@ static long init_record(pbo)
|
||||
else pbo->val = 0;
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pbo))) return(status);
|
||||
if((status=(*pdset->init_record)(pbo,process))) return(status);
|
||||
}
|
||||
pcallback = (struct callback *)(calloc(1,sizeof(struct callback *)));
|
||||
pbo->dpvt = (caddr_t)pcallback;
|
||||
pcallback->callback = myCallback;
|
||||
if(dbNameToAddr(pbo->name,&(pcallback->dbAddr))) {
|
||||
logMsg("dbNameToAddr failed in init_record for devAiTestAsyn\n");
|
||||
exit(1);
|
||||
}
|
||||
pbo->time = pbo->high * 60; /* seconds to ticks */
|
||||
pbo->lalm = -1;
|
||||
pbo->mlst = -1;
|
||||
return(0);
|
||||
@ -170,11 +196,13 @@ static long process(paddr)
|
||||
struct bodset *pdset = (struct bodset *)(pbo->dset);
|
||||
long status;
|
||||
long nRequest;
|
||||
float fval;
|
||||
struct callback *pcallback;
|
||||
int wait_time;
|
||||
short val;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_bo==NULL) ) {
|
||||
if( (pdset==NULL) || (pdset->write_bo==NULL) ) {
|
||||
pbo->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pbo,"read_bo");
|
||||
recGblRecordError(S_dev_missingSup,pbo,"write_bo");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
@ -182,35 +210,28 @@ static long process(paddr)
|
||||
/* fetch the desired output if there is a database link */
|
||||
if ( !(pbo->pact) && (pbo->dol.type == DB_LINK) && (pbo->omsl == CLOSED_LOOP)){
|
||||
nRequest = 1;
|
||||
if (dbGetLink(&pbo->dol.value,DBF_SHORT,&fval,&nRequest) < 0){
|
||||
if (pbo->stat != READ_ALARM){
|
||||
pbo->stat = READ_ALARM;
|
||||
pbo->sevr = MAJOR_ALARM;
|
||||
pbo->achn = 1;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
if (fval != 0) pbo->val = 1;
|
||||
else pbo->val = 0;
|
||||
status = dbGetLink(&pbo->dol.value,DBF_SHORT,&val,&nRequest);
|
||||
if(status == 0){
|
||||
if (val != 0) pbo->val = 1;
|
||||
else pbo->val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
status=(*pdset->write_bo)(pbo); /* write the new value */
|
||||
pbo->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(1);
|
||||
else if(status == -1) {
|
||||
if(pbo->stat != WRITE_ALARM) {/* error. set alarm condition */
|
||||
pbo->stat = WRITE_ALARM;
|
||||
pbo->sevr = MAJOR_ALARM;
|
||||
pbo->achn=1;
|
||||
}
|
||||
}
|
||||
else if(status!=0) return(status);
|
||||
else if(pbo->stat == WRITE_ALARM) {
|
||||
pbo->stat = NO_ALARM;
|
||||
pbo->sevr = NO_ALARM;
|
||||
pbo->achn=1;
|
||||
if(status==1) return(0);
|
||||
|
||||
wait_time = (int)(pbo->high) * vxTicksPerSecond; /* seconds to ticks */
|
||||
if(pbo->val==1 && wait_time>0) {
|
||||
pcallback = (struct callback *)(pbo->dpvt);
|
||||
if(pcallback->completion==TRUE) {
|
||||
pcallback->completion=FALSE;
|
||||
} else {
|
||||
if(pcallback->wd_id==NULL) pcallback->wd_id = wdCreate();
|
||||
wdStart(pcallback->wd_id,wait_time,callbackRequest,pcallback);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
@ -218,10 +239,10 @@ static long process(paddr)
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pbo->disa) status = monitor(pbo);
|
||||
monitor(pbo);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pbo->flnk.type==DB_LINK) dbScanPassive(&pbo->flnk.value);
|
||||
if (pbo->flnk.type==DB_LINK) dbScanPassive(&pbo->flnk.value.db_link.pdbAddr);
|
||||
|
||||
pbo->pact=FALSE;
|
||||
return(status);
|
||||
@ -246,11 +267,11 @@ static long get_enum_str(paddr,pstring)
|
||||
if(pbo->val==0) {
|
||||
strncpy(pstring,pbo->znam,sizeof(pbo->znam));
|
||||
pstring[sizeof(pbo->znam)] = 0;
|
||||
} else if(pbo->val==0) {
|
||||
} else if(pbo->val==1) {
|
||||
strncpy(pstring,pbo->onam,sizeof(pbo->onam));
|
||||
pstring[sizeof(pbo->onam)] = 0;
|
||||
} else {
|
||||
strcpy(pstring,"Illegal Value");
|
||||
strcpy(pstring,"Illegal_Value");
|
||||
}
|
||||
return(0L);
|
||||
}
|
||||
@ -268,98 +289,81 @@ static long get_enum_strs(paddr,pes)
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long alarm(pbo)
|
||||
static void alarm(pbo)
|
||||
struct boRecord *pbo;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (pbo->stat == WRITE_ALARM || pbo->stat == READ_ALARM) return(0);
|
||||
|
||||
if (pbo->val == pbo->lalm){
|
||||
/* no new message for COS alarms */
|
||||
if (pbo->stat == COS_ALARM){
|
||||
pbo->stat = NO_ALARM;
|
||||
pbo->sevr = NO_ALARM;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (pbo->val == pbo->lalm) return;
|
||||
|
||||
/* set last alarmed value */
|
||||
pbo->lalm = pbo->val;
|
||||
|
||||
/* check for state alarm */
|
||||
if (pbo->val == 0){
|
||||
if (pbo->zsv != NO_ALARM){
|
||||
pbo->stat = STATE_ALARM;
|
||||
pbo->sevr = pbo->zsv;
|
||||
pbo->achn = 1;
|
||||
return;
|
||||
if (pbo->nsev<pbo->zsv){
|
||||
pbo->nsta = STATE_ALARM;
|
||||
pbo->nsev = pbo->zsv;
|
||||
}
|
||||
}else{
|
||||
if (pbo->osv != NO_ALARM){
|
||||
pbo->stat = STATE_ALARM;
|
||||
pbo->sevr = pbo->osv;
|
||||
pbo->achn = 1;
|
||||
return;
|
||||
if (pbo->nsev<pbo->osv){
|
||||
pbo->nsta = STATE_ALARM;
|
||||
pbo->nsev = pbo->osv;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for cos alarm */
|
||||
if (pbo->cosv != NO_ALARM){
|
||||
pbo->sevr = pbo->cosv;
|
||||
pbo->stat = COS_ALARM;
|
||||
pbo->achn = 1;
|
||||
return;
|
||||
if (pbo->nsev<pbo->cosv) {
|
||||
pbo->nsta = COS_ALARM;
|
||||
pbo->nsev = pbo->cosv;
|
||||
}
|
||||
|
||||
/* check for change from alarm to no alarm */
|
||||
if (pbo->sevr != NO_ALARM){
|
||||
pbo->sevr = NO_ALARM;
|
||||
pbo->stat = NO_ALARM;
|
||||
pbo->achn = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(pbo)
|
||||
static void monitor(pbo)
|
||||
struct boRecord *pbo;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pbo->mlis.count == 0) return(0L);
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pbo->stat;
|
||||
sevr=pbo->sevr;
|
||||
nsta=pbo->nsta;
|
||||
nsev=pbo->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pbo->stat = nsta;
|
||||
pbo->sevr = nsev;
|
||||
pbo->nsta = 0;
|
||||
pbo->nsev = 0;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pbo->mlis.count == 0) return;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pbo->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pbo,&pbo->stat,DBE_VALUE);
|
||||
db_post_events(pbo,&pbo->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pbo->mlst = pbo->val;
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev){
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pbo,&pbo->stat,DBE_VALUE);
|
||||
db_post_events(pbo,&pbo->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
}else if (pbo->mlst != pbo->val){
|
||||
if (pbo->mlst != pbo->val){
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
|
||||
/* update last value monitored */
|
||||
pbo->mlst = pbo->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pbo,&pbo->val,monitor_mask);
|
||||
db_post_events(pbo,&pbo->rval,monitor_mask);
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pbo,&pbo->val,monitor_mask);
|
||||
db_post_events(pbo,&pbo->rval,monitor_mask);
|
||||
db_post_events(pbo,&pbo->rbv,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recCalc.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -64,11 +63,9 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <devSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
@ -109,6 +106,308 @@ struct rset calcRSET={
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_enum_strs };
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
int do_calc();
|
||||
long postfix();
|
||||
void fetch_values();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord*)(paddr->precord);
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
if(fprintf(fp,"VAL %-12.4G\n",pcalc->val)) return(-1);
|
||||
if(recGblReportLink(fp,"INPA ",&(pcalc->inpa))) return(-1);
|
||||
if(recGblReportLink(fp,"INPB ",&(pcalc->inpb))) return(-1);
|
||||
if(recGblReportLink(fp,"INPC ",&(pcalc->inpc))) return(-1);
|
||||
if(recGblReportLink(fp,"INPD ",&(pcalc->inpd))) return(-1);
|
||||
if(recGblReportLink(fp,"INPE ",&(pcalc->inpe))) return(-1);
|
||||
if(recGblReportLink(fp,"INPF ",&(pcalc->inpf))) return(-1);
|
||||
if(recGblReportLink(fp,"FLNK",&(pcalc->flnk))) return(-1);
|
||||
if(fprintf(fp,"A %-12.4G\n",pcalc->a)) return(-1);
|
||||
if(fprintf(fp,"B %-12.4G\n",pcalc->b)) return(-1);
|
||||
if(fprintf(fp,"C %-12.4G\n",pcalc->c)) return(-1);
|
||||
if(fprintf(fp,"D %-12.4G\n",pcalc->d)) return(-1);
|
||||
if(fprintf(fp,"E %-12.4G\n",pcalc->e)) return(-1);
|
||||
if(fprintf(fp,"F %-12.4G\n",pcalc->f)) return(-1);
|
||||
if(fprintf(fp,"PREC %d EGU %-8s\n",pcalc->prec,pcalc->egu)) return(-1);
|
||||
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
|
||||
pcalc->hopr,pcalc->lopr)) return(-1);
|
||||
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
|
||||
pcalc->hihi,pcalc->high,pcalc->low,pcalc->lolo)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"HHSV",pcalc->hhsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"HSV ",pcalc->hsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"LSV ",pcalc->lsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"LLSV",pcalc->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G\n",
|
||||
pcalc->hyst,pcalc->adel,pcalc->mdel)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
pcalc->lalm,pcalc->alst,pcalc->mlst)) return(-1);
|
||||
if(fprintf(fp,"CALC %s\n",pcalc->calc)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init_record(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
long status;
|
||||
short error_number;
|
||||
char rpbuf[80];
|
||||
|
||||
/* initialize so that first alarm, archive, and monitor get generated*/
|
||||
pcalc->lalm = 1e30;
|
||||
pcalc->alst = 1e30;
|
||||
pcalc->mlst = 1e30;
|
||||
|
||||
if(pcalc->inpa.type==CONSTANT) pcalc->a = pcalc->inpa.value.value;
|
||||
if(pcalc->inpb.type==CONSTANT) pcalc->b = pcalc->inpb.value.value;
|
||||
if(pcalc->inpc.type==CONSTANT) pcalc->c = pcalc->inpc.value.value;
|
||||
if(pcalc->inpd.type==CONSTANT) pcalc->d = pcalc->inpd.value.value;
|
||||
if(pcalc->inpe.type==CONSTANT) pcalc->e = pcalc->inpe.value.value;
|
||||
if(pcalc->inpf.type==CONSTANT) pcalc->f = pcalc->inpf.value.value;
|
||||
status=postfix(pcalc->calc,rpbuf,&error_number);
|
||||
if(status) return(status);
|
||||
bcopy(rpbuf,pcalc->rpcl,sizeof(pcalc->rpcl));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long special(paddr,after)
|
||||
struct dbAddr *paddr;
|
||||
int after;
|
||||
{
|
||||
long status;
|
||||
struct calcRecord *pcalc = (struct calcRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
short error_number;
|
||||
char rpbuf[80];
|
||||
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_CALC):
|
||||
status=postfix(pcalc->calc,rpbuf,&error_number);
|
||||
if(status) return(status);
|
||||
bcopy(rpbuf,pcalc->rpcl,sizeof(pcalc->rpcl));
|
||||
return(0);
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"calc: special");
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
}
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
long *precision;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
*precision = pcalc->prec;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(pcalc,pvdes)
|
||||
struct calcRecord *pcalc;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
pvdes->field_type = DBF_FLOAT;
|
||||
pvdes->no_elements=1;
|
||||
(float *)(pvdes->pvalue) = &pcalc->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,pcalc->egu,sizeof(pcalc->egu));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_grDouble *pgd;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
pgd->upper_disp_limit = pcalc->hopr;
|
||||
pgd->lower_disp_limit = pcalc->lopr;
|
||||
pgd->upper_alarm_limit = pcalc->hihi;
|
||||
pgd->upper_warning_limit = pcalc->high;
|
||||
pgd->lower_warning_limit = pcalc->low;
|
||||
pgd->lower_alarm_limit = pcalc->lolo;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_ctrlDouble *pcd;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
pcd->upper_ctrl_limit = pcalc->hopr;
|
||||
pcd->lower_ctrl_limit = pcalc->lopr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)(paddr->precord);
|
||||
|
||||
pcalc->pact = TRUE;
|
||||
fetch_values(pcalc);
|
||||
if(do_calc(pcalc)) {
|
||||
if(pcalc->nsev<MAJOR_ALARM) {
|
||||
pcalc->nsta = CALC_ALARM;
|
||||
pcalc->nsev = MAJOR_ALARM;
|
||||
}
|
||||
}
|
||||
if(pcalc->hopr!=pcalc->lopr) {
|
||||
if(pcalc->val>pcalc->hopr) pcalc->val = pcalc->hopr;
|
||||
if(pcalc->val<pcalc->lopr) pcalc->val = pcalc->lopr;
|
||||
}
|
||||
/* check for alarms */
|
||||
alarm(pcalc);
|
||||
/* check event list */
|
||||
monitor(pcalc);
|
||||
/* process the forward scan link record */
|
||||
if (pcalc->flnk.type==DB_LINK) dbScanPassive(&pcalc->flnk.value.db_link.pdbAddr);
|
||||
pcalc->pact = FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void alarm(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* if difference is not > hysterisis don't bother */
|
||||
ftemp = pcalc->lalm - pcalc->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < pcalc->hyst) return;
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (pcalc->nsev<pcalc->hhsv){
|
||||
if (pcalc->val > pcalc->hihi){
|
||||
pcalc->lalm = pcalc->val;
|
||||
pcalc->nsta = HIHI_ALARM;
|
||||
pcalc->nsev = pcalc->hhsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pcalc->nsev<pcalc->llsv){
|
||||
if (pcalc->val < pcalc->lolo){
|
||||
pcalc->lalm = pcalc->val;
|
||||
pcalc->nsta = LOLO_ALARM;
|
||||
pcalc->nsev = pcalc->llsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (pcalc->nsev<pcalc->hsv){
|
||||
if (pcalc->val > pcalc->high){
|
||||
pcalc->lalm = pcalc->val;
|
||||
pcalc->nsta = HIGH_ALARM;
|
||||
pcalc->nsev =pcalc->hsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pcalc->nsev<pcalc->lsv){
|
||||
if (pcalc->val < pcalc->low){
|
||||
pcalc->lalm = pcalc->val;
|
||||
pcalc->nsta = LOW_ALARM;
|
||||
pcalc->nsev = pcalc->lsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void monitor(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pcalc->stat;
|
||||
sevr=pcalc->sevr;
|
||||
nsta=pcalc->nsta;
|
||||
nsev=pcalc->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pcalc->stat = nsta;
|
||||
pcalc->sevr = nsev;
|
||||
pcalc->nsta = 0;
|
||||
pcalc->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pcalc->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(pcalc,&pcalc->stat,DBE_VALUE);
|
||||
db_post_events(pcalc,&pcalc->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
delta = pcalc->mlst - pcalc->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > pcalc->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
pcalc->mlst = pcalc->val;
|
||||
}
|
||||
/* check for archive change */
|
||||
delta = pcalc->alst - pcalc->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > pcalc->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
pcalc->alst = pcalc->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pcalc,&pcalc->val,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void fetch_values(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
struct link *plink; /* structure of the link field */
|
||||
float *pvalue;
|
||||
long options,nRequest;
|
||||
int i;
|
||||
|
||||
for(i=0, plink=&pcalc->inpa, pvalue=&pcalc->a; i<6; i++, plink++, pvalue++) {
|
||||
if(plink->type!=DB_LINK) continue;
|
||||
options=0;
|
||||
nRequest=1;
|
||||
(void)dbGetLink(&plink->value.db_link,pcalc,DBR_FLOAT,
|
||||
pvalue,&options,&nRequest);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* the floating point math routines need to be declared as doubles */
|
||||
static double random(); /* random number generator */
|
||||
@ -172,201 +471,6 @@ double cosh(),sinh(),tanh();
|
||||
#define PAREN -1
|
||||
#define END_STACK -1
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord*)(paddr->precord);
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
if(fprintf(fp,"VAL %-12.4G\n",pcalc->val)) return(-1);
|
||||
if(recGblReportLink(fp,"INPA ",&(pcalc->inpa))) return(-1);
|
||||
if(recGblReportLink(fp,"INPB ",&(pcalc->inpb))) return(-1);
|
||||
if(recGblReportLink(fp,"INPC ",&(pcalc->inpc))) return(-1);
|
||||
if(recGblReportLink(fp,"INPD ",&(pcalc->inpd))) return(-1);
|
||||
if(recGblReportLink(fp,"INPE ",&(pcalc->inpe))) return(-1);
|
||||
if(recGblReportLink(fp,"INPF ",&(pcalc->inpf))) return(-1);
|
||||
if(recGblReportLink(fp,"FLNK",&(pcalc->flnk))) return(-1);
|
||||
if(fprintf(fp,"A %-12.4G\n",pcalc->a)) return(-1);
|
||||
if(fprintf(fp,"B %-12.4G\n",pcalc->b)) return(-1);
|
||||
if(fprintf(fp,"C %-12.4G\n",pcalc->c)) return(-1);
|
||||
if(fprintf(fp,"D %-12.4G\n",pcalc->d)) return(-1);
|
||||
if(fprintf(fp,"E %-12.4G\n",pcalc->e)) return(-1);
|
||||
if(fprintf(fp,"F %-12.4G\n",pcalc->f)) return(-1);
|
||||
if(fprintf(fp,"PREC %d EGU %-8s\n",pcalc->prec,pcalc->egu)) return(-1);
|
||||
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
|
||||
pcalc->hopr,pcalc->lopr)) return(-1);
|
||||
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
|
||||
pcalc->hihi,pcalc->high,pcalc->low,pcalc->lolo)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"HHSV",pcalc->hhsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"HSV ",pcalc->hsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"LSV ",pcalc->lsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,pcalc,"LLSV",pcalc->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G\n",
|
||||
pcalc->hyst,pcalc->adel,pcalc->mdel)) return(-1);
|
||||
if(fprintf(fp,"ACHN %d\n",pcalc->achn)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
pcalc->lalm,pcalc->alst,pcalc->mlst)) return(-1);
|
||||
if(fprintf(fp,"CALC %s\n",pcalc->calc)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init_record(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
long status;
|
||||
short error_number;
|
||||
char rpbuf[80];
|
||||
|
||||
if(pcalc->inpa.type==CONSTANT) pcalc->a = pcalc->inpa.value.value;
|
||||
if(pcalc->inpb.type==CONSTANT) pcalc->b = pcalc->inpb.value.value;
|
||||
if(pcalc->inpc.type==CONSTANT) pcalc->c = pcalc->inpc.value.value;
|
||||
if(pcalc->inpd.type==CONSTANT) pcalc->d = pcalc->inpd.value.value;
|
||||
if(pcalc->inpe.type==CONSTANT) pcalc->e = pcalc->inpe.value.value;
|
||||
if(pcalc->inpf.type==CONSTANT) pcalc->f = pcalc->inpf.value.value;
|
||||
status=postfix(pcalc->calc,rpbuf,&error_number);
|
||||
if(status) return(status);
|
||||
bcopy(rpbuf,pcalc->rpcl,sizeof(pcalc->rpcl));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long special(paddr,after)
|
||||
struct dbAddr *paddr;
|
||||
int after;
|
||||
{
|
||||
long status;
|
||||
struct calcRecord *pcalc = (struct calcRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
short error_number;
|
||||
char rpbuf[80];
|
||||
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_CALC):
|
||||
status=postfix(pcalc->calc,rpbuf,&error_number);
|
||||
if(status) return(status);
|
||||
bcopy(rpbuf,pcalc->rpcl,sizeof(pcalc->rpcl));
|
||||
return(0);
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"calc: special");
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
}
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
long *precision;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
*precision = pcalc->prec;
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long get_value(pcalc,pvdes)
|
||||
struct calcRecord *pcalc;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
pvdes->field_type = DBF_FLOAT;
|
||||
pvdes->no_elements=1;
|
||||
(float *)(pvdes->pvalue) = &pcalc->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,pcalc->egu,sizeof(pcalc->egu));
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_grDouble *pgd;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
pgd->upper_disp_limit = pcalc->hopr;
|
||||
pgd->lower_disp_limit = pcalc->lopr;
|
||||
pgd->upper_alarm_limit = pcalc->hihi;
|
||||
pgd->upper_warning_limit = pcalc->high;
|
||||
pgd->lower_warning_limit = pcalc->low;
|
||||
pgd->lower_alarm_limit = pcalc->lolo;
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_ctrlDouble *pcd;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)paddr->precord;
|
||||
|
||||
pcd->upper_ctrl_limit = pcalc->hopr;
|
||||
pcd->lower_ctrl_limit = pcalc->lopr;
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct calcRecord *pcalc=(struct calcRecord *)(paddr->precord);
|
||||
struct calcdset *pdset = (struct calcdset *)(pcalc->dset);
|
||||
long status;
|
||||
|
||||
pcalc->achn = 0;
|
||||
/* read inputs */
|
||||
if (fetch_values(pcalc) < 0){
|
||||
if (pcalc->stat != READ_ALARM){
|
||||
pcalc->stat = READ_ALARM;
|
||||
pcalc->sevr = MAJOR_ALARM;
|
||||
pcalc->achn = 1;
|
||||
monitor_calc(pcalc);
|
||||
}
|
||||
pcalc->pact = 0;
|
||||
return(0);
|
||||
}else{
|
||||
if (pcalc->stat == READ_ALARM){
|
||||
pcalc->stat = NO_ALARM;
|
||||
pcalc->sevr = NO_ALARM;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform calculation */
|
||||
if (do_calc(pcalc) < 0){
|
||||
if (pcalc->stat != CALC_ALARM){
|
||||
pcalc->stat = CALC_ALARM;
|
||||
pcalc->sevr = MAJOR_ALARM;
|
||||
pcalc->achn = 1;
|
||||
monitor_calc(pcalc);
|
||||
}
|
||||
pcalc->pact = 0;
|
||||
return;
|
||||
}else{
|
||||
if (pcalc->stat == CALC_ALARM){
|
||||
pcalc->stat = NO_ALARM;
|
||||
pcalc->sevr = NO_ALARM;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pcalc);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pcalc->disa) status = monitor(pcalc);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pcalc->flnk.type==DB_LINK) dbScanPassive(&pcalc->flnk.value);
|
||||
|
||||
pcalc->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* DO_CALC
|
||||
*
|
||||
@ -376,14 +480,13 @@ static long process(paddr)
|
||||
#define TRUE_COND 1
|
||||
#define FALSE_COND 2
|
||||
|
||||
static do_calc(pcalc)
|
||||
static int do_calc(pcalc)
|
||||
struct calcRecord *pcalc; /* pointer to calculation record */
|
||||
{
|
||||
char *post; /* postfix expression */
|
||||
double *pstacktop; /* stack of values */
|
||||
double stack[80];
|
||||
double temp;
|
||||
short temp1;
|
||||
int temp;
|
||||
short i;
|
||||
double *top;
|
||||
int itop; /* integer top value */
|
||||
@ -517,12 +620,12 @@ struct calcRecord *pcalc; /* pointer to calculation record */
|
||||
case EXPON:
|
||||
--pstacktop;
|
||||
if (*pstacktop < 0){
|
||||
temp1 = (int) *(pstacktop+1);
|
||||
temp = (int) *(pstacktop+1);
|
||||
/* is exponent an integer */
|
||||
if ((*(pstacktop+1) - (double)temp1) != 0) return (-1);
|
||||
if ((*(pstacktop+1) - (double)temp) != 0) return (-1);
|
||||
*pstacktop = exp(*(pstacktop+1) * log(-*pstacktop));
|
||||
/* is value negative */
|
||||
if ((temp1 % 2) > 0) *pstacktop = -*pstacktop;
|
||||
if ((temp % 2) > 0) *pstacktop = -*pstacktop;
|
||||
}else{
|
||||
*pstacktop = exp(*(pstacktop+1) * log(*pstacktop));
|
||||
}
|
||||
@ -664,62 +767,13 @@ struct calcRecord *pcalc; /* pointer to calculation record */
|
||||
/* if everything is peachy,the stack should end at its first position */
|
||||
if (++top == pstacktop)
|
||||
pcalc->val = *pstacktop;
|
||||
else
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* FETCH_VALUES
|
||||
*
|
||||
* fetch the values for the variables in the calculation
|
||||
*/
|
||||
static fetch_values(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
short status;
|
||||
|
||||
/* note - currently not using alarm status */
|
||||
status = 0;
|
||||
status |= get_calc_inp(&pcalc->inpa,&pcalc->a);
|
||||
status |= get_calc_inp(&pcalc->inpb,&pcalc->b);
|
||||
status |= get_calc_inp(&pcalc->inpc,&pcalc->c);
|
||||
status |= get_calc_inp(&pcalc->inpd,&pcalc->d);
|
||||
status |= get_calc_inp(&pcalc->inpe,&pcalc->e);
|
||||
status |= get_calc_inp(&pcalc->inpf,&pcalc->f);
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* GET_CALC_INPUT
|
||||
*
|
||||
* return an input value
|
||||
*/
|
||||
static get_calc_inp(plink,pvalue)
|
||||
struct link *plink; /* structure of the link field */
|
||||
float *pvalue;
|
||||
{
|
||||
float float_value;
|
||||
|
||||
/* hardware io into a calc not currently supported */
|
||||
if (plink->type == VME_IO){
|
||||
return(-1);
|
||||
|
||||
/* database link */
|
||||
}else if (plink->type == DB_LINK){
|
||||
if (dbGetLink(&plink->value.db_link,DBR_FLOAT,&float_value,1) < 0)
|
||||
return(-1);
|
||||
*pvalue = float_value;
|
||||
|
||||
/* constant */
|
||||
}else if (plink->type == CONSTANT){
|
||||
;
|
||||
/* illegal link type */
|
||||
}else{
|
||||
return(-1);
|
||||
else {
|
||||
if(pcalc->nsev < MAJOR_ALARM) {
|
||||
pcalc->nsev = MAJOR_ALARM;
|
||||
pcalc->nsta = CALC_ALARM;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -746,135 +800,6 @@ static double random()
|
||||
return(randy);
|
||||
}
|
||||
|
||||
static long alarm(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (pcalc->stat != NO_ALARM){
|
||||
ftemp = pcalc->lalm - pcalc->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < pcalc->hyst) return(0);
|
||||
}
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (pcalc->hhsv != NO_ALARM){
|
||||
if (pcalc->val > pcalc->hihi){
|
||||
pcalc->lalm = pcalc->val;
|
||||
if (pcalc->stat != HIHI_ALARM){
|
||||
pcalc->stat = HIHI_ALARM;
|
||||
pcalc->sevr = pcalc->hhsv;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pcalc->llsv != NO_ALARM){
|
||||
if (pcalc->val < pcalc->lolo){
|
||||
pcalc->lalm = pcalc->val;
|
||||
if (pcalc->stat != LOLO_ALARM){
|
||||
pcalc->stat = LOLO_ALARM;
|
||||
pcalc->sevr = pcalc->llsv;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (pcalc->hsv != NO_ALARM){
|
||||
if (pcalc->val > pcalc->high){
|
||||
pcalc->lalm = pcalc->val;
|
||||
if (pcalc->stat != HIGH_ALARM){
|
||||
pcalc->stat = HIGH_ALARM;
|
||||
pcalc->sevr =pcalc->hsv;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (pcalc->lsv != NO_ALARM){
|
||||
if (pcalc->val < pcalc->low){
|
||||
pcalc->lalm = pcalc->val;
|
||||
if (pcalc->stat != LOW_ALARM){
|
||||
pcalc->stat = LOW_ALARM;
|
||||
pcalc->sevr = pcalc->lsv;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (pcalc->stat != NO_ALARM){
|
||||
pcalc->stat = NO_ALARM;
|
||||
pcalc->sevr = NO_ALARM;
|
||||
pcalc->achn = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long monitor(pcalc)
|
||||
struct calcRecord *pcalc;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
|
||||
/* anyone wcalcting for an event on this record */
|
||||
if (pcalc->mlis.count == 0) return(0L);
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pcalc->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pcalc,&pcalc->stat,DBE_VALUE);
|
||||
db_post_events(pcalc,&pcalc->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pcalc->mlst = pcalc->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = pcalc->mlst - pcalc->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > pcalc->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
pcalc->mlst = pcalc->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
delta = pcalc->alst - pcalc->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > pcalc->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
pcalc->alst = pcalc->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pcalc,&pcalc->val,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
}
|
||||
|
||||
/*
|
||||
* POSTFIX.C
|
||||
*
|
||||
@ -933,13 +858,6 @@ static long monitor(pcalc)
|
||||
* FINE found an expression element
|
||||
* VARIABLE found a database reference
|
||||
* UNKNOWN_ELEMENT unknown element found in the infix expression
|
||||
* match_element finds an alpha element in the expression table
|
||||
* args
|
||||
* pbuffer pointer to an alpha expression element
|
||||
* pelement pointer to the expression element table
|
||||
* returns
|
||||
* TRUE found the element in the element table
|
||||
* FLASE expression element not found
|
||||
* postfix convert an algebraic expression to symbolic postfix
|
||||
* args
|
||||
* pinfix the algebraic expression
|
||||
@ -1051,7 +969,7 @@ static struct expression_element elements[] = {
|
||||
*
|
||||
* find the pointer to an entry in the element table
|
||||
*/
|
||||
find_element(pbuffer,pelement,pno_bytes)
|
||||
static find_element(pbuffer,pelement,pno_bytes)
|
||||
#define SAME 0
|
||||
char *pbuffer;
|
||||
struct expression_element **pelement;
|
||||
@ -1076,13 +994,11 @@ static struct expression_element elements[] = {
|
||||
*
|
||||
* get an expression element
|
||||
*/
|
||||
get_element(pinfix,pelement,pno_bytes)
|
||||
static get_element(pinfix,pelement,pno_bytes)
|
||||
char *pinfix;
|
||||
struct expression_element **pelement;
|
||||
short *pno_bytes;
|
||||
{
|
||||
char buffer[40];
|
||||
short i;
|
||||
|
||||
/* get the next expression element from the infix expression */
|
||||
if (*pinfix == NULL) return(END);
|
||||
@ -1103,7 +1019,7 @@ short *pno_bytes;
|
||||
*
|
||||
* convert an infix expression to a postfix expression
|
||||
*/
|
||||
long postfix(pinfix,ppostfix,perror)
|
||||
static long postfix(pinfix,ppostfix,perror)
|
||||
char *pinfix;
|
||||
char *ppostfix;
|
||||
short *perror;
|
||||
@ -1113,7 +1029,6 @@ short *perror;
|
||||
short no_bytes;
|
||||
short operand_needed;
|
||||
short new_expression;
|
||||
short link_inx; /* index into variable table */
|
||||
struct expression_element stack[80];
|
||||
struct expression_element *pelement;
|
||||
struct expression_element *pstacktop;
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recCompress.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -57,15 +56,13 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <devSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <recSup.h>
|
||||
#include <compressRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -73,7 +70,7 @@ long report();
|
||||
#define initialize NULL
|
||||
long init_record();
|
||||
long process();
|
||||
#define special NULL
|
||||
long special();
|
||||
long get_precision();
|
||||
long get_value();
|
||||
long cvt_dbaddr();
|
||||
@ -102,12 +99,23 @@ struct rset compressRSET={
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_enum_strs };
|
||||
|
||||
#define NTO1LOW 0
|
||||
#define NTO1HIGH 1
|
||||
#define NTO1AVG 2
|
||||
#define AVERAGE 3
|
||||
#define CIRBUF 4
|
||||
void alarm();
|
||||
void monitor();
|
||||
void put_value();
|
||||
int compress_array();
|
||||
int compress_value();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord*)(paddr->precord);
|
||||
struct compressRecord *pcompress=(struct compressRecord*)(paddr->precord);
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
return(0);
|
||||
@ -116,27 +124,51 @@ static long report(fp,paddr)
|
||||
static long init_record(pcompress)
|
||||
struct compressRecord *pcompress;
|
||||
{
|
||||
long status;
|
||||
|
||||
/* This routine may get called twice. Once by cvt_dbaddr. Once by iocInit*/
|
||||
/* allocate bptr and sptr */
|
||||
if(pcompress->bptr==NULL) {
|
||||
if(pcompress->nsam<=0) pcompress->nsam=1;
|
||||
pcompress->bptr = (float *)malloc(pcompress->nsam * sizeof(float));
|
||||
pcompress->bptr = (float *)calloc(pcompress->nsam,sizeof(float));
|
||||
/* allocate memory for the summing buffer for conversions requiring it */
|
||||
if (pcompress->alg == AVERAGE){
|
||||
pcompress->sptr = (float *)malloc(pcompress->nsam * sizeof(float));
|
||||
pcompress->sptr = (float *)calloc(pcompress->nsam,sizeof(float));
|
||||
}
|
||||
}
|
||||
/*allocate wptr*/
|
||||
if(pcompress->wptr==NULL && pcompress->inp.type==PV_LINK) {
|
||||
struct dbAddr *pdbAddr = (struct dbAddr *)(pcompress->inp.value.db_link.pdbAddr);
|
||||
pcompress->sptr = (float *)malloc(pdbAddr->no_elements * sizeof(float));
|
||||
if(pcompress->wptr==NULL && pcompress->inp.type==DB_LINK) {
|
||||
struct dbAddr *pdbAddr = (struct dbAddr *)(pcompress->inp.value.db_link.pdbAddr);
|
||||
|
||||
pcompress->wptr = (float *)calloc(pdbAddr->no_elements,sizeof(float));
|
||||
}
|
||||
/* initialize the monitor count */
|
||||
pcompress->mdct = pcompress->mcnt;
|
||||
/* initialize all counters */
|
||||
pcompress->nuse = 0;
|
||||
pcompress->off= 0;
|
||||
pcompress->inx = 0;
|
||||
pcompress->cvb = 0.0;
|
||||
pcompress->res = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long special(paddr,after)
|
||||
struct dbAddr *paddr;
|
||||
int after;
|
||||
{
|
||||
struct compressRecord *pcompress = (struct compressRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_RESET):
|
||||
pcompress->nuse = 0;
|
||||
pcompress->off= 0;
|
||||
pcompress->inx = 0;
|
||||
pcompress->cvb = 0.0;
|
||||
pcompress->res = 0;
|
||||
return(0);
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"compress: special");
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
}
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
@ -145,11 +177,11 @@ static long get_precision(paddr,precision)
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
*precision = pcompress->prec;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(pcompress,pvdes)
|
||||
struct compressRecord *pcompress;
|
||||
struct compressRecord *pcompress;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
pvdes->field_type = DBF_FLOAT;
|
||||
@ -164,7 +196,7 @@ static long cvt_dbaddr(paddr)
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
/* This may get called before init_record. If so just call it*/
|
||||
if(pcompress->bptr==NULL) init_record(paddr);
|
||||
if(pcompress->bptr==NULL) (void)init_record(pcompress);
|
||||
|
||||
paddr->pfield = (caddr_t)(pcompress->bptr);
|
||||
paddr->no_elements = pcompress->nsam;
|
||||
@ -179,42 +211,40 @@ static long get_array_info(paddr,no_elements,offset)
|
||||
long *no_elements;
|
||||
long *offset;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
*no_elements = pcompress->nuse;
|
||||
*offset = inx+1;
|
||||
*offset = pcompress->off;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long put_array_info(paddr,nNew)
|
||||
struct dbAddr *paddr;
|
||||
long nNew;
|
||||
long offset;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
pcompress->inx = (pcompress->inx + nNew) % (pcompress->nsam);
|
||||
pcompress->off = (pcompress->off + nNew) % (pcompress->nsam);
|
||||
pcompress->nuse = (pcompress->nuse + nNew);
|
||||
if(pcompress->nuse > pcompress->nsam) pcompress->nuse = pcompress->nsam;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,pcompress->egu,sizeof(pcompress->egu));
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_grDouble *pgd;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
pgd->upper_disp_limit = pcompress->hopr;
|
||||
pgd->lower_disp_limit = pcompress->lopr;
|
||||
@ -222,277 +252,273 @@ static long get_graphic_double(paddr,pgd)
|
||||
pgd->upper_warning_limit = 0.0;
|
||||
pgd->lower_warning_limit = 0.0;
|
||||
pgd->lower_alarm_limit = 0.0;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
static long get_control_double(paddr,pcd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_ctrlDouble *pcd;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
|
||||
|
||||
pgd->upper_disp_limit = pcompress->hopr;
|
||||
pgd->lower_disp_limit = pcompress->lopr;
|
||||
return(0L);
|
||||
pcd->upper_ctrl_limit = pcompress->hopr;
|
||||
pcd->lower_ctrl_limit = pcompress->lopr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct compressRecord *pcompress=(struct compressRecord *)(paddr->precord);
|
||||
struct compressdset *pdset = (struct compressdset *)(pcompress->dset);
|
||||
long status;
|
||||
struct compressRecord *pcompress=(struct compressRecord *)(paddr->precord);
|
||||
long status;
|
||||
struct dbAddr *pdbAddr =
|
||||
(struct dbAddr *)(pcompress->inp.value.db_link.pdbAddr);
|
||||
long options=0;
|
||||
long no_elements=pdbAddr->no_elements;
|
||||
int alg=pcompress->alg;
|
||||
|
||||
pcompress->achn = 0;
|
||||
/* read inputs */
|
||||
if (do_compression(pcompress) < 0){
|
||||
if (pcompress->stat != READ_ALARM){
|
||||
pcompress->stat = READ_ALARM;
|
||||
pcompress->sevr = MAJOR_ALARM;
|
||||
pcompress->achn = 1;
|
||||
monitor_compress(pcompress);
|
||||
}
|
||||
pcompress->pact = 0;
|
||||
return(0);
|
||||
}else{
|
||||
if (pcompress->stat == READ_ALARM){
|
||||
pcompress->stat = NO_ALARM;
|
||||
pcompress->sevr = NO_ALARM;
|
||||
pcompress->achn = 1;
|
||||
pcompress->pact = TRUE;
|
||||
|
||||
if (pcompress->inp.type != DB_LINK) {
|
||||
status=0;
|
||||
}else if (pcompress->wptr == NULL) {
|
||||
if(pcompress->nsev<MAJOR_ALARM) {
|
||||
pcompress->nsta = READ_ALARM;
|
||||
pcompress->nsev = MAJOR_ALARM;
|
||||
}
|
||||
status=0;
|
||||
} else {
|
||||
(void)dbGetLink(&pcompress->inp.value.db_link,pcompress,DBR_FLOAT,pcompress->wptr,
|
||||
&options,&no_elements);
|
||||
if(alg==AVERAGE) {
|
||||
status = array_average(pcompress,pcompress->wptr,no_elements);
|
||||
} else if(alg==CIRBUF) {
|
||||
(void)put_value(pcompress,pcompress->wptr,no_elements);
|
||||
status = 0;
|
||||
} else if(pdbAddr->no_elements>1) {
|
||||
status = compress_array(pcompress,pcompress->wptr,no_elements);
|
||||
}else if(no_elements==1){
|
||||
status = compress_value(pcompress);
|
||||
}else status=1;
|
||||
}
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pcompress->disa) status = monitor(pcompress);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pcompress->flnk.type==DB_LINK) dbScanPassive(&pcompress->flnk.value);
|
||||
if(status!=1) {
|
||||
monitor(pcompress);
|
||||
/* process the forward scan link record */
|
||||
if (pcompress->flnk.type==DB_LINK) dbScanPassive(&pcompress->flnk.value.db_link.pdbAddr);
|
||||
}
|
||||
|
||||
pcompress->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long monitor(pcompress)
|
||||
struct compressRecord *pcompress;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
|
||||
/* anyone wcompressting for an event on this record */
|
||||
if (pcompress->mlis.count == 0) return(0L);
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pcompress->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pcompress,&pcompress->stat,DBE_VALUE);
|
||||
db_post_events(pcompress,&pcompress->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pcompress->mlst = pcompress->val;
|
||||
}
|
||||
monitor_mask |= DBE_LOG|DBE_VALUE;
|
||||
db_post_events(pcompress,&pcompress->val,monitor_mask);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long do_compression(pcompress)
|
||||
struct compress *pcompress;
|
||||
{
|
||||
struct dbAddr *pdbAddr = (struct dbAddr *)(pcompress->inp.value.db_link.pdbAddr);
|
||||
long options=0;
|
||||
long no_elements=pdbAddr->no_elements;
|
||||
|
||||
if (pcompress->inp.type != DB_LINK) return(0);
|
||||
if (pcompress->wptr == NULL) return(-1);
|
||||
if(status=dbGetLink(&(pcompress->inp),DBR_FLOAT,pcompress->wprt,&options,&no_elements);
|
||||
|
||||
if(pdbAddr->no_elements>1) {
|
||||
compress_array(pcompress,no_elements);
|
||||
}else if(no_elements==1){
|
||||
compress_value(pcompress);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
compress_array(pcompress,no_elements)
|
||||
struct compress *pcompress;
|
||||
long no_elements;
|
||||
static void monitor(pcompress)
|
||||
struct compressRecord *pcompress;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
short mdct;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pcompress->stat;
|
||||
sevr=pcompress->sevr;
|
||||
nsta=pcompress->nsta;
|
||||
nsev=pcompress->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pcompress->stat = nsta;
|
||||
pcompress->sevr = nsev;
|
||||
pcompress->nsta = 0;
|
||||
pcompress->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if(pcompress->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(pcompress,&pcompress->stat,DBE_VALUE);
|
||||
db_post_events(pcompress,&pcompress->sevr,DBE_VALUE);
|
||||
}
|
||||
monitor_mask |= DBE_LOG|DBE_VALUE;
|
||||
if(monitor_mask) db_post_events(pcompress,pcompress->bptr,monitor_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
static void put_value(pcompress,psource,n)
|
||||
struct compressRecord *pcompress;
|
||||
float *psource;
|
||||
long n;
|
||||
{
|
||||
/* treat bptr as pointer to a circular buffer*/
|
||||
float *pdest;
|
||||
short offset=pcompress->off;
|
||||
short nuse=pcompress->nuse;
|
||||
short nsam=pcompress->nsam;
|
||||
long i;
|
||||
|
||||
pdest = pcompress->bptr + offset;
|
||||
for(i=0; i<n; i++, psource++) {
|
||||
*pdest=*psource;
|
||||
offset++;
|
||||
if(offset>=nsam) {
|
||||
pdest=pcompress->bptr;
|
||||
offset=0;
|
||||
} else pdest++;
|
||||
}
|
||||
nuse = nuse+n;
|
||||
if(nuse>nsam) nuse=nsam;
|
||||
pcompress->off = offset;
|
||||
pcompress->nuse = nuse;
|
||||
}
|
||||
|
||||
static int compress_array(pcompress,psource,no_elements)
|
||||
struct compressRecord *pcompress;
|
||||
float *psource;
|
||||
long no_elements;
|
||||
{
|
||||
long i,j;
|
||||
int buff_size;
|
||||
float *psource=pcompress->wptr;
|
||||
short *off=&(pcompress->off);
|
||||
short nsam=pconpress->nsam;
|
||||
int nnew;
|
||||
short nsam=pcompress->nsam;
|
||||
float *pdest;
|
||||
float value;
|
||||
short n;
|
||||
|
||||
/* for all algorithms but AVERAGE apply the front end filter */
|
||||
if (pcompress->alg != AVERAGE){
|
||||
/* skip out of limit data */
|
||||
if ((pcompress->ilil != 0.0) || (pcompress->ihil != 0.0)){
|
||||
while (((*psource < pcompress->ilil)
|
||||
|| (*psource > pcompress->ihil))
|
||||
/* skip out of limit data */
|
||||
if (pcompress->ilil < pcompress->ihil){
|
||||
while (((*psource < pcompress->ilil) || (*psource > pcompress->ihil))
|
||||
&& (no_elements > 0)){
|
||||
no_elements--;
|
||||
psource++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pcompress->n <= 0) pcompress->n = 1;
|
||||
n = pcompress->n;
|
||||
if(no_elements<n) return(1); /*dont do anything*/
|
||||
|
||||
/* determine number of samples to take */
|
||||
if ((no_elements - *off) < (pcompress->nsam * pcompress->n)){
|
||||
buff_size = (no_elements / pcompress->n);
|
||||
}else{
|
||||
buff_size = pcompress->nsam;
|
||||
}
|
||||
|
||||
/* destination pointer */
|
||||
pdest = pcompress->bptr + pcompress->off;
|
||||
if (no_elements < (nsam * n)) nnew = (no_elements / n);
|
||||
else nnew = nsam;
|
||||
|
||||
/* compress according to specified algorithm */
|
||||
switch (pcompress->alg){
|
||||
case (NTO1LOW):
|
||||
/* compress N to 1 keeping the lowest value */
|
||||
for (i = 0; i < buff_size; i++){
|
||||
for (i = 0; i < nnew; i++){
|
||||
value = *psource++;
|
||||
for (j = 1; j < pcompress->n; j++, psource++){
|
||||
if (value > *psource)
|
||||
value = *psource;
|
||||
}
|
||||
*pdest = value;
|
||||
if( (*off)++ <nsam) {
|
||||
pdest++;
|
||||
} else {
|
||||
pdest = pcompress->bptr;
|
||||
*off=0;
|
||||
if (value > *psource) value = *psource;
|
||||
}
|
||||
put_value(pcompress,&value,1);
|
||||
}
|
||||
break;
|
||||
case (NTO1HIGH):
|
||||
/* compress N to 1 keeping the highest value */
|
||||
for (i = 0; i < buff_size; i++){
|
||||
for (i = 0; i < nnew; i++){
|
||||
value = *psource++;
|
||||
for (j = 1; j < pcompress->n; j++, psource++){
|
||||
if (value < *psource)
|
||||
value = *psource;
|
||||
}
|
||||
*pdest = value;
|
||||
if( (*off)++ <nsam) {
|
||||
pdest++;
|
||||
} else {
|
||||
pdest = pcompress->bptr;
|
||||
*off=0;
|
||||
if (value < *psource) value = *psource;
|
||||
}
|
||||
put_value(pcompress,&value,1);
|
||||
}
|
||||
break;
|
||||
case (NTO1AVG):
|
||||
/* compress N to 1 keeping the average value */
|
||||
i = 0;
|
||||
for (i = 0; i < buff_size; i++){
|
||||
for (i = 0; i < nnew; i++){
|
||||
value = 0;
|
||||
for (j = 0; j < pcompress->n; j++, psource++){
|
||||
for (j = 0; j < pcompress->n; j++, psource++)
|
||||
value += *psource;
|
||||
}
|
||||
*pdest = value / j;
|
||||
if( (*off)++ <nsam) {
|
||||
pdest++;
|
||||
} else {
|
||||
pdest = pcompress->bptr;
|
||||
*off=0;
|
||||
}
|
||||
put_value(pcompress,&value,1);
|
||||
}
|
||||
break;
|
||||
case (AVERAGE):
|
||||
{
|
||||
register float *psum;
|
||||
register int divider;
|
||||
|
||||
psum = (float *)pcompress->sptr;
|
||||
|
||||
/* add in the new waveform */
|
||||
if (pcompress->mdct == pcompress->mcnt ||
|
||||
pcompress->mdct == 0){
|
||||
for (i = 0; i < buff_size; i++, psource++, psum++)
|
||||
*psum = *psource;
|
||||
}else{
|
||||
for (i = 0; i < buff_size; i++, psource++, psum++)
|
||||
*psum += *psource;
|
||||
}
|
||||
|
||||
/* do we need to calculate the result */
|
||||
if (pcompress->mdct == 1){
|
||||
psum = (float *)pcompress->sptr;
|
||||
divider = pcompress->mcnt;
|
||||
for (i = 0; i < buff_size; i++, psum++) {
|
||||
*pdest = *psum / divider;
|
||||
if( (*off)++ <nsam) {
|
||||
pdest++;
|
||||
} else {
|
||||
pdest = pcompress->bptr;
|
||||
*off=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} /* end case average */
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static compress_value(pcompress)
|
||||
register struct compress *pcompress;
|
||||
static int array_average(pcompress,psource,no_elements)
|
||||
struct compressRecord *pcompress;
|
||||
float *psource;
|
||||
long no_elements;
|
||||
{
|
||||
float value = *pcompress->wptr;;
|
||||
short inx;
|
||||
long i;
|
||||
int nnow;
|
||||
short nsam=pcompress->nsam;
|
||||
float *psum;
|
||||
float multiplier;
|
||||
short inx=pcompress->inx;
|
||||
struct dbAddr *pdbAddr = (struct dbAddr *)(pcompress->inp.value.db_link.pdbAddr);
|
||||
long ninp=pdbAddr->no_elements;
|
||||
short nuse,n;
|
||||
|
||||
nuse = nsam;
|
||||
if(nuse>ninp) nuse = ninp;
|
||||
nnow=nuse;
|
||||
if(nnow>no_elements) nnow=no_elements;
|
||||
psum = (float *)pcompress->sptr;
|
||||
|
||||
float *pdest;
|
||||
/* add in the new waveform */
|
||||
if (inx == 0){
|
||||
for (i = 0; i < nnow; i++)
|
||||
*psum++ = *psource++;
|
||||
for(i=nnow; i<nuse; i++) *psum++ = 0;
|
||||
}else{
|
||||
for (i = 0; i < nnow; i++)
|
||||
*psum++ += *psource++;
|
||||
}
|
||||
|
||||
/* do we need to calculate the result */
|
||||
inx++;
|
||||
if(pcompress->n<=0)pcompress->n=1;
|
||||
n = pcompress->n;
|
||||
if(inx<n) return(1);
|
||||
if(n>1) {
|
||||
psum = (float *)pcompress->sptr;
|
||||
multiplier = 1.0/((float)n);
|
||||
for (i = 0; i < nuse; i++, psum++)
|
||||
*psum = *psum * multiplier;
|
||||
}
|
||||
put_value(pcompress,pcompress->sptr,nuse);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int compress_value(pcompress,psource)
|
||||
struct compressRecord *pcompress;
|
||||
float *psource;
|
||||
{
|
||||
float value = *psource;
|
||||
float *pdest=&pcompress->cvb;
|
||||
short inx = pcompress->inx;
|
||||
|
||||
/* compress according to specified algorithm */
|
||||
switch (pcompress->alg){
|
||||
case (NTO1LOW):
|
||||
pdest = pcompress->bptr + pcompress->inx;
|
||||
if ((value < *pdest) || (pcompress->ccnt == 0))
|
||||
if ((value < *pdest) || (inx == 0))
|
||||
*pdest = value;
|
||||
pcompress->ccnt++;
|
||||
if (pcompress->ccnt >= pcompress->n){
|
||||
pcompress->ccnt = 0;
|
||||
if (++pcompress->inx >= pcompress->nsam)
|
||||
pcompress->inx = 0;
|
||||
}
|
||||
break;
|
||||
case (NTO1HIGH):
|
||||
pdest = pcompress->bptr + pcompress->inx;
|
||||
if ((value > *pdest) || (pcompress->ccnt == 0))
|
||||
if ((value > *pdest) || (inx == 0))
|
||||
*pdest = value;
|
||||
pcompress->ccnt++;
|
||||
if (pcompress->ccnt >= pcompress->n){
|
||||
pcompress->ccnt = 0;
|
||||
if (++pcompress->inx >= pcompress->nsam)
|
||||
pcompress->inx = 0;
|
||||
}
|
||||
break;
|
||||
case (NTO1AVG):
|
||||
if (pcompress->ccnt == 0)
|
||||
pcompress->sum = value;
|
||||
else
|
||||
pcompress->sum += value;
|
||||
pcompress->ccnt++;
|
||||
if (pcompress->ccnt >= pcompress->n){
|
||||
pdest=pcompress->bptr + pcompress->inx;
|
||||
*pdest = pcompress->sum / pcompress->n;
|
||||
pcompress->ccnt = 0;
|
||||
if (++pcompress->inx >= pcompress->nsam)
|
||||
pcompress->inx = 0;
|
||||
if (inx == 0)
|
||||
*pdest = value;
|
||||
else {
|
||||
*pdest += value;
|
||||
if(inx+1>=(pcompress->n)) *pdest = *pdest/(inx+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
inx++;
|
||||
if(inx>=pcompress->n) {
|
||||
put_value(pcompress,pdest,1);
|
||||
pcompress->inx = 0;
|
||||
return(0);
|
||||
} else {
|
||||
pcompress->inx = inx;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
|
||||
/* recFanout.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
/* recFanout.c - Record Support Routines for Fanout records
|
||||
*
|
||||
* Author: Marty Kraimer
|
||||
* Date: 10/10/90
|
||||
* Author: Bob Dalesio
|
||||
* Date: 12-20-88
|
||||
*
|
||||
* Control System Software for the GTA Project
|
||||
*
|
||||
@ -29,7 +28,13 @@
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 10-10-90 mrk extensible record and device support
|
||||
* .01 12-23-88 lrd Alarm on locked MAX_LOCKED times
|
||||
* .02 05-03-89 lrd removed process mask from arg list
|
||||
* .03 09-25-89 lrd add conditional scanning
|
||||
* .04 01-21-90 lrd unlock on scan disable exit
|
||||
* .05 04-19-90 lrd user select disable on 0 or 1
|
||||
* .06 10-31-90 mrk no user select disable on 0 or 1
|
||||
* .07 10-31-90 mrk extensible record and device support
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
@ -38,11 +43,9 @@
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <devSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
@ -55,7 +58,7 @@ long report();
|
||||
long process();
|
||||
#define special NULL
|
||||
#define get_precision NULL
|
||||
long get_value();
|
||||
#define get_value NULL
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
@ -104,12 +107,13 @@ static long process(paddr)
|
||||
{
|
||||
struct fanoutRecord *pfanout=(struct fanoutRecord *)(paddr->precord);
|
||||
|
||||
if (pfanout->lnk1.type==DB_LINK) dbScanPassive(&pfanout->lnk1.value);
|
||||
if (pfanout->lnk2.type==DB_LINK) dbScanPassive(&pfanout->lnk2.value);
|
||||
if (pfanout->lnk3.type==DB_LINK) dbScanPassive(&pfanout->lnk3.value);
|
||||
if (pfanout->lnk4.type==DB_LINK) dbScanPassive(&pfanout->lnk4.value);
|
||||
if (pfanout->lnk5.type==DB_LINK) dbScanPassive(&pfanout->lnk5.value);
|
||||
if (pfanout->lnk6.type==DB_LINK) dbScanPassive(&pfanout->lnk6.value);
|
||||
pfanout->pact = TRUE;
|
||||
if (pfanout->lnk1.type==DB_LINK) dbScanPassive(&pfanout->lnk1.value.db_link.pdbAddr);
|
||||
if (pfanout->lnk2.type==DB_LINK) dbScanPassive(&pfanout->lnk2.value.db_link.pdbAddr);
|
||||
if (pfanout->lnk3.type==DB_LINK) dbScanPassive(&pfanout->lnk3.value.db_link.pdbAddr);
|
||||
if (pfanout->lnk4.type==DB_LINK) dbScanPassive(&pfanout->lnk4.value.db_link.pdbAddr);
|
||||
if (pfanout->lnk5.type==DB_LINK) dbScanPassive(&pfanout->lnk5.value.db_link.pdbAddr);
|
||||
if (pfanout->lnk6.type==DB_LINK) dbScanPassive(&pfanout->lnk6.value.db_link.pdbAddr);
|
||||
pfanout->pact=FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recMbbi.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -44,7 +43,7 @@
|
||||
* states are defined - like the mbbo
|
||||
* .11 12-06-89 lrd add database fetch support
|
||||
* .12 02-08-90 lrd add Allen-Bradley PLC support
|
||||
* .13 10-11-90 mrk changes for new record and device support
|
||||
* .13 10-31-90 mrk changes for new record and device support
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
@ -54,7 +53,6 @@
|
||||
#include <strLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -70,8 +68,8 @@ long report();
|
||||
#define initialize NULL
|
||||
long init_record();
|
||||
long process();
|
||||
long special();
|
||||
long get_precision();
|
||||
long special();
|
||||
#define get_precision NULL
|
||||
long get_value();
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
@ -108,6 +106,9 @@ struct mbbidset { /* multi bit binary input dset */
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_mbbi;/*(-1,0,1)=>(failure,success,don't Continue*/
|
||||
};
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -119,17 +120,37 @@ static long report(fp,paddr)
|
||||
if(fprintf(fp,"VAL %d\n",pmbbi->val)) return(-1);
|
||||
if(recGblReportLink(fp,"INP ",&(pmbbi->inp))) return(-1);
|
||||
if(recGblReportLink(fp,"FLNK",&(pmbbi->flnk))) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X\n",
|
||||
pmbbi->rval)) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X\n",pmbbi->rval)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void init_common(pmbbi)
|
||||
struct mbbiRecord *pmbbi;
|
||||
{
|
||||
unsigned long *pstate_values;
|
||||
short i;
|
||||
|
||||
/* determine if any states are defined */
|
||||
pstate_values = &(pmbbi->zrvl);
|
||||
pmbbi->sdef = FALSE;
|
||||
for (i=0; i<16; i++) {
|
||||
if (*(pstate_values+i)) {
|
||||
pmbbi->sdef = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long init_record(pmbbi)
|
||||
struct mbbiRecord *pmbbi;
|
||||
{
|
||||
struct mbbidset *pdset;
|
||||
long status;
|
||||
|
||||
init_common(pmbbi);
|
||||
pmbbi->mlst = -1;
|
||||
pmbbi->lalm = -1;
|
||||
if(!(pdset = (struct mbbidset *)(pmbbi->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,pmbbi,"mbbi: init_record");
|
||||
return(S_dev_noDSET);
|
||||
@ -140,79 +161,27 @@ static long init_record(pmbbi)
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pmbbi))) return(status);
|
||||
if((status=(*pdset->init_record)(pmbbi,process))) return(status);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
|
||||
static long special(paddr,after)
|
||||
struct dbAddr *paddr;
|
||||
int after;
|
||||
{
|
||||
struct mbbiRecord *pmbbi=(struct mbbiRecord *)(paddr->precord);
|
||||
struct mbbidset *pdset = (struct mbbidset *)(pmbbi->dset);
|
||||
long status;
|
||||
unsigned long *pstate_values;
|
||||
short i,states_defined;
|
||||
struct mbbiRecord *pmbbi = (struct mbbiRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_mbbi==NULL) ) {
|
||||
pmbbi->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pmbbi,"read_mbbi");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
status=(*pdset->read_mbbi)(pmbbi); /* read the new value */
|
||||
pmbbi->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(1);
|
||||
else if(status == -1) {
|
||||
if(pmbbi->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
pmbbi->stat = READ_ALARM;
|
||||
pmbbi->sevr = MAJOR_ALARM;
|
||||
pmbbi->achn=1;
|
||||
}
|
||||
}
|
||||
else if(status!=0) return(status);
|
||||
else if(pmbbi->stat == READ_ALARM) {
|
||||
pmbbi->stat = NO_ALARM;
|
||||
pmbbi->sevr = NO_ALARM;
|
||||
pmbbi->achn=1;
|
||||
}
|
||||
|
||||
/* determine if any states are defined */
|
||||
pstate_values = &(pmbbi->zrvl);
|
||||
states_defined = 0;
|
||||
for (i=0; (i<16) && (!states_defined); i++)
|
||||
if (*(pstate_values+i)) states_defined = 1;
|
||||
|
||||
/* convert the value */
|
||||
if (states_defined){
|
||||
pstate_values = &(pmbbi->zrvl);
|
||||
for (i = 0; i < 16; i++){
|
||||
if (*pstate_values == pmbbi->rval){
|
||||
pmbbi->val = i;
|
||||
return(0);
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
pmbbi->val = -2; /* unknown state-other than init LALM */
|
||||
}else{
|
||||
/* the raw value is the desired value */
|
||||
pmbbi->val = pmbbi->rval;
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pmbbi);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pmbbi->disa) status = monitor(pmbbi);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pmbbi->flnk.type==DB_LINK) dbScanPassive(&pmbbi->flnk.value);
|
||||
|
||||
pmbbi->pact=FALSE;
|
||||
return(status);
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_MOD):
|
||||
init_common(pmbbi);
|
||||
return(0);
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"mbbi: special");
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
}
|
||||
|
||||
static long get_value(pmbbi,pvdes)
|
||||
@ -233,14 +202,14 @@ static long get_enum_str(paddr,pstring)
|
||||
char *psource;
|
||||
unsigned short val=pmbbi->val;
|
||||
|
||||
if( val>0 && val<= 15) {
|
||||
if(val<= 15) {
|
||||
psource = (pmbbi->zrst);
|
||||
psource += (val * sizeof(pmbbi->zrst));
|
||||
strncpy(pstring,psource,sizeof(pmbbi->zrst));
|
||||
} else {
|
||||
strcpy(pstring,"Illegal Value");
|
||||
}
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_enum_strs(paddr,pes)
|
||||
@ -254,103 +223,138 @@ static long get_enum_strs(paddr,pes)
|
||||
pes->no_str = 16;
|
||||
bzero(pes->strs,sizeof(pes->strs));
|
||||
for(i=0,psource=(pmbbi->zrst); i<15; i++, psource += sizeof(pmbbi->zrst) )
|
||||
strncpy(pes->strs[i],pmbbi->zrst,sizeof(pmbbi->zrst));
|
||||
return(0L);
|
||||
strncpy(pes->strs[i],psource,sizeof(pmbbi->zrst));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long alarm(pmbbi)
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct mbbiRecord *pmbbi=(struct mbbiRecord *)(paddr->precord);
|
||||
struct mbbidset *pdset = (struct mbbidset *)(pmbbi->dset);
|
||||
long status;
|
||||
unsigned long *pstate_values;
|
||||
short i,val;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_mbbi==NULL) ) {
|
||||
pmbbi->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pmbbi,"read_mbbi");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
status=(*pdset->read_mbbi)(pmbbi); /* read the new value */
|
||||
pmbbi->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(0);
|
||||
|
||||
/* convert the value */
|
||||
if (pmbbi->sdef){
|
||||
pstate_values = &(pmbbi->zrvl);
|
||||
val = -1; /* initalize to unknown state*/
|
||||
for (i = 0; i < 16; i++){
|
||||
if (*pstate_values == pmbbi->rval){
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}else{
|
||||
/* the raw value is the desired value */
|
||||
*((unsigned short *)(&val)) = (unsigned short)(pmbbi->rval);
|
||||
}
|
||||
pmbbi->val = val;
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pmbbi);
|
||||
|
||||
|
||||
/* check event list */
|
||||
monitor(pmbbi);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pmbbi->flnk.type==DB_LINK) dbScanPassive(&pmbbi->flnk.value.db_link.pdbAddr);
|
||||
|
||||
pmbbi->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static void alarm(pmbbi)
|
||||
struct mbbiRecord *pmbbi;
|
||||
{
|
||||
float ftemp;
|
||||
unsigned short *severities;
|
||||
short val=pmbbi->val;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (pmbbi->stat == READ_ALARM) return(0);
|
||||
|
||||
if (pmbbi->val == pmbbi->lalm){
|
||||
/* no new message for COS alarms */
|
||||
if (pmbbi->stat == COS_ALARM){
|
||||
pmbbi->stat = NO_ALARM;
|
||||
pmbbi->sevr = NO_ALARM;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* set last alarmed value */
|
||||
pmbbi->lalm = pmbbi->val;
|
||||
if(val = pmbbi->lalm) return;
|
||||
pmbbi->lalm = val;
|
||||
|
||||
/* check for state alarm */
|
||||
/* unknown state */
|
||||
if ((pmbbi->val < 0) || (pmbbi->val > 15)){
|
||||
if (pmbbi->unsv != NO_ALARM){
|
||||
pmbbi->stat = STATE_ALARM;
|
||||
pmbbi->sevr = pmbbi->unsv;
|
||||
pmbbi->achn = 1;
|
||||
return;
|
||||
if ((val < 0) || (val > 15)){
|
||||
if (pmbbi->nsev<pmbbi->unsv){
|
||||
pmbbi->nsta = STATE_ALARM;
|
||||
pmbbi->nsev = pmbbi->unsv;
|
||||
}
|
||||
}
|
||||
/* in a state which is an error */
|
||||
severities = (unsigned short *)&(pmbbi->zrsv);
|
||||
if (severities[pmbbi->val] != NO_ALARM){
|
||||
pmbbi->stat = STATE_ALARM;
|
||||
pmbbi->sevr = severities[pmbbi->val];
|
||||
pmbbi->achn = 1;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* in a state which is an error */
|
||||
severities = (unsigned short *)&(pmbbi->zrsv);
|
||||
if (pmbbi->nsev<severities[pmbbi->val]){
|
||||
pmbbi->nsta = STATE_ALARM;
|
||||
pmbbi->nsev = severities[pmbbi->val];
|
||||
}
|
||||
}
|
||||
|
||||
/* check for cos alarm */
|
||||
if (pmbbi->cosv != NO_ALARM){
|
||||
pmbbi->sevr = pmbbi->cosv;
|
||||
pmbbi->stat = COS_ALARM;
|
||||
pmbbi->achn = 1;
|
||||
if (pmbbi->nsev<pmbbi->cosv){
|
||||
pmbbi->nsta = COS_ALARM;
|
||||
pmbbi->nsev = pmbbi->cosv;
|
||||
return;
|
||||
}
|
||||
/* check for change from alarm to no alarm */
|
||||
if (pmbbi->sevr != NO_ALARM){
|
||||
pmbbi->sevr = NO_ALARM;
|
||||
pmbbi->stat = NO_ALARM;
|
||||
pmbbi->achn = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(pmbbi)
|
||||
static void monitor(pmbbi)
|
||||
struct mbbiRecord *pmbbi;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pmbbi->stat;
|
||||
sevr=pmbbi->sevr;
|
||||
nsta=pmbbi->nsta;
|
||||
nsev=pmbbi->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pmbbi->stat = nsta;
|
||||
pmbbi->sevr = nsev;
|
||||
pmbbi->nsta = 0;
|
||||
pmbbi->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pmbbi->mlis.count == 0) return(0L);
|
||||
if (pmbbi->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pmbbi->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pmbbi,&pmbbi->stat,DBE_VALUE);
|
||||
db_post_events(pmbbi,&pmbbi->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pmbbi->mlst = pmbbi->val;
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev){
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pmbbi,&pmbbi->stat,DBE_VALUE);
|
||||
db_post_events(pmbbi,&pmbbi->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
}else if (pmbbi->mlst != pmbbi->val){
|
||||
if (pmbbi->mlst != pmbbi->val){
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
|
||||
/* update last value monitored */
|
||||
pmbbi->mlst = pmbbi->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pmbbi,&pmbbi->val,monitor_mask);
|
||||
db_post_events(pmbbi,&pmbbi->rval,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pmbbi,&pmbbi->val,monitor_mask);
|
||||
db_post_events(pmbbi,&pmbbi->rval,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recMbbo.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -57,7 +56,6 @@
|
||||
#include <strLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -74,7 +72,7 @@ long report();
|
||||
long init_record();
|
||||
long process();
|
||||
long special();
|
||||
long get_precision();
|
||||
#define get_precision NULL
|
||||
long get_value();
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
@ -113,8 +111,11 @@ struct mbbodset { /* multi bit binary input dset */
|
||||
};
|
||||
|
||||
/* the following definitions must match those in choiceGbl.ascii */
|
||||
#define OUTPUT_FULL 0
|
||||
#define SUPERVISORY 0
|
||||
#define CLOSED_LOOP 1
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -131,11 +132,35 @@ static long report(fp,paddr)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void init_common(pmbbo)
|
||||
struct mbboRecord *pmbbo;
|
||||
{
|
||||
unsigned long *pstate_values;
|
||||
short i;
|
||||
|
||||
/* determine if any states are defined */
|
||||
pstate_values = &(pmbbo->zrvl);
|
||||
pmbbo->sdef = FALSE;
|
||||
for (i=0; i<16; i++) {
|
||||
if (*(pstate_values+i)) {
|
||||
pmbbo->sdef = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long init_record(pmbbo)
|
||||
struct mbboRecord *pmbbo;
|
||||
{
|
||||
struct mbbodset *pdset;
|
||||
long status;
|
||||
unsigned long *pstate_values;
|
||||
short i,rbv;
|
||||
|
||||
init_common(pmbbo);
|
||||
pmbbo->mlst = -1;
|
||||
pmbbo->lalm = -1;
|
||||
|
||||
if(!(pdset = (struct mbbodset *)(pmbbo->dset))) {
|
||||
recGblRecordError(S_dev_noDSET,pmbbo,"mbbo: init_record");
|
||||
@ -147,79 +172,45 @@ static long init_record(pmbbo)
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pmbbo))) return(status);
|
||||
if((status=(*pdset->init_record)(pmbbo,process))) return(status);
|
||||
if (pmbbo->sdef){
|
||||
pstate_values = &(pmbbo->zrvl);
|
||||
rbv = -1; /* initalize to unknown state*/
|
||||
for (i = 0; i < 16; i++){
|
||||
if (*pstate_values == pmbbo->rval){
|
||||
rbv = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}else{
|
||||
/* the raw is the desired rbv */
|
||||
rbv = (unsigned short)(pmbbo->rval);
|
||||
}
|
||||
pmbbo->rbv = rbv;
|
||||
pmbbo->val = rbv;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
static long special(paddr,after)
|
||||
struct dbAddr *paddr;
|
||||
int after;
|
||||
{
|
||||
struct mbboRecord *pmbbo=(struct mbboRecord *)(paddr->precord);
|
||||
struct mbbodset *pdset = (struct mbbodset *)(pmbbo->dset);
|
||||
long status;
|
||||
unsigned long *pvalues;
|
||||
short states_defined,i;
|
||||
struct mbboRecord *pmbbo = (struct mbboRecord *)(paddr->precord);
|
||||
int special_type = paddr->special;
|
||||
|
||||
if( (pdset==NULL) || (pdset->write_mbbo==NULL) ) {
|
||||
pmbbo->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pmbbo,"write_mbbo");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
status=(*pdset->write_mbbo)(pmbbo); /* read the new value */
|
||||
pmbbo->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(1);
|
||||
else if(status == -1) {
|
||||
if(pmbbo->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
pmbbo->stat = READ_ALARM;
|
||||
pmbbo->sevr = MAJOR_ALARM;
|
||||
pmbbo->achn=1;
|
||||
}
|
||||
}
|
||||
else if(status!=0) return(status);
|
||||
else if(pmbbo->stat == READ_ALARM) {
|
||||
pmbbo->stat = NO_ALARM;
|
||||
pmbbo->sevr = NO_ALARM;
|
||||
pmbbo->achn=1;
|
||||
}
|
||||
|
||||
/* determine if any states are defined */
|
||||
pvalues = &(pmbbo->zrvl);
|
||||
states_defined = FALSE;
|
||||
for (i=0; (i<16) && (!states_defined); i++)
|
||||
if (*(pvalues+i)) states_defined = TRUE;
|
||||
|
||||
/* convert the value */
|
||||
if (states_defined){
|
||||
pvalues = (unsigned long *)&(pmbbo->zrvl);
|
||||
pmbbo->rbv = -1; /* initialize to unknown state */
|
||||
for (i = 0; i < 16; i++,pvalues++){
|
||||
if (*pvalues == pmbbo->rval){
|
||||
pmbbo->rbv = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
pmbbo->rbv = pmbbo->rval;
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pmbbo);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!pmbbo->disa) status = monitor(pmbbo);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pmbbo->flnk.type==DB_LINK) dbScanPassive(&pmbbo->flnk.value);
|
||||
|
||||
pmbbo->pact=FALSE;
|
||||
return(status);
|
||||
if(!after) return(0);
|
||||
switch(special_type) {
|
||||
case(SPC_MOD):
|
||||
init_common(pmbbo);
|
||||
return(0);
|
||||
default:
|
||||
recGblDbaddrError(S_db_badChoice,paddr,"mbbo: special");
|
||||
return(S_db_badChoice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static long get_value(pmbbo,pvdes)
|
||||
struct mbboRecord *pmbbo;
|
||||
struct valueDes *pvdes;
|
||||
@ -238,14 +229,14 @@ static long get_enum_str(paddr,pstring)
|
||||
char *psource;
|
||||
unsigned short val=pmbbo->val;
|
||||
|
||||
if( val>0 && val<= 15) {
|
||||
if(val<= 15) {
|
||||
psource = (pmbbo->zrst);
|
||||
psource += (val * sizeof(pmbbo->zrst));
|
||||
strncpy(pstring,psource,sizeof(pmbbo->zrst));
|
||||
} else {
|
||||
strcpy(pstring,"Illegal Value");
|
||||
}
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_enum_strs(paddr,pes)
|
||||
@ -259,104 +250,150 @@ static long get_enum_strs(paddr,pes)
|
||||
pes->no_str = 16;
|
||||
bzero(pes->strs,sizeof(pes->strs));
|
||||
for(i=0,psource=(pmbbo->zrst); i<15; i++, psource += sizeof(pmbbo->zrst) )
|
||||
strncpy(pes->strs[i],pmbbo->zrst,sizeof(pmbbo->zrst));
|
||||
return(0L);
|
||||
strncpy(pes->strs[i],psource,sizeof(pmbbo->zrst));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long alarm(pmbbo)
|
||||
struct mbboRecord *pmbbo;
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
float ftemp;
|
||||
unsigned short *severities;
|
||||
struct mbboRecord *pmbbo=(struct mbboRecord *)(paddr->precord);
|
||||
struct mbbodset *pdset = (struct mbbodset *)(pmbbo->dset);
|
||||
long status;
|
||||
unsigned long *pstate_values;
|
||||
short i,rbv;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (pmbbo->stat == READ_ALARM) return(0);
|
||||
if (pmbbo->stat == WRITE_ALARM) return(0);
|
||||
if( (pdset==NULL) || (pdset->write_mbbo==NULL) ) {
|
||||
pmbbo->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pmbbo,"write_mbbo");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
if (pmbbo->val == pmbbo->lalm){
|
||||
/* no new message for COS alarms */
|
||||
if (pmbbo->stat == COS_ALARM){
|
||||
pmbbo->stat = NO_ALARM;
|
||||
pmbbo->sevr = NO_ALARM;
|
||||
}
|
||||
return;
|
||||
/* fetch the desired output if there is a database link */
|
||||
if (pmbbo->dol.type == DB_LINK && pmbbo->omsl == CLOSED_LOOP){
|
||||
long options=0;
|
||||
long nRequest=1;
|
||||
short savepact=pmbbo->pact;
|
||||
|
||||
pmbbo->pact = TRUE;
|
||||
(void)dbGetLink(&pmbbo->dol.value.db_link,pmbbo,DBR_ENUM,
|
||||
&(pmbbo->val),&options,&nRequest);
|
||||
pmbbo->pact = savepact;
|
||||
}
|
||||
|
||||
/* set last alarmed value */
|
||||
pmbbo->lalm = pmbbo->val;
|
||||
status=(*pdset->write_mbbo)(pmbbo); /* write the new value */
|
||||
pmbbo->pact = TRUE;
|
||||
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(0);
|
||||
|
||||
/* convert the value */
|
||||
if (pmbbo->sdef){
|
||||
pstate_values = &(pmbbo->zrvl);
|
||||
rbv = -1; /* initalize to unknown state*/
|
||||
for (i = 0; i < 16; i++){
|
||||
if (*pstate_values == pmbbo->rval){
|
||||
rbv = i;
|
||||
break;
|
||||
}
|
||||
pstate_values++;
|
||||
}
|
||||
}else{
|
||||
/* the raw value is the desired value */
|
||||
rbv = (unsigned short)(pmbbo->rval);
|
||||
}
|
||||
pmbbo->rbv = rbv;
|
||||
|
||||
/* check for alarms */
|
||||
alarm(pmbbo);
|
||||
|
||||
|
||||
/* check event list */
|
||||
monitor(pmbbo);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pmbbo->flnk.type==DB_LINK) dbScanPassive(&pmbbo->flnk.value.db_link.pdbAddr);
|
||||
|
||||
pmbbo->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static void alarm(pmbbo)
|
||||
struct mbboRecord *pmbbo;
|
||||
{
|
||||
unsigned short *severities;
|
||||
short val=pmbbo->val;
|
||||
|
||||
if(val = pmbbo->lalm) return;
|
||||
pmbbo->lalm = val;
|
||||
|
||||
/* check for state alarm */
|
||||
/* unknown state */
|
||||
if ((pmbbo->val < 0) || (pmbbo->val > 15)){
|
||||
if (pmbbo->unsv != NO_ALARM){
|
||||
pmbbo->stat = STATE_ALARM;
|
||||
pmbbo->sevr = pmbbo->unsv;
|
||||
pmbbo->achn = 1;
|
||||
return;
|
||||
if ((val < 0) || (val > 15)){
|
||||
if (pmbbo->nsev<pmbbo->unsv){
|
||||
pmbbo->nsta = STATE_ALARM;
|
||||
pmbbo->nsev = pmbbo->unsv;
|
||||
}
|
||||
}
|
||||
/* in a state which is an error */
|
||||
severities = (unsigned short *)&(pmbbo->zrsv);
|
||||
if (severities[pmbbo->val] != NO_ALARM){
|
||||
pmbbo->stat = STATE_ALARM;
|
||||
pmbbo->sevr = severities[pmbbo->val];
|
||||
pmbbo->achn = 1;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* in a state which is an error */
|
||||
severities = (unsigned short *)&(pmbbo->zrsv);
|
||||
if (pmbbo->nsev<severities[pmbbo->val]){
|
||||
pmbbo->nsta = STATE_ALARM;
|
||||
pmbbo->nsev = severities[pmbbo->val];
|
||||
}
|
||||
}
|
||||
|
||||
/* check for cos alarm */
|
||||
if (pmbbo->cosv != NO_ALARM){
|
||||
pmbbo->sevr = pmbbo->cosv;
|
||||
pmbbo->stat = COS_ALARM;
|
||||
pmbbo->achn = 1;
|
||||
if (pmbbo->nsev<pmbbo->cosv){
|
||||
pmbbo->nsta = COS_ALARM;
|
||||
pmbbo->nsev = pmbbo->cosv;
|
||||
return;
|
||||
}
|
||||
/* check for change from alarm to no alarm */
|
||||
if (pmbbo->sevr != NO_ALARM){
|
||||
pmbbo->sevr = NO_ALARM;
|
||||
pmbbo->stat = NO_ALARM;
|
||||
pmbbo->achn = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(pmbbo)
|
||||
static void monitor(pmbbo)
|
||||
struct mbboRecord *pmbbo;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pmbbo->stat;
|
||||
sevr=pmbbo->sevr;
|
||||
nsta=pmbbo->nsta;
|
||||
nsev=pmbbo->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pmbbo->stat = nsta;
|
||||
pmbbo->sevr = nsev;
|
||||
pmbbo->nsta = 0;
|
||||
pmbbo->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (pmbbo->mlis.count == 0) return(0L);
|
||||
if (pmbbo->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pmbbo->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pmbbo,&pmbbo->stat,DBE_VALUE);
|
||||
db_post_events(pmbbo,&pmbbo->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pmbbo->mlst = pmbbo->val;
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev){
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pmbbo,&pmbbo->stat,DBE_VALUE);
|
||||
db_post_events(pmbbo,&pmbbo->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
}else if (pmbbo->mlst != pmbbo->val){
|
||||
if (pmbbo->mlst != pmbbo->val){
|
||||
/* post events for value change and archive change */
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
|
||||
/* update last value monitored */
|
||||
pmbbo->mlst = pmbbo->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pmbbo,&pmbbo->val,monitor_mask);
|
||||
db_post_events(pmbbo,&pmbbo->rval,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(pmbbo,&pmbbo->val,monitor_mask);
|
||||
db_post_events(pmbbo,&pmbbo->rval,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recPermissive.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -37,16 +36,12 @@
|
||||
#include <stdioLib.h>
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <devSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <permissiveRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -97,11 +92,24 @@ static long report(fp,paddr)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(ppermissive,pvdes)
|
||||
struct permissiveRecord *ppermissive;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
pvdes->field_type = DBF_SHORT;
|
||||
pvdes->no_elements=1;
|
||||
(short *)(pvdes->pvalue) = &(ppermissive->val);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct permissiveRecord *ppermissive=(struct permissiveRecord *)(paddr->precord);
|
||||
/* anyone waiting for an event on this record */
|
||||
struct permissiveRecord *ppermissive=(struct permissiveRecord *)(paddr->precord);
|
||||
|
||||
ppermissive->pact=TRUE;
|
||||
if(ppermissive->mlis.count!=0)
|
||||
db_post_events(ppermissive,&ppermissive->val,DBE_VALUE);
|
||||
ppermissive->pact=FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
454
src/rec/recPid.c
454
src/rec/recPid.c
@ -1,4 +1,3 @@
|
||||
|
||||
/* recPid.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -36,16 +35,16 @@
|
||||
#include <types.h>
|
||||
#include <stdioLib.h>
|
||||
#include <lstLib.h>
|
||||
/*since tickLib is not defined just define tickGet*/
|
||||
unsigned long tickGet();
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <pidRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -83,6 +82,14 @@ struct rset pidRSET={
|
||||
get_control_double,
|
||||
get_enum_strs };
|
||||
|
||||
/* the following definitions must match those in choiceGbl.ascii */
|
||||
#define SUPERVISORY 0
|
||||
#define CLOSED_LOOP 1
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
long do_pid();
|
||||
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -92,78 +99,23 @@ static long report(fp,paddr)
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
if(fprintf(fp,"VAL %-12.4G\n",ppid->val)) return(-1);
|
||||
if(recGblReportLink(fp,"INP ",&(ppid->inp))) return(-1);
|
||||
if(fprintf(fp,"PREC %d\n",ppid->prec)) return(-1);
|
||||
if(recGblReportCvtChoice(fp,"LINR",ppid->linr)) return(-1);
|
||||
if(fprintf(fp,"EGUF %-12.4G EGUL %-12.4G EGU %-8s\n",
|
||||
ppid->eguf,ppid->egul,ppid->egu)) return(-1);
|
||||
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
|
||||
ppid->hopr,ppid->lopr)) return(-1);
|
||||
if(recGblReportLink(fp,"FLNK",&(ppid->flnk))) return(-1);
|
||||
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
|
||||
ppid->hihi,ppid->high,ppid->low,ppid->lolo)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ppid,"HHSV",ppid->hhsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ppid,"HSV ",ppid->hsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ppid,"LSV ",ppid->lsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ppid,"LLSV",ppid->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G ESLO %-12.4G\n",
|
||||
ppid->hyst,ppid->adel,ppid->mdel,ppid->eslo)) return(-1);
|
||||
if(fprintf(fp,"ACHN %d\n", ppid->achn)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
ppid->lalm,ppid->alst,ppid->mlst)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
^L
|
||||
static pid_intervals[] = {1,5,4,3,2,1,1,1};
|
||||
|
||||
|
||||
static long init_record(ppid)
|
||||
struct pidRecord *ppid;
|
||||
{
|
||||
/* get the interval based on the scan type */
|
||||
ppid->intv = pid_intervals[ppid->scan];
|
||||
/* initialize so that first alarm, archive, and monitor get generated*/
|
||||
ppid->lalm = 1e30;
|
||||
ppid->alst = 1e30;
|
||||
ppid->mlst = 1e30;
|
||||
|
||||
/* initialize the setpoint for constant setpoint */
|
||||
if (ppid->stpl.type == CONSTANT)
|
||||
ppid->val = ppid->stpl.value.value;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct pidRecord *ppid=(struct pidRecord *)(paddr->precord);
|
||||
long status;
|
||||
|
||||
ppid->pact = TRUE;
|
||||
status=do_pid(ppid);
|
||||
if(status == -1) {
|
||||
if(ppid->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
ppid->stat = READ_ALARM;
|
||||
ppid->sevr = MAJOR_ALARM;
|
||||
ppid->achn=1;
|
||||
}
|
||||
}else if(status!=0) return(status);
|
||||
else if(ppid->stat == READ_ALARM || ppid->stat == HW_LIMIT_ALARM) {
|
||||
ppid->stat = NO_ALARM;
|
||||
ppid->sevr = NO_ALARM;
|
||||
ppid->achn=1;
|
||||
}
|
||||
if(status==0) do_pidect(ppid);
|
||||
|
||||
/* check for alarms */
|
||||
alarm(ppid);
|
||||
|
||||
|
||||
/* check event list */
|
||||
monitor(ppid);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (ppid->flnk.type==DB_LINK) dbScanPassive(&ppid->flnk.value);
|
||||
|
||||
ppid->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
long *precision;
|
||||
@ -171,7 +123,7 @@ static long get_precision(paddr,precision)
|
||||
struct pidRecord *ppid=(struct pidRecord *)paddr->precord;
|
||||
|
||||
*precision = ppid->prec;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(ppid,pvdes)
|
||||
@ -183,7 +135,7 @@ static long get_value(ppid,pvdes)
|
||||
(float *)(pvdes->pvalue) = &ppid->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
@ -191,7 +143,7 @@ static long get_units(paddr,units)
|
||||
struct pidRecord *ppid=(struct pidRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,ppid->egu,sizeof(ppid->egu));
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
@ -206,7 +158,7 @@ static long get_graphic_double(paddr,pgd)
|
||||
pgd->upper_warning_limit = ppid->high;
|
||||
pgd->lower_warning_limit = ppid->low;
|
||||
pgd->lower_alarm_limit = ppid->lolo;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
@ -217,7 +169,34 @@ static long get_control_double(paddr,pcd)
|
||||
|
||||
pcd->upper_ctrl_limit = ppid->hopr;
|
||||
pcd->lower_ctrl_limit = ppid->lopr;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct pidRecord *ppid=(struct pidRecord *)(paddr->precord);
|
||||
long status;
|
||||
|
||||
ppid->pact = TRUE;
|
||||
status=do_pid(ppid);
|
||||
if(status==1) {
|
||||
ppid->pact = FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(ppid);
|
||||
|
||||
|
||||
/* check event list */
|
||||
monitor(ppid);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (ppid->flnk.type==DB_LINK) dbScanPassive(&ppid->flnk.value.db_link.pdbAddr);
|
||||
|
||||
ppid->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static void alarm(ppid)
|
||||
@ -225,76 +204,51 @@ static void alarm(ppid)
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (ppid->stat == READ_ALARM) return(0);
|
||||
/* if difference is not > hysterisis don't bother */
|
||||
ftemp = ppid->lalm - ppid->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < ppid->hyst) return;
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (ppid->stat != NO_ALARM){
|
||||
ftemp = ppid->lalm - ppid->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < ppid->hyst) return;
|
||||
}
|
||||
/* alarm condition hihi */
|
||||
if (ppid->nsev<ppid->hhsv){
|
||||
if (ppid->val > ppid->hihi){
|
||||
ppid->lalm = ppid->val;
|
||||
ppid->nsta = HIHI_ALARM;
|
||||
ppid->nsev = ppid->hhsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (ppid->hhsv != NO_ALARM){
|
||||
if (ppid->val > ppid->hihi){
|
||||
ppid->lalm = ppid->val;
|
||||
if (ppid->stat != HIHI_ALARM){
|
||||
ppid->stat = HIHI_ALARM;
|
||||
ppid->sevr = ppid->hhsv;
|
||||
ppid->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* alarm condition lolo */
|
||||
if (ppid->nsev<ppid->llsv){
|
||||
if (ppid->val < ppid->lolo){
|
||||
ppid->lalm = ppid->val;
|
||||
ppid->nsta = LOLO_ALARM;
|
||||
ppid->nsev = ppid->llsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (ppid->llsv != NO_ALARM){
|
||||
if (ppid->val < ppid->lolo){
|
||||
ppid->lalm = ppid->val;
|
||||
if (ppid->stat != LOLO_ALARM){
|
||||
ppid->stat = LOLO_ALARM;
|
||||
ppid->sevr = ppid->llsv;
|
||||
ppid->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* alarm condition high */
|
||||
if (ppid->nsev<ppid->hsv){
|
||||
if (ppid->val > ppid->high){
|
||||
ppid->lalm = ppid->val;
|
||||
ppid->nsta = HIGH_ALARM;
|
||||
ppid->nsev =ppid->hsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (ppid->hsv != NO_ALARM){
|
||||
if (ppid->val > ppid->high){
|
||||
ppid->lalm = ppid->val;
|
||||
if (ppid->stat != HIGH_ALARM){
|
||||
ppid->stat = HIGH_ALARM;
|
||||
ppid->sevr =ppid->hsv;
|
||||
ppid->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (ppid->lsv != NO_ALARM){
|
||||
if (ppid->val < ppid->low){
|
||||
ppid->lalm = ppid->val;
|
||||
if (ppid->stat != LOW_ALARM){
|
||||
ppid->stat = LOW_ALARM;
|
||||
ppid->sevr = ppid->lsv;
|
||||
ppid->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (ppid->stat != NO_ALARM){
|
||||
ppid->stat = NO_ALARM;
|
||||
ppid->sevr = NO_ALARM;
|
||||
ppid->achn = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
/* alarm condition lolo */
|
||||
if (ppid->nsev<ppid->lsv){
|
||||
if (ppid->val < ppid->low){
|
||||
ppid->lalm = ppid->val;
|
||||
ppid->nsta = LOW_ALARM;
|
||||
ppid->nsev = ppid->lsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void monitor(ppid)
|
||||
@ -302,108 +256,160 @@ static void monitor(ppid)
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (ppid->mlis.count == 0) return;
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=ppid->stat;
|
||||
sevr=ppid->sevr;
|
||||
nsta=ppid->nsta;
|
||||
nsev=ppid->nsev;
|
||||
/*set current stat and sevr*/
|
||||
ppid->stat = nsta;
|
||||
ppid->sevr = nsev;
|
||||
ppid->nsta = 0;
|
||||
ppid->nsev = 0;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
/* anyone waiting for an event on this record */
|
||||
if (ppid->mlis.count == 0) return;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (ppid->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(ppid,&ppid->stat,DBE_VALUE);
|
||||
db_post_events(ppid,&ppid->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
ppid->mlst = ppid->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = ppid->mlst - ppid->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > ppid->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
ppid->mlst = ppid->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
delta = ppid->alst - ppid->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > ppid->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
ppid->alst = ppid->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(ppid,&ppid->val,monitor_mask);
|
||||
db_post_events(ppid,&ppid->rval,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long do_pid(ppid)
|
||||
register struct pid *ppid;
|
||||
{
|
||||
/* fetch the controlled value */
|
||||
if (ppid->cvl.type != DB_LINK) return(-1); /* nothing to control */
|
||||
if (db_fetch(&ppid->cvl.value,&ppid->cval) < 0){
|
||||
if (ppid->stat != READ_ALARM){
|
||||
ppid->stat = READ_ALARM;
|
||||
ppid->sevr = MAJOR;
|
||||
ppid->achn = 1;
|
||||
return(-1);
|
||||
}
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(ppid,&ppid->stat,DBE_VALUE);
|
||||
db_post_events(ppid,&ppid->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
delta = ppid->mlst - ppid->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > ppid->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
ppid->mlst = ppid->val;
|
||||
}
|
||||
/* check for archive change */
|
||||
delta = ppid->alst - ppid->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > ppid->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
ppid->alst = ppid->val;
|
||||
}
|
||||
|
||||
/* rate of change on the setpoint? */
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(ppid,&ppid->val,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* A discrete form of the PID algorithm is as follows
|
||||
* M(n) = KP*(E(n) + KI*SUMi(E(i)*dT(i))
|
||||
* + KD*(E(n) -E(n-1))/dT(i) + Mr
|
||||
* where
|
||||
* M(n) Value of manipulated variable at nth sampling instant
|
||||
* KP,KI,KD Proportional, Integral, and Differential Gains
|
||||
* NOTE: KI is inverse of normal KI
|
||||
* E(n) Error at nth sampling instant
|
||||
* SUMi Sum from i=0 to i=n
|
||||
* dT(n) Time difference between n-1 and n
|
||||
* Mr midrange adjustment
|
||||
*
|
||||
* Taking first difference yields
|
||||
* delM(n) = KP*((E(n)-E(n-1)) + E(n)*dT(n)*KI
|
||||
* + KD*((E(n)-E(n-1))/dT(n) - (E(n-1)-E(n-2))/dT(n-1))
|
||||
* or using variables defined in following
|
||||
* out = kp*(de + e*dt*ki + kd*(de/dt - dep/dtp)
|
||||
*/
|
||||
|
||||
static long do_pid(ppid)
|
||||
struct pidRecord *ppid;
|
||||
{
|
||||
long options,nRequest;
|
||||
unsigned long ctp; /*clock ticks previous */
|
||||
unsigned long ct; /*clock ticks */
|
||||
float cval; /*actual value */
|
||||
float val; /*desired value(setpoint)*/
|
||||
float dt; /*delta time (seconds) */
|
||||
float dtp; /*previous dt */
|
||||
float kp,ki,kd;/*gains */
|
||||
float e; /*error */
|
||||
float ep; /*previous error */
|
||||
float de; /*change in error */
|
||||
float dep; /*prev change in error */
|
||||
float out; /*output value */
|
||||
|
||||
/* fetch the controlled value */
|
||||
if (ppid->cvl.type != DB_LINK) { /* nothing to control*/
|
||||
if (ppid->nsev<MAJOR_ALARM) {
|
||||
ppid->nsta = SOFT_ALARM;
|
||||
ppid->nsev = MAJOR_ALARM;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
options=0;
|
||||
nRequest=1;
|
||||
if(!dbGetLink(&(ppid->cvl.value.db_link),ppid,DBR_FLOAT,
|
||||
&cval,&options,&nRequest)) {
|
||||
if (ppid->nsev<MAJOR_ALARM) {
|
||||
ppid->nsta = READ_ALARM;
|
||||
ppid->nsev = MAJOR_ALARM;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* fetch the setpoint */
|
||||
if ((ppid->stpl.type == DB_LINK) && (ppid->smsl == CLOSED_LOOP)){
|
||||
if (db_fetch(&ppid->stpl.value,&ppid->val) < 0){
|
||||
if (ppid->stat != READ_ALARM){
|
||||
if(ppid->stpl.type == DB_LINK && ppid->smsl == CLOSED_LOOP){
|
||||
options=0;
|
||||
nRequest=1;
|
||||
if(!dbGetLink(&(ppid->stpl.value.db_link),ppid,DBR_FLOAT,
|
||||
&(ppid->val),&options,&nRequest)) {
|
||||
if (ppid->nsev<MAJOR_ALARM) {
|
||||
ppid->stat = READ_ALARM;
|
||||
ppid->sevr = MAJOR;
|
||||
ppid->achn = 1;
|
||||
ppid->sevr = MAJOR_ALARM;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
val = ppid->val;
|
||||
|
||||
/* reset the integral term when the setpoint changes */
|
||||
if (ppid->val != ppid->lval){
|
||||
ppid->lval = ppid->val;
|
||||
ppid->inte = 0;
|
||||
}
|
||||
|
||||
/* determine the error */
|
||||
ppid->lerr = ppid->err;
|
||||
ppid->err = ppid->val - ppid->cval;
|
||||
ppid->derr = ppid->err - ppid->lerr;
|
||||
|
||||
/* determine the proportional contribution */
|
||||
ppid->prop = ppid->err * ppid->kp;
|
||||
|
||||
/* determine the integral contribution */
|
||||
ppid->inte += ppid->err;
|
||||
ppid->intg = ppid->inte * ppid->ki * ppid->intv;
|
||||
|
||||
/* determine the derivative contribution */
|
||||
/* we are implementing the derivativa term on error - do we want value also? */
|
||||
ppid->der = (ppid->derr * ppid->kd) / ppid->intv;
|
||||
|
||||
/* delta output contributions weighted by the proportional constant */
|
||||
ppid->out = ppid->intg + ppid->der + ppid->prop;
|
||||
|
||||
/* compute time difference and make sure it is large enough*/
|
||||
ctp = ppid->ct;
|
||||
ct = tickGet();
|
||||
if(ctp==ct) return(1);
|
||||
if(ctp<ct) {
|
||||
dt = (float)(ct-ctp);
|
||||
}else { /* clock has overflowed */
|
||||
dt = (unsigned long)(0xffffffff) - ctp;
|
||||
dt = dt + ct + 1;
|
||||
}
|
||||
dt = dt/vxTicksPerSecond;
|
||||
if(dt<ppid->mdt) return(1);
|
||||
/* get the rest of values needed */
|
||||
dtp = ppid->dt;
|
||||
kp = ppid->kp;
|
||||
ki = ppid->ki;
|
||||
kd = ppid->kd;
|
||||
ep = ppid->err;
|
||||
dep = ppid->derr;
|
||||
e = val - cval;
|
||||
de = e - ep;
|
||||
out = de;
|
||||
out = out + e*dt*ki;
|
||||
if(dtp!=0.0) out = out + kd*(de/dt - dep/dtp);
|
||||
out = kp*out;
|
||||
/* update record*/
|
||||
ppid->ct = ct;
|
||||
ppid->dt = dt;
|
||||
ppid->err = e;
|
||||
ppid->derr = de;
|
||||
ppid->val = val;
|
||||
ppid->cval = cval;
|
||||
ppid->out = out;
|
||||
return(0);
|
||||
}
|
||||
|
331
src/rec/recSel.c
331
src/rec/recSel.c
@ -1,4 +1,3 @@
|
||||
|
||||
/* recSel.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -41,14 +40,12 @@
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <selRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -87,6 +84,15 @@ struct rset selRSET={
|
||||
get_enum_strs };
|
||||
|
||||
#define SEL_MAX 6
|
||||
#define SELECTED 0
|
||||
#define SELECT_HIGH 1
|
||||
#define SELECT_LOW 2
|
||||
#define SELECT_MEDIAN 3
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
void fetch_values();
|
||||
int do_sel();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -96,31 +102,16 @@ static long report(fp,paddr)
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
if(fprintf(fp,"VAL %-12.4G\n",psel->val)) return(-1);
|
||||
if(recGblReportLink(fp,"INP ",&(psel->inp))) return(-1);
|
||||
if(fprintf(fp,"PREC %d\n",psel->prec)) return(-1);
|
||||
if(recGblReportCvtChoice(fp,"LINR",psel->linr)) return(-1);
|
||||
if(fprintf(fp,"EGUF %-12.4G EGUL %-12.4G EGU %-8s\n",
|
||||
psel->eguf,psel->egul,psel->egu)) return(-1);
|
||||
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
|
||||
psel->hopr,psel->lopr)) return(-1);
|
||||
if(recGblReportLink(fp,"FLNK",&(psel->flnk))) return(-1);
|
||||
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
|
||||
psel->hihi,psel->high,psel->low,psel->lolo)) return(-1);
|
||||
if(recGblReportGblChoice(fp,psel,"HHSV",psel->hhsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,psel,"HSV ",psel->hsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,psel,"LSV ",psel->lsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,psel,"LLSV",psel->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G ESLO %-12.4G\n",
|
||||
psel->hyst,psel->adel,psel->mdel,psel->eslo)) return(-1);
|
||||
if(fprintf(fp,"ACHN %d\n", psel->achn)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
psel->lalm,psel->alst,psel->mlst)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
^L
|
||||
|
||||
static long init_record(psel)
|
||||
struct selRecord *psel;
|
||||
{
|
||||
/* initialize so that first alarm, archive, and monitor get generated*/
|
||||
psel->lalm = 1e30;
|
||||
psel->alst = 1e30;
|
||||
psel->mlst = 1e30;
|
||||
|
||||
if(psel->inpa.type==CONSTANT) psel->a = psel->inpa.value.value;
|
||||
if(psel->inpb.type==CONSTANT) psel->b = psel->inpb.value.value;
|
||||
@ -130,43 +121,7 @@ static long init_record(psel)
|
||||
if(psel->inpf.type==CONSTANT) psel->f = psel->inpf.value.value;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct selRecord *psel=(struct selRecord *)(paddr->precord);
|
||||
long status;
|
||||
|
||||
psel->pact = TRUE;
|
||||
status=fetch_values(psel);
|
||||
if(status == -1) {
|
||||
if(psel->stat != READ_ALARM) {/* error. set alarm condition */
|
||||
psel->stat = READ_ALARM;
|
||||
psel->sevr = MAJOR_ALARM;
|
||||
psel->achn=1;
|
||||
}
|
||||
}else if(status!=0) return(status);
|
||||
else if(psel->stat == READ_ALARM || psel->stat == HW_LIMIT_ALARM) {
|
||||
psel->stat = NO_ALARM;
|
||||
psel->sevr = NO_ALARM;
|
||||
psel->achn=1;
|
||||
}
|
||||
if(status==0) do_select(psel);
|
||||
|
||||
/* check for alarms */
|
||||
alarm(psel);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!psel->disa) status = monitor(psel);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (psel->flnk.type==DB_LINK) dbScanPassive(&psel->flnk.value);
|
||||
|
||||
psel->pact=FALSE;
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
long *precision;
|
||||
@ -174,7 +129,7 @@ static long get_precision(paddr,precision)
|
||||
struct selRecord *psel=(struct selRecord *)paddr->precord;
|
||||
|
||||
*precision = psel->prec;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(psel,pvdes)
|
||||
@ -186,7 +141,7 @@ static long get_value(psel,pvdes)
|
||||
(float *)(pvdes->pvalue) = &psel->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
@ -194,7 +149,7 @@ static long get_units(paddr,units)
|
||||
struct selRecord *psel=(struct selRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,psel->egu,sizeof(psel->egu));
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
@ -209,7 +164,7 @@ static long get_graphic_double(paddr,pgd)
|
||||
pgd->upper_warning_limit = psel->high;
|
||||
pgd->lower_warning_limit = psel->low;
|
||||
pgd->lower_alarm_limit = psel->lolo;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
@ -220,144 +175,146 @@ static long get_control_double(paddr,pcd)
|
||||
|
||||
pcd->upper_ctrl_limit = psel->hopr;
|
||||
pcd->lower_ctrl_limit = psel->lopr;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long alarm(psel)
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct selRecord *psel=(struct selRecord *)(paddr->precord);
|
||||
|
||||
psel->pact = TRUE;
|
||||
fetch_values(psel);
|
||||
if(!do_sel(psel)) {
|
||||
if(psel->nsev<MAJOR_ALARM) {
|
||||
psel->nsta = CALC_ALARM;
|
||||
psel->nsev = MAJOR_ALARM;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(psel);
|
||||
|
||||
|
||||
/* check event list */
|
||||
monitor(psel);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (psel->flnk.type==DB_LINK) dbScanPassive(&psel->flnk.value.db_link.pdbAddr);
|
||||
|
||||
psel->pact=FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void alarm(psel)
|
||||
struct selRecord *psel;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* check for a hardware alarm */
|
||||
if (psel->stat == READ_ALARM) return(0);
|
||||
/* if difference is not > hysterisis don't bother */
|
||||
ftemp = psel->lalm - psel->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < psel->hyst) return;
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (psel->stat != NO_ALARM){
|
||||
ftemp = psel->lalm - psel->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < psel->hyst) return(0);
|
||||
}
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (psel->hhsv != NO_ALARM){
|
||||
if (psel->val > psel->hihi){
|
||||
psel->lalm = psel->val;
|
||||
if (psel->stat != HIHI_ALARM){
|
||||
psel->stat = HIHI_ALARM;
|
||||
psel->sevr = psel->hhsv;
|
||||
psel->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (psel->llsv != NO_ALARM){
|
||||
if (psel->val < psel->lolo){
|
||||
psel->lalm = psel->val;
|
||||
if (psel->stat != LOLO_ALARM){
|
||||
psel->stat = LOLO_ALARM;
|
||||
psel->sevr = psel->llsv;
|
||||
psel->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (psel->hsv != NO_ALARM){
|
||||
if (psel->val > psel->high){
|
||||
psel->lalm = psel->val;
|
||||
if (psel->stat != HIGH_ALARM){
|
||||
psel->stat = HIGH_ALARM;
|
||||
psel->sevr =psel->hsv;
|
||||
psel->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (psel->lsv != NO_ALARM){
|
||||
if (psel->val < psel->low){
|
||||
psel->lalm = psel->val;
|
||||
if (psel->stat != LOW_ALARM){
|
||||
psel->stat = LOW_ALARM;
|
||||
psel->sevr = psel->lsv;
|
||||
psel->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (psel->stat != NO_ALARM){
|
||||
psel->stat = NO_ALARM;
|
||||
psel->sevr = NO_ALARM;
|
||||
psel->achn = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
/* alarm condition hihi */
|
||||
if (psel->nsev<psel->hhsv){
|
||||
if (psel->val > psel->hihi){
|
||||
psel->lalm = psel->val;
|
||||
psel->nsta = HIHI_ALARM;
|
||||
psel->nsev = psel->hhsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* alarm condition lolo */
|
||||
if (psel->nsev<psel->llsv){
|
||||
if (psel->val < psel->lolo){
|
||||
psel->lalm = psel->val;
|
||||
psel->nsta = LOLO_ALARM;
|
||||
psel->nsev = psel->llsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* alarm condition high */
|
||||
if (psel->nsev<psel->hsv){
|
||||
if (psel->val > psel->high){
|
||||
psel->lalm = psel->val;
|
||||
psel->nsta = HIGH_ALARM;
|
||||
psel->nsev =psel->hsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* alarm condition lolo */
|
||||
if (psel->nsev<psel->lsv){
|
||||
if (psel->val < psel->low){
|
||||
psel->lalm = psel->val;
|
||||
psel->nsta = LOW_ALARM;
|
||||
psel->nsev = psel->lsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(psel)
|
||||
static void monitor(psel)
|
||||
struct selRecord *psel;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (psel->mlis.count == 0) return(0L);
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=psel->stat;
|
||||
sevr=psel->sevr;
|
||||
nsta=psel->nsta;
|
||||
nsev=psel->nsev;
|
||||
/*set current stat and sevr*/
|
||||
psel->stat = nsta;
|
||||
psel->sevr = nsev;
|
||||
psel->nsta = 0;
|
||||
psel->nsev = 0;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
/* anyone waiting for an event on this record */
|
||||
if (psel->mlis.count == 0) return;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (psel->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(psel,&psel->stat,DBE_VALUE);
|
||||
db_post_events(psel,&psel->sevr,DBE_VALUE);
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(psel,&psel->stat,DBE_VALUE);
|
||||
db_post_events(psel,&psel->sevr,DBE_VALUE);
|
||||
}
|
||||
/* check for value change */
|
||||
delta = psel->mlst - psel->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > psel->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
psel->mlst = psel->val;
|
||||
}
|
||||
/* check for archive change */
|
||||
delta = psel->alst - psel->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > psel->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
/* update last archive value monitored */
|
||||
psel->alst = psel->val;
|
||||
}
|
||||
|
||||
/* update last value monitored */
|
||||
psel->mlst = psel->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = psel->mlst - psel->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > psel->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
psel->mlst = psel->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
delta = psel->alst - psel->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > psel->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
psel->alst = psel->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(psel,&psel->val,monitor_mask);
|
||||
db_post_events(psel,&psel->rval,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(psel,&psel->val,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long do_sel(psel)
|
||||
struct sel *psel; /* pointer to selection record */
|
||||
static int do_sel(psel)
|
||||
struct selRecord *psel; /* pointer to selection record */
|
||||
{
|
||||
float *pvalue;
|
||||
struct link *plink;
|
||||
@ -402,6 +359,8 @@ struct sel *psel; /* pointer to selection record */
|
||||
}
|
||||
psel->val = order[order_inx/2];
|
||||
break;
|
||||
default:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* initialize flag */
|
||||
@ -413,22 +372,22 @@ struct sel *psel; /* pointer to selection record */
|
||||
*
|
||||
* fetch the values for the variables from which to select
|
||||
*/
|
||||
static fetch_values(psel)
|
||||
register struct sel *psel;
|
||||
static void fetch_values(psel)
|
||||
struct selRecord *psel;
|
||||
{
|
||||
long nRequest;
|
||||
long options=0;
|
||||
struct link *plink;
|
||||
float *pvalue;
|
||||
int i;
|
||||
|
||||
plink = &psel->inpa;
|
||||
pvalue = &psel->a;
|
||||
for(i=0; i<SEL_MAX; i++, plink++, pvalue++) {
|
||||
if(plink->type==DB_LINK) {
|
||||
nRequest=1;
|
||||
status=dbGetLink(plink,DBR_FLOAT,pvalue,&options,&nRequest);
|
||||
if(status!=0) return(status);
|
||||
(void)dbGetLink(&plink->value.db_link,psel,DBR_FLOAT,pvalue,&options,&nRequest);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recState.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -37,8 +36,6 @@
|
||||
#include <stdioLib.h>
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -46,7 +43,6 @@
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <stateRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -91,15 +87,29 @@ static long report(fp,paddr)
|
||||
struct stateRecord *pstate=(struct stateRecord*)(paddr->precord);
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
if(fprintf(fp,"VAL %d\n",pstate->val)) return(-1);
|
||||
if(fprintf(fp,"VAL %s\n",pstate->val)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(pstate,pvdes)
|
||||
struct stateRecord *pstate;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
pvdes->field_type = DBF_STRING;
|
||||
pvdes->no_elements=1;
|
||||
pvdes->pvalue = (caddr_t)(&pstate->val[0]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct stateRecord *pstate=(struct stateRecord *)(paddr->precord);
|
||||
/* anyone waiting for an event on this record */
|
||||
pstate->pact=FALSE;
|
||||
struct stateRecord *pstate=(struct stateRecord *)(paddr->precord);
|
||||
|
||||
pstate->pact=TRUE;
|
||||
if(pstate->mlis.count != 0)
|
||||
db_post_events(pstate,&(pstate->val[0]),DBE_VALUE);
|
||||
pstate->pact=FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
691
src/rec/recSub.c
691
src/rec/recSub.c
@ -1,4 +1,3 @@
|
||||
|
||||
/* recSub.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -35,17 +34,18 @@
|
||||
#include <vxWorks.h>
|
||||
#include <types.h>
|
||||
#include <stdioLib.h>
|
||||
#include <lstLib.h>
|
||||
#include <symLib.h>
|
||||
#include <sysSymTbl.h> /* for sysSymTbl*/
|
||||
#include <a_out.h> /* for N_TEXT */
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
#include <devSup.h>
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <subRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -82,6 +82,11 @@ struct rset subRSET={
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_enum_strs };
|
||||
|
||||
void alarm();
|
||||
void monitor();
|
||||
long do_sub();
|
||||
void fetch_values();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -115,21 +120,19 @@ static long report(fp,paddr)
|
||||
if(recGblReportGblChoice(fp,psub,"LLSV",psub->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G\n",
|
||||
psub->hyst,psub->adel,psub->mdel)) return(-1);
|
||||
if(fprintf(fp,"ACHN %d\n",psub->achn)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
psub->lalm,psub->alst,psub->mlst)) return(-1);
|
||||
if(fprintf(fp,"CALC %s\n",psub->sub)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init_record(psub)
|
||||
struct subRecord *psub;
|
||||
{
|
||||
long status;
|
||||
FUNCPTR psubroutine;
|
||||
char sub_type;
|
||||
char temp[40];
|
||||
short ret;
|
||||
long status;
|
||||
STATUS ret;
|
||||
|
||||
if(psub->inpa.type==CONSTANT) psub->a = psub->inpa.value.value;
|
||||
if(psub->inpb.type==CONSTANT) psub->b = psub->inpb.value.value;
|
||||
@ -146,27 +149,15 @@ static long init_record(psub)
|
||||
}
|
||||
strcat(temp,psub->inam);
|
||||
ret = symFindByName(sysSymTbl,temp,&psub->sadr,&sub_type);
|
||||
if ((ret < 0) || ((sub_type & N_TEXT) == 0)){
|
||||
psub->stat = BAD_SUB_ALARM;
|
||||
psub->sevr = MAJOR;
|
||||
psub->achn = 1;
|
||||
monitor_sub(psub);
|
||||
return(-1);
|
||||
if ((ret !=OK) || ((sub_type & N_TEXT) == 0)){
|
||||
recGblRecordError(S_db_BadSub,psub,"recSub(init_record)");
|
||||
return(S_db_BadSub);
|
||||
}
|
||||
|
||||
/* invoke the initialization subroutine */
|
||||
(long)psubroutine = psub->sadr;
|
||||
if (psubroutine(psub,sub_callback,
|
||||
&psub->a,&psub->b,&psub->c,&psub->d,&psub->e,&psub->f,
|
||||
&psub->val) < 0){
|
||||
if (psub->brsv != NO_ALARM){
|
||||
psub->stat = RETURN_ALARM;
|
||||
psub->sevr = psub->brsv;
|
||||
psub->achn = 1;
|
||||
monitor_sub(psub);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
psubroutine = (FUNCPTR)(psub->sadr);
|
||||
status = psubroutine(psub);
|
||||
if(!status) return(status);
|
||||
|
||||
/* convert the subroutine name to an address and type */
|
||||
/* convert the initialization subroutine name */
|
||||
@ -177,15 +168,8 @@ static long init_record(psub)
|
||||
strcat(temp,psub->snam);
|
||||
ret = symFindByName(sysSymTbl,temp,&psub->sadr,&sub_type);
|
||||
if ((ret < 0) || ((sub_type & N_TEXT) == 0)){
|
||||
psub->styp = sub_type;
|
||||
psub->stat = BAD_SUB_ALARM;
|
||||
psub->sevr = MAJOR;
|
||||
psub->achn = 1;
|
||||
monitor_sub(psub);
|
||||
return(-1);
|
||||
}else if (psub->stat != NO_ALARM){
|
||||
psub->sevr = psub->stat = NO_ALARM;
|
||||
psub->achn = 1;
|
||||
recGblRecordError(S_db_BadSub,psub,"recSub(init_record)");
|
||||
return(S_db_BadSub);
|
||||
}
|
||||
psub->styp = sub_type;
|
||||
return(0);
|
||||
@ -198,7 +182,7 @@ static long get_precision(paddr,precision)
|
||||
struct subRecord *psub=(struct subRecord *)paddr->precord;
|
||||
|
||||
*precision = psub->prec;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(psub,pvdes)
|
||||
@ -210,7 +194,7 @@ static long get_value(psub,pvdes)
|
||||
(float *)(pvdes->pvalue) = &psub->val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
@ -218,7 +202,7 @@ static long get_units(paddr,units)
|
||||
struct subRecord *psub=(struct subRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,psub->egu,sizeof(psub->egu));
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
@ -233,7 +217,7 @@ static long get_graphic_double(paddr,pgd)
|
||||
pgd->upper_warning_limit = psub->high;
|
||||
pgd->lower_warning_limit = psub->low;
|
||||
pgd->lower_alarm_limit = psub->lolo;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_control_double(paddr,pcd)
|
||||
@ -244,538 +228,189 @@ static long get_control_double(paddr,pcd)
|
||||
|
||||
pcd->upper_ctrl_limit = psub->hopr;
|
||||
pcd->lower_ctrl_limit = psub->lopr;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct subRecord *psub=(struct subRecord *)(paddr->precord);
|
||||
struct subdset *pdset = (struct subdset *)(psub->dset);
|
||||
struct subRecord *psub=(struct subRecord *)(paddr->precord);
|
||||
long status;
|
||||
|
||||
psub->achn = 0;
|
||||
/* read inputs */
|
||||
if (fetch_values(psub) < 0){
|
||||
if (psub->stat != READ_ALARM){
|
||||
psub->stat = READ_ALARM;
|
||||
psub->sevr = MAJOR_ALARM;
|
||||
psub->achn = 1;
|
||||
monitor_sub(psub);
|
||||
}
|
||||
psub->pact = 0;
|
||||
return(0);
|
||||
}else{
|
||||
if (psub->stat == READ_ALARM){
|
||||
psub->stat = NO_ALARM;
|
||||
psub->sevr = NO_ALARM;
|
||||
psub->achn = 1;
|
||||
}
|
||||
if(!psub->pact){
|
||||
psub->pact = TRUE;
|
||||
fetch_values(psub);
|
||||
psub->pact = FALSE;
|
||||
}
|
||||
|
||||
/* perform subulation */
|
||||
if (do_sub(psub) < 0){
|
||||
if (psub->stat != CALC_ALARM){
|
||||
psub->stat = CALC_ALARM;
|
||||
psub->sevr = MAJOR_ALARM;
|
||||
psub->achn = 1;
|
||||
monitor_sub(psub);
|
||||
}
|
||||
psub->pact = 0;
|
||||
return;
|
||||
}else{
|
||||
if (psub->stat == CALC_ALARM){
|
||||
psub->stat = NO_ALARM;
|
||||
psub->sevr = NO_ALARM;
|
||||
psub->achn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for alarms */
|
||||
alarm(psub);
|
||||
|
||||
|
||||
/* check event list */
|
||||
if(!psub->disa) status = monitor(psub);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (psub->flnk.type==DB_LINK) dbScanPassive(&psub->flnk.value);
|
||||
|
||||
psub->pact=FALSE;
|
||||
return(status);
|
||||
status = do_sub(psub);
|
||||
psub->pact = TRUE;
|
||||
if(status==1) return(0);
|
||||
/* check for alarms */
|
||||
alarm(psub);
|
||||
/* check event list */
|
||||
monitor(psub);
|
||||
/* process the forward scan link record */
|
||||
if (psub->flnk.type==DB_LINK) dbScanPassive(&psub->flnk.value.db_link.pdbAddr);
|
||||
psub->pact = FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* FETCH_VALUES
|
||||
*
|
||||
* fetch the values for the variables in the subulation
|
||||
*/
|
||||
static fetch_values(psub)
|
||||
struct subRecord *psub;
|
||||
{
|
||||
short status;
|
||||
|
||||
/* note - currently not using alarm status */
|
||||
status = 0;
|
||||
status |= get_sub_inp(&psub->inpa,&psub->a);
|
||||
status |= get_sub_inp(&psub->inpb,&psub->b);
|
||||
status |= get_sub_inp(&psub->inpc,&psub->c);
|
||||
status |= get_sub_inp(&psub->inpd,&psub->d);
|
||||
status |= get_sub_inp(&psub->inpe,&psub->e);
|
||||
status |= get_sub_inp(&psub->inpf,&psub->f);
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* GET_CALC_INPUT
|
||||
*
|
||||
* return an input value
|
||||
*/
|
||||
static get_sub_inp(plink,pvalue)
|
||||
struct link *plink; /* structure of the link field */
|
||||
float *pvalue;
|
||||
{
|
||||
float float_value;
|
||||
|
||||
/* database link */
|
||||
if (plink->type == DB_LINK){
|
||||
if (dbGetLink(&plink->value.db_link,DBR_FLOAT,&float_value,1) < 0)
|
||||
return(-1);
|
||||
*pvalue = float_value;
|
||||
|
||||
/* constant */
|
||||
}else if (plink->type == CONSTANT){
|
||||
;
|
||||
/* illegal link type */
|
||||
}else{
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
static long alarm(psub)
|
||||
static void alarm(psub)
|
||||
struct subRecord *psub;
|
||||
{
|
||||
float ftemp;
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (psub->stat != NO_ALARM){
|
||||
ftemp = psub->lalm - psub->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < psub->hyst) return(0);
|
||||
}
|
||||
/* if difference is not > hysterisis don't bother */
|
||||
ftemp = psub->lalm - psub->val;
|
||||
if(ftemp<0.0) ftemp = -ftemp;
|
||||
if (ftemp < psub->hyst) return;
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (psub->hhsv != NO_ALARM){
|
||||
if (psub->val > psub->hihi){
|
||||
psub->lalm = psub->val;
|
||||
if (psub->stat != HIHI_ALARM){
|
||||
psub->stat = HIHI_ALARM;
|
||||
psub->sevr = psub->hhsv;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* alarm condition hihi */
|
||||
if (psub->nsev<psub->hhsv){
|
||||
if (psub->val > psub->hihi){
|
||||
psub->lalm = psub->val;
|
||||
psub->nsta = HIHI_ALARM;
|
||||
psub->nsev = psub->hhsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (psub->llsv != NO_ALARM){
|
||||
if (psub->val < psub->lolo){
|
||||
psub->lalm = psub->val;
|
||||
if (psub->stat != LOLO_ALARM){
|
||||
psub->stat = LOLO_ALARM;
|
||||
psub->sevr = psub->llsv;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* alarm condition lolo */
|
||||
if (psub->nsev<psub->llsv){
|
||||
if (psub->val < psub->lolo){
|
||||
psub->lalm = psub->val;
|
||||
psub->nsta = LOLO_ALARM;
|
||||
psub->nsev = psub->llsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (psub->hsv != NO_ALARM){
|
||||
if (psub->val > psub->high){
|
||||
psub->lalm = psub->val;
|
||||
if (psub->stat != HIGH_ALARM){
|
||||
psub->stat = HIGH_ALARM;
|
||||
psub->sevr =psub->hsv;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (psub->lsv != NO_ALARM){
|
||||
if (psub->val < psub->low){
|
||||
psub->lalm = psub->val;
|
||||
if (psub->stat != LOW_ALARM){
|
||||
psub->stat = LOW_ALARM;
|
||||
psub->sevr = psub->lsv;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (psub->stat != NO_ALARM){
|
||||
psub->stat = NO_ALARM;
|
||||
psub->sevr = NO_ALARM;
|
||||
psub->achn = 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
/* alarm condition high */
|
||||
if (psub->nsev<psub->hsv){
|
||||
if (psub->val > psub->high){
|
||||
psub->lalm = psub->val;
|
||||
psub->nsta = HIGH_ALARM;
|
||||
psub->nsev =psub->hsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* alarm condition lolo */
|
||||
if (psub->nsev<psub->lsv){
|
||||
if (psub->val < psub->low){
|
||||
psub->lalm = psub->val;
|
||||
psub->nsta = LOW_ALARM;
|
||||
psub->nsev = psub->lsv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static long monitor(psub)
|
||||
static void monitor(psub)
|
||||
struct subRecord *psub;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* anyone wsubting for an event on this record */
|
||||
if (psub->mlis.count == 0) return(0L);
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (psub->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE | DBE_LOG;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(psub,&psub->stat,DBE_VALUE);
|
||||
db_post_events(psub,&psub->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
psub->mlst = psub->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = psub->mlst - psub->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > psub->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
psub->mlst = psub->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
delta = psub->alst - psub->val;
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > psub->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
psub->alst = psub->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask){
|
||||
db_post_events(psub,&psub->val,monitor_mask);
|
||||
}
|
||||
return(0L);
|
||||
}
|
||||
|
||||
process_sub(psub)
|
||||
register struct sub *psub; /* pointer to subroutine record */
|
||||
{
|
||||
psub->achn = 0;
|
||||
|
||||
/* lock the record */
|
||||
if (psub->lock){
|
||||
if (psub->lcnt >= MAX_LOCK){
|
||||
psub->stat = SCAN_ALARM;
|
||||
psub->sevr = MAJOR;
|
||||
psub->achn = 1;
|
||||
monitor_sub(psub);
|
||||
}else{
|
||||
psub->lcnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
psub->lcnt = 0;
|
||||
psub->lock = 1;
|
||||
|
||||
if (psub->init == 0){
|
||||
if (sub_init(psub) < 0){
|
||||
psub->lock = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for valid subroutine connection */
|
||||
if (psub->stat == BAD_SUB_ALARM){
|
||||
psub->lock = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* perform the subroutine call */
|
||||
do_sub(psub);
|
||||
|
||||
/* do post processing for synchronous routines */
|
||||
if (psub->rtcb == FALSE){
|
||||
sub_callback(psub);
|
||||
}
|
||||
/* unlock of record is done in sub_callback either directly (above) */
|
||||
/* or asynchronously through the callback mechanism */
|
||||
}
|
||||
|
||||
/*
|
||||
* SUB_CALLBACK
|
||||
*
|
||||
* subroutine values returned handling -
|
||||
* either called immediately for fast routines or asynchronously for slow
|
||||
* routines (i.e. GPIB interfaces that require a wait)
|
||||
*/
|
||||
sub_callback(psub)
|
||||
register struct sub *psub; /* pointer to subroutine record */
|
||||
{
|
||||
/* check for alarms */
|
||||
if ((psub->stat != READ_ALARM) && (psub->stat != RETURN_ALARM)
|
||||
&& (psub->stat != BAD_SUB_ALARM))
|
||||
alarm_sub(psub);
|
||||
|
||||
/* check for monitors */
|
||||
monitor_sub(psub);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (psub->flnk.type == DB_LINK)
|
||||
db_scan(&psub->flnk.value);
|
||||
|
||||
/* unlock the record */
|
||||
psub->lock = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* DO_SUB
|
||||
*
|
||||
* invoke the subroutine
|
||||
*/
|
||||
static do_sub(psub)
|
||||
register struct sub *psub; /* pointer to subroutine record */
|
||||
{
|
||||
register short status;
|
||||
register FUNCPTR psubroutine;
|
||||
|
||||
/* get the subroutine arguments */
|
||||
status = 0;
|
||||
if (psub->inpa.type == DB_LINK){
|
||||
if (db_fetch(&psub->inpa.value.db_link,&psub->a) < 0)
|
||||
status |= -1;
|
||||
}
|
||||
if (psub->inpb.type == DB_LINK){
|
||||
if (db_fetch(&psub->inpb.value.db_link,&psub->b) < 0)
|
||||
status |= -1;
|
||||
}
|
||||
if (psub->inpc.type == DB_LINK){
|
||||
if (db_fetch(&psub->inpc.value.db_link,&psub->c) < 0)
|
||||
status |= -1;
|
||||
}
|
||||
if (psub->inpd.type == DB_LINK){
|
||||
if (db_fetch(&psub->inpd.value.db_link,&psub->d) < 0)
|
||||
status |= -1;
|
||||
}
|
||||
if (psub->inpe.type == DB_LINK){
|
||||
if (db_fetch(&psub->inpe.value.db_link,&psub->e) < 0)
|
||||
status |= -1;
|
||||
}
|
||||
if (psub->inpf.type == DB_LINK){
|
||||
if (db_fetch(&psub->inpf.value.db_link,&psub->f) < 0)
|
||||
status |= -1;
|
||||
}
|
||||
if (status != 0){
|
||||
psub->stat = READ_ALARM;
|
||||
psub->sevr = MAJOR;
|
||||
psub->achn = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* call the subroutine */
|
||||
(long)psubroutine = psub->sadr;
|
||||
if (psubroutine(psub,sub_callback,
|
||||
&psub->a,&psub->b,&psub->c,&psub->d,&psub->e,&psub->f,
|
||||
&psub->val) < 0){
|
||||
if (psub->brsv != NO_ALARM){
|
||||
psub->stat = RETURN_ALARM;
|
||||
psub->sevr = psub->brsv;
|
||||
psub->achn = 1;
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
if (psub->brsv != NO_ALARM){
|
||||
psub->stat = NO_ALARM;
|
||||
psub->sevr = NO_ALARM;
|
||||
psub->achn = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ALARM_SUB
|
||||
*
|
||||
* check the alarm condition
|
||||
*/
|
||||
static alarm_sub(psub)
|
||||
register struct sub *psub;
|
||||
{
|
||||
register float ftemp;
|
||||
|
||||
/* if in alarm and difference is not > hysterisis don't bother */
|
||||
if (psub->stat != NO_ALARM){
|
||||
ftemp = psub->lalm - psub->val;
|
||||
if ( (ftemp < psub->hyst) && (ftemp > -psub->hyst))
|
||||
return;
|
||||
}
|
||||
|
||||
/* alarm condition hihi */
|
||||
if (psub->hhsv != NO_ALARM){
|
||||
if (psub->val > psub->hihi){
|
||||
if (psub->stat != HIHI_ALARM){
|
||||
psub->stat = HIHI_ALARM;
|
||||
psub->sevr = psub->hhsv;
|
||||
psub->lalm = psub->val;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition lolo */
|
||||
if (psub->llsv != NO_ALARM){
|
||||
if (psub->val < psub->lolo){
|
||||
if (psub->stat != LOLO_ALARM){
|
||||
psub->stat = LOLO_ALARM;
|
||||
psub->sevr = psub->llsv;
|
||||
psub->lalm = psub->val;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition high */
|
||||
if (psub->hsv != NO_ALARM){
|
||||
if (psub->val > psub->high){
|
||||
if (psub->stat != HIGH_ALARM){
|
||||
psub->stat = HIGH_ALARM;
|
||||
psub->sevr = psub->hsv;
|
||||
psub->lalm = psub->val;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alarm condition low */
|
||||
if (psub->lsv != NO_ALARM){
|
||||
if (psub->val < psub->low){
|
||||
if (psub->stat != LOW_ALARM){
|
||||
psub->stat = LOW_ALARM;
|
||||
psub->sevr = psub->lsv;
|
||||
psub->lalm = psub->val;
|
||||
psub->achn = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* no alarm */
|
||||
if (psub->stat != NO_ALARM){
|
||||
psub->stat = NO_ALARM;
|
||||
psub->sevr = NO_ALARM;
|
||||
psub->achn = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* MONITOR_SUB
|
||||
*
|
||||
* process subroutine record monitors
|
||||
*/
|
||||
static monitor_sub(psub)
|
||||
register struct sub *psub; /* pointer to the subroutine record */
|
||||
{
|
||||
register unsigned short monitor_mask;
|
||||
register float delta;
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=psub->stat;
|
||||
sevr=psub->sevr;
|
||||
nsta=psub->nsta;
|
||||
nsev=psub->nsev;
|
||||
/*set current stat and sevr*/
|
||||
psub->stat = nsta;
|
||||
psub->sevr = nsev;
|
||||
psub->nsta = 0;
|
||||
psub->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (psub->mqct == 0) return;
|
||||
|
||||
/* check monitors for each of the argument fields */
|
||||
if (psub->la != psub->a){
|
||||
db_post_events(psub,&psub->a,DBE_VALUE);
|
||||
psub->la = psub->a;
|
||||
}
|
||||
if (psub->lb != psub->b){
|
||||
db_post_events(psub,&psub->b,DBE_VALUE);
|
||||
psub->la = psub->b;
|
||||
}
|
||||
if (psub->lc != psub->c){
|
||||
db_post_events(psub,&psub->c,DBE_VALUE);
|
||||
psub->lc = psub->c;
|
||||
}
|
||||
if (psub->ld != psub->d){
|
||||
db_post_events(psub,&psub->d,DBE_VALUE);
|
||||
psub->ld = psub->d;
|
||||
}
|
||||
if (psub->le != psub->e){
|
||||
db_post_events(psub,&psub->e,DBE_VALUE);
|
||||
psub->le = psub->e;
|
||||
}
|
||||
if (psub->lf != psub->f){
|
||||
db_post_events(psub,&psub->f,DBE_VALUE);
|
||||
psub->lf = psub->f;
|
||||
}
|
||||
if (psub->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (psub->achn != 0){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM | DBE_VALUE;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(psub,&psub->stat,DBE_VALUE);
|
||||
db_post_events(psub,&psub->sevr,DBE_VALUE);
|
||||
|
||||
}
|
||||
/* check for value change */
|
||||
delta = psub->mlst - psub->val;
|
||||
if(delta<0.0) delta = -delta;
|
||||
if (delta > psub->mdel) {
|
||||
/* post events for value change */
|
||||
monitor_mask |= DBE_VALUE;
|
||||
/* update last value monitored */
|
||||
psub->mlst = psub->val;
|
||||
|
||||
/* check for value change */
|
||||
}else{
|
||||
delta = psub->mlst - psub->val;
|
||||
if ((delta > psub->mdel) || (delta < -psub->mdel)){
|
||||
/* post events for value change */
|
||||
monitor_mask = DBE_VALUE;
|
||||
|
||||
/* update last value monitored */
|
||||
psub->mlst = psub->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for archive change */
|
||||
delta = psub->alst - psub->val;
|
||||
if ((delta > psub->adel) || (delta < -psub->adel)){
|
||||
if(delta<0.0) delta = 0.0;
|
||||
if (delta > psub->adel) {
|
||||
/* post events on value field for archive change */
|
||||
monitor_mask |= DBE_LOG;
|
||||
|
||||
/* update last archive value monitored */
|
||||
psub->alst = psub->val;
|
||||
}
|
||||
|
||||
/* send out monitors connected to the value field */
|
||||
if (monitor_mask)
|
||||
if (monitor_mask){
|
||||
db_post_events(psub,&psub->val,monitor_mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void fetch_values(psub)
|
||||
struct subRecord *psub;
|
||||
{
|
||||
struct link *plink; /* structure of the link field */
|
||||
float *pvalue;
|
||||
long options,nRequest;
|
||||
int i;
|
||||
|
||||
for(i=0, plink=&psub->inpa, pvalue=&psub->a; i<6; i++, plink++, pvalue++) {
|
||||
if(plink->type!=DB_LINK) continue;
|
||||
options=0;
|
||||
nRequest=1;
|
||||
(void)dbGetLink(&plink->value.db_link,psub,DBR_FLOAT,
|
||||
pvalue,&options,&nRequest);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void callback(psub)
|
||||
struct subRecord *psub; /* pointer to subroutine record */
|
||||
{
|
||||
dbScanLock(psub);
|
||||
(void)process(psub);
|
||||
dbScanUnlock(psub);
|
||||
}
|
||||
|
||||
static long do_sub(psub)
|
||||
struct subRecord *psub; /* pointer to subroutine record */
|
||||
{
|
||||
short status;
|
||||
FUNCPTR psubroutine;
|
||||
|
||||
|
||||
/* call the subroutine */
|
||||
psubroutine = (FUNCPTR)(psub->sadr);
|
||||
if(psubroutine==NULL) {
|
||||
if(psub->nsev<MAJOR_ALARM) {
|
||||
psub->nsta = BAD_SUB_ALARM;
|
||||
psub->nsev = MAJOR_ALARM;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
status = psubroutine(psub,callback);
|
||||
if(status < 0){
|
||||
if (psub->nsev<psub->brsv){
|
||||
psub->nsta = SOFT_ALARM;
|
||||
psub->nsev = psub->brsv;
|
||||
}
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* recTimer.c */
|
||||
/* share/src/rec $Id$ */
|
||||
|
||||
@ -48,7 +47,6 @@
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -56,7 +54,6 @@
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <timerRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -64,16 +61,16 @@ long report();
|
||||
#define initialize NULL
|
||||
long init_record();
|
||||
long process();
|
||||
#define special();
|
||||
#define get_precision();
|
||||
#define special NULL
|
||||
#define get_precision NULL
|
||||
long get_value();
|
||||
#define cvt_dbaddr NULL
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
#define get_enum_str NULL
|
||||
#define get_units();
|
||||
#define get_graphic_double();
|
||||
#define get_control_double();
|
||||
#define get_units NULL
|
||||
#define get_graphic_double NULL
|
||||
#define get_control_double NULL
|
||||
#define get_enum_strs NULL
|
||||
|
||||
struct rset timerRSET={
|
||||
@ -95,9 +92,16 @@ struct rset timerRSET={
|
||||
get_enum_strs };
|
||||
|
||||
/* because the driver does all the work just declare device support here*/
|
||||
struct dset devMizar8310={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devDg535={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devVxiAt5Time={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devTmMizar8310={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devTmDg535={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devTmVxiAt5={4,NULL,NULL,NULL,NULL};
|
||||
|
||||
extern int post_event();
|
||||
|
||||
void monitor();
|
||||
void read_timer();
|
||||
void convert_timer();
|
||||
void write_timer();
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
@ -107,37 +111,18 @@ static long report(fp,paddr)
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
if(fprintf(fp,"VAL %-12.4G\n",ptimer->val)) return(-1);
|
||||
if(recGblReportLink(fp,"INP ",&(ptimer->inp))) return(-1);
|
||||
if(fprintf(fp,"PREC %d\n",ptimer->prec)) return(-1);
|
||||
if(recGblReportCvtChoice(fp,"LINR",ptimer->linr)) return(-1);
|
||||
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
|
||||
ptimer->hopr,ptimer->lopr)) return(-1);
|
||||
if(recGblReportLink(fp,"FLNK",&(ptimer->flnk))) return(-1);
|
||||
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
|
||||
ptimer->hihi,ptimer->high,ptimer->low,ptimer->lolo)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ptimer,"HHSV",ptimer->hhsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ptimer,"HSV ",ptimer->hsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ptimer,"LSV ",ptimer->lsv)) return(-1);
|
||||
if(recGblReportGblChoice(fp,ptimer,"LLSV",ptimer->llsv)) return(-1);
|
||||
if(fprintf(fp,"HYST %-12.4G ADEL %-12.4G MDEL %-12.4G ESLO %-12.4G\n",
|
||||
ptimer->hyst,ptimer->adel,ptimer->mdel,ptimer->eslo)) return(-1);
|
||||
if(fprintf(fp,"RVAL 0x%-8X ACHN %d\n",
|
||||
ptimer->rval,ptimer->achn)) return(-1);
|
||||
if(fprintf(fp,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
|
||||
ptimer->lalm,ptimer->alst,ptimer->mlst)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init_record(ptimer)
|
||||
struct timerRecord *ptimer;
|
||||
{
|
||||
long status;
|
||||
|
||||
/* read to maintain time pulses over a restart */
|
||||
read_timer(ptimer);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long get_value(ptimer,pvdes)
|
||||
struct timerRecord *ptimer;
|
||||
struct valueDes *pvdes;
|
||||
@ -148,39 +133,63 @@ static long get_value(ptimer,pvdes)
|
||||
return(0);
|
||||
}
|
||||
|
||||
extern int post_event();
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct timerRecord *ptimer=(struct timerRecord *)(paddr->precord);
|
||||
long status;
|
||||
|
||||
ptimer->pact=TRUE;
|
||||
ptimer->achn = 0; /* init the alarm change flag */
|
||||
|
||||
/* write the new value */
|
||||
write_timer(ptimer);
|
||||
|
||||
/* need to post events for an alarm condition change */
|
||||
if ((ptimer->achn) && (ptimer->mlis.count!=0))
|
||||
db_post_events(ptimer,&ptimer->val,DBE_ALARM);
|
||||
/* check event list */
|
||||
monitor(ptimer);
|
||||
/* process the forward scan link record */
|
||||
if (ptimer->flnk.type==DB_LINK) dbScanPassive(&ptimer->flnk.value.db_link.pdbAddr);
|
||||
|
||||
if (ptimer->mlis.count!=0){
|
||||
db_post_events(ptimer,&ptimer->val,DBE_VALUE);
|
||||
db_post_events(ptimer,&ptimer->t1wd,DBE_VALUE);
|
||||
db_post_events(ptimer,&ptimer->t1ld,DBE_VALUE);
|
||||
db_post_events(ptimer,&ptimer->t1td,DBE_VALUE);
|
||||
}
|
||||
ptimer->pact=FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (ptimer->flnk.type == DB_LINK)
|
||||
dbScanPassive(&ptimer->flnk.value);
|
||||
static void monitor(ptimer)
|
||||
struct timerRecord *ptimer;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* unlock the record */
|
||||
ptimer->lock = 0;
|
||||
ptimer->pact=FALSE;
|
||||
return(0);
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=ptimer->stat;
|
||||
sevr=ptimer->sevr;
|
||||
nsta=ptimer->nsta;
|
||||
nsev=ptimer->nsev;
|
||||
/*set current stat and sevr*/
|
||||
ptimer->stat = nsta;
|
||||
ptimer->sevr = nsev;
|
||||
ptimer->nsta = 0;
|
||||
ptimer->nsev = 0;
|
||||
|
||||
/* anyone waiting for an event on this record */
|
||||
if (ptimer->mlis.count == 0) return;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev){
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(ptimer,&ptimer->stat,DBE_VALUE);
|
||||
db_post_events(ptimer,&ptimer->sevr,DBE_VALUE);
|
||||
}
|
||||
|
||||
monitor_mask |= (DBE_VALUE | DBE_LOG);
|
||||
db_post_events(ptimer,&ptimer->val,monitor_mask);
|
||||
db_post_events(ptimer,&ptimer->t1wd,monitor_mask);
|
||||
db_post_events(ptimer,&ptimer->t1ld,monitor_mask);
|
||||
db_post_events(ptimer,&ptimer->t1td,monitor_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -192,8 +201,8 @@ static double constants[] = {1000,1000000,1000000000,1000000000000};
|
||||
* CONVERT_TIMER
|
||||
*
|
||||
*/
|
||||
static convert_timer(ptimer)
|
||||
register struct timer *ptimer;
|
||||
static void convert_timer(ptimer)
|
||||
struct timerRecord *ptimer;
|
||||
{
|
||||
double constant;
|
||||
|
||||
@ -246,32 +255,27 @@ register struct timer *ptimer;
|
||||
*
|
||||
* convert the value and write it
|
||||
*/
|
||||
static write_timer(ptimer)
|
||||
register struct timer *ptimer;
|
||||
static void write_timer(ptimer)
|
||||
struct timerRecord *ptimer;
|
||||
{
|
||||
register struct vmeio *pvmeio;
|
||||
register double *pdelay;
|
||||
register short count;
|
||||
register short i;
|
||||
struct vmeio *pvmeio;
|
||||
long status,options,nRequest;
|
||||
|
||||
/* get the delay from trigger source */
|
||||
if (ptimer->torg.type == DB_LINK){
|
||||
if (db_fetch(&ptimer->torg.value,&ptimer->trdl) < 0){
|
||||
if (ptimer->stat != READ_ALARM){
|
||||
ptimer->stat = READ_ALARM;
|
||||
ptimer->sevr = MAJOR;
|
||||
ptimer->achn = 1;
|
||||
}
|
||||
return(-1);
|
||||
}else if (ptimer->stat == READ_ALARM){
|
||||
ptimer->stat = NO_ALARM;
|
||||
ptimer->sevr = NO_ALARM;
|
||||
ptimer->achn = 1;
|
||||
}
|
||||
if (ptimer->torg.type == DB_LINK) {
|
||||
options=0;
|
||||
nRequest=1;
|
||||
status = dbGetLink(&(ptimer->torg.value.db_link),ptimer,DBR_FLOAT,
|
||||
&(ptimer->trdl),&options,&nRequest);
|
||||
if(status!=0) return;
|
||||
}
|
||||
if (ptimer->out.type != VME_IO) {
|
||||
if(ptimer->nsev<MAJOR_ALARM) {
|
||||
ptimer->nsta = WRITE_ALARM;
|
||||
ptimer->nsev = MAJOR_ALARM;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptimer->out.type != VME_IO) return(-1);
|
||||
|
||||
pvmeio = (struct vmeio *)(&ptimer->out.value);
|
||||
|
||||
/* convert the value */
|
||||
@ -280,26 +284,20 @@ register struct timer *ptimer;
|
||||
/* put the value to the ao driver */
|
||||
if (time_driver((int)pvmeio->card, /* card number */
|
||||
(int)pvmeio->signal, /* signal number */
|
||||
(int)ptimer->type, /* card type */
|
||||
(int)ptimer->dtyp, /* card type */
|
||||
(int)ptimer->tsrc, /* trigger source */
|
||||
(int)ptimer->ptst, /* pre-trigger state */
|
||||
&ptimer->t1dl, /* delay/width array */
|
||||
1, /* number of pulses */
|
||||
((ptimer->tevt == 0)?0:post_event), /* addr of event post routine */
|
||||
(int)ptimer->tevt) /* event to post on trigger */
|
||||
!= NO_ALARM){
|
||||
if (ptimer->stat != WRITE_ALARM){
|
||||
ptimer->stat = WRITE_ALARM;
|
||||
ptimer->sevr = MAJOR;
|
||||
ptimer->achn = 1;
|
||||
!= 0){
|
||||
if (ptimer->nsev<MAJOR_ALARM) {
|
||||
ptimer->nsta = WRITE_ALARM;
|
||||
ptimer->nsev = MAJOR_ALARM;
|
||||
}
|
||||
return(-1);
|
||||
}else if (ptimer->stat == WRITE_ALARM){
|
||||
ptimer->stat = NO_ALARM;
|
||||
ptimer->sevr = NO_ALARM;
|
||||
ptimer->achn = 1;
|
||||
}
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -307,10 +305,10 @@ register struct timer *ptimer;
|
||||
*
|
||||
* read the current timer pulses and convert them to engineering units
|
||||
*/
|
||||
static read_timer(ptimer)
|
||||
register struct timer *ptimer;
|
||||
static void read_timer(ptimer)
|
||||
struct timerRecord *ptimer;
|
||||
{
|
||||
register struct vmeio *pvmeio;
|
||||
struct vmeio *pvmeio;
|
||||
int source;
|
||||
int ptst;
|
||||
int no_pulses;
|
||||
@ -318,17 +316,19 @@ register struct timer *ptimer;
|
||||
double constant;
|
||||
|
||||
/* initiate the write */
|
||||
if (ptimer->out.type != VME_IO) return(-1);
|
||||
if (ptimer->out.type != VME_IO) {
|
||||
recGblRecordError(S_dev_badOutType,ptimer,"read_timer");
|
||||
return;
|
||||
}
|
||||
|
||||
/* only supports a one channel VME timer module !!!! */
|
||||
|
||||
|
||||
pvmeio = (struct vmeio *)(&ptimer->out.value);
|
||||
|
||||
/* put the value to the ao driver */
|
||||
if (time_driver_read((int)pvmeio->card, /* card number */
|
||||
(int)pvmeio->signal, /* signal number */
|
||||
(int)ptimer->type, /* card type */
|
||||
(int)ptimer->dtyp, /* card type */
|
||||
&source, /* trigger source */
|
||||
&ptst, /* pre-trigger state */
|
||||
&time_pulse[0], /* delay/width */
|
||||
@ -347,5 +347,5 @@ register struct timer *ptimer;
|
||||
ptimer->opw1 = time_pulse[1] * constant; /* pulse width */
|
||||
ptimer->ptst = ptst; /* pre-trigger state */
|
||||
ptimer->tsrc = source; /* clock source */
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* recWaveform.c - Record Support Routines for Waveform records
|
||||
/* share/src/rec $Id$ */
|
||||
*
|
||||
/*
|
||||
* Author: Bob Dalesio
|
||||
* Date: 7-14-89
|
||||
|
||||
@ -51,10 +51,8 @@
|
||||
#include <types.h>
|
||||
#include <stdioLib.h>
|
||||
#include <lstLib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <alarm.h>
|
||||
#include <cvtTable.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbDefs.h>
|
||||
#include <dbFldTypes.h>
|
||||
@ -62,7 +60,6 @@
|
||||
#include <errMdef.h>
|
||||
#include <link.h>
|
||||
#include <recSup.h>
|
||||
#include <special.h>
|
||||
#include <waveformRecord.h>
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
@ -99,70 +96,88 @@ struct rset waveformRSET={
|
||||
get_graphic_double,
|
||||
get_control_double,
|
||||
get_enum_strs };
|
||||
/* because the driver does all the work just declare device support here*/
|
||||
struct dset devWaveformSoft={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devXycom566SingleChan={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devLecroy8837={4,NULL,NULL,NULL,NULL};
|
||||
struct dset devJoergerVtr1={4,NULL,NULL,NULL,NULL};
|
||||
struct wfdset { /* waveform dset */
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
DEVSUPFUN init;
|
||||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||||
DEVSUPFUN get_ioint_info;
|
||||
DEVSUPFUN read_wf;/*(0,1)=> success and */
|
||||
/*(convert,don't continue)*/
|
||||
};
|
||||
|
||||
/*sizes of field types*/
|
||||
static int sizeofTypes[] = {0,1,1,2,2,4,4,4,8,2};
|
||||
void monitor();
|
||||
|
||||
|
||||
static long report(fp,paddr)
|
||||
FILE *fp;
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord*)(paddr->precord);
|
||||
struct waveformRecord *pwf=(struct waveformRecord*)(paddr->precord);
|
||||
|
||||
if(recGblReportDbCommon(fp,paddr)) return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init_record(pwaveform)
|
||||
struct waveformRecord *pwaveform;
|
||||
static long init_record(pwf)
|
||||
struct waveformRecord *pwf;
|
||||
{
|
||||
struct wfdset *pdset;
|
||||
long status;
|
||||
|
||||
/* This routine may get called twice. Once by cvt_dbaddr. Once by iocInit*/
|
||||
/* allocate bptr and sptr */
|
||||
if(pwaveform->bptr==NULL) {
|
||||
if(pwaveform->nsam<=0) pwaveform->nsam=1;
|
||||
pwaveform->bptr = (char *)malloc(pwaveform->nsam * pwaveform->selm);
|
||||
if(pwf->bptr==NULL) {
|
||||
if(pwf->nelm<=0) pwf->nelm=1;
|
||||
if(pwf->ftvl<=0|| pwf->ftvl>DBF_ENUM) pwf->ftvl=2;
|
||||
pwf->bptr = (char *)malloc(pwf->nelm * sizeofTypes[pwf->ftvl]);
|
||||
pwf->nord = 0;
|
||||
/* must have read_wf function defined */
|
||||
if( (pdset->number < 6) || (pdset->read_wf == NULL) ) {
|
||||
recGblRecordError(S_dev_missingSup,pwf,"wf: init_record");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
if( pdset->init_record ) {
|
||||
if((status=(*pdset->init_record)(pwf,process))) return(status);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static long get_precision(paddr,precision)
|
||||
struct dbAddr *paddr;
|
||||
long *precision;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
*precision = pwaveform->prec;
|
||||
return(0L);
|
||||
}
|
||||
|
||||
static long get_value(pwaveform,pvdes)
|
||||
struct waveformRecord *pwaveform;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
pvdes->field_type = DBF_FLOAT;
|
||||
pvdes->no_elements=pwaveform->nsam;
|
||||
(float *)(pvdes->pvalue) = pwaveform->bptr;
|
||||
*precision = pwf->prec;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_value(pwf,pvdes)
|
||||
struct waveformRecord *pwf;
|
||||
struct valueDes *pvdes;
|
||||
{
|
||||
|
||||
pvdes->no_elements=pwf->nord;
|
||||
pvdes->pvalue = pwf->bptr;
|
||||
pvdes->field_type = pwf->ftvl;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long cvt_dbaddr(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
/* This may get called before init_record. If so just call it*/
|
||||
if(pwaveform->bptr==NULL) init_record(paddr);
|
||||
|
||||
paddr->pfield = (caddr_t)(pwaveform->bptr);
|
||||
paddr->no_elements = pwaveform->nsam;
|
||||
paddr->field_type = DBF_FLOAT;
|
||||
paddr->field_size = sizeof(float);
|
||||
paddr->dbr_field_type = DBF_FLOAT;
|
||||
if(pwf->bptr==NULL) init_record(pwf);
|
||||
paddr->pfield = (caddr_t)(pwf->bptr);
|
||||
paddr->no_elements = pwf->nelm;
|
||||
paddr->field_type = pwf->ftvl;
|
||||
paddr->field_size = sizeofTypes[pwf->ftvl];
|
||||
paddr->dbr_field_type = pwf->ftvl;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -171,289 +186,118 @@ static long get_array_info(paddr,no_elements,offset)
|
||||
long *no_elements;
|
||||
long *offset;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
*no_elements = pwaveform->nuse;
|
||||
*offset = inx+1;
|
||||
*no_elements = pwf->nord;
|
||||
*offset = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long put_array_info(paddr,nNew)
|
||||
struct dbAddr *paddr;
|
||||
long nNew;
|
||||
long offset;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
pwaveform->inx = (pwaveform->inx + nNew) % (pwaveform->nsam);
|
||||
pwaveform->nuse = (pwaveform->nuse + nNew);
|
||||
if(pwaveform->nuse > pwaveform->nsam) pwaveform->nuse = pwaveform->nsam;
|
||||
pwf->nord = (pwf->nord + nNew);
|
||||
if(pwf->nord > pwf->nelm) pwf->nord = pwf->nelm;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long get_units(paddr,units)
|
||||
struct dbAddr *paddr;
|
||||
char *units;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
strncpy(units,pwaveform->egu,sizeof(pwaveform->egu));
|
||||
return(0L);
|
||||
strncpy(units,pwf->egu,sizeof(pwf->egu));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long get_graphic_double(paddr,pgd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_grDouble *pgd;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
pgd->upper_disp_limit = pwaveform->hopr;
|
||||
pgd->lower_disp_limit = pwaveform->lopr;
|
||||
pgd->upper_disp_limit = pwf->hopr;
|
||||
pgd->lower_disp_limit = pwf->lopr;
|
||||
pgd->upper_alarm_limit = 0.0;
|
||||
pgd->upper_warning_limit = 0.0;
|
||||
pgd->lower_warning_limit = 0.0;
|
||||
pgd->lower_alarm_limit = 0.0;
|
||||
return(0L);
|
||||
return(0);
|
||||
}
|
||||
static long get_control_double(paddr,pcd)
|
||||
struct dbAddr *paddr;
|
||||
struct dbr_ctrlDouble *pcd;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)paddr->precord;
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)paddr->precord;
|
||||
|
||||
pgd->upper_disp_limit = pwaveform->hopr;
|
||||
pgd->lower_disp_limit = pwaveform->lopr;
|
||||
return(0L);
|
||||
pcd->upper_ctrl_limit = pwf->hopr;
|
||||
pcd->lower_ctrl_limit = pwf->lopr;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long process(paddr)
|
||||
struct dbAddr *paddr;
|
||||
{
|
||||
struct waveformRecord *pwaveform=(struct waveformRecord *)(paddr->precord);
|
||||
struct waveformdset *pdset = (struct waveformdset *)(pwaveform->dset);
|
||||
struct waveformRecord *pwf=(struct waveformRecord *)(paddr->precord);
|
||||
struct wfdset *pdset = (struct wfdset *)(pwf->dset);
|
||||
long status;
|
||||
|
||||
pwaveform->achn = 0;
|
||||
/* read inputs */
|
||||
if (do_waveformion(pwaveform) < 0){
|
||||
if (pwaveform->stat != READ_ALARM){
|
||||
pwaveform->stat = READ_ALARM;
|
||||
pwaveform->sevr = MAJOR_ALARM;
|
||||
pwaveform->achn = 1;
|
||||
monitor_waveform(pwaveform);
|
||||
}
|
||||
pwaveform->pact = 0;
|
||||
return(0);
|
||||
}else{
|
||||
if (pwaveform->stat == READ_ALARM){
|
||||
pwaveform->stat = NO_ALARM;
|
||||
pwaveform->sevr = NO_ALARM;
|
||||
pwaveform->achn = 1;
|
||||
}
|
||||
}
|
||||
if( (pdset==NULL) || (pdset->read_wf==NULL) ) {
|
||||
pwf->pact=TRUE;
|
||||
recGblRecordError(S_dev_missingSup,pwf,"read_wf");
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
/*pact must not be set true until read_wf completes*/
|
||||
status=(*pdset->read_wf)(pwf); /* read the new value */
|
||||
pwf->pact = TRUE;
|
||||
/* status is one if an asynchronous record is being processed*/
|
||||
if(status==1) return(0);
|
||||
|
||||
monitor(pwf);
|
||||
/* process the forward scan link record */
|
||||
if (pwf->flnk.type==DB_LINK) dbScanPassive(&pwf->flnk.value.db_link.pdbAddr);
|
||||
|
||||
/* check event list */
|
||||
if(!pwaveform->disa) status = monitor(pwaveform);
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pwaveform->flnk.type==DB_LINK) dbScanPassive(&pwaveform->flnk.value);
|
||||
|
||||
pwaveform->pact=FALSE;
|
||||
return(status);
|
||||
pwf->pact=FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long monitor(pwaveform)
|
||||
struct waveformRecord *pwaveform;
|
||||
static void monitor(pwf)
|
||||
struct waveformRecord *pwf;
|
||||
{
|
||||
unsigned short monitor_mask;
|
||||
float delta;
|
||||
short stat,sevr,nsta,nsev;
|
||||
|
||||
/* anyone wwaveformting for an event on this record */
|
||||
if (pwaveform->mlis.count == 0) return(0L);
|
||||
/* get previous stat and sevr and new stat and sevr*/
|
||||
stat=pwf->stat;
|
||||
sevr=pwf->sevr;
|
||||
nsta=pwf->nsta;
|
||||
nsev=pwf->nsev;
|
||||
/*set current stat and sevr*/
|
||||
pwf->stat = nsta;
|
||||
pwf->sevr = nsev;
|
||||
pwf->nsta = 0;
|
||||
pwf->nsev = 0;
|
||||
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
/* anyone waiting for an event on this record */
|
||||
if(pwf->mlis.count == 0) return;
|
||||
|
||||
/* alarm condition changed this scan */
|
||||
if (pwaveform->achn){
|
||||
/* post events for alarm condition change and value change */
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* Flags which events to fire on the value field */
|
||||
monitor_mask = 0;
|
||||
|
||||
/* post stat and sevr fields */
|
||||
db_post_events(pwaveform,&pwaveform->stat,DBE_VALUE);
|
||||
db_post_events(pwaveform,&pwaveform->sevr,DBE_VALUE);
|
||||
|
||||
/* update last value monitored */
|
||||
pwaveform->mlst = pwaveform->val;
|
||||
}
|
||||
/* alarm condition changed this scan */
|
||||
if (stat!=nsta || sevr!=nsev) {
|
||||
/* post events for alarm condition change*/
|
||||
monitor_mask = DBE_ALARM;
|
||||
/* post stat and nsev fields */
|
||||
db_post_events(pwf,&pwf->stat,DBE_VALUE);
|
||||
db_post_events(pwf,&pwf->sevr,DBE_VALUE);
|
||||
}
|
||||
monitor_mask |= DBE_LOG|DBE_VALUE;
|
||||
db_post_events(pwaveform,&pwaveform->val,monitor_mask);
|
||||
return(0L);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* WFCB_READ
|
||||
*
|
||||
* callback routine when the waveform is read
|
||||
*/
|
||||
static wfcb_read(pwf,no_read,pdata)
|
||||
register struct waveform *pwf;
|
||||
register int no_read;
|
||||
register char *pdata;
|
||||
{
|
||||
if (pwf->inp.type == VME_IO){
|
||||
pwf->bptr = pdata; /* mem addr of buffer */
|
||||
pwf->nord = no_read; /* number of values read */
|
||||
pwf->busy = 0;
|
||||
|
||||
/* post events on value, busy and number read */
|
||||
if (pwf->mqct != 0){
|
||||
db_post_events(pwf,&pwf->busy,DBE_VALUE);
|
||||
db_post_events(pwf,&pwf->nord,DBE_VALUE);
|
||||
db_post_events(pwf,&pwf->val,DBE_VALUE|DBE_LOG);
|
||||
}
|
||||
}
|
||||
|
||||
/* process the forward scan link record */
|
||||
if (pwf->flnk.type == DB_LINK)
|
||||
db_scan(&pwf->flnk.value);
|
||||
|
||||
/* determine if the waveform is to be re-armed */
|
||||
if (pwf->rarm){
|
||||
arm_wf(pwf);
|
||||
pwf->rarm = 0;
|
||||
if (pwf->mqct)
|
||||
db_post_events(pwf,&pwf->rarm,DBE_VALUE);
|
||||
}
|
||||
|
||||
/* record is only unlocked when the waveform is read */
|
||||
/* unlock the record */
|
||||
pwf->lock = 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* PROCESS_WAVEFORM
|
||||
*
|
||||
* process waveform record
|
||||
*/
|
||||
process_waveform(pwf)
|
||||
register struct waveform *pwf; /* pointer to the analog input record */
|
||||
{
|
||||
pwf->achn = 0; /* flags alarm condition changed */
|
||||
|
||||
/* lock the record */
|
||||
if (pwf->lock){
|
||||
if (pwf->lcnt >= MAX_LOCK){
|
||||
pwf->stat = SCAN_ALARM;
|
||||
pwf->sevr = MAJOR;
|
||||
pwf->achn = 1;
|
||||
}else{
|
||||
pwf->lcnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
pwf->lcnt = 0;
|
||||
pwf->lock = 1;
|
||||
|
||||
/* initialize the record */
|
||||
if(pwf->init == 0){
|
||||
init_wf(pwf);
|
||||
pwf->init = 1;
|
||||
}
|
||||
|
||||
/* arm the waveform */
|
||||
arm_wf(pwf);
|
||||
|
||||
/* monitors on alarm condition */
|
||||
if (pwf->mqct != 0){
|
||||
if (pwf->achn){
|
||||
db_post_events(pwf,&pwf->val,DBE_ALARM);
|
||||
db_post_events(pwf,&pwf->stat,DBE_VALUE);
|
||||
db_post_events(pwf,&pwf->sevr,DBE_VALUE);
|
||||
}
|
||||
if (pwf->inp.type == CONSTANT){
|
||||
db_post_events(pwf,&pwf->val,DBE_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ARM_WF
|
||||
*
|
||||
* arm the waveform
|
||||
*/
|
||||
static arm_wf(pwf)
|
||||
register struct waveform *pwf;
|
||||
{
|
||||
short temp;
|
||||
|
||||
switch(pwf->inp.type){
|
||||
case(VME_IO):
|
||||
if (pwf->busy) return; /* already armed */
|
||||
|
||||
/* setup callback for data collection complete */
|
||||
if (wf_driver(pwf->type, /* card type */
|
||||
pwf->inp.value.vmeio.card, /* card number */
|
||||
wfcb_read, /* callback routine */
|
||||
pwf) < 0){ /* callback argument */
|
||||
if (pwf->stat != READ_ALARM){
|
||||
pwf->stat = READ_ALARM;
|
||||
pwf->sevr = MAJOR;
|
||||
pwf->achn = 1;
|
||||
}
|
||||
return(-1);
|
||||
}else{
|
||||
pwf->busy = 1;
|
||||
if (pwf->mqct != 0)
|
||||
db_post_events(pwf,&pwf->busy,DBE_VALUE);
|
||||
if (pwf->stat == READ_ALARM){
|
||||
pwf->sevr = pwf->stat = NO_ALARM;
|
||||
pwf->achn = 1;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
|
||||
case(CAMAC_IO):
|
||||
case(CONSTANT):
|
||||
case(DB_LINK):
|
||||
default:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* INIT_WF
|
||||
*
|
||||
* initialize the waveform parameters
|
||||
*/
|
||||
static init_wf(pwf)
|
||||
register struct waveform *pwf;
|
||||
{
|
||||
short temp;
|
||||
|
||||
/* initialize the monitor mutual exclusion semaphore */
|
||||
semInit(&pwf->msem[0]);
|
||||
semGive(&pwf->msem[0]); /* initially available */
|
||||
|
||||
|
||||
switch(pwf->inp.type){
|
||||
case(VME_IO):
|
||||
return(0);
|
||||
|
||||
case(CONSTANT):
|
||||
pwf->bptr = (char *)malloc(pwf->nelm * pwf->selm);
|
||||
pwf->nord = pwf->nelm;
|
||||
return(0);
|
||||
|
||||
case(DB_LINK):
|
||||
case(CAMAC_IO):
|
||||
default:
|
||||
return(-1);
|
||||
}
|
||||
if(monitor_mask) db_post_events(pwf,pwf->bptr,monitor_mask);
|
||||
return;
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user