new string is identical to the old one. Default value is "On Change" with behaviour identical to before, set to "Always" to fire monitors every time the record is processed (analagous to setting MDEL=-1 for numeric record types).
238 lines
6.6 KiB
C
238 lines
6.6 KiB
C
/*************************************************************************\
|
||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||
* National Laboratory.
|
||
* Copyright (c) 2002 The Regents of the University of California, as
|
||
* Operator of Los Alamos National Laboratory.
|
||
* EPICS BASE Versions 3.13.7
|
||
* and higher are distributed subject to a Software License Agreement found
|
||
* in file LICENSE that is included with this distribution.
|
||
\*************************************************************************/
|
||
/* recStringout.c */
|
||
/* base/src/rec $Id$ */
|
||
|
||
/* recStringout.c - Record Support Routines for Stringout records */
|
||
/*
|
||
* Author: Janet Anderson
|
||
* Date: 4/23/91
|
||
*/
|
||
|
||
|
||
#include <stddef.h>
|
||
#include <stdlib.h>
|
||
#include <stdarg.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
|
||
#include "dbDefs.h"
|
||
#include "epicsPrint.h"
|
||
#include "alarm.h"
|
||
#include "dbAccess.h"
|
||
#include "dbEvent.h"
|
||
#include "dbFldTypes.h"
|
||
#include "devSup.h"
|
||
#include "errMdef.h"
|
||
#include "recSup.h"
|
||
#include "recGbl.h"
|
||
#define GEN_SIZE_OFFSET
|
||
#include "stringoutRecord.h"
|
||
#undef GEN_SIZE_OFFSET
|
||
#include "menuOmsl.h"
|
||
#include "menuIvoa.h"
|
||
#include "epicsExport.h"
|
||
|
||
/* Create RSET - Record Support Entry Table*/
|
||
#define report NULL
|
||
#define initialize NULL
|
||
static long init_record();
|
||
static long process();
|
||
#define special NULL
|
||
#define get_value NULL
|
||
#define cvt_dbaddr NULL
|
||
#define get_array_info NULL
|
||
#define put_array_info NULL
|
||
#define get_units NULL
|
||
#define get_precision NULL
|
||
#define get_enum_str NULL
|
||
#define get_enum_strs NULL
|
||
#define put_enum_str NULL
|
||
#define get_graphic_double NULL
|
||
#define get_control_double NULL
|
||
#define get_alarm_double NULL
|
||
|
||
rset stringoutRSET={
|
||
RSETNUMBER,
|
||
report,
|
||
initialize,
|
||
init_record,
|
||
process,
|
||
special,
|
||
get_value,
|
||
cvt_dbaddr,
|
||
get_array_info,
|
||
put_array_info,
|
||
get_units,
|
||
get_precision,
|
||
get_enum_str,
|
||
get_enum_strs,
|
||
put_enum_str,
|
||
get_graphic_double,
|
||
get_control_double,
|
||
get_alarm_double
|
||
};
|
||
epicsExportAddress(rset,stringoutRSET);
|
||
|
||
struct stringoutdset { /* stringout input dset */
|
||
long number;
|
||
DEVSUPFUN dev_report;
|
||
DEVSUPFUN init;
|
||
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
|
||
DEVSUPFUN get_ioint_info;
|
||
DEVSUPFUN write_stringout;/*(-1,0)=>(failure,success)*/
|
||
};
|
||
static void monitor();
|
||
static long writeValue();
|
||
|
||
|
||
static long init_record(pstringout,pass)
|
||
struct stringoutRecord *pstringout;
|
||
int pass;
|
||
{
|
||
struct stringoutdset *pdset;
|
||
long status=0;
|
||
|
||
if (pass==0) return(0);
|
||
|
||
if (pstringout->siml.type == CONSTANT) {
|
||
recGblInitConstantLink(&pstringout->siml,DBF_USHORT,&pstringout->simm);
|
||
}
|
||
|
||
if(!(pdset = (struct stringoutdset *)(pstringout->dset))) {
|
||
recGblRecordError(S_dev_noDSET,(void *)pstringout,"stringout: init_record");
|
||
return(S_dev_noDSET);
|
||
}
|
||
/* must have write_stringout functions defined */
|
||
if( (pdset->number < 5) || (pdset->write_stringout == NULL) ) {
|
||
recGblRecordError(S_dev_missingSup,(void *)pstringout,"stringout: init_record");
|
||
return(S_dev_missingSup);
|
||
}
|
||
/* get the initial value dol is a constant*/
|
||
if (pstringout->dol.type == CONSTANT){
|
||
if(recGblInitConstantLink(&pstringout->dol,DBF_STRING,pstringout->val))
|
||
pstringout->udf=FALSE;
|
||
}
|
||
if( pdset->init_record ) {
|
||
if((status=(*pdset->init_record)(pstringout))) return(status);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
static long process(pstringout)
|
||
struct stringoutRecord *pstringout;
|
||
{
|
||
struct stringoutdset *pdset = (struct stringoutdset *)(pstringout->dset);
|
||
long status=0;
|
||
unsigned char pact=pstringout->pact;
|
||
|
||
if( (pdset==NULL) || (pdset->write_stringout==NULL) ) {
|
||
pstringout->pact=TRUE;
|
||
recGblRecordError(S_dev_missingSup,(void *)pstringout,"write_stringout");
|
||
return(S_dev_missingSup);
|
||
}
|
||
if (!pstringout->pact
|
||
&& (pstringout->dol.type != CONSTANT)
|
||
&& (pstringout->omsl == menuOmslclosed_loop)) {
|
||
status = dbGetLink(&(pstringout->dol),
|
||
DBR_STRING,pstringout->val,0,0);
|
||
if(pstringout->dol.type!=CONSTANT && RTN_SUCCESS(status)) pstringout->udf=FALSE;
|
||
}
|
||
|
||
if(pstringout->udf == TRUE ){
|
||
recGblSetSevr(pstringout,UDF_ALARM,INVALID_ALARM);
|
||
goto finish;
|
||
}
|
||
|
||
if (pstringout->nsev < INVALID_ALARM )
|
||
status=writeValue(pstringout); /* write the new value */
|
||
else {
|
||
switch (pstringout->ivoa) {
|
||
case (menuIvoaContinue_normally) :
|
||
status=writeValue(pstringout); /* write the new value */
|
||
break;
|
||
case (menuIvoaDon_t_drive_outputs) :
|
||
break;
|
||
case (menuIvoaSet_output_to_IVOV) :
|
||
if(pstringout->pact == FALSE){
|
||
strcpy(pstringout->val,pstringout->ivov);
|
||
}
|
||
status=writeValue(pstringout); /* write the new value */
|
||
break;
|
||
default :
|
||
status=-1;
|
||
recGblRecordError(S_db_badField,(void *)pstringout,
|
||
"stringout:process Illegal IVOA field");
|
||
}
|
||
}
|
||
|
||
/* check if device support set pact */
|
||
if ( !pact && pstringout->pact ) return(0);
|
||
finish:
|
||
pstringout->pact = TRUE;
|
||
recGblGetTimeStamp(pstringout);
|
||
monitor(pstringout);
|
||
recGblFwdLink(pstringout);
|
||
pstringout->pact=FALSE;
|
||
return(status);
|
||
}
|
||
|
||
static void monitor(pstringout)
|
||
struct stringoutRecord *pstringout;
|
||
{
|
||
unsigned short monitor_mask;
|
||
|
||
monitor_mask = recGblResetAlarms(pstringout);
|
||
if(strncmp(pstringout->oval,pstringout->val,sizeof(pstringout->val))) {
|
||
monitor_mask |= DBE_VALUE|DBE_LOG;
|
||
strncpy(pstringout->oval,pstringout->val,sizeof(pstringout->val));
|
||
}
|
||
if (pstringout->mpst == stringoutPOST_Always)
|
||
monitor_mask |= DBE_VALUE;
|
||
if (pstringout->apst == stringoutPOST_Always)
|
||
monitor_mask |= DBE_LOG;
|
||
if(monitor_mask)
|
||
db_post_events(pstringout,&(pstringout->val[0]),monitor_mask);
|
||
return;
|
||
}
|
||
|
||
static long writeValue(pstringout)
|
||
struct stringoutRecord *pstringout;
|
||
{
|
||
long status;
|
||
struct stringoutdset *pdset = (struct stringoutdset *) (pstringout->dset);
|
||
|
||
if (pstringout->pact == TRUE){
|
||
status=(*pdset->write_stringout)(pstringout);
|
||
return(status);
|
||
}
|
||
|
||
status=dbGetLink(&(pstringout->siml),DBR_USHORT,
|
||
&(pstringout->simm),0,0);
|
||
if (status)
|
||
return(status);
|
||
|
||
if (pstringout->simm == NO){
|
||
status=(*pdset->write_stringout)(pstringout);
|
||
return(status);
|
||
}
|
||
if (pstringout->simm == YES){
|
||
status=dbPutLink(&pstringout->siol,DBR_STRING,
|
||
pstringout->val,1);
|
||
} else {
|
||
status=-1;
|
||
recGblSetSevr(pstringout,SOFT_ALARM,INVALID_ALARM);
|
||
return(status);
|
||
}
|
||
recGblSetSevr(pstringout,SIMM_ALARM,pstringout->sims);
|
||
|
||
return(status);
|
||
}
|