Initial revision

This commit is contained in:
Bob Zieman
1990-10-17 06:28:14 +00:00
parent e27769db68
commit 1dbd526476
15 changed files with 6507 additions and 0 deletions

527
src/rec/recAi.c Normal file
View File

@ -0,0 +1,527 @@
/* recAi.c */
/* share/src/rec $Id$ */
/* recAi.c - Record Support Routines for Analog Input records
*
* Author: Bob Dalesio
* Date: 7-9-87
* @(#)iocai.c 1.1 9/22/88
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 8-12-88 lrd Put in breakpoint conversions
* Fix conversions for bipolar xy566 cards
* .02 12-12-88 lrd Lock record on entry and unlock on exit
* .03 12-15-88 lrd Process the forward scan link
* .04 12-23-88 lrd Alarm on locked MAX_LOCKED times
* .05 01-13-89 lrd deleted db_read_ai
* .06 01-18-89 lrd modify adjustment offset to be independent of
* adjustment slope
* clamp xy566 breakpoint table negative values t o
* zero
* .07 03-27-89 lrd make hardware errors MAJOR alarms
* remove hardware severity from the database
* .08 04-03-89 lrd add monitor code
* removed signal units conversion stuff
* .09 04-05-89 lrd modified so that negative adjustment slope ASLO
* would work
* .10 05-03-89 lrd removed process mask from arg list
* .11 08-01-89 lrd only set value for constant when val != 0
* .12 10-11-89 lrd fix smoothing initial condition
* .13 01-31-90 lrd add AB plc flag to the ab_aidriver call
* .14 03-21-90 lrd add db_post_event for RVAL
* .15 04-11-90 lrd make locals static
* .16 04-18-90 mrk extensible record and device support
*/
#include <vxWorks.h>
#include <types.h>
#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 <aiRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
long special();
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
#define get_enum_str NULL
long get_units();
long get_graphic_double();
long get_control_double();
#define get_enum_strs NULL
struct rset aiRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
struct aidset { /* analog input dset */
long number;
DEVSUPFUN report;
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 special_linconv;
};
long convert_ai();
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct aiRecord *pai=(struct aiRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %-12.4G\n",pai->val)) return(-1);
if(recGblReportLink(fp,"INP ",&(pai->inp))) return(-1);
if(fprintf(fp,"PREC %d\n",pai->prec)) return(-1);
if(recGblReportCvtChoice(fp,"LINR",pai->linr)) return(-1);
if(fprintf(fp,"EGUF %-12.4G EGUL %-12.4G EGU %-8s\n",
pai->eguf,pai->egul,pai->egu)) return(-1);
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
pai->hopr,pai->lopr)) return(-1);
if(fprintf(fp,"AOFF %-12.4G ASLO %-12.4G SMOO %-12.4G\n",
pai->aoff,pai->aslo,pai->smoo)) return(-1);
if(recGblReportLink(fp,"FLNK",&(pai->flnk))) return(-1);
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
pai->hihi,pai->high,pai->low,pai->lolo)) return(-1);
if(recGblReportGblChoice(fp,pai,"HHSV",pai->hhsv)) return(-1);
if(recGblReportGblChoice(fp,pai,"HSV ",pai->hsv)) return(-1);
if(recGblReportGblChoice(fp,pai,"LSV ",pai->lsv)) return(-1);
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,"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);
return(0);
}
static long init_record(pai)
struct aiRecord *pai;
{
struct aidset *pdset;
long status;
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) ) {
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(pai->linr >= 2) { /*must find breakpoint table*/
if( !cvtTable || (cvtTable->number < pai->linr)
|| (!(cvtTable->papBrkTable[pai->linr]))) {
errMessage(S_db_badField,"Breakpoint Table not Found");
return(S_db_badField);
}
pai->pbrk = (char *)(cvtTable->papBrkTable[pai->linr]);
pai->lbrk=0;
}
return(0);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct aiRecord *pai=(struct aiRecord *)(paddr->precord);
struct aidset *pdset = (struct aidset *)(pai->dset);
long status;
if( (pdset==NULL) || (pdset->read_ai==NULL) ) {
pai->pact=TRUE;
recGblRecordError(S_dev_missingSup,pai,"read_ai");
return(S_dev_missingSup);
}
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);
/* check for alarms */
alarm(pai);
/* check event list */
if(!pai->disa) status = monitor(pai);
/* process the forward scan link record */
if (pai->flnk.type==DB_LINK) dbScanPassive(&pai->flnk.value);
pai->init=FALSE;
pai->pact=FALSE;
return(status);
}
static long special(paddr,after)
struct dbAddr *paddr;
int after;
{
struct aiRecord *pai = (struct aiRecord *)(paddr->precord);
struct aidset *pdset = (struct aidset *) (pai->dset);
int special_type = paddr->special;
switch(special_type) {
case(SPC_LINCONV):
if(pdset->number<5 || !(pdset->special_linconv)) {
recGblDbaddrError(S_db_noMod,paddr,"ai: special");
return(S_db_noMod);
}
pai->init=TRUE;
return((*pdset->special_linconv)(pai,after));
default:
recGblDbaddrError(S_db_badChoice,paddr,"ai: special");
return(S_db_badChoice);
}
}
static long get_precision(paddr,precision)
struct dbAddr *paddr;
long *precision;
{
struct aiRecord *pai=(struct aiRecord *)paddr->precord;
*precision = pai->prec;
return(0L);
}
static long get_value(pai,pvdes)
struct aiRecord *pai;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_FLOAT;
pvdes->no_elements=1;
(float *)(pvdes->pvalue) = &pai->val;
return(0);
}
static long get_units(paddr,units)
struct dbAddr *paddr;
char *units;
{
struct aiRecord *pai=(struct aiRecord *)paddr->precord;
strncpy(units,pai->egu,sizeof(pai->egu));
return(0L);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct aiRecord *pai=(struct aiRecord *)paddr->precord;
pgd->upper_disp_limit = pai->hopr;
pgd->lower_disp_limit = pai->lopr;
pgd->upper_alarm_limit = pai->hihi;
pgd->upper_warning_limit = pai->high;
pgd->lower_warning_limit = pai->low;
pgd->lower_alarm_limit = pai->lolo;
return(0L);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct aiRecord *pai=(struct aiRecord *)paddr->precord;
pcd->upper_ctrl_limit = pai->hopr;
pcd->lower_ctrl_limit = pai->lopr;
return(0L);
}
static long 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);
}
/* alarm condition hihi */
if (pai->hhsv != NO_ALARM){
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);
}
}
/* alarm condition lolo */
if (pai->llsv != NO_ALARM){
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);
}
}
/* alarm condition high */
if (pai->hsv != NO_ALARM){
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);
}
}
/* alarm condition lolo */
if (pai->lsv != NO_ALARM){
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);
}
}
/* no alarm */
if (pai->stat != NO_ALARM){
pai->stat = NO_ALARM;
pai->sevr = NO_ALARM;
pai->achn = 1;
}
return(0);
}
static long monitor(pai)
struct aiRecord *pai;
{
unsigned short monitor_mask;
float delta;
/* anyone waiting for an event on this record */
if (pai->mlis.count == 0) return(0L);
/* 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 */
db_post_events(pai,&pai->stat,DBE_VALUE);
db_post_events(pai,&pai->sevr,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 */
delta = pai->alst - pai->val;
if(delta<0.0) delta = 0.0;
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;
}
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(pai,&pai->val,monitor_mask);
db_post_events(pai,&pai->rval,monitor_mask);
}
return(0L);
}
static long convert_ai(pai)
struct aiRecord *pai;
{
float val;
/* 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;
/* convert raw to engineering units and signal units */
if(pai->linr == 0) {
val = pai->val;
}
else if(pai->linr == 1) {
val = (val * pai->eslo) + pai->egul;
}
else { /* must use breakpoint table */
struct brkTable *pbrkTable;
struct brkInt *pInt;
struct brkInt *pnxtInt;
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 {
lbrk = (pai->lbrk);
/*make sure we dont go off end of table*/
if( (lbrk+1) >= number ) lbrk--;
}
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);
}
lbrk++;
pInt = pbrkTable->papBrkInt[lbrk];
}
while( (pInt->raw) > val) {
if(lbrk==0) {
errMessage(S_db_badField,"breakpoint table error");
return(S_db_badField);
}
lbrk--;
pInt = pbrkTable->papBrkInt[lbrk];
}
pai->lbrk = lbrk;
val = pInt->eng + (val - pInt->raw) * pInt->slope;
}
/* apply smoothing algorithm */
if (pai->smoo != 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);
}

499
src/rec/recAo.c Normal file
View File

@ -0,0 +1,499 @@
/* recAo.c */
/* share/src/rec $Id$ */
/* recAo.c - Record Support Routines for Analog Output records
*
* Author: Bob Dalesio
* Date: 7-9-87
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 09-26-88 lrd interface the Ziomek085 card
* .02 12-12-88 lrd lock record on entry unlock on exit
* .03 12-15-88 lrd Process the forward scan link
* .04 12-23-88 lrd Alarm on locked MAX_LOCKED times
* .05 01-13-89 lrd deleted db_write_ao
* .06 01-20-89 lrd fixed vx includes
* .07 03-03-89 lrd mods for closed loop/supervisory control
* .08 03-17-89 lrd add read_ao routine and call at initialization
* .09 03-23-89 lrd convert AB readbacks
* .10 03-29-89 lrd make hardware errors MAJOR
* remove hw severity spec from database
* .11 04-06-89 lrd remove signal conversions
* .12 05-03-89 lrd removed process mask from arg list
* .13 05-08-89 lrd fixed init to unlock on return condition
* .14 05-25-89 lrd added rate of change add incremental/absolute
* .15 01-31-90 lrd add plc_flag to ab_aodriver
* .16 03-21-90 lrd add db_post_events for RVAL and RBV
* .17 04-11-90 lrd make locals static
* .18 07-27-90 lrd implement the output to a database record
* .19 10-10-90 mrk extensible record and device support
*/
#include <vxWorks.h>
#include <types.h>
#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 <aoRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
long special();
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
#define get_enum_str NULL
long get_units();
long get_graphic_double();
long get_control_double();
#define get_enum_strs NULL
struct rset aoRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
struct aodset { /* analog input dset */
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_ao;
DEVSUPFUN write_ao;
DEVSUPFUN special_linconv;
};
/* the following definitions must match those in choiceGbl.ascii */
#define OUTPUT_FULL 0
#define CLOSED_LOOP 1
/* The following must match the definition in choiceGbl.ascii */
#define LINEAR 1
long convert_ao();
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct aoRecord *pao=(struct aoRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %-12.4G OROC %-12.4G\n",pao->val,pao->oroc)) return(-1);
if(recGblReportLink(fp,"OUT ",&(pao->out))) return(-1);
if(fprintf(fp,"PREC %d\n",pao->prec)) return(-1);
if(recGblReportCvtChoice(fp,"LINR",pao->linr)) return(-1);
if(fprintf(fp,"EGUF %-12.4G EGUL %-12.4G EGU %-8s\n",
pao->eguf,pao->egul,pao->egu)) return(-1);
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
pao->hopr,pao->lopr)) return(-1);
if(fprintf(fp,"AOFF %-12.4G ASLO %-12.4G\n",
pao->aoff,pao->aslo)) return(-1);
if(recGblReportLink(fp,"FLNK",&(pao->flnk))) return(-1);
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
pao->hihi,pao->high,pao->low,pao->lolo)) return(-1);
if(recGblReportGblChoice(fp,pao,"HHSV",pao->hhsv)) return(-1);
if(recGblReportGblChoice(fp,pao,"HSV ",pao->hsv)) return(-1);
if(recGblReportGblChoice(fp,pao,"LSV ",pao->lsv)) return(-1);
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,"LALM %-12.4G ALST %-12.4G MLST %-12.4G\n",
pao->lalm,pao->alst,pao->mlst)) return(-1);
return(0);
}
static long init_record(pao)
struct aoRecord *pao;
{
struct aodset *pdset;
long status;
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) ) {
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);
}
/* get the intial value */
if ((pao->dol.type == CONSTANT) && (pao->dol.value.value != 0)){
pao->val = pao->dol.value.value;
}
return(0);
}
static long process(paddr)
struct dbAddr *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*/
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;
}
/* check for alarms */
alarm(pao);
/* check event list */
if(!pao->disa) status = monitor(pao);
/* process the forward scan link record */
if (pao->flnk.type==DB_LINK) dbScanPassive(&pao->flnk.value);
pao->init=FALSE;
pao->pact=FALSE;
return(status);
}
static long get_precision(paddr,precision)
struct dbAddr *paddr;
long *precision;
{
struct aoRecord *pao=(struct aoRecord *)paddr->precord;
*precision = pao->prec;
return(0L);
}
static long get_value(pao,pvdes)
struct aoRecord *pao;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_FLOAT;
pvdes->no_elements=1;
(float *)(pvdes->pvalue) = &pao->val;
return(0);
}
static long get_units(paddr,units)
struct dbAddr *paddr;
char *units;
{
struct aoRecord *pao=(struct aoRecord *)paddr->precord;
strncpy(units,pao->egu,sizeof(pao->egu));
return(0L);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct aoRecord *pao=(struct aoRecord *)paddr->precord;
pgd->upper_disp_limit = pao->hopr;
pgd->lower_disp_limit = pao->lopr;
pgd->upper_alarm_limit = pao->hihi;
pgd->upper_warning_limit = pao->high;
pgd->lower_warning_limit = pao->low;
pgd->lower_alarm_limit = pao->lolo;
return(0L);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct aoRecord *pao=(struct aoRecord *)paddr->precord;
pcd->upper_ctrl_limit = pao->hopr;
pcd->lower_ctrl_limit = pao->lopr;
return(0L);
}
static long 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 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->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->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->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);
}
static long monitor(pao)
struct aoRecord *pao;
{
unsigned short monitor_mask;
float delta;
/* anyone waiting for an event on this record */
if (pao->mlis.count == 0) return(0L);
/* 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;
/* post stat and sevr fields */
db_post_events(pao,&pao->stat,DBE_VALUE);
db_post_events(pao,&pao->sevr,DBE_VALUE);
/* 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);
db_post_events(pao,&pao->rbv,monitor_mask);
}
return(0L);
}
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)
struct aoRecord *pao;
{
/* check drive limits */
if (pao->oval > pao->drvh) pao->oval = pao->drvh;
else if (pao->oval < pao->drvl) pao->oval = pao->drvl;
/* convert */
if (pao->linr == LINEAR){
if (pao->eslo == 0) pao->rval = 0;
else pao->rval = (pao->oval - pao->egul) / pao->eslo;
}else{
pao->rval = pao->oval;
}
}

325
src/rec/recBi.c Normal file
View File

@ -0,0 +1,325 @@
/* recBi.c */
/* share/src/rec $Id$ */
/* recBi.c - Record Support Routines for Binary Input records
*
* Author: Bob Dalesio
* Date: 7-9-87
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 12-12-88 lrd lock the record on entry and unlock on exit
* .02 12-15-88 lrd Process the forward scan link
* .03 12-23-88 lrd Alarm on locked MAX_LOCKED times
* .04 01-13-89 lrd delete db_read_bi
* .05 03-17-89 lrd database link inputs
* .06 03-29-89 lrd make hardware errors MAJOR
* remove hw severity spec from database
* .07 04-06-89 lrd add monitor detection
* .08 05-03-89 lrd removed process mask from arg list
* .09 01-31-90 lrd add the plc_flag arg to the ab_bidriver call
* .10 03-21-90 lrd add db_post_events for RVAL
* .11 04-11-90 lrd make local variables static
* .12 10-10-90 mrk Made changes for new record and device support
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <lstLib.h>
#include <strLib.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 <biRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
long special();
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
long get_enum_str();
#define get_units NULL
#define get_graphic_double NULL
#define get_control_double NULL
long get_enum_strs();
struct rset biRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
struct bidset { /* binary input dset */
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;/*(-1,0,1)=>(failure,success,don't Continue*/
};
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct biRecord *pbi=(struct biRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %d\n",pbi->val)) return(-1);
if(recGblReportLink(fp,"INP ",&(pbi->inp))) return(-1);
if(recGblReportLink(fp,"FLNK",&(pbi->flnk))) return(-1);
if(fprintf(fp,"RVAL 0x%-8X\n",
pbi->rval)) return(-1);
return(0);
}
static long init_record(pbi)
struct biRecord *pbi;
{
struct bidset *pdset;
long status;
if(!(pdset = (struct bidset *)(pbi->dset))) {
recGblRecordError(S_dev_noDSET,pbi,"bi: init_record");
return(S_dev_noDSET);
}
/* must have read_bi function defined */
if( (pdset->number < 5) || (pdset->read_bi == NULL) ) {
recGblRecordError(S_dev_missingSup,pbi,"bi: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(pbi))) return(status);
}
return(0);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct biRecord *pbi=(struct biRecord *)(paddr->precord);
struct bidset *pdset = (struct bidset *)(pbi->dset);
long status;
if( (pdset==NULL) || (pdset->read_bi==NULL) ) {
pbi->pact=TRUE;
recGblRecordError(S_dev_missingSup,pbi,"read_bi");
return(S_dev_missingSup);
}
status=(*pdset->read_bi)(pbi); /* read the new value */
pbi->pact = TRUE;
/* 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);
/* process the forward scan link record */
if (pbi->flnk.type==DB_LINK) dbScanPassive(&pbi->flnk.value);
pbi->pact=FALSE;
return(status);
}
static long get_value(pbi,pvdes)
struct biRecord *pbi;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_ENUM;
pvdes->no_elements=1;
(unsigned short *)(pvdes->pvalue) = &pbi->val;
return(0);
}
static long get_enum_str(paddr,pstring)
struct dbAddr *paddr;
char *pstring;
{
struct biRecord *pbi=(struct biRecord *)paddr->precord;
if(pbi->val==0) {
strncpy(pstring,pbi->znam,sizeof(pbi->znam));
pstring[sizeof(pbi->znam)] = 0;
} else if(pbi->val==0) {
strncpy(pstring,pbi->onam,sizeof(pbi->onam));
pstring[sizeof(pbi->onam)] = 0;
} else {
strcpy(pstring,"Illegal Value");
}
return(0L);
}
static long get_enum_strs(paddr,pes)
struct dbAddr *paddr;
struct dbr_enumStrs *pes;
{
struct biRecord *pbi=(struct biRecord *)paddr->precord;
pes->no_str = 2;
bzero(pes->strs,sizeof(pes->strs));
strncpy(pes->strs[0],pbi->znam,sizeof(pbi->znam));
strncpy(pes->strs[1],pbi->onam,sizeof(pbi->onam));
return(0L);
}
static long 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;
}
/* 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;
}
}else{
if (pbi->osv != NO_ALARM){
pbi->stat = STATE_ALARM;
pbi->sevr = pbi->osv;
pbi->achn = 1;
return;
}
}
/* check for cos alarm */
if (pbi->cosv != NO_ALARM){
pbi->sevr = pbi->cosv;
pbi->stat = COS_ALARM;
pbi->achn = 1;
return;
}
/* 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);
}
static long monitor(pbi)
struct biRecord *pbi;
{
unsigned short monitor_mask;
/* anyone waiting for an event on this record */
if (pbi->mlis.count == 0) return(0L);
/* 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;
/* 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){
/* post events for value change and archive change */
monitor_mask |= (DBE_VALUE | DBE_LOG);
/* update last value monitored */
pbi->mlst = pbi->val;
}
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(pbi,&pbi->val,monitor_mask);
db_post_events(pbi,&pbi->rval,monitor_mask);
}
return(0L);
}

365
src/rec/recBo.c Normal file
View File

@ -0,0 +1,365 @@
/* recBo.c */
/* share/src/rec $Id$ */
/* recBo.c - Record Support Routines for Binary Output records
*
* Author: Bob Dalesio
* Date: 7-17-87
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 12-9-88 lrd lock the record during processing
* .02 12-15-88 lrd process the forward scan link
* .03 12-23-88 lrd Alarm on locked MAX_LOCKED times
* .04 01-13-89 lrd delete db_read_bo and db_write_bo
* .05 01-20-89 lrd fixed vx includes
* .06 03-29-89 lrd make hardware errors MAJOR
* remove hw severity spec from database
* add continuous control
* .07 04-06-89 lrd add monitor detection
* .08 05-03-89 lrd removed process mask from arg list
* .09 08-16-89 lrd add ability to do softchannel momentary
* .10 08-17-89 lrd add soft channel support
* .11 01-31-90 lrd add the plc_flag arg to the ab_bodriver call
* .12 03-21-90 lrd add db_post_events for RVAL and RBV
* .13 04-02-90 ba/lrd add monitor handling for momentary outputs
* remove rbv arg to ab_bodriver
* .14 04-05-90 lrd make momentary output handling a task
* as the watchdog runs at interrupt level
* .15 04-11-90 lrd make locals static
* .16 05-02-90 lrd fix initial value set in the DOL field
* .17 10-10-90 mrk Changes for record and device support
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <lstLib.h>
#include <strLib.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 <boRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
long special();
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
long get_enum_str();
#define get_units NULL
#define get_graphic_double NULL
#define get_control_double NULL
long get_enum_strs();
struct rset boRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
struct bodset { /* binary output dset */
long number;
DEVSUPFUN report;
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 CLOSED_LOOP 1
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct boRecord *pbo=(struct boRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %d\n",pbo->val)) return(-1);
if(recGblReportLink(fp,"OUT ",&(pbo->out))) return(-1);
if(recGblReportLink(fp,"FLNK",&(pbo->flnk))) return(-1);
if(fprintf(fp,"RVAL 0x%-8X\n",
pbo->rval)) return(-1);
return(0);
}
static long init_record(pbo)
struct boRecord *pbo;
{
struct bodset *pdset;
long status;
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) ) {
recGblRecordError(S_dev_missingSup,pbo,"bo: init_record");
return(S_dev_missingSup);
}
/* get the intial value */
if (pbo->dol.type == CONSTANT){
if (pbo->dol.value.value != 0) pbo->val = 1;
else pbo->val = 0;
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(pbo))) return(status);
}
pbo->time = pbo->high * 60; /* seconds to ticks */
pbo->lalm = -1;
pbo->mlst = -1;
return(0);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct boRecord *pbo=(struct boRecord *)(paddr->precord);
struct bodset *pdset = (struct bodset *)(pbo->dset);
long status;
long nRequest;
float fval;
if( (pdset==NULL) || (pdset->read_bo==NULL) ) {
pbo->pact=TRUE;
recGblRecordError(S_dev_missingSup,pbo,"read_bo");
return(S_dev_missingSup);
}
/* 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=(*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;
}
/* check for alarms */
alarm(pbo);
/* check event list */
if(!pbo->disa) status = monitor(pbo);
/* process the forward scan link record */
if (pbo->flnk.type==DB_LINK) dbScanPassive(&pbo->flnk.value);
pbo->pact=FALSE;
return(status);
}
static long get_value(pbo,pvdes)
struct boRecord *pbo;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_ENUM;
pvdes->no_elements=1;
(unsigned short *)(pvdes->pvalue) = &pbo->val;
return(0);
}
static long get_enum_str(paddr,pstring)
struct dbAddr *paddr;
char *pstring;
{
struct boRecord *pbo=(struct boRecord *)paddr->precord;
if(pbo->val==0) {
strncpy(pstring,pbo->znam,sizeof(pbo->znam));
pstring[sizeof(pbo->znam)] = 0;
} else if(pbo->val==0) {
strncpy(pstring,pbo->onam,sizeof(pbo->onam));
pstring[sizeof(pbo->onam)] = 0;
} else {
strcpy(pstring,"Illegal Value");
}
return(0L);
}
static long get_enum_strs(paddr,pes)
struct dbAddr *paddr;
struct dbr_enumStrs *pes;
{
struct boRecord *pbo=(struct boRecord *)paddr->precord;
pes->no_str = 2;
bzero(pes->strs,sizeof(pes->strs));
strncpy(pes->strs[0],pbo->znam,sizeof(pbo->znam));
strncpy(pes->strs[1],pbo->onam,sizeof(pbo->onam));
return(0L);
}
static long 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;
}
/* 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;
}
}else{
if (pbo->osv != NO_ALARM){
pbo->stat = STATE_ALARM;
pbo->sevr = pbo->osv;
pbo->achn = 1;
return;
}
}
/* check for cos alarm */
if (pbo->cosv != NO_ALARM){
pbo->sevr = pbo->cosv;
pbo->stat = COS_ALARM;
pbo->achn = 1;
return;
}
/* 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);
}
static long monitor(pbo)
struct boRecord *pbo;
{
unsigned short monitor_mask;
/* anyone waiting for an event on this record */
if (pbo->mlis.count == 0) return(0L);
/* Flags which events to fire on the value field */
monitor_mask = 0;
/* 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;
/* 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;
/* check for value change */
}else 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);
db_post_events(pbo,&pbo->rbv,monitor_mask);
}
return(0L);
}

1273
src/rec/recCalc.c Normal file

File diff suppressed because it is too large Load Diff

498
src/rec/recCompress.c Normal file
View File

@ -0,0 +1,498 @@
/* recCompress.c */
/* share/src/rec $Id$ */
/* recCompress.c - Record Support Routines for Compression records
*
* Author: Bob Dalesio
* Date: 7-14-89
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 11-27-89 lrd using one more buffer entry than allocated
* .02 11-27-89 lrd throttle on monitor requests
* .03 02-27-90 lrd handle character value links for Joerger
* digitizer (convert to short array for access
* .04 03-05-90 lrd add averaging of entire waveforms
* .05 04-02-90 ba/lrd fix the joerger processing and
* add get_a_byte macro
* fix the determination of buff_size
* .06 04-11-90 lrd make locals static
* .07 05-02-90 lrd fix mdct so that it would remain 0 on the
* pass where the monitors are sent
* .08 05-08-90 ba mdct is never equal to mcnt during record pro-
* cessing, causing some code never to run. Fix
* is to check (mdct==mcnt || mdct==0) to indicate
* first time through an averaging loop.
* .09 07-26-90 lrd fixed the N-to-1 character compression
* value was not initialized
* .10 10-11-90 mrk Made changes for new record support
*/
#include <vxWorks.h>
#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>
#include <devSup.h>
#include <errMdef.h>
#include <link.h>
#include <recSup.h>
#include <special.h>
#include <compressRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
#define special NULL
long get_precision();
long get_value();
long cvt_dbaddr();
long get_array_info();
long put_array_info();
#define get_enum_str NULL
long get_units();
long get_graphic_double();
long get_control_double();
#define get_enum_strs NULL
struct rset compressRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct compressRecord *pcompress=(struct compressRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
return(0);
}
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));
/* allocate memory for the summing buffer for conversions requiring it */
if (pcompress->alg == AVERAGE){
pcompress->sptr = (float *)malloc(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));
}
/* initialize the monitor count */
pcompress->mdct = pcompress->mcnt;
return(0);
}
static long get_precision(paddr,precision)
struct dbAddr *paddr;
long *precision;
{
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
*precision = pcompress->prec;
return(0L);
}
static long get_value(pcompress,pvdes)
struct compressRecord *pcompress;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_FLOAT;
pvdes->no_elements=pcompress->nsam;
(float *)(pvdes->pvalue) = pcompress->bptr;
return(0);
}
static long cvt_dbaddr(paddr)
struct 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);
paddr->pfield = (caddr_t)(pcompress->bptr);
paddr->no_elements = pcompress->nsam;
paddr->field_type = DBF_FLOAT;
paddr->field_size = sizeof(float);
paddr->dbr_field_type = DBF_FLOAT;
return(0);
}
static long get_array_info(paddr,no_elements,offset)
struct dbAddr *paddr;
long *no_elements;
long *offset;
{
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
*no_elements = pcompress->nuse;
*offset = inx+1;
return(0);
}
static long put_array_info(paddr,nNew)
struct dbAddr *paddr;
long nNew;
long offset;
{
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
pcompress->inx = (pcompress->inx + 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;
strncpy(units,pcompress->egu,sizeof(pcompress->egu));
return(0L);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
pgd->upper_disp_limit = pcompress->hopr;
pgd->lower_disp_limit = pcompress->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);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct compressRecord *pcompress=(struct compressRecord *)paddr->precord;
pgd->upper_disp_limit = pcompress->hopr;
pgd->lower_disp_limit = pcompress->lopr;
return(0L);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct compressRecord *pcompress=(struct compressRecord *)(paddr->precord);
struct compressdset *pdset = (struct compressdset *)(pcompress->dset);
long status;
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;
}
}
/* 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);
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;
{
long i,j;
int buff_size;
float *psource=pcompress->wptr;
short *off=&(pcompress->off);
short nsam=pconpress->nsam;
float *pdest;
float value;
/* 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))
&& (no_elements > 0)){
no_elements--;
psource++;
}
}
}
/* 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;
/* 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++){
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;
}
}
break;
case (NTO1HIGH):
/* compress N to 1 keeping the highest value */
for (i = 0; i < buff_size; 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;
}
}
break;
case (NTO1AVG):
/* compress N to 1 keeping the average value */
i = 0;
for (i = 0; i < buff_size; i++){
value = 0;
for (j = 0; j < pcompress->n; j++, psource++){
value += *psource;
}
*pdest = value / j;
if( (*off)++ <nsam) {
pdest++;
} else {
pdest = pcompress->bptr;
*off=0;
}
}
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 */
}
}
}
static compress_value(pcompress)
register struct compress *pcompress;
{
float value = *pcompress->wptr;;
short inx;
float *pdest;
/* compress according to specified algorithm */
switch (pcompress->alg){
case (NTO1LOW):
pdest = pcompress->bptr + pcompress->inx;
if ((value < *pdest) || (pcompress->ccnt == 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))
*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;
}
break;
}
}
}

115
src/rec/recFanout.c Normal file
View File

@ -0,0 +1,115 @@
/* recFanout.c */
/* share/src/rec $Id$ */
/* recFanout.c - Record Support Routines for Fanout records
*
* Author: Marty Kraimer
* Date: 10/10/90
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 10-10-90 mrk extensible record and device support
*/
#include <vxWorks.h>
#include <types.h>
#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 <fanoutRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
#define init_record NULL
long process();
#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 NULL
#define get_graphic_double NULL
#define get_control_double NULL
#define get_enum_strs NULL
struct rset fanoutRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct fanoutRecord *pfanout=(struct fanoutRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(recGblReportLink(fp,"LNK1",&(pfanout->lnk1))) return(-1);
if(recGblReportLink(fp,"LNK2",&(pfanout->lnk2))) return(-1);
if(recGblReportLink(fp,"LNK3",&(pfanout->lnk3))) return(-1);
if(recGblReportLink(fp,"LNK4",&(pfanout->lnk4))) return(-1);
if(recGblReportLink(fp,"LNK5",&(pfanout->lnk5))) return(-1);
if(recGblReportLink(fp,"LNK6",&(pfanout->lnk6))) return(-1);
return(0);
}
static long process(paddr)
struct dbAddr *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=FALSE;
return(0);
}

356
src/rec/recMbbi.c Normal file
View File

@ -0,0 +1,356 @@
/* recMbbi.c */
/* share/src/rec $Id$ */
/* recMbbi.c - Record Support Routines for multi bit binary Input records
*
* Author: Bob Dalesio
* Date: 5-9-88
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 12-12-88 lrd lock the record while processing
* .02 12-15-88 lrd Process the forward scan link
* .03 12-23-88 lrd Alarm on locked MAX_LOCKED times
* .04 01-13-89 lrd delete db_read_mbbi
* .05 03-29-89 lrd make hardware errors MAJOR
* remove hw severity spec from database
* .06 04-07-89 lrd add monitor detection
* .07 05-03-89 lrd removed process mask from arg list
* .08 05-29-89 lrd support 16 states
* .09 05-30-89 lrd fixed masks for allen-bradley IO
* .10 06-06-89 lrd fixed AB mbbi conversion - signal wrong
* added ability to enter raw numbers if no
* 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
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <lstLib.h>
#include <strLib.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 <mbbiRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
long special();
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
long get_enum_str();
#define get_units NULL
#define get_graphic_double NULL
#define get_control_double NULL
long get_enum_strs();
struct rset mbbiRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
struct mbbidset { /* multi bit binary input dset */
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbi;/*(-1,0,1)=>(failure,success,don't Continue*/
};
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct mbbiRecord *pmbbi=(struct mbbiRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
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);
return(0);
}
static long init_record(pmbbi)
struct mbbiRecord *pmbbi;
{
struct mbbidset *pdset;
long status;
if(!(pdset = (struct mbbidset *)(pmbbi->dset))) {
recGblRecordError(S_dev_noDSET,pmbbi,"mbbi: init_record");
return(S_dev_noDSET);
}
/* must have read_mbbi function defined */
if( (pdset->number < 5) || (pdset->read_mbbi == NULL) ) {
recGblRecordError(S_dev_missingSup,pmbbi,"mbbi: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(pmbbi))) return(status);
}
return(0);
}
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,states_defined;
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);
}
static long get_value(pmbbi,pvdes)
struct mbbiRecord *pmbbi;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_ENUM;
pvdes->no_elements=1;
(unsigned short *)(pvdes->pvalue) = &pmbbi->val;
return(0);
}
static long get_enum_str(paddr,pstring)
struct dbAddr *paddr;
char *pstring;
{
struct mbbiRecord *pmbbi=(struct mbbiRecord *)paddr->precord;
char *psource;
unsigned short val=pmbbi->val;
if( val>0 && val<= 15) {
psource = (pmbbi->zrst);
psource += (val * sizeof(pmbbi->zrst));
strncpy(pstring,psource,sizeof(pmbbi->zrst));
} else {
strcpy(pstring,"Illegal Value");
}
return(0L);
}
static long get_enum_strs(paddr,pes)
struct dbAddr *paddr;
struct dbr_enumStrs *pes;
{
struct mbbiRecord *pmbbi=(struct mbbiRecord *)paddr->precord;
char *psource;
int i;
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);
}
static long alarm(pmbbi)
struct mbbiRecord *pmbbi;
{
float ftemp;
unsigned short *severities;
/* 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;
/* 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;
}
}
/* 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;
}
/* check for cos alarm */
if (pmbbi->cosv != NO_ALARM){
pmbbi->sevr = pmbbi->cosv;
pmbbi->stat = COS_ALARM;
pmbbi->achn = 1;
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);
}
static long monitor(pmbbi)
struct mbbiRecord *pmbbi;
{
unsigned short monitor_mask;
/* anyone waiting for an event on this record */
if (pmbbi->mlis.count == 0) return(0L);
/* 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;
/* check for value change */
}else 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);
}

362
src/rec/recMbbo.c Normal file
View File

@ -0,0 +1,362 @@
/* recMbbo.c */
/* share/src/rec $Id$ */
/* recMbbo.c - Record Support Routines for multi bit binary Output records
*
* Author: Bob Dalesio
* Date: 7-17-87
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 11-28-88 lrd add desired value fetched
* .02 12-12-88 lrd lock the record while processing
* .03 12-15-88 lrd Process the forward scan link
* .04 12-23-88 lrd Alarm on locked MAX_LOCKED times
* .05 01-09-89 lrd Fix direct value outputs so that they shift the
* value into the correct bit position
* .06 01-13-89 lrd delete db_write_mbbo and db_write_mbbo
* .07 01-20-89 lrd fixed vx inlcudes
* .08 03-03-89 lrd add supervisory/closed loop control
* .09 03-29-89 lrd make hardware errors MAJOR
* remove hw severity spec from database
* .10 04-07-89 lrd add monitor service
* .11 05-03-89 lrd removed process mask from arg list
* .12 05-30-89 lrd fixed mask for allen-bradley IO
* .13 01-05-90 joh,lrd fixed write_mbbo() to set rval
* .14 02-08-90 lrd/cr fixed the mbbo to read at initialization for
* Allen-Bradley and added PLC support
* .15 04-11-90 lrd make locals static
* .16 10-11-90 mrk make changes for new record and device support
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <lstLib.h>
#include <strLib.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 <mbboRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
long special();
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
long get_enum_str();
#define get_units NULL
#define get_graphic_double NULL
#define get_control_double NULL
long get_enum_strs();
struct rset mbboRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
struct mbbodset { /* multi bit binary input dset */
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbbo;/*(-1,0,1)=>(failure,success,don't Continue*/
};
/* the following definitions must match those in choiceGbl.ascii */
#define OUTPUT_FULL 0
#define CLOSED_LOOP 1
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct mbboRecord *pmbbo=(struct mbboRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %d\n",pmbbo->val)) return(-1);
if(recGblReportLink(fp,"OUT ",&(pmbbo->out))) return(-1);
if(recGblReportLink(fp,"FLNK",&(pmbbo->flnk))) return(-1);
if(fprintf(fp,"RVAL 0x%-8X\n",
pmbbo->rval)) return(-1);
return(0);
}
static long init_record(pmbbo)
struct mbboRecord *pmbbo;
{
struct mbbodset *pdset;
long status;
if(!(pdset = (struct mbbodset *)(pmbbo->dset))) {
recGblRecordError(S_dev_noDSET,pmbbo,"mbbo: init_record");
return(S_dev_noDSET);
}
/* must have write_mbbo function defined */
if( (pdset->number < 5) || (pdset->write_mbbo == NULL) ) {
recGblRecordError(S_dev_missingSup,pmbbo,"mbbo: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(pmbbo))) return(status);
}
return(0);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct mbboRecord *pmbbo=(struct mbboRecord *)(paddr->precord);
struct mbbodset *pdset = (struct mbbodset *)(pmbbo->dset);
long status;
unsigned long *pvalues;
short states_defined,i;
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);
}
static long get_value(pmbbo,pvdes)
struct mbboRecord *pmbbo;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_ENUM;
pvdes->no_elements=1;
(unsigned short *)(pvdes->pvalue) = &pmbbo->val;
return(0);
}
static long get_enum_str(paddr,pstring)
struct dbAddr *paddr;
char *pstring;
{
struct mbboRecord *pmbbo=(struct mbboRecord *)paddr->precord;
char *psource;
unsigned short val=pmbbo->val;
if( val>0 && val<= 15) {
psource = (pmbbo->zrst);
psource += (val * sizeof(pmbbo->zrst));
strncpy(pstring,psource,sizeof(pmbbo->zrst));
} else {
strcpy(pstring,"Illegal Value");
}
return(0L);
}
static long get_enum_strs(paddr,pes)
struct dbAddr *paddr;
struct dbr_enumStrs *pes;
{
struct mbboRecord *pmbbo=(struct mbboRecord *)paddr->precord;
char *psource;
int i;
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);
}
static long alarm(pmbbo)
struct mbboRecord *pmbbo;
{
float ftemp;
unsigned short *severities;
/* check for a hardware alarm */
if (pmbbo->stat == READ_ALARM) return(0);
if (pmbbo->stat == WRITE_ALARM) return(0);
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;
}
/* set last alarmed value */
pmbbo->lalm = pmbbo->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;
}
}
/* 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;
}
/* check for cos alarm */
if (pmbbo->cosv != NO_ALARM){
pmbbo->sevr = pmbbo->cosv;
pmbbo->stat = COS_ALARM;
pmbbo->achn = 1;
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);
}
static long monitor(pmbbo)
struct mbboRecord *pmbbo;
{
unsigned short monitor_mask;
/* anyone waiting for an event on this record */
if (pmbbo->mlis.count == 0) return(0L);
/* 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;
/* check for value change */
}else 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);
}

107
src/rec/recPermissive.c Normal file
View File

@ -0,0 +1,107 @@
/* recPermissive.c */
/* share/src/rec $Id$ */
/* recPermissive.c - Record Support Routines for Permissive records
*
* Author: Marty Kraimer
* Date: 10/10/90
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 10-10-90 mrk extensible record and device support
*/
#include <vxWorks.h>
#include <types.h>
#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*/
long report();
#define initialize NULL
#define init_record NULL
long process();
#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 NULL
#define get_graphic_double NULL
#define get_control_double NULL
#define get_enum_strs NULL
struct rset permissiveRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct permissiveRecord *ppermissive=(struct permissiveRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"LABL %s\n",ppermissive->labl)) return(-1);
if(fprintf(fp,"VAL %d\n",ppermissive->val)) return(-1);
if(fprintf(fp,"WFLG %d\n",ppermissive->wflg)) return(-1);
return(0);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct permissiveRecord *ppermissive=(struct permissiveRecord *)(paddr->precord);
/* anyone waiting for an event on this record */
ppermissive->pact=FALSE;
return(0);
}

409
src/rec/recPid.c Normal file
View File

@ -0,0 +1,409 @@
/* recPid.c */
/* share/src/rec $Id$ */
/* recPid.c - Record Support Routines for Pid records
*
* Author: Bob Dalesio
* Date: 05-19-89
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 10-15-90 mrk changes for new record support
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#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 <pidRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
#define special NULL
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
#define get_enum_str NULL
long get_units();
long get_graphic_double();
long get_control_double();
#define get_enum_strs NULL
struct rset pidRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct pidRecord *ppid=(struct pidRecord*)(paddr->precord);
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 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;
{
struct pidRecord *ppid=(struct pidRecord *)paddr->precord;
*precision = ppid->prec;
return(0L);
}
static long get_value(ppid,pvdes)
struct pidRecord *ppid;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_FLOAT;
pvdes->no_elements=1;
(float *)(pvdes->pvalue) = &ppid->val;
return(0);
}
static long get_units(paddr,units)
struct dbAddr *paddr;
char *units;
{
struct pidRecord *ppid=(struct pidRecord *)paddr->precord;
strncpy(units,ppid->egu,sizeof(ppid->egu));
return(0L);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct pidRecord *ppid=(struct pidRecord *)paddr->precord;
pgd->upper_disp_limit = ppid->hopr;
pgd->lower_disp_limit = ppid->lopr;
pgd->upper_alarm_limit = ppid->hihi;
pgd->upper_warning_limit = ppid->high;
pgd->lower_warning_limit = ppid->low;
pgd->lower_alarm_limit = ppid->lolo;
return(0L);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct pidRecord *ppid=(struct pidRecord *)paddr->precord;
pcd->upper_ctrl_limit = ppid->hopr;
pcd->lower_ctrl_limit = ppid->lopr;
return(0L);
}
static void alarm(ppid)
struct pidRecord *ppid;
{
float ftemp;
/* check for a hardware alarm */
if (ppid->stat == READ_ALARM) return(0);
/* 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->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->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->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;
}
static void monitor(ppid)
struct pidRecord *ppid;
{
unsigned short monitor_mask;
float delta;
/* anyone waiting for an event on this record */
if (ppid->mlis.count == 0) return;
/* Flags which events to fire on the value field */
monitor_mask = 0;
/* 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;
/* 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);
}
}
/* rate of change on the setpoint? */
/* 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){
ppid->stat = READ_ALARM;
ppid->sevr = MAJOR;
ppid->achn = 1;
return(-1);
}
}
}
/* 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;
return(0);
}

434
src/rec/recSel.c Normal file
View File

@ -0,0 +1,434 @@
/* recSel.c */
/* share/src/rec $Id$ */
/* recSel.c - Record Support Routines for Select records
*
* Author: Bob Dalesio
* Date: 06-02-89
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 11-16-89 lrd fixed select algorithms not to compare against
* the previous value
*
* .02 10-12-90 mrk changes for new record support
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#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*/
long report();
#define initialize NULL
long init_record();
long process();
#define special NULL
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
#define get_enum_str NULL
long get_units();
long get_graphic_double();
long get_control_double();
#define get_enum_strs NULL
struct rset selRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
#define SEL_MAX 6
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct selRecord *psel=(struct selRecord*)(paddr->precord);
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;
{
if(psel->inpa.type==CONSTANT) psel->a = psel->inpa.value.value;
if(psel->inpb.type==CONSTANT) psel->b = psel->inpb.value.value;
if(psel->inpc.type==CONSTANT) psel->c = psel->inpc.value.value;
if(psel->inpd.type==CONSTANT) psel->d = psel->inpd.value.value;
if(psel->inpe.type==CONSTANT) psel->e = psel->inpe.value.value;
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;
{
struct selRecord *psel=(struct selRecord *)paddr->precord;
*precision = psel->prec;
return(0L);
}
static long get_value(psel,pvdes)
struct selRecord *psel;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_FLOAT;
pvdes->no_elements=1;
(float *)(pvdes->pvalue) = &psel->val;
return(0);
}
static long get_units(paddr,units)
struct dbAddr *paddr;
char *units;
{
struct selRecord *psel=(struct selRecord *)paddr->precord;
strncpy(units,psel->egu,sizeof(psel->egu));
return(0L);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct selRecord *psel=(struct selRecord *)paddr->precord;
pgd->upper_disp_limit = psel->hopr;
pgd->lower_disp_limit = psel->lopr;
pgd->upper_alarm_limit = psel->hihi;
pgd->upper_warning_limit = psel->high;
pgd->lower_warning_limit = psel->low;
pgd->lower_alarm_limit = psel->lolo;
return(0L);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct selRecord *psel=(struct selRecord *)paddr->precord;
pcd->upper_ctrl_limit = psel->hopr;
pcd->lower_ctrl_limit = psel->lopr;
return(0L);
}
static long alarm(psel)
struct selRecord *psel;
{
float ftemp;
/* check for a hardware alarm */
if (psel->stat == READ_ALARM) return(0);
/* 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);
}
static long monitor(psel)
struct selRecord *psel;
{
unsigned short monitor_mask;
float delta;
/* anyone waiting for an event on this record */
if (psel->mlis.count == 0) return(0L);
/* Flags which events to fire on the value field */
monitor_mask = 0;
/* 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;
/* post stat and sevr fields */
db_post_events(psel,&psel->stat,DBE_VALUE);
db_post_events(psel,&psel->sevr,DBE_VALUE);
/* 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);
}
static long do_sel(psel)
struct sel *psel; /* pointer to selection record */
{
float *pvalue;
struct link *plink;
float order[SEL_MAX];
unsigned short order_inx;
unsigned short i,j;
/* selection mechanism */
pvalue = &psel->a;
switch (psel->selm){
case (SELECTED):
psel->val = *(pvalue+psel->seln);
break;
case (SELECT_HIGH):
psel->val = *pvalue;
for (i = 0; i < SEL_MAX; i++,pvalue++){
if (psel->val < *pvalue)
psel->val = *pvalue;
}
break;
case (SELECT_LOW):
psel->val = *pvalue;
for (i = 0; i < SEL_MAX; i++,pvalue++){
if (psel->val > *pvalue)
psel->val = *pvalue;
}
break;
case (SELECT_MEDIAN):
/* order only those fetched from another record */
plink = &psel->inpa;
order_inx = 0;
for (i = 0; i < SEL_MAX; i++,pvalue++,plink++){
if (plink->type == DB_LINK){
j = order_inx;
while ((order[j-1] > *pvalue) && (j > 0)){
order[j] = order[j-1];
j--;
}
order[j] = *pvalue;
order_inx++;
}
}
psel->val = order[order_inx/2];
break;
}
/* initialize flag */
return(0);
}
/*
* FETCH_VALUES
*
* fetch the values for the variables from which to select
*/
static fetch_values(psel)
register struct sel *psel;
{
long nRequest;
long options=0;
struct link *plink;
float *pvalue;
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);
}
}
return(0);
}

105
src/rec/recState.c Normal file
View File

@ -0,0 +1,105 @@
/* recState.c */
/* share/src/rec $Id$ */
/* recState.c - Record Support Routines for State records
*
* Author: Marty Kraimer
* Date: 10/10/90
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 10-10-90 mrk extensible record and device support
*/
#include <vxWorks.h>
#include <types.h>
#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 <stateRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
#define init_record NULL
long process();
#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 NULL
#define get_graphic_double NULL
#define get_control_double NULL
#define get_enum_strs NULL
struct rset stateRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct stateRecord *pstate=(struct stateRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %d\n",pstate->val)) return(-1);
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;
return(0);
}

781
src/rec/recSub.c Normal file
View File

@ -0,0 +1,781 @@
/* recSub.c */
/* share/src/rec $Id$ */
/* recSub.c - Record Support Routines for Subroutine records
*
* Author: Bob Dalesio
* Date: 01-25-90
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 10-10-90 mrk Made changes for new record support
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.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 <subRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
#define special NULL
long get_precision();
long get_value();
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
#define get_enum_str NULL
long get_units();
long get_graphic_double();
long get_control_double();
#define get_enum_strs NULL
struct rset subRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
get_enum_strs };
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct subRecord *psub=(struct subRecord*)(paddr->precord);
if(recGblReportDbCommon(fp,paddr)) return(-1);
if(fprintf(fp,"VAL %-12.4G\n",psub->val)) return(-1);
if(recGblReportLink(fp,"INPA ",&(psub->inpa))) return(-1);
if(recGblReportLink(fp,"INPB ",&(psub->inpb))) return(-1);
if(recGblReportLink(fp,"INPC ",&(psub->inpc))) return(-1);
if(recGblReportLink(fp,"INPD ",&(psub->inpd))) return(-1);
if(recGblReportLink(fp,"INPE ",&(psub->inpe))) return(-1);
if(recGblReportLink(fp,"INPF ",&(psub->inpf))) return(-1);
if(recGblReportLink(fp,"FLNK",&(psub->flnk))) return(-1);
if(fprintf(fp,"A %-12.4G\n",psub->a)) return(-1);
if(fprintf(fp,"B %-12.4G\n",psub->b)) return(-1);
if(fprintf(fp,"C %-12.4G\n",psub->c)) return(-1);
if(fprintf(fp,"D %-12.4G\n",psub->d)) return(-1);
if(fprintf(fp,"E %-12.4G\n",psub->e)) return(-1);
if(fprintf(fp,"F %-12.4G\n",psub->f)) return(-1);
if(fprintf(fp,"PREC %d EGU %-8s\n",psub->prec,psub->egu)) return(-1);
if(fprintf(fp,"HOPR %-12.4G LOPR %-12.4G\n",
psub->hopr,psub->lopr)) return(-1);
if(fprintf(fp,"HIHI %-12.4G HIGH %-12.4G LOW %-12.4G LOLO %-12.4G\n",
psub->hihi,psub->high,psub->low,psub->lolo)) return(-1);
if(recGblReportGblChoice(fp,psub,"HHSV",psub->hhsv)) return(-1);
if(recGblReportGblChoice(fp,psub,"HSV ",psub->hsv)) return(-1);
if(recGblReportGblChoice(fp,psub,"LSV ",psub->lsv)) return(-1);
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;
if(psub->inpa.type==CONSTANT) psub->a = psub->inpa.value.value;
if(psub->inpb.type==CONSTANT) psub->b = psub->inpb.value.value;
if(psub->inpc.type==CONSTANT) psub->c = psub->inpc.value.value;
if(psub->inpd.type==CONSTANT) psub->d = psub->inpd.value.value;
if(psub->inpe.type==CONSTANT) psub->e = psub->inpe.value.value;
if(psub->inpf.type==CONSTANT) psub->f = psub->inpf.value.value;
/* convert the initialization subroutine name */
temp[0] = 0; /* all global variables start with _ */
if (psub->inam[0] != '_'){
strcpy(temp,"_");
}
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);
}
/* 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);
}
}
/* convert the subroutine name to an address and type */
/* convert the initialization subroutine name */
temp[0] = 0; /* all global variables start with _ */
if (psub->snam[0] != '_'){
strcpy(temp,"_");
}
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;
}
psub->styp = sub_type;
return(0);
}
static long get_precision(paddr,precision)
struct dbAddr *paddr;
long *precision;
{
struct subRecord *psub=(struct subRecord *)paddr->precord;
*precision = psub->prec;
return(0L);
}
static long get_value(psub,pvdes)
struct subRecord *psub;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_FLOAT;
pvdes->no_elements=1;
(float *)(pvdes->pvalue) = &psub->val;
return(0);
}
static long get_units(paddr,units)
struct dbAddr *paddr;
char *units;
{
struct subRecord *psub=(struct subRecord *)paddr->precord;
strncpy(units,psub->egu,sizeof(psub->egu));
return(0L);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct subRecord *psub=(struct subRecord *)paddr->precord;
pgd->upper_disp_limit = psub->hopr;
pgd->lower_disp_limit = psub->lopr;
pgd->upper_alarm_limit = psub->hihi;
pgd->upper_warning_limit = psub->high;
pgd->lower_warning_limit = psub->low;
pgd->lower_alarm_limit = psub->lolo;
return(0L);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct subRecord *psub=(struct subRecord *)paddr->precord;
pcd->upper_ctrl_limit = psub->hopr;
pcd->lower_ctrl_limit = psub->lopr;
return(0L);
}
static long process(paddr)
struct dbAddr *paddr;
{
struct subRecord *psub=(struct subRecord *)(paddr->precord);
struct subdset *pdset = (struct subdset *)(psub->dset);
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;
}
}
/* 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);
}
/*
* 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)
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);
}
/* 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 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 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);
}
static long monitor(psub)
struct subRecord *psub;
{
unsigned short monitor_mask;
float delta;
/* 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;
/* 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;
}
/* 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 */
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 > 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)){
/* 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);
}

351
src/rec/recTimer.c Normal file
View File

@ -0,0 +1,351 @@
/* recTimer.c */
/* share/src/rec $Id$ */
/* recTimer.c - Record Support Routines for Timer records
*
* Author: Bob Dalesio
* Date: 1-9-89
*
* Control System Software for the GTA Project
*
* Copyright 1988, 1989, the Regents of the University of California.
*
* This software was produced under a U.S. Government contract
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
* operated by the University of California for the U.S. Department
* of Energy.
*
* Developed by the Controls and Automation Group (AT-8)
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Direct inqueries to:
* Bob Dalesio, AT-8, Mail Stop H820
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
* Phone: (505) 667-3414
* E-mail: dalesio@luke.lanl.gov
*
* Modification Log:
* -----------------
* .01 01-20-89 lrd fix vx includes
* .02 02-06-89 lrd add event post capability
* .03 03-29-89 lrd make hardware errors MAJOR
* remove hw severity spec from database
* .04 04-07-89 lrd service monitors
* .05 05-03-89 lrd removed process mask from arg list
* .06 05-03-89 lrd modified to read the timing on startup
* .07 05-03-89 lrd read trigger delay from trigger origin record
* .08 07-03-89 lrd add processing a forward link
* .09 08-15-89 lrd add post events for timing pulse 1 fields
* .10 10-15-90 mrk extensible record and device support
*/
#include <vxWorks.h>
#include <types.h>
#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 <timerRecord.h>
/* Create RSET - Record Support Entry Table*/
long report();
#define initialize NULL
long init_record();
long process();
#define special();
#define get_precision();
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_enum_strs NULL
struct rset timerRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_precision,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_enum_str,
get_units,
get_graphic_double,
get_control_double,
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};
static long report(fp,paddr)
FILE *fp;
struct dbAddr *paddr;
{
struct timerRecord *ptimer=(struct timerRecord*)(paddr->precord);
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;
{
pvdes->field_type = DBF_SHORT;
pvdes->no_elements=1;
(short *)(pvdes->pvalue) = &ptimer->val;
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);
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);
}
/* process the forward scan link record */
if (ptimer->flnk.type == DB_LINK)
dbScanPassive(&ptimer->flnk.value);
/* unlock the record */
ptimer->lock = 0;
ptimer->pact=FALSE;
return(0);
}
/*
* These constants are indexed by the time units field in the timer record.
* Values are converted to seconds.
*/
static double constants[] = {1000,1000000,1000000000,1000000000000};
/*
* CONVERT_TIMER
*
*/
static convert_timer(ptimer)
register struct timer *ptimer;
{
double constant;
/* check the tdisble bit */
if (ptimer->tdis == 1){
ptimer->t1dl = ptimer->t1wd = 0;
ptimer->t2dl = ptimer->t2wd = 0;
ptimer->t3dl = ptimer->t3wd = 0;
ptimer->t4dl = ptimer->t4wd = 0;
ptimer->t5dl = ptimer->t5wd = 0;
return;
}
/* convert according to time units */
constant = constants[ptimer->timu];
/* timing pulse 1 */
ptimer->t1dl = (ptimer->dut1 + ptimer->trdl) / constant; /* delay */
ptimer->t1wd = ptimer->opw1 / constant; /* width */
ptimer->t1ld = ptimer->dut1 + ptimer->trdl; /* leading edge delay */
ptimer->t1td = ptimer->t1ld + ptimer->opw1; /* trailing edge delay */
/* timing pulse 2 */
ptimer->t2dl = (ptimer->dut2 + ptimer->trdl) / constant; /* delay */
ptimer->t2wd = ptimer->opw2 / constant; /* width */
ptimer->t2ld = ptimer->dut2 + ptimer->trdl; /* leading edge delay */
ptimer->t2td = ptimer->t2ld + ptimer->opw2; /* trailing edge delay */
/* timing pulse 3 */
ptimer->t3dl = (ptimer->dut3 + ptimer->trdl) / constant; /* delay */
ptimer->t3wd = ptimer->opw3 / constant; /* width */
ptimer->t3ld = ptimer->dut3 + ptimer->trdl; /* leading edge delay */
ptimer->t3td = ptimer->t3ld + ptimer->opw3; /* trailing edge delay */
/* timing pulse 4 */
ptimer->t4dl = (ptimer->dut4 + ptimer->trdl) / constant; /* delay */
ptimer->t4wd = ptimer->opw4 / constant; /* width */
ptimer->t4ld = ptimer->dut4 + ptimer->trdl; /* leading edge delay */
ptimer->t4td = ptimer->t4ld + ptimer->opw4; /* trailing edge delay */
/* timing pulse 5 */
ptimer->t5dl = (ptimer->dut5 + ptimer->trdl) / constant; /* delay */
ptimer->t5wd = ptimer->opw5 / constant; /* width */
ptimer->t5ld = ptimer->dut5 + ptimer->trdl; /* leading edge delay */
ptimer->t5td = ptimer->t5ld + ptimer->opw5; /* trailing edge delay */
}
/*
* WRITE_TIMER
*
* convert the value and write it
*/
static write_timer(ptimer)
register struct timer *ptimer;
{
register struct vmeio *pvmeio;
register double *pdelay;
register short count;
register short i;
/* 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->out.type != VME_IO) return(-1);
pvmeio = (struct vmeio *)(&ptimer->out.value);
/* convert the value */
convert_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->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;
}
return(-1);
}else if (ptimer->stat == WRITE_ALARM){
ptimer->stat = NO_ALARM;
ptimer->sevr = NO_ALARM;
ptimer->achn = 1;
}
return(0);
}
/*
* READ_TIMER
*
* read the current timer pulses and convert them to engineering units
*/
static read_timer(ptimer)
register struct timer *ptimer;
{
register struct vmeio *pvmeio;
int source;
int ptst;
int no_pulses;
double time_pulse[2]; /* delay and width */
double constant;
/* initiate the write */
if (ptimer->out.type != VME_IO) return(-1);
/* 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 */
&source, /* trigger source */
&ptst, /* pre-trigger state */
&time_pulse[0], /* delay/width */
&no_pulses, /* number pulses found */
1) < 0) return;
if (no_pulses == 0) return;
/* convert according to time units */
constant = constants[ptimer->timu];
/* timing pulse 1 is currently active */
/* put its parameters into the database so that it will not change */
/* when the timer record is written */
ptimer->dut1 = time_pulse[0] * constant; /* delay to trigger */
ptimer->opw1 = time_pulse[1] * constant; /* pulse width */
ptimer->ptst = ptst; /* pre-trigger state */
ptimer->tsrc = source; /* clock source */
return(0);
}