Merge branch '7.0' release 7.4.0.1 into PSI-7.0

Conflicts:
	.gitmodules
	modules/database/src/ioc/db/Makefile
	modules/libcom/test/epicsAtomicTest.cpp
	modules/pvAccess
	modules/pvData
	modules/pvDatabase
	modules/pva2pva
This commit is contained in:
2020-06-02 14:55:30 +02:00
868 changed files with 33281 additions and 27367 deletions
+6 -2
View File
@@ -11,9 +11,13 @@ TOP = ../../../..
include $(TOP)/configure/CONFIG
USR_CPPFLAGS += -DUSE_TYPED_RSET
USR_CPPFLAGS += -DUSE_TYPED_RSET -DUSE_TYPED_DSET
SHRLIB_VERSION = 3.17.0
# Shared library ABI version.
SHRLIB_VERSION = $(EPICS_DATABASE_MAJOR_VERSION).$(EPICS_DATABASE_MINOR_VERSION).$(EPICS_DATABASE_MAINTENANCE_VERSION)
API_HEADER = dbRecStdAPI.h
dbRecStd_API = dbRecStd
LIBRARY_IOC += dbRecStd
dbRecStd_LIBS = dbCore ca Com
+1 -1
View File
@@ -47,7 +47,6 @@ dbRecStd_SRCS += devSASoft.c
dbRecStd_SRCS += devSiSoft.c
dbRecStd_SRCS += devSoSoft.c
dbRecStd_SRCS += devWfSoft.c
dbRecStd_SRCS += devGeneralTime.c
dbRecStd_SRCS += devAiSoftCallback.c
dbRecStd_SRCS += devBiSoftCallback.c
@@ -68,6 +67,7 @@ dbRecStd_SRCS += devMbboDirectSoftCallback.c
dbRecStd_SRCS += devPrintfSoftCallback.c
dbRecStd_SRCS += devSoSoftCallback.c
dbRecStd_SRCS += devGeneralTime.c
dbRecStd_SRCS += devTimestamp.c
dbRecStd_SRCS += devStdio.c
dbRecStd_SRCS += devEnviron.c
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* asSubRecordFunctions.c */
@@ -36,16 +36,16 @@
static void myCallback(epicsCallback *pcallback)
{
ASDBCALLBACK *pasdbcallback = (ASDBCALLBACK *)pcallback;
subRecord *precord;
rset *prset;
ASDBCALLBACK *pasdbcallback = (ASDBCALLBACK *)pcallback;
subRecord *precord;
rset *prset;
callbackGetUser(precord,pcallback);
prset=(rset *)(precord->rset);
precord->val = 0.0;
if(pasdbcallback->status) {
recGblSetSevr(precord,READ_ALARM,precord->brsv);
recGblRecordError(pasdbcallback->status,precord,"asInit Failed");
recGblSetSevr(precord,READ_ALARM,precord->brsv);
recGblRecordError(pasdbcallback->status,precord,"asInit Failed");
}
dbScanLock((dbCommon *)precord);
(*prset->process)((dbCommon *)precord);
@@ -69,11 +69,11 @@ long asSubProcess(subRecord *precord)
ASDBCALLBACK *pcallback = (ASDBCALLBACK *)precord->dpvt;
if(!precord->pact && precord->val==1.0) {
db_post_events(precord,&precord->val,DBE_VALUE);
callbackSetPriority(precord->prio,&pcallback->callback);
asInitAsyn(pcallback);
precord->pact=TRUE;
return(1);
db_post_events(precord,&precord->val,DBE_VALUE);
callbackSetPriority(precord->prio,&pcallback->callback);
asInitAsyn(pcallback);
precord->pact=TRUE;
return(1);
}
db_post_events(precord,&precord->val,DBE_VALUE);
return(0);
+7 -17
View File
@@ -32,28 +32,18 @@
#include "epicsExport.h"
/* Create the dset for devAaiSoft */
static long init_record();
static long read_aai();
static long init_record(dbCommon *pcommon);
static long read_aai(aaiRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_aai;
} devAaiSoft = {
5,
NULL,
NULL,
init_record,
NULL,
aaidset devAaiSoft = {
{5, NULL, NULL, init_record, NULL},
read_aai
};
epicsExportAddress(dset,devAaiSoft);
epicsExportAddress(dset, devAaiSoft);
static long init_record(aaiRecord *prec)
static long init_record(dbCommon *pcommon)
{
aaiRecord *prec = (aaiRecord *)pcommon;
DBLINK *plink = &prec->inp;
/* This is pass 0, link hasn't been initialized yet */
+10 -19
View File
@@ -4,12 +4,12 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* devAaoSoft.c - Device Support Routines for soft Waveform Records
*
*
* Original Author: Bob Dalesio
* Current Author: Dirk Zimoch
* Date: 27-MAY-2010
@@ -30,28 +30,19 @@
#include "epicsExport.h"
/* Create the dset for devAaoSoft */
static long init_record();
static long write_aao();
static long init_record(dbCommon *pcommon);
static long write_aao(aaoRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_aao;
} devAaoSoft = {
5,
NULL,
NULL,
init_record,
NULL,
aaodset devAaoSoft = {
{5, NULL, NULL, init_record, NULL},
write_aao
};
epicsExportAddress(dset,devAaoSoft);
epicsExportAddress(dset, devAaoSoft);
static long init_record(aaoRecord *prec)
static long init_record(dbCommon *pcommon)
{
aaoRecord *prec = (aaoRecord *)pcommon;
if (dbLinkIsConstant(&prec->out)) {
prec->nord = 0;
}
+8 -19
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -26,30 +26,19 @@
#include "epicsExport.h"
/* Create the dset for devAiSoft */
static long init_record(aiRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_ai(aiRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_ai;
DEVSUPFUN special_linconv;
} devAiSoft = {
6,
NULL,
NULL,
init_record,
NULL,
read_ai,
NULL
aidset devAiSoft = {
{6, NULL, NULL, init_record, NULL},
read_ai, NULL
};
epicsExportAddress(dset, devAiSoft);
static long init_record(aiRecord *prec)
static long init_record(dbCommon *pcommon)
{
aiRecord *prec = (aiRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_DOUBLE, &prec->val))
prec->udf = FALSE;
@@ -153,8 +153,10 @@ static long init(int pass)
return 0;
}
static long init_record(aiRecord *prec)
static long init_record(dbCommon *pcommon)
{
aiRecord *prec = (aiRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_DOUBLE, &prec->val))
prec->udf = FALSE;
@@ -213,14 +215,8 @@ static long read_ai(aiRecord *prec)
return 2;
}
/* Create the dset for devAiSoftCallback */
struct {
dset common;
DEVSUPFUN read_ai;
DEVSUPFUN special_linconv;
} devAiSoftCallback = {
aidset devAiSoftCallback = {
{6, NULL, init, init_record, NULL},
read_ai,
NULL
read_ai, NULL
};
epicsExportAddress(dset, devAiSoftCallback);
+8 -19
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,30 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devAiSoftRaw */
static long init_record(aiRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_ai(aiRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_ai;
DEVSUPFUN special_linconv;
} devAiSoftRaw = {
6,
NULL,
NULL,
init_record,
NULL,
read_ai,
NULL
aidset devAiSoftRaw = {
{6, NULL, NULL, init_record, NULL},
read_ai, NULL
};
epicsExportAddress(dset, devAiSoftRaw);
static long init_record(aiRecord *prec)
static long init_record(dbCommon *pcommon)
{
aiRecord *prec = (aiRecord *)pcommon;
recGblInitConstantLink(&prec->inp, DBF_LONG, &prec->rval);
return 0;
+9 -23
View File
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devAoSoft.c */
@@ -31,31 +31,17 @@
#include "aoRecord.h"
#include "epicsExport.h"
/* added for Channel Access Links */
static long init_record(aoRecord *prec);
/* Create the dset for devAoSoft */
static long init_record(dbCommon *pcommon);
static long write_ao(aoRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_ao;
DEVSUPFUN special_linconv;
}devAoSoft={
6,
NULL,
NULL,
init_record,
NULL,
write_ao,
NULL};
epicsExportAddress(dset,devAoSoft);
static long init_record(aoRecord *prec)
aodset devAoSoft = {
{6, NULL, NULL, init_record, NULL},
write_ao, NULL
};
epicsExportAddress(dset, devAoSoft);
static long init_record(dbCommon *pcommon)
{
long status=0;
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devAoSoftCallbackCallback.c */
/*
@@ -31,23 +31,12 @@
/* Create the dset for devAoSoftCallback */
static long write_ao(aoRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_ao;
DEVSUPFUN special_linconv;
}devAoSoftCallback={
6,
NULL,
NULL,
NULL,
NULL,
write_ao,
NULL};
epicsExportAddress(dset,devAoSoftCallback);
aodset devAoSoftCallback = {
{6, NULL, NULL, NULL, NULL},
write_ao, NULL
};
epicsExportAddress(dset, devAoSoftCallback);
static long write_ao(aoRecord *prec)
{
+7 -19
View File
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devAoSoftRaw.c */
@@ -33,25 +33,13 @@
/* Create the dset for devAoSoftRaw */
static long write_ao(aoRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_ao;
DEVSUPFUN special_linconv;
}devAoSoftRaw={
6,
NULL,
NULL,
NULL,
NULL,
write_ao,
NULL
aodset devAoSoftRaw = {
{6, NULL, NULL, NULL, NULL},
write_ao, NULL
};
epicsExportAddress(dset,devAoSoftRaw);
epicsExportAddress(dset, devAoSoftRaw);
static long write_ao(aoRecord *prec)
{
long status;
+4 -15
View File
@@ -69,20 +69,9 @@ static long read_bi(biRecord *prec)
return 2;
}
static struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;
} devBiDbState = {
5,
NULL,
init,
NULL,
NULL,
read_bi
/* Create the dset for devBiDbState */
bidset devBiDbState = {
{5, NULL, init, NULL, NULL},
read_bi
};
epicsExportAddress(dset, devBiDbState);
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devBiSoft */
static long init_record(biRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_bi(biRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;
} devBiSoft = {
5,
NULL,
NULL,
init_record,
NULL,
bidset devBiSoft = {
{5, NULL, NULL, init_record, NULL},
read_bi
};
epicsExportAddress(dset, devBiSoft);
static long init_record(biRecord *prec)
static long init_record(dbCommon *pcommon)
{
biRecord *prec = (biRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_ENUM, &prec->val))
prec->udf = FALSE;
return 0;
@@ -151,8 +151,10 @@ static long init(int pass)
return 0;
}
static long init_record(biRecord *prec)
static long init_record(dbCommon *pcommon)
{
biRecord *prec = (biRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBR_ENUM, &prec->val))
prec->udf = FALSE;
@@ -204,10 +206,7 @@ static long read_bi(biRecord *prec)
}
/* Create the dset for devBiSoftCallback */
struct {
dset common;
DEVSUPFUN read_bi;
} devBiSoftCallback = {
bidset devBiSoftCallback = {
{5, NULL, init, init_record, NULL},
read_bi
};
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devBiSoftRaw */
static long init_record(biRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_bi(biRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;
} devBiSoftRaw = {
5,
NULL,
NULL,
init_record,
NULL,
bidset devBiSoftRaw = {
{5, NULL, NULL, init_record, NULL},
read_bi
};
epicsExportAddress(dset, devBiSoftRaw);
static long init_record(biRecord *prec)
static long init_record(dbCommon *pcommon)
{
biRecord *prec = (biRecord *)pcommon;
recGblInitConstantLink(&prec->inp, DBF_ULONG, &prec->rval);
return 0;
+4 -15
View File
@@ -67,20 +67,9 @@ static long write_bo(boRecord *prec)
return 0;
}
static struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
} devBoDbState = {
5,
NULL,
init,
NULL,
NULL,
write_bo
/* Create the dset for devBoDbState */
bodset devBoDbState = {
{5, NULL, init, NULL, NULL},
write_bo
};
epicsExportAddress(dset, devBoDbState);
+10 -23
View File
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devBoSoft.c - Device Support Routines for Soft Binary Output*/
@@ -29,37 +29,24 @@
#include "boRecord.h"
#include "epicsExport.h"
static long init_record(boRecord *prec);
/* Create the dset for devBoSoft */
static long init_record(dbCommon *pcommon);
static long write_bo(boRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBoSoft={
5,
NULL,
NULL,
init_record,
NULL,
write_bo
bodset devBoSoft = {
{5, NULL, NULL, init_record, NULL},
write_bo
};
epicsExportAddress(dset,devBoSoft);
static long init_record(boRecord *prec)
epicsExportAddress(dset, devBoSoft);
static long init_record(dbCommon *pcommon)
{
long status=0;
/* dont convert */
status=2;
return status;
} /* end init_record() */
static long write_bo(boRecord *prec)
@@ -31,22 +31,11 @@
/* Create the dset for devBoCallbackSoft */
static long write_bo(boRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBoSoftCallback={
5,
NULL,
NULL,
NULL,
NULL,
write_bo
bodset devBoSoftCallback = {
{5, NULL, NULL, NULL, NULL},
write_bo
};
epicsExportAddress(dset,devBoSoftCallback);
epicsExportAddress(dset, devBoSoftCallback);
static long write_bo(boRecord *prec)
{
@@ -64,4 +53,3 @@ static long write_bo(boRecord *prec)
return status;
}
+12 -25
View File
@@ -5,13 +5,13 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devBoSoftRaw.c - Device Support Routines for SoftRaw Binary Output*/
/*
* Author: Janet Anderson
* Date: 3-28-92
* Author: Janet Anderson
* Date: 3-28-92
*/
@@ -28,37 +28,24 @@
#include "boRecord.h"
#include "epicsExport.h"
/* added for Channel Access Links */
static long init_record(boRecord *prec);
/* Create the dset for devBoSoftRaw */
static long init_record(dbCommon *pcommon);
static long write_bo(boRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBoSoftRaw={
5,
NULL,
NULL,
init_record,
NULL,
write_bo
bodset devBoSoftRaw = {
{5, NULL, NULL, init_record, NULL},
write_bo
};
epicsExportAddress(dset,devBoSoftRaw);
static long init_record(boRecord *prec)
epicsExportAddress(dset, devBoSoftRaw);
static long init_record(dbCommon *pcommon)
{
long status;
/*Don't convert*/
status = 2;
return status;
} /* end init_record() */
static long write_bo(boRecord *prec)
+4 -10
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devCalcoutSoft.c */
@@ -31,15 +31,9 @@
static long write_calcout(calcoutRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write;
} devCalcoutSoft = {
5, NULL, NULL, NULL, NULL, write_calcout
calcoutdset devCalcoutSoft = {
{5, NULL, NULL, NULL, NULL},
write_calcout
};
epicsExportAddress(dset, devCalcoutSoft);
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devCalcoutSoftCallback.c */
@@ -31,15 +31,9 @@
static long write_calcout(calcoutRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write;
} devCalcoutSoftCallback = {
5, NULL, NULL, NULL, NULL, write_calcout
calcoutdset devCalcoutSoftCallback = {
{5, NULL, NULL, NULL, NULL},
write_calcout
};
epicsExportAddress(dset, devCalcoutSoftCallback);
+5 -7
View File
@@ -2,7 +2,7 @@
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devEnviron.c */
@@ -69,7 +69,7 @@ static long read_lsi(lsiRecord *prec)
}
lsidset devLsiEnviron = {
5, NULL, init_lsi, NULL, NULL, read_lsi
{5, NULL, init_lsi, NULL, NULL }, read_lsi
};
epicsExportAddress(dset, devLsiEnviron);
@@ -119,10 +119,8 @@ static long read_stringin(stringinRecord *prec)
return 0;
}
static struct {
dset common;
DEVSUPFUN read;
} devSiEnviron = {
{5, NULL, init_stringin, NULL, NULL}, read_stringin
stringindset devSiEnviron = {
{5, NULL, init_stringin, NULL, NULL},
read_stringin
};
epicsExportAddress(dset, devSiEnviron);
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devEventSoft */
static long init_record(eventRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_event(eventRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_event;
} devEventSoft = {
5,
NULL,
NULL,
init_record,
NULL,
eventdset devEventSoft = {
{5, NULL, NULL, init_record, NULL},
read_event
};
epicsExportAddress(dset, devEventSoft);
static long init_record(eventRecord *prec)
static long init_record(dbCommon *pcommon)
{
eventRecord *prec = (eventRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_STRING, prec->val))
prec->udf = FALSE;
+23 -27
View File
@@ -4,8 +4,8 @@
\*************************************************************************/
/*
* Original Author: Sheng Peng, ORNL / SNS Project
* Date: 07/2004
* Original Author: Sheng Peng, ORNL / SNS Project
* Date: 07/2004
*
* EPICS device support for general timestamp support
*
@@ -50,8 +50,9 @@ static struct ai_channel {
{"TIME", getCurrentTime},
};
static long init_ai(aiRecord *prec)
static long init_ai(dbCommon *pcommon)
{
aiRecord *prec = (aiRecord *)pcommon;
int i;
if (prec->inp.type != INST_IO) {
@@ -91,12 +92,9 @@ static long read_ai(aiRecord *prec)
return -1;
}
struct {
dset common;
DEVSUPFUN read_write;
DEVSUPFUN special_linconv;
} devAiGeneralTime = {
{6, NULL, NULL, init_ai, NULL}, read_ai, NULL
aidset devAiGeneralTime = {
{6, NULL, NULL, init_ai, NULL},
read_ai, NULL
};
epicsExportAddress(dset, devAiGeneralTime);
@@ -114,8 +112,9 @@ static struct bo_channel {
{"RSTERRCNT", resetErrors},
};
static long init_bo(boRecord *prec)
static long init_bo(dbCommon *pcommon)
{
boRecord *prec = (boRecord *)pcommon;
int i;
if (prec->out.type != INST_IO) {
@@ -151,15 +150,14 @@ static long write_bo(boRecord *prec)
return 0;
}
struct {
dset common;
DEVSUPFUN read_write;
} devBoGeneralTime = {
{5, NULL, NULL, init_bo, NULL}, write_bo
bodset devBoGeneralTime = {
{5, NULL, NULL, init_bo, NULL},
write_bo
};
epicsExportAddress(dset, devBoGeneralTime);
/******* longin record *************/
static int errorCount(void)
{
@@ -173,8 +171,9 @@ static struct li_channel {
{"GETERRCNT", errorCount},
};
static long init_li(longinRecord *prec)
static long init_li(dbCommon *pcommon)
{
longinRecord *prec = (longinRecord *)pcommon;
int i;
if (prec->inp.type != INST_IO) {
@@ -209,11 +208,9 @@ static long read_li(longinRecord *prec)
return 0;
}
struct {
dset common;
DEVSUPFUN read_write;
} devLiGeneralTime = {
{5, NULL, NULL, init_li, NULL}, read_li
longindset devLiGeneralTime = {
{5, NULL, NULL, init_li, NULL},
read_li
};
epicsExportAddress(dset, devLiGeneralTime);
@@ -243,8 +240,9 @@ static struct si_channel {
{"BESTTEP", eventProvider},
};
static long init_si(stringinRecord *prec)
static long init_si(dbCommon *pcommon)
{
stringinRecord *prec = (stringinRecord *)pcommon;
int i;
if (prec->inp.type != INST_IO) {
@@ -288,10 +286,8 @@ static long read_si(stringinRecord *prec)
return 0;
}
struct {
dset common;
DEVSUPFUN read_write;
} devSiGeneralTime = {
{5, NULL, NULL, init_si, NULL}, read_si
stringindset devSiGeneralTime = {
{5, NULL, NULL, init_si, NULL},
read_si
};
epicsExportAddress(dset, devSiGeneralTime);
+13 -23
View File
@@ -5,12 +5,12 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devHistogramSoft.c */
/*
* Author: Janet Anderson
* Date: 07/02/91
* Author: Janet Anderson
* Date: 07/02/91
*/
#include <stdlib.h>
#include <stdio.h>
@@ -28,29 +28,19 @@
#include "epicsExport.h"
/* Create the dset for devHistogramSoft */
static long init_record(histogramRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_histogram(histogramRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_histogram;
DEVSUPFUN special_linconv;
}devHistogramSoft={
6,
NULL,
NULL,
init_record,
NULL,
read_histogram,
NULL
histogramdset devHistogramSoft = {
{6, NULL, NULL, init_record, NULL},
read_histogram, NULL
};
epicsExportAddress(dset,devHistogramSoft);
static long init_record(histogramRecord *prec)
epicsExportAddress(dset, devHistogramSoft);
static long init_record(dbCommon *pcommon)
{
histogramRecord *prec = (histogramRecord *)pcommon;
if (recGblInitConstantLink(&prec->svl,DBF_DOUBLE,&prec->sgnl))
prec->udf = FALSE;
+11 -23
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -24,29 +24,9 @@
#include "int64inRecord.h"
#include "epicsExport.h"
/* Create the dset for devI64inSoft */
static long init_record(int64inRecord *prec);
static long read_int64in(int64inRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_int64in;
} devI64inSoft = {
5,
NULL,
NULL,
init_record,
NULL,
read_int64in
};
epicsExportAddress(dset, devI64inSoft);
static long init_record(int64inRecord *prec)
static long init_record(dbCommon *common)
{
int64inRecord *prec = (int64inRecord *)common;
if (recGblInitConstantLink(&prec->inp, DBF_INT64, &prec->val))
prec->udf = FALSE;
@@ -76,3 +56,11 @@ static long read_int64in(int64inRecord *prec)
return status;
}
/* Create the dset for devI64inSoft */
int64indset devI64inSoft = {
{ 5, NULL, NULL, init_record, NULL }, read_int64in
};
epicsExportAddress(dset, devI64inSoft);
@@ -151,8 +151,9 @@ static long init(int pass)
return 0;
}
static long init_record(int64inRecord *prec)
static long init_record(dbCommon *common)
{
int64inRecord *prec = (int64inRecord *)common;
if (recGblInitConstantLink(&prec->inp, DBR_INT64, &prec->val))
prec->udf = FALSE;
@@ -204,11 +205,7 @@ static long read_int64in(int64inRecord *prec)
}
/* Create the dset for devI64inSoftCallback */
struct {
dset common;
DEVSUPFUN read_int64in;
} devI64inSoftCallback = {
{5, NULL, init, init_record, NULL},
read_int64in
int64indset devI64inSoftCallback = {
{ 5, NULL, init, init_record, NULL }, read_int64in
};
epicsExportAddress(dset, devI64inSoftCallback);
+9 -22
View File
@@ -9,7 +9,7 @@
/*
* Original Author: Janet Anderson
* Date: 09-23-91
* Date: 09-23-91
*/
#include <stdlib.h>
@@ -25,27 +25,7 @@
#include "int64outRecord.h"
#include "epicsExport.h"
/* Create the dset for devI64outSoft */
static long init_record(int64outRecord *prec);
static long write_int64out(int64outRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_int64out;
} devI64outSoft = {
5,
NULL,
NULL,
init_record,
NULL,
write_int64out
};
epicsExportAddress(dset, devI64outSoft);
static long init_record(int64outRecord *prec)
static long init_record(dbCommon *common)
{
return 0;
}
@@ -55,3 +35,10 @@ static long write_int64out(int64outRecord *prec)
dbPutLink(&prec->out, DBR_INT64, &prec->val,1);
return 0;
}
/* Create the dset for devI64outSoft */
int64outdset devI64outSoft = {
{ 5, NULL, NULL, init_record, NULL }, write_int64out
};
epicsExportAddress(dset, devI64outSoft);
@@ -25,25 +25,6 @@
#include "int64outRecord.h"
#include "epicsExport.h"
/* Create the dset for devI64outSoftCallback */
static long write_int64out(int64outRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_int64out;
} devI64outSoftCallback = {
5,
NULL,
NULL,
NULL,
NULL,
write_int64out
};
epicsExportAddress(dset, devI64outSoftCallback);
static long write_int64out(int64outRecord *prec)
{
struct link *plink = &prec->out;
@@ -60,3 +41,9 @@ static long write_int64out(int64outRecord *prec)
return status;
}
/* Create the dset for devI64outSoftCallback */
int64outdset devI64outSoftCallback = {
{ 5, NULL, NULL, NULL, NULL }, write_int64out
};
epicsExportAddress(dset, devI64outSoftCallback);
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devLiSoft */
static long init_record(longinRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_longin(longinRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_longin;
} devLiSoft = {
5,
NULL,
NULL,
init_record,
NULL,
longindset devLiSoft = {
{5, NULL, NULL, init_record, NULL},
read_longin
};
epicsExportAddress(dset, devLiSoft);
static long init_record(longinRecord *prec)
static long init_record(dbCommon *pcommon)
{
longinRecord *prec = (longinRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_LONG, &prec->val))
prec->udf = FALSE;
@@ -151,8 +151,10 @@ static long init(int pass)
return 0;
}
static long init_record(longinRecord *prec)
static long init_record(dbCommon *pcommon)
{
longinRecord *prec = (longinRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBR_LONG, &prec->val))
prec->udf = FALSE;
@@ -204,10 +206,7 @@ static long read_li(longinRecord *prec)
}
/* Create the dset for devLiSoftCallback */
struct {
dset common;
DEVSUPFUN read_li;
} devLiSoftCallback = {
longindset devLiSoftCallback = {
{5, NULL, init, init_record, NULL},
read_li
};
+12 -22
View File
@@ -5,12 +5,12 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLoSoft.c */
/*
* Author: Janet Anderson
* Date: 09-23-91
* Author: Janet Anderson
* Date: 09-23-91
*/
#include <stdlib.h>
#include <stdio.h>
@@ -26,31 +26,21 @@
#include "epicsExport.h"
/* Create the dset for devLoSoft */
static long init_record(longoutRecord *prec);
static long init_record(dbCommon *pcommon);
static long write_longout(longoutRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
}devLoSoft={
5,
NULL,
NULL,
init_record,
NULL,
write_longout
longoutdset devLoSoft = {
{5, NULL, NULL, init_record, NULL},
write_longout
};
epicsExportAddress(dset,devLoSoft);
static long init_record(longoutRecord *prec)
epicsExportAddress(dset, devLoSoft);
static long init_record(dbCommon *pcommon)
{
return 0;
} /* end init_record() */
static long write_longout(longoutRecord *prec)
static long write_longout(longoutRecord *prec)
{
dbPutLink(&prec->out,DBR_LONG, &prec->val,1);
return 0;
@@ -29,24 +29,14 @@
/* Create the dset for devLoSoftCallback */
static long write_longout(longoutRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
}devLoSoftCallback={
5,
NULL,
NULL,
NULL,
NULL,
write_longout
};
epicsExportAddress(dset,devLoSoftCallback);
static long write_longout(longoutRecord *prec)
longoutdset devLoSoftCallback = {
{5, NULL, NULL, NULL, NULL},
write_longout
};
epicsExportAddress(dset, devLoSoftCallback);
static long write_longout(longoutRecord *prec)
{
struct link *plink = &prec->out;
long status;
@@ -62,4 +52,3 @@ static long write_longout(longoutRecord *prec)
return status;
}
+3 -2
View File
@@ -17,8 +17,9 @@
#include "lsiRecord.h"
#include "epicsExport.h"
static long init_record(lsiRecord *prec)
static long init_record(dbCommon *common)
{
lsiRecord *prec = (lsiRecord *)common;
dbLoadLinkLS(&prec->inp, prec->val, prec->sizv, &prec->len);
return 0;
@@ -49,6 +50,6 @@ static long read_string(lsiRecord *prec)
}
lsidset devLsiSoft = {
5, NULL, NULL, init_record, NULL, read_string
{ 5, NULL, NULL, init_record, NULL }, read_string
};
epicsExportAddress(dset, devLsiSoft);
+1 -1
View File
@@ -21,6 +21,6 @@ static long write_string(lsoRecord *prec)
}
lsodset devLsoSoft = {
5, NULL, NULL, NULL, NULL, write_string
{ 5, NULL, NULL, NULL, NULL }, write_string
};
epicsExportAddress(dset, devLsoSoft);
@@ -2,7 +2,7 @@
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Andrew Johnson
@@ -40,7 +40,7 @@ static long write_string(lsoRecord *prec)
}
lsodset devLsoSoftCallback = {
5, NULL, NULL, NULL, NULL, write_string
{ 5, NULL, NULL, NULL, NULL }, write_string
};
epicsExportAddress(dset, devLsoSoftCallback);
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devMbbiDirectSoft */
static long init_record(mbbiDirectRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_mbbi(mbbiDirectRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbi;
} devMbbiDirectSoft = {
5,
NULL,
NULL,
init_record,
NULL,
mbbidirectdset devMbbiDirectSoft = {
{5, NULL, NULL, init_record, NULL},
read_mbbi
};
epicsExportAddress(dset, devMbbiDirectSoft);
static long init_record(mbbiDirectRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBR_ULONG, &prec->val))
prec->udf = FALSE;
@@ -151,8 +151,10 @@ static long init(int pass)
return 0;
}
static long init_record(mbbiDirectRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBR_ULONG, &prec->val))
prec->udf = FALSE;
@@ -204,10 +206,7 @@ static long read_mbbiDirect(mbbiDirectRecord *prec)
}
/* Create the dset for devMbbiDirectSoftCallback */
struct {
dset common;
DEVSUPFUN read_mbbiDirect;
} devMbbiDirectSoftCallback = {
mbbidirectdset devMbbiDirectSoftCallback = {
{5, NULL, init, init_record, NULL},
read_mbbiDirect
};
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devMbbiDirectSoftRaw */
static long init_record(mbbiDirectRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_mbbi(mbbiDirectRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbi;
} devMbbiDirectSoftRaw = {
5,
NULL,
NULL,
init_record,
NULL,
mbbidirectdset devMbbiDirectSoftRaw = {
{5, NULL, NULL, init_record, NULL},
read_mbbi
};
epicsExportAddress(dset, devMbbiDirectSoftRaw);
static long init_record(mbbiDirectRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbbiDirectRecord *prec = (mbbiDirectRecord *)pcommon;
recGblInitConstantLink(&prec->inp, DBF_ULONG, &prec->rval);
/* Preserve old functionality */
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devMbbiSoft */
static long init_record(mbbiRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_mbbi(mbbiRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbi;
} devMbbiSoft = {
5,
NULL,
NULL,
init_record,
NULL,
mbbidset devMbbiSoft = {
{5, NULL, NULL, init_record, NULL},
read_mbbi
};
epicsExportAddress(dset, devMbbiSoft);
static long init_record(mbbiRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbbiRecord *prec = (mbbiRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_ENUM, &prec->val))
prec->udf = FALSE;
@@ -100,7 +100,7 @@ static long add_record(dbCommon *pcommon)
pdevPvt = calloc(1, sizeof(*pdevPvt));
if (!pdevPvt) {
long status = S_db_noMemory;
long status = S_db_noMemory;
recGblRecordError(status, (void *)prec,
"devMbbiSoftCallback (add_record) out of memory, calloc() failed");
@@ -151,8 +151,10 @@ static long init(int pass)
return 0;
}
static long init_record(mbbiRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbbiRecord *prec = (mbbiRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBR_ENUM, &prec->val))
prec->udf = FALSE;
@@ -204,11 +206,8 @@ static long read_mbbi(mbbiRecord *prec)
}
/* Create the dset for devMbbiSoftCallback */
struct {
dset common;
DEVSUPFUN read_mbbi;
} devMbbiSoftCallback = {
mbbidset devMbbiSoftCallback = {
{5, NULL, init, init_record, NULL},
read_mbbi
};
epicsExportAddress(dset,devMbbiSoftCallback);
epicsExportAddress(dset, devMbbiSoftCallback);
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,28 +25,19 @@
#include "epicsExport.h"
/* Create the dset for devMbbiSoftRaw */
static long init_record(mbbiRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_mbbi(mbbiRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbi;
} devMbbiSoftRaw = {
5,
NULL,
NULL,
init_record,
NULL,
mbbidset devMbbiSoftRaw = {
{5, NULL, NULL, init_record, NULL},
read_mbbi
};
epicsExportAddress(dset, devMbbiSoftRaw);
static long init_record(mbbiRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbbiRecord *prec = (mbbiRecord *)pcommon;
recGblInitConstantLink(&prec->inp, DBF_ULONG, &prec->rval);
/* Preserve old functionality*/
@@ -19,17 +19,14 @@
#include "mbboDirectRecord.h"
#include "epicsExport.h"
static long write_mbbo(mbboDirectRecord *prec)
static long write_mbbo(mbboDirectRecord *prec)
{
dbPutLink(&prec->out, DBR_ULONG, &prec->val, 1);
return 0;
}
/* Create the dset for devMbboDirectSoft */
struct {
dset common;
DEVSUPFUN write;
} devMbboDirectSoft = {
mbbodirectdset devMbboDirectSoft = {
{5, NULL, NULL, NULL, NULL},
write_mbbo
};
@@ -38,11 +38,8 @@ static long write_mbbo(mbboDirectRecord *prec)
return status;
}
/* Create the dset for devMbboSoft */
struct {
dset common;
DEVSUPFUN write;
} devMbboDirectSoftCallback = {
/* Create the dset for devMbboDirectSoftCallback */
mbbodirectdset devMbboDirectSoftCallback = {
{5, NULL, NULL, NULL, NULL},
write_mbbo
};
@@ -20,8 +20,10 @@
#include "mbboDirectRecord.h"
#include "epicsExport.h"
static long init_record(mbboDirectRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbboDirectRecord *prec = (mbboDirectRecord *)pcommon;
if (prec->nobt == 0)
prec->mask = 0xffffffff;
@@ -30,7 +32,7 @@ static long init_record(mbboDirectRecord *prec)
return 2; /* Don't convert */
}
static long write_mbbo(mbboDirectRecord *prec)
static long write_mbbo(mbboDirectRecord *prec)
{
epicsUInt32 data;
@@ -40,10 +42,7 @@ static long write_mbbo(mbboDirectRecord *prec)
}
/* Create the dset for devMbboDirectSoftRaw */
struct {
dset common;
DEVSUPFUN write;
} devMbboDirectSoftRaw = {
mbbodirectdset devMbboDirectSoftRaw = {
{5, NULL, NULL, init_record, NULL},
write_mbbo
};
+10 -20
View File
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devMbboSoft.c */
/*
@@ -27,30 +27,20 @@
#include "epicsExport.h"
/* Create the dset for devMbboSoft */
static long init_record(mbboRecord *prec);
static long init_record(dbCommon *pcommon);
static long write_mbbo(mbboRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbbo;
}devMbboSoft={
5,
NULL,
NULL,
init_record,
NULL,
write_mbbo
mbbodset devMbboSoft = {
{5, NULL, NULL, init_record, NULL},
write_mbbo
};
epicsExportAddress(dset,devMbboSoft);
static long init_record(mbboRecord *prec)
epicsExportAddress(dset, devMbboSoft);
static long init_record(dbCommon *pcommon)
{
/*dont convert*/
return 2;
} /* end init_record() */
static long write_mbbo(mbboRecord *prec)
@@ -28,22 +28,12 @@
/* Create the dset for devMbboSoftCallback */
static long write_mbbo(mbboRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbbo;
}devMbboSoftCallback={
5,
NULL,
NULL,
NULL,
NULL,
write_mbbo
mbbodset devMbboSoftCallback = {
{5, NULL, NULL, NULL, NULL},
write_mbbo
};
epicsExportAddress(dset,devMbboSoftCallback);
epicsExportAddress(dset, devMbboSoftCallback);
static long write_mbbo(mbboRecord *prec)
{
@@ -20,8 +20,10 @@
#include "mbboRecord.h"
#include "epicsExport.h"
static long init_record(mbboRecord *prec)
static long init_record(dbCommon *pcommon)
{
mbboRecord *prec = (mbboRecord *)pcommon;
if (prec->nobt == 0)
prec->mask = 0xffffffff;
@@ -40,10 +42,7 @@ static long write_mbbo(mbboRecord *prec)
}
/* Create the dset for devMbboSoftRaw */
struct {
dset common;
DEVSUPFUN write;
} devMbboSoftRaw = {
mbbodset devMbboSoftRaw = {
{5, NULL, NULL, init_record, NULL},
write_mbbo
};
+2 -2
View File
@@ -2,7 +2,7 @@
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Andrew Johnson
@@ -19,7 +19,7 @@ static long write_string(printfRecord *prec)
}
printfdset devPrintfSoft = {
5, NULL, NULL, NULL, NULL, write_string
{ 5, NULL, NULL, NULL, NULL }, write_string
};
epicsExportAddress(dset, devPrintfSoft);
@@ -2,7 +2,7 @@
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Andrew Johnson
@@ -40,6 +40,6 @@ static long write_string(printfRecord *prec)
}
printfdset devPrintfSoftCallback = {
5, NULL, NULL, NULL, NULL, write_string
{ 5, NULL, NULL, NULL, NULL }, write_string
};
epicsExportAddress(dset, devPrintfSoftCallback);
+5 -15
View File
@@ -26,22 +26,11 @@
#include "epicsExport.h"
/* Create the dset for devSASoft */
static long init_record(subArrayRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_sa(subArrayRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_sa;
} devSASoft = {
5,
NULL,
NULL,
init_record,
NULL,
sadset devSASoft = {
{5, NULL, NULL, init_record, NULL},
read_sa
};
epicsExportAddress(dset, devSASoft);
@@ -65,8 +54,9 @@ static void subset(subArrayRecord *prec, long nRequest)
prec->udf = FALSE;
}
static long init_record(subArrayRecord *prec)
static long init_record(dbCommon *pcommon)
{
subArrayRecord *prec = (subArrayRecord *)pcommon;
long nRequest = prec->indx + prec->nelm;
long status;
+7 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -27,28 +27,19 @@
#include "epicsExport.h"
/* Create the dset for devSiSoft */
static long init_record(stringinRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_stringin(stringinRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_stringin;
} devSiSoft = {
5,
NULL,
NULL,
init_record,
NULL,
stringindset devSiSoft = {
{5, NULL, NULL, init_record, NULL},
read_stringin
};
epicsExportAddress(dset, devSiSoft);
static long init_record(stringinRecord *prec)
static long init_record(dbCommon *pcommon)
{
stringinRecord *prec = (stringinRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBF_STRING, prec->val))
prec->udf = FALSE;
@@ -153,8 +153,10 @@ static long init(int pass)
return 0;
}
static long init_record(stringinRecord *prec)
static long init_record(dbCommon *pcommon)
{
stringinRecord *prec = (stringinRecord *)pcommon;
if (recGblInitConstantLink(&prec->inp, DBR_STRING, &prec->val))
prec->udf = FALSE;
@@ -207,11 +209,8 @@ static long read_si(stringinRecord *prec)
}
/* Create the dset for devSiSoftCallback */
struct {
dset common;
DEVSUPFUN read_li;
} devSiSoftCallback = {
stringindset devSiSoftCallback = {
{5, NULL, init, init_record, NULL},
read_si
};
epicsExportAddress(dset,devSiSoftCallback);
epicsExportAddress(dset, devSiSoftCallback);
+4 -14
View File
@@ -5,7 +5,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Janet Anderson
@@ -27,19 +27,9 @@
/* Create the dset for devSoSoft */
static long write_stringout(stringoutRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_stringout;
} devSoSoft = {
5,
NULL,
NULL,
NULL,
NULL,
stringoutdset devSoSoft = {
{5, NULL, NULL, NULL, NULL},
write_stringout
};
epicsExportAddress(dset, devSoSoft);
@@ -27,19 +27,9 @@
/* Create the dset for devSoSoftCallback */
static long write_stringout(stringoutRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_stringout;
} devSoSoftCallback = {
5,
NULL,
NULL,
NULL,
NULL,
stringoutdset devSoSoftCallback = {
{5, NULL, NULL, NULL, NULL},
write_stringout
};
epicsExportAddress(dset, devSoSoftCallback);
@@ -60,4 +50,3 @@ static long write_stringout(stringoutRecord *prec)
return status;
}
+6 -8
View File
@@ -2,7 +2,7 @@
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
@@ -103,7 +103,7 @@ static long write_lso(lsoRecord *prec)
}
lsodset devLsoStdio = {
5, NULL, init_lso, NULL, NULL, write_lso
{ 5, NULL, init_lso, NULL, NULL }, write_lso
};
epicsExportAddress(dset, devLsoStdio);
@@ -153,7 +153,7 @@ static long write_printf(printfRecord *prec)
}
printfdset devPrintfStdio = {
5, NULL, init_printf, NULL, NULL, write_printf
{5, NULL, init_printf, NULL, NULL }, write_printf
};
epicsExportAddress(dset, devPrintfStdio);
@@ -202,10 +202,8 @@ static long write_stringout(stringoutRecord *prec)
return 0;
}
static struct {
dset common;
DEVSUPFUN write;
} devSoStdio = {
{5, NULL, init_stringout, NULL, NULL}, write_stringout
stringoutdset devSoStdio = {
{5, NULL, init_stringout, NULL, NULL},
write_stringout
};
epicsExportAddress(dset, devSoStdio);
+7 -12
View File
@@ -8,7 +8,7 @@
/*
* Device support for EPICS time stamps
*
* Original Author: Eric Norum
* Original Author: Eric Norum
*/
#include "dbDefs.h"
@@ -40,12 +40,9 @@ static long read_ai(aiRecord *prec)
return 2;
}
struct {
dset common;
DEVSUPFUN read_write;
DEVSUPFUN special_linconv;
} devTimestampAI = {
{6, NULL, initAllow, NULL, NULL}, read_ai, NULL
aidset devTimestampAI = {
{6, NULL, initAllow, NULL, NULL},
read_ai, NULL
};
epicsExportAddress(dset, devTimestampAI);
@@ -68,10 +65,8 @@ static long read_stringin (stringinRecord *prec)
return 0;
}
struct {
dset common;
DEVSUPFUN read_stringin;
} devTimestampSI = {
{5, NULL, initAllow, NULL, NULL}, read_stringin
stringindset devTimestampSI = {
{5, NULL, initAllow, NULL, NULL},
read_stringin
};
epicsExportAddress(dset, devTimestampSI);
+5 -15
View File
@@ -26,28 +26,18 @@
#include "epicsExport.h"
/* Create the dset for devWfSoft */
static long init_record(waveformRecord *prec);
static long init_record(dbCommon *pcommon);
static long read_wf(waveformRecord *prec);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_wf;
} devWfSoft = {
5,
NULL,
NULL,
init_record,
NULL,
wfdset devWfSoft = {
{5, NULL, NULL, init_record, NULL},
read_wf
};
epicsExportAddress(dset, devWfSoft);
static long init_record(waveformRecord *prec)
static long init_record(dbCommon *pcommon)
{
waveformRecord *prec = (waveformRecord *)pcommon;
long nelm = prec->nelm;
long status = dbLoadLinkArray(&prec->inp, prec->ftvl, prec->bptr, &nelm);
+7 -7
View File
@@ -99,7 +99,7 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl)
long end = my->end;
long nTarget = 0;
long offset = 0;
long nSource = chan->addr.no_elements;
long nSource = dbChannelElements(chan);
long capacity = nSource;
void *pdst;
@@ -110,12 +110,12 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl)
case dbfl_type_rec:
/* Extract from record */
if (chan->addr.special == SPC_DBADDR &&
if (dbChannelSpecial(chan) == SPC_DBADDR &&
nSource > 1 &&
(prset = dbGetRset(&chan->addr)) &&
prset->get_array_info)
{
void *pfieldsave = chan->addr.pfield;
void *pfieldsave = dbChannelField(chan);
prec = dbChannelRecord(chan);
dbScanLock(prec);
prset->get_array_info(&chan->addr, &nSource, &offset);
@@ -124,22 +124,22 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl)
pfl->stat = prec->stat;
pfl->sevr = prec->sevr;
pfl->time = prec->time;
pfl->field_type = chan->addr.field_type;
pfl->field_size = chan->addr.field_size;
pfl->field_type = dbChannelFieldType(chan);
pfl->field_size = dbChannelFieldSize(chan);
pfl->no_elements = nTarget;
if (nTarget) {
pdst = freeListCalloc(my->arrayFreeList);
if (pdst) {
pfl->u.r.dtor = freeArray;
pfl->u.r.pvt = my->arrayFreeList;
offset = (offset + start) % chan->addr.no_elements;
offset = (offset + start) % dbChannelElements(chan);
dbExtractArrayFromRec(&chan->addr, pdst, nTarget, capacity,
offset, my->incr);
pfl->u.r.field = pdst;
}
}
dbScanUnlock(prec);
chan->addr.pfield = pfieldsave;
dbChannelField(chan) = pfieldsave;
}
break;
+2 -2
View File
@@ -152,7 +152,7 @@ result should be displayed. Equivalent to the C<PREC> field of a record.
=item time
An optional string containing a single upper or lower-case letter C<A> ... C<L>
which must correspond to an input provided in the c<args> parameter. When the
which must correspond to an input provided in the C<args> parameter. When the
record containing such a link has C<TSEL> set to -2 (epicsTimeEventDeviceTime)
the record's timestamp field C<TIME> will be read from the indicated input link
atomically with the value of the input argument.
@@ -161,7 +161,7 @@ atomically with the value of the input argument.
=head4 Example
{calc: {expr:"A*B", args:[{db:"record.VAL"}, 1.5], prec:3}}
{calc: {expr:"A*B", args:[{pva:"record"}, 1.5], prec:3}}
=cut
+3 -2
View File
@@ -127,8 +127,8 @@ static jlif_result lnkCalc_integer(jlink *pjlink, long long num)
}
if (clink->pstate != ps_args) {
return jlif_stop;
errlogPrintf("lnkCalc: Unexpected integer %lld\n", num);
return jlif_stop;
}
if (clink->nArgs == CALCPERFORM_NARGS) {
@@ -147,8 +147,8 @@ static jlif_result lnkCalc_double(jlink *pjlink, double num)
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
if (clink->pstate != ps_args) {
return jlif_stop;
errlogPrintf("lnkCalc: Unexpected double %g\n", num);
return jlif_stop;
}
if (clink->nArgs == CALCPERFORM_NARGS) {
@@ -198,6 +198,7 @@ static jlif_result lnkCalc_string(jlink *pjlink, const char *val, size_t len)
inbuf = malloc(len+1);
if(!inbuf) {
errlogPrintf("lnkCalc: Out of memory\n");
free(postbuf);
return jlif_stop;
}
memcpy(inbuf, val, len);
+1 -1
View File
@@ -348,7 +348,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
aSubRecord *prec = (aSubRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
int linkNumber;
linkNumber = get_inlinkNumber(fieldIndex);
if (linkNumber >= 0) {
dbGetGraphicLimits(&prec->inpa + linkNumber,
+516 -23
View File
@@ -4,37 +4,53 @@
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Array Subroutine Record (aSub)
...
The aSub record is an advanced variant of the 'sub' (subroutine) record which
has a number of additional features:
=over
=item *
It provides 20 different input and output fields which can hold array or
scalar values.
The types and array capacities of these are user configurable, and they all
have an associated input or output link.
=item *
The name of the C or C++ subroutine to be called when the record processes
can be changed dynamically while the IOC is running.
The name can either be fetched from another record using an input link, or
written directly into the SNAM field.
=item *
The user can choose whether monitor events should be posted for the output
fields.
=item *
The VAL field is set to the return value from the user subroutine, which is
treated as a status value and controls whether the output links will be used
or not. The record can also raise an alarm with a chosen severity if the status
value is non-zero.
=back
=head2 Record-specific Menus
=head3 Menu aSubLFLG
The LFLG field uses this menu to ...
The LFLG menu field controls whether the SUBL link will be read to update
the name of the subroutine to be called when the record processes.
=menu aSubLFLG
=head3 Menu aSubEFLG
The EFLG field uses this menu to ...
=menu aSubEFLG
...
=head2 Parameter Fields
The record-specific fields are described below.
=recordtype aSub
...
=cut
menu(aSubLFLG) {
@@ -42,14 +58,69 @@ menu(aSubLFLG) {
choice(aSubLFLG_READ,"READ")
}
=head3 Menu aSubEFLG
The EFLG menu field indicates whether monitor events should be posted for the
VALA..VALU output value fields.
=menu aSubEFLG
=cut
menu(aSubEFLG) {
choice(aSubEFLG_NEVER,"NEVER")
choice(aSubEFLG_ON_CHANGE,"ON CHANGE")
choice(aSubEFLG_ALWAYS,"ALWAYS")
}
=head2 Parameter Fields
The record-specific fields are described below.
=recordtype aSub
=cut
recordtype(aSub) {
include "dbCommon.dbd"
=head3 Subroutine Fields
The VAL field is set to the value returned by the user subroutine.
The value is treated as an error status value where zero mean success.
The output links OUTA ... OUTU will only be used to forward the associated
output value fields when the subroutine has returned a zero status.
If the return status was non-zero, the record will be put into C<SOFT_ALARM>
state with severity given by the BRSV field.
The INAM field may be used to name a subroutine that will be called once at
IOC initialization time.
LFLG tells the record whether to read or ignore the SUBL link.
If the value is C<READ>, then the name of the subroutine to be called at
process time is read from SUBL.
If the value is C<IGNORE>, the name of the subroutine is that currently held
in SNAM.
A string is read from the SUBL link to fetch the name of the subroutine to
be run during record processing.
SNAM holds the name of the subroutine to be called when the record processes.
The value in this field can be overwritten by the SUBL link if LFLG is set
to C<READ>.
The SADR field is only accessible from C code; it points to the subroutine
to be called.
The CADR field may be set by the user subroutine to point to another function
that will be called immediately before setting the SADR field to some other
routine. This allows the main user subroutine to allocate resources when it is
first called and be able to release them again when they are no longer needed.
=fields VAL, OVAL, INAM, LFLG, SUBL, SNAM, ONAM, SADR, CADR, BRSV
=cut
field(VAL,DBF_LONG) {
prompt("Subr. return value")
asl(ASL0)
@@ -112,12 +183,34 @@ recordtype(aSub) {
interest(1)
menu(menuAlarmSevr)
}
=head3 Operator Display Parameters
The PREC field specifies the number of decimal places with which to display
the values of the value fields A ... U and VALA ... VALU.
Except when it doesn't.
=cut
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
=head3 Output Event Flag
This field tells the record when to post change events on the output fields
VALA ... VALU. If the value is C<NEVER>, events are never posted. If the value
is C<ALWAYS>, events are posted every time the record processes. If the value
is C<ON CHANGE>, events are posted when any element of an array changes value.
This flag controls value, log (archive) and alarm change events.
=fields EFLG
=cut
field(EFLG,DBF_MENU) {
prompt("Output Event Flag")
promptgroup("50 - Output")
@@ -125,6 +218,16 @@ recordtype(aSub) {
menu(aSubEFLG)
initial("1")
}
=head3 Input Link Fields
The input links from where the values of A,...,U are fetched
during record processing.
=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL, INPM, INPN, INPO, INPP, INPQ, INPR, INPS, INPT, INPU
=cut
field(INPA,DBF_INLINK) {
prompt("Input Link A")
promptgroup("41 - Input A-G")
@@ -231,9 +334,10 @@ recordtype(aSub) {
interest(1)
}
=head3 Input Fields
=head3 Input Value Fields
...
Thse fields hold the scalar or array values fetched through the input links
INPA,...,INPU.
=fields A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U
@@ -449,6 +553,16 @@ recordtype(aSub) {
#=write Yes
#=type Set by FTU
}
=head3 Input Value Data Types
Field types of the input value fields.
The choices can be found by following the link to the menuFtype definition.
=fields FTA, FTB, FTC, FTD, FTE, FTF, FTG, FTH, FTI, FTJ, FTK, FTL, FTM, FTN, FTO, FTP, FTQ, FTR, FTS, FTT, FTU
=cut
field(FTA,DBF_MENU) {
prompt("Type of A")
promptgroup("41 - Input A-G")
@@ -617,6 +731,15 @@ recordtype(aSub) {
initial("DOUBLE")
menu(menuFtype)
}
=head3 Input Value Array Capacity
These fields specify how many array elements the input value fields may hold.
=fields NOA, NOB, NOC, NOD, NOE, NOF, NOG, NOH, NOI, NOJ, NOK, NOL, NOM, NON, NOO, NOP, NOQ, NOR, NOS, NOT, NOU
=cut
field(NOA,DBF_ULONG) {
prompt("Max. elements in A")
promptgroup("41 - Input A-G")
@@ -764,6 +887,16 @@ recordtype(aSub) {
interest(1)
initial("1")
}
=head3 Input Value Array Size
These fields specify how many array elements the input value fields currently
contain.
=fields NEA, NEB, NEC, NED, NEE, NEF, NEG, NEH, NEI, NEJ, NEK, NEL, NEM, NEN, NEO, NEP, NEQ, NER, NES, NET, NEU
=cut
field(NEA,DBF_ULONG) {
prompt("Num. elements in A")
special(SPC_NOMOD)
@@ -890,6 +1023,15 @@ recordtype(aSub) {
interest(3)
initial("1")
}
=head3 Output Link Fields
The output links through which the VALA ... VALU field values are sent
during record processing, provided the subroutine returned 0.
=fields OUTA, OUTB, OUTC, OUTD, OUTE, OUTF, OUTG, OUTH, OUTI, OUTJ, OUTK, OUTL, OUTM, OUTN, OUTO, OUTP, OUTQ, OUTR, OUTS, OUTT, OUTU
=cut
field(OUTA,DBF_OUTLINK) {
prompt("Output Link A")
promptgroup("51 - Output A-G")
@@ -996,9 +1138,10 @@ recordtype(aSub) {
interest(1)
}
=head3 Value Fields
=head3 Output Value Fields
...
These fields hold scalar or array data generated by the subroutine which will
be sent through the OUTA ... OUTU links during record processing.
=fields VALA, VALB, VALC, VALD, VALE, VALF, VALG, VALH, VALI, VALJ, VALK, VALL, VALM, VALN, VALO, VALP, VALQ, VALR, VALS, VALT, VALU
@@ -1214,6 +1357,16 @@ recordtype(aSub) {
#=write Yes
#=type Set by FTVU
}
=head3 Old Value Fields
The previous values of the output fields.
These are used to determine when to post events if EFLG is set to C<ON CHANGE>.
=fields VALA, VALB, VALC, VALD, VALE, VALF, VALG, VALH, VALI, VALJ, VALK, VALL, VALM, VALN, VALO, VALP, VALQ, VALR, VALS, VALT, VALU
=cut
field(OVLA,DBF_NOACCESS) {
prompt("Old Output A")
asl(ASL0)
@@ -1361,6 +1514,16 @@ recordtype(aSub) {
interest(4)
extra("void *ovlu")
}
=head3 Output Value Data Types
Field types of the output value fields.
The choices can be found by following a link to the menuFtype definition.
=fields FTVA, FTVB, FTVC, FTVD, FTVE, FTVF, FTVG, FTVH, FTVI, FTVJ, FTVK, FTVL, FTVM, FTVN, FTVO, FTVP, FTVQ, FTVR, FTVS, FTVT, FTVU
=cut
field(FTVA,DBF_MENU) {
prompt("Type of VALA")
promptgroup("51 - Output A-G")
@@ -1529,6 +1692,15 @@ recordtype(aSub) {
initial("DOUBLE")
menu(menuFtype)
}
=head3 Output Value Array Capacity
These fields specify how many array elements the output value fields may hold.
=fields NOVA, NOVB, NOVC, NOVD, NOVE, NOVF, NOVG, NOVH, NOVI, NOVJ, NOVK, NOVL, NOVM, NOVN, NOVO, NOVP, NOVQ, NOVR, NOVS, NOVT, NOVU
=cut
field(NOVA,DBF_ULONG) {
prompt("Max. elements in VALA")
promptgroup("51 - Output A-G")
@@ -1676,6 +1848,16 @@ recordtype(aSub) {
interest(1)
initial("1")
}
=head3 Output Value Array Size
These fields specify how many array elements the output value fields currently
contain.
=fields NEVA, NEVB, NEVC, NEVD, NEVE, NEVF, NEVG, NEVH, NEVI, NEVJ, NEVK, NEVL, NEVM, NEVN, NEVO, NEVP, NEVQ, NEVR, NEVS, NEVT, NEVU
=cut
field(NEVA,DBF_ULONG) {
prompt("Num. elements in VALA")
special(SPC_NOMOD)
@@ -1802,6 +1984,16 @@ recordtype(aSub) {
interest(3)
initial("1")
}
=head3 Old Value Array Size
These fields specify how many array elements the old value fields currently
contain.
=fields ONVA, ONVB, ONVC, ONVD, ONVE, ONVF, ONVG, ONVH, ONVI, ONVJ, ONVK, ONVL, ONVM, ONVN, ONVO, ONVP, ONVQ, ONVR, ONVS, ONVT, ONVU
=cut
field(ONVA,DBF_ULONG) {
prompt("Num. elements in OVLA")
special(SPC_NOMOD)
@@ -1928,4 +2120,305 @@ recordtype(aSub) {
interest(4)
initial("1")
}
=begin html
<br>
<hr>
<br>
=end html
=head2 Record Support Routines
=head3 init_record
long (*init_record)(struct dbCommon *precord, int pass)
This routine is called twice at iocInit. On the first call it does the
following:
=over
=item *
Calloc sufficient space to hold the number of input scalars and/or arrays
defined by the settings of the fields FTA-FTU and NOA-NOU. Initialize fields
NE* to the values of the associated NO* field values.
=item *
Calloc sufficient space to hold the number of output scalars and/or arrays
defined by the settings of the fields FTVA-FTVU and NOVA-NOVU. For the output
fields, also calloc space to hold the previous value of a field. This is
required when the decision is made on whether or not to post events.
=back
On the second call, it does the following:
=over
=item *
Initializes SUBL if it is a constant link.
=item *
Initializes each constant input link.
=item *
If the field INAM is set, look-up the address of the routine and call it.
=item *
If the field LFLG is set to IGNORE and SNAM is defined, look up the address of
the process routine.
=back
=head3 process
long (*process)(struct dbCommon *precord)
This routine implements the following algorithm:
=over
=item *
If PACT is FALSE, perform normal processing
=item *
If PACT is TRUE, perform asynchronous-completion processing
=back
Normal processing:
=over
=item *
Set PACT to TRUE.
=item *
If the field LFLG is set to READ, get the subroutine name from the SUBL link.
If the name is not NULL and it is not the same as the previous subroutine name,
look up the subroutine address. Set the old subroutine name, ONAM, equal to the
current name, SNAM.
=item *
Fetch the values from the input links.
=item *
Set PACT to FALSE
=item *
If all input-link fetches succeeded, call the routine specified by SNAM.
=item *
Set VAL equal to the return value from the routine specified by SNAM.
=item *
If the SNAM routine set PACT to TRUE, then return. In this case, we presume
the routine has arranged that process will be called at some later time for
asynchronous completion.
=item *
Set PACT to TRUE.
=item *
If VAL is zero, write the output values using the output links.
=item *
Get the time of processing and put it into the timestamp field.
=item *
If VAL has changed, post a change-of value and log event for this field.
If EFLG is set to ALWAYS, post change-of-value and log events for every output
field. If EFLG is set to ON CHANGE, post change-of-value and log events for
every output field which has changed. In the case of an array, an event will be
posted if any single element of the array has changed. If EFLG is set to NEVER,
no change-of-value or log events are posted for the output fields.
=item *
Process the record on the end of the forward link, if one exists.
=item *
Set PACT to FALSE.
=back
Asynchronous-completion processing:
=over
=item *
Call the routine specified by SNAM (again).
=item *
Set VAL equal to the return value from the routine specified by SNAM.
=item *
Set PACT to TRUE.
=item *
If VAL is zero, write the output values using the output links.
=item *
Get the time of processing and put it into the timestamp field.
=item *
If VAL has changed, post a change-of value and log event for this field. If
EFLG is set to ALWAYS, post change-of-value and log events for every output
field. If EFLG is set to ON CHANGE, post change-of-value and log events for
every output field which has changed. In the case of an array, an event will
be posted if any single element of the array has changed. If EFLG is set to
NEVER, no change-of-value or log events are posted for the output fields.
=item *
Process the record on the end of the forward link, if one exists.
=item *
Set PACT to FALSE.
=back
=begin html
<br>
<hr>
<br>
=end html
=head2 Use of the aSub Record
The aSub record has input-value fields (A-U) and output-value fields
(VALA-VALU), which are completely independent. The input-value fields have
associated input links (INPA-INPU), and the output-value fields have associated
output links (OUTA-OUTU). Both inputs and outputs have type fields (FTA-FTU,
FTVA-FTVU, which default to 'DOUBLE') and number-of-element fields (NOA-NOU,
NOVA-NOVU, which default to '1'). The output links OUTA-OUTU will only be
processed if the subroutine returns a zero (OK) status value.
=head3 Example database fragment
To use the A field to read an array from some other record, then, you would
need a database fragment that might look something like this:
record(aSub,"my_asub_record") {
field(SNAM,"my_asub_routine")
...
field(FTA, "LONG")
field(NOA, "100")
field(INPA, "myWaveform_1 NPP NMS")
...
}
If you wanted some other record to be able to write to the A field, then you
would delete the input link above. If you wanted the A field to hold a scalar
value, you would either delete the NOA specification, or specify it as "1".
=head3 Example subroutine fragment
The associated subroutine code that uses the A field might look like this:
static long my_asub_routine(aSubRecord *prec) {
long i, *a;
double sum=0;
...
a = (long *)prec->a;
for (i=0; i<prec->noa; i++) {
sum += a[i];
}
...
return 0; /* process output links */
}
Note that the subroutine code must always handle the value fields (A-U,
VALA-VALU) as arrays, even if they contain only a single element.
=head3 Required export code
Aside from your own code, you must export and register your subroutines so the
record can locate them. The simplest way is as follows:
#include <registryFunction.h>
#include <epicsExport.h>
static long my_asub_routine(aSubRecord *prec) {
...
}
epicsRegisterFunction(my_asub_routine);
=head3 Required database-definition code
The .dbd file loaded by the ioc must then contain the following line, which
tells the linker to include your object file in the IOC binary:
function(my_asub_routine)
=head3 Device support, writing to hardware
The aSub record does not call any device support routines. If you want to write
to hardware, you might use your output fields and links to write to some other
record that can write to hardware.
=head3 Dynamically Changing the User Routine called during Record Processing
The aSub record allows the user to dynamically change which routine is called
when the record processes. This can be done in two ways:
=over
=item *
The LFLG field can be set to READ so that the name of the routine is read from
the SUBL link. Thus, whatever is feeding this link can change the name of the
routine before the aSub record is processed. In this case, the record looks in
the symbol table for the symbol name whenever the name of routine fetched from
the link changes.
=item *
The LFLG field can be set to IGNORE. In this case, the routine called during
record processing is that specified in the SNAM field. Under these conditions,
the SNAM field can be changed by a Channel Access write to that field. During
development when trying several versions of the routine, it is not necessary
to reboot the IOC and reload the database. A new routine can be loaded with
the vxWorks ld command, and Channel Access or the dbpf command used to put the
name of the routine into the record's SNAM field. The record will look up the
symbol name in the symbol table whenever the SNAM field gets modified. The
same routine name can even be used as the vxWorks symbol lookup returns the
latest version of the code to have been loaded.
=back
=cut
}
+6 -15
View File
@@ -90,22 +90,13 @@ rset aaiRSET={
};
epicsExportAddress(rset,aaiRSET);
struct aaidset { /* aai dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/
};
static void monitor(aaiRecord *);
static long readValue(aaiRecord *);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct aaiRecord *prec = (struct aaiRecord *)pcommon;
struct aaidset *pdset = (struct aaidset *)(prec->dset);
aaidset *pdset = (aaidset *)(prec->dset);
/* must have dset defined */
if (!pdset) {
@@ -125,8 +116,8 @@ static long init_record(struct dbCommon *pcommon, int pass)
not change after links are established before pass 1
*/
if (pdset->init_record) {
long status = pdset->init_record(prec);
if (pdset->common.init_record) {
long status = pdset->common.init_record(pcommon);
/* init_record may set the bptr to point to the data */
if (status)
@@ -143,7 +134,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
/* must have read_aai function defined */
if (pdset->number < 5 || pdset->read_aai == NULL) {
if (pdset->common.number < 5 || pdset->read_aai == NULL) {
recGblRecordError(S_dev_missingSup, prec, "aai: init_record");
return S_dev_missingSup;
}
@@ -153,7 +144,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct aaiRecord *prec = (struct aaiRecord *)pcommon;
struct aaidset *pdset = (struct aaidset *)(prec->dset);
aaidset *pdset = (aaidset *)(prec->dset);
long status;
unsigned char pact = prec->pact;
@@ -339,7 +330,7 @@ static void monitor(aaiRecord *prec)
static long readValue(aaiRecord *prec)
{
struct aaidset *pdset = (struct aaidset *) prec->dset;
aaidset *pdset = (aaidset *) prec->dset;
long status;
/* NB: Device support must post updates to NORD */
-143
View File
@@ -1,143 +0,0 @@
#*************************************************************************
# 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 is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(aaiPOST) {
choice(aaiPOST_Always,"Always")
choice(aaiPOST_OnChange,"On Change")
}
recordtype(aai) {
include "dbCommon.dbd"
field(VAL,DBF_NOACCESS) {
prompt("Value")
asl(ASL0)
special(SPC_DBADDR)
pp(TRUE)
extra("void * val")
#=type DOUBLE[]
#=read Yes
#=write Yes
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup("40 - Input")
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(NELM,DBF_ULONG) {
prompt("Number of Elements")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(FTVL,DBF_MENU) {
prompt("Field Type of Value")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
menu(menuFtype)
}
field(NORD,DBF_ULONG) {
prompt("Number elements read")
special(SPC_NOMOD)
}
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
interest(4)
extra("void * bptr")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
interest(1)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
}
field(MPST,DBF_MENU) {
prompt("Post Value Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaiPOST)
}
field(APST,DBF_MENU) {
prompt("Post Archive Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaiPOST)
}
field(HASH,DBF_ULONG) {
prompt("Hash of OnChange data.")
interest(3)
}
}
@@ -0,0 +1,516 @@
#*************************************************************************
# 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 is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Array Analog Input (aai)
The array analog input record type is used to read array data. The array data can
contain any of the supported data types. The record is in many ways similar to the
waveform record. It allows, however, the device support to allocate the array
storage.
=recordtype aai
=cut
menu(aaiPOST) {
choice(aaiPOST_Always,"Always")
choice(aaiPOST_OnChange,"On Change")
}
recordtype(aai) {
=head2 Parameter Fields
The record-specific fields are described below, grouped by functionality.
=head3 Scan Parameters
The array analog input record has the standard fields for specifying under what
circumstances the record will be processed.
These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Read Parameters
These fields are configurable by the user to specify how and from where the record
reads its data. The INP field determines from where the array analog input gets
its input. It can be a hardware address, a channel access or database link, or a
constant. Only in records that use soft device support can the INP field be a
channel access link, a database link, or a constant. Otherwise, the INP field must
be a hardware address.
=head4 Fields related to waveform reading
The DTYP field must contain the name of the appropriate device support module.
The values retrieved from the input link are placed in an array referenced by
VAL. (If the INP link is a constant, elements can be placed in the array via
dbPuts.) NELM specifies the number of elements that the array will hold, while
FTVL specifies the data type of the elements (follow the link in the table below
for a list of the available choices).
=fields DTYP, INP, NELM, FTVL
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. They
display the value and other parameters of the waveform either textually or
graphically.
=head4 Fields related to I<Operator Display>
EGU is a string of up to 16 characters describing the units that the array data
measures. It is retrieved by the C<<< get_units() >>> record support routine.
The HOPR and LOPR fields set the upper and lower display limits for array
elements referenced by the VAL field. Both the C<<< get_graphic_double() >>> and
C<<< get_control_double() >>> record support routines retrieve these fields.
The PREC field determines the floating point precision with which to display the
array values. It is used whenever the C<<< get_precision() >>> record support
routine is called.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, HOPR, LOPR, PREC, NAME, DESC
=head3 Alarm Parameters
The array analog input record has the alarm parameters common to all record types.
=head3 Monitor Parameters
These parameters are used to determine when to send monitors placed on the VAL
field. The APST and MPST fields are a menu with choices C<Always> and C<On
Change>. The default is C<Always>, thus monitors will normally be sent every time
the record processes. Selecting C<On Change> causes a 32-bit hash of the VAL
field buffer to be calculated and compared with the previous hash value every
time the record processes; the monitor will only be sent if the hash is
different, indicating that the buffer has changed. Note that there is a small
chance that two different value buffers might result in the same hash value, so
for critical systems C<Always> may be a better choice, even though it re-sends
duplicate data.
=fields APST, MPST, HASH
=head4 Menu aaiPOST
These are the possible choices for the C<APST> and C<MPST> fields:
=menu aaiPOST
=head3 Run-time Parameters
These parameters are used by the run-time code for processing the array analog
input record. They are not configured using a configuration tool. Only the VAL
field is modifiable at run-time.
VAL references the array where the array analog input record stores its data. The
BPTR field holds the address of the array.
The NORD field holds a counter of the number of elements that have been read
into the array.
=fields VAL, BPTR, NORD
=head3 Simulation Mode Parameters
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is fetched through SIOL.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Input Simulation Fields|dbCommonInput/Input Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SIMS, SDLY, SSCN
=begin html
<br>
<hr>
<br>
=end html
=head2 Record Support
=head3 Record Support Routines
=head4 init_record
static long init_record(aaiRecord *prec, int pass)
If device support includes C<init_record()>, it is called.
Checks if device support allocated array space. If not, space for the array is
allocated using NELM and FTVL. The array address is stored in the record.
This routine initializes SIMM with the value of SIML if SIML type is CONSTANT
link or creates a channel access link if SIML type is PV_LINK. VAL is likewise
initialized if SIOL is CONSTANT or PV_LINK.
This routine next checks to see that device support is available and a device
support read routine is defined. If either does not exist, an error message is
issued and processing is terminated
=head4 process
static long process(aaiRecord *prec)
See L</"Record Processing"> section below.
=head4 cvt_dbaddr
static long cvt_dbaddr(DBADDR *paddr)
This is called by dbNameToAddr. It makes the dbAddr structure refer to the
actual buffer holding the result.
=head4 get_array_info
static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
Obtains values from the array referenced by VAL.
=head4 put_array_info
static long put_array_info(DBADDR *paddr, long nNew)
Writes values into the array referenced by VAL.
=head4 get_units
static long get_units(DBADDR *paddr, char *units)
Retrieves EGU.
=head4 get_prec
static long get_precision(DBADDR *paddr, long *precision)
Retrieves PREC if field is VAL field. Otherwise, calls C<<< recGblGetPrec() >>>.
=head4 get_graphic_double
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
Sets the upper display and lower display limits for a field. If the field is VAL
the limits are set to HOPR and LOPR, else if the field has upper and lower
limits defined they will be used, else the upper and lower maximum values for
the field type will be used.
Sets the following values:
upper_disp_limit = HOPR
lower_disp_limit = LOPR
=head4 get_control_double
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
Sets the upper control and the lower control limits for a field. If the field is
VAL the limits are set to HOPR and LOPR, else if the field has upper and lower
limits defined they will be used, else the upper and lower maximum values for
the field type will be used.
Sets the following values
upper_ctrl_limit = HOPR
lower_ctrl_limit = LOPR
=head3 Record Processing
Routine process implements the following algorithm:
=over
=item 1.
Check to see that the appropriate device support module exists. If it doesn't,
an error message is issued and processing is terminated with the PACT field
still set to TRUE. This ensures that processes will no longer be called for this
record. Thus error storms will not occur.
=item 2.
Call device support read routine C<read_aai()>.
=item 3.
If PACT has been changed to TRUE, the device support read routine has started
but has not completed writing the new value. In this case, the processing
routine merely returns, leaving PACT TRUE.
=item 4.
Check to see if monitors should be invoked.
=over
=item *
Alarm monitors are invoked if the alarm status or severity has changed.
=item *
Archive and value change monitors are invoked if APST or MPST are Always or if
the result of the hash calculation is different.
=item *
NSEV and NSTA are reset to 0.
=back
=item 5.
Scan forward link if necessary, set PACT FALSE, and return.
=back
=begin html
<br>
<hr>
<br>
=end html
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct aaiRecord;
%typedef struct aaidset {
% dset common; /*init_record returns: (-1,0)=>(failure,success)*/
% long (*read_aai)(struct aaiRecord *prec); /*returns: (-1,0)=>(failure,success)*/
%} aaidset;
%#define HAS_aaidset
%
field(VAL,DBF_NOACCESS) {
prompt("Value")
asl(ASL0)
special(SPC_DBADDR)
pp(TRUE)
extra("void * val")
#=type DOUBLE[NELM]
#=read Yes
#=write Yes
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup("40 - Input")
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(NELM,DBF_ULONG) {
prompt("Number of Elements")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(FTVL,DBF_MENU) {
prompt("Field Type of Value")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
menu(menuFtype)
}
field(NORD,DBF_ULONG) {
prompt("Number elements read")
special(SPC_NOMOD)
}
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
interest(4)
extra("void * bptr")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
interest(1)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
}
field(MPST,DBF_MENU) {
prompt("Post Value Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaiPOST)
}
field(APST,DBF_MENU) {
prompt("Post Archive Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaiPOST)
}
field(HASH,DBF_ULONG) {
prompt("Hash of OnChange data.")
interest(3)
}
=head2 Device Support
=head3 Fields Of Interest To Device Support
Each array analog input record record must have an associated set of device
support routines. The primary responsibility of the device support routines is to
obtain a new array value whenever C<read_aai()> is called. The device support
routines are primarily interested in the following fields:
=fields PACT, DPVT, NSEV, NSTA, INP, NELM, FTVL, BPTR, NORD
=head3 Device Support Routines
Device support consists of the following routines:
=head4 report
long report(int level)
This optional routine is called by the IOC command C<dbior> and is passed the
report level that was requested by the user.
It should print a report on the state of the device support to stdout.
The C<level> parameter may be used to output increasingly more detailed
information at higher levels, or to select different types of information with
different levels.
Level zero should print no more than a small summary.
=head4 init
long init(int after)
This optional routine is called twice at IOC initialization time.
The first call happens before any of the C<init_record()> calls are made, with
the integer parameter C<after> set to 0.
The second call happens after all of the C<init_record()> calls have been made,
with C<after> set to 1.
=head4 init_record
long init_record(dbCommon *precord)
This routine is optional. If provided, it is called by the record support
C<init_record()> routine.
=head4 get_ioint_info
long get_ioint_info(int cmd, dbCommon *precord, IOSCANPVT *ppvt)
This routine is called by the ioEventScan system each time the record is added
or deleted from an I/O event scan list. C<cmd> has the value (0,1) if the
record is being (added to, deleted from) an I/O event list. It must be
provided for any device type that can use the ioEvent scanner.
=head4 read_aai
long read_aai(dbCommon *precord)
This routine must provide a new input value. It returns the following values:
=over
=item *
0: Success.
=item *
Other: Error.
=back
=head3 Device Support For Soft Records
The C<<< Soft Channel >>> device support module is provided to read values from
other records and store them in arrays. If INP is a constant link, then read_aai
does nothing. In this case, the record can be used to hold arrays written via
dbPuts. If INP is a database or channel access link, the new array value is read
from the link. NORD is set.
This module places a value directly in VAL and NORD is set to the number of items
in the array.
If the INP link type is constant, then NORD is set to zero.
=cut
}
+6 -15
View File
@@ -90,22 +90,13 @@ rset aaoRSET={
};
epicsExportAddress(rset,aaoRSET);
struct aaodset { /* aao dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/
};
static void monitor(aaoRecord *);
static long writeValue(aaoRecord *);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct aaoRecord *prec = (struct aaoRecord *)pcommon;
struct aaodset *pdset = (struct aaodset *)(prec->dset);
aaodset *pdset = (aaodset *)(prec->dset);
long status;
/* must have dset defined */
@@ -130,9 +121,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
not change after links are established before pass 1
*/
if (pdset->init_record) {
if (pdset->common.init_record) {
/* init_record may set the bptr to point to the data */
if ((status = pdset->init_record(prec)))
if ((status = pdset->common.init_record(pcommon)))
return status;
}
if (!prec->bptr) {
@@ -146,7 +137,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
/* must have write_aao function defined */
if (pdset->number < 5 || pdset->write_aao == NULL) {
if (pdset->common.number < 5 || pdset->write_aao == NULL) {
recGblRecordError(S_dev_missingSup, prec, "aao: init_record");
return S_dev_missingSup;
}
@@ -156,7 +147,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct aaoRecord *prec = (struct aaoRecord *)pcommon;
struct aaodset *pdset = (struct aaodset *)(prec->dset);
aaodset *pdset = (aaodset *)(prec->dset);
long status;
unsigned char pact = prec->pact;
@@ -339,7 +330,7 @@ static void monitor(aaoRecord *prec)
static long writeValue(aaoRecord *prec)
{
struct aaodset *pdset = (struct aaodset *) prec->dset;
aaodset *pdset = (aaodset *) prec->dset;
long status = 0;
if (!prec->pact) {
-143
View File
@@ -1,143 +0,0 @@
#*************************************************************************
# 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 is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(aaoPOST) {
choice(aaoPOST_Always,"Always")
choice(aaoPOST_OnChange,"On Change")
}
recordtype(aao) {
include "dbCommon.dbd"
field(VAL,DBF_NOACCESS) {
prompt("Value")
asl(ASL0)
special(SPC_DBADDR)
pp(TRUE)
extra("void * val")
#=type DOUBLE[]
#=read Yes
#=write Yes
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(OUT,DBF_OUTLINK) {
prompt("Output Specification")
promptgroup("50 - Output")
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(NELM,DBF_ULONG) {
prompt("Number of Elements")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(FTVL,DBF_MENU) {
prompt("Field Type of Value")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
menu(menuFtype)
}
field(NORD,DBF_ULONG) {
prompt("Number elements read")
special(SPC_NOMOD)
}
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
interest(4)
extra("void * bptr")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(SIOL,DBF_OUTLINK) {
prompt("Simulation Output Link")
promptgroup("90 - Simulate")
interest(1)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
}
field(MPST,DBF_MENU) {
prompt("Post Value Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaoPOST)
}
field(APST,DBF_MENU) {
prompt("Post Archive Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaoPOST)
}
field(HASH,DBF_ULONG) {
prompt("Hash of OnChange data.")
interest(3)
}
}
@@ -0,0 +1,519 @@
#*************************************************************************
# 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 is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Array Analog Output (aao)
The array analog output record type is used to write array data. The array data
can contain any of the supported data types. The record is in many ways similar to
the waveform record but outputs arrays instead of reading them. It also allows the
device support to allocate the array storage.
=recordtype aao
=cut
menu(aaoPOST) {
choice(aaoPOST_Always,"Always")
choice(aaoPOST_OnChange,"On Change")
}
recordtype(aao) {
=head2 Parameter Fields
The record-specific fields are described below, grouped by functionality.
=head3 Scan Parameters
The array analog output record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in L<Scan
Fields>. In addition, L<Scanning Specification> explains how these fields are
used. I/O event scanning is only available when supported by device support.
=head3 Write Parameters
These fields are configurable by the user to specify how and where to the record
writes its data. The OUT field determines where the array analog output writes its
output. It can be a hardware address, a channel access or database link, or a
constant. Only in records that use soft device support can the OUT field be a
channel access link, a database link, or a constant. Otherwise, the OUT field must
be a hardware address. See L<Address Specification> for information on the format
of hardware addresses and database links.
=head4 Fields related to array writing
The DTYP field must contain the name of the appropriate device support module. The
values in the array referenced by are written to the location specified in the OUT
field. (If the OUT link is a constant, no data are written.) NELM specifies the
maximum number of elements that the array can hold, while FTVL specifies the data
type of the elements (follow the link in the table below for a list of the
available choices).
=fields DTYP, OUT, NELM, FTVL
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. They
display the value and other parameters of the waveform either textually or
graphically.
=head4 Fields related to I<Operator Display>
EGU is a string of up to 16 characters describing the units that the array data
measures. It is retrieved by the C<<< get_units >>> record support routine.
The HOPR and LOPR fields set the upper and lower display limits for array
elements referenced by the VAL field. Both the C<<< get_graphic_double >>> and
C<<< get_control_double >>> record support routines retrieve these fields.
The PREC field determines the floating point precision with which to display the
array values. It is used whenever the C<<< get_precision >>> record support
routine is called.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, HOPR, LOPR, PREC, NAME, DESC
=head3 Alarm Parameters
The array analog output record has the alarm parameters common to all record
types.
=head3 Monitor Parameters
These parameters are used to determine when to send monitors placed on the VAL
field. The APST and MPST fields are a menu with choices "Always" and "On
Change". The default is "Always", thus monitors will normally be sent every time
the record processes. Selecting "On Change" causes a 32-bit hash of the VAL
field buffer to be calculated and compared with the previous hash value every
time the record processes; the monitor will only be sent if the hash is
different, indicating that the buffer has changed. Note that there is a small
chance that two different value buffers might result in the same hash value, so
for critical systems "Always" may be a better choice, even though it re-sends
duplicate data.
=head4 Record fields related to I<Monitor Parameters>
=fields APST, MPST, HASH
=head4 Menu aaoPOST
These are the choices available for the C<APST> and C<MPST> fields
=menu aaoPOST
=head3 Run-time Parameters
These parameters are used by the run-time code for processing the array analog
output record. They are not configured using a configuration tool. Only the VAL
field is modifiable at run-time.
VAL references the array where the array analog output record stores its data. The
BPTR field holds the address of the array.
The NORD field holds a counter of the number of elements that have been written to
the output,
=fields VAL, BPTR, NORD
=head3 Simulation Mode Parameters
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is written through SIOL.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Output Simulation Fields|dbCommonOutput/Output Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SIMS, SDLY, SSCN
=begin html
<br>
<hr>
<br>
=end html
=head2 Record Support
=head3 Record Support Routines
=head4 init_record
static long init_record(aaoRecord *prec, int pass)
If device support includes C<init_record()>, it is called.
Checks if device support allocated array space. If not, space for the array is
allocated using NELM and FTVL. The array address is stored in the record.
This routine initializes SIMM with the value of SIML if SIML type is CONSTANT
link or creates a channel access link if SIML type is PV_LINK. VAL is likewise
initialized if SIOL is CONSTANT or PV_LINK.
This routine next checks to see that device support is available and a device
support write routine is defined. If either does not exist, an error message is
issued and processing is terminated
=head4 process
static long process(aaoRecord *prec)
See L</"Record Processing"> section below.
=head4 cvt_dbaddr
static long cvt_dbaddr(DBADDR *paddr)
This is called by dbNameToAddr. It makes the dbAddr structure refer to the
actual buffer holding the result.
=head4 get_array_info
static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
Obtains values from the array referenced by VAL.
=head4 put_array_info
static long put_array_info(DBADDR *paddr, long nNew)
Writes values into the array referenced by VAL.
=head4 get_units
static long get_units(DBADDR *paddr, char *units)
Retrieves EGU.
=head4 get_prec
static long get_precision(DBADDR *paddr, long *precision)
Retrieves PREC if field is VAL field. Otherwise, calls C<<< recGblGetPrec() >>>.
=head4 get_graphic_double
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
Sets the upper display and lower display limits for a field. If the field is VAL
the limits are set to HOPR and LOPR, else if the field has upper and lower
limits defined they will be used, else the upper and lower maximum values for
the field type will be used.
Sets the following values:
upper_disp_limit = HOPR
lower_disp_limit = LOPR
=head4 get_control_double
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
Sets the upper control and the lower control limits for a field. If the field is
VAL the limits are set to HOPR and LOPR, else if the field has upper and lower
limits defined they will be used, else the upper and lower maximum values for
the field type will be used.
Sets the following values
upper_ctrl_limit = HOPR
lower_ctrl_limit = LOPR
=head3 Record Processing
Routine process implements the following algorithm:
=over
=item 1.
Check to see that the appropriate device support module exists. If it doesn't,
an error message is issued and processing is terminated with the PACT field
still set to TRUE. This ensures that processes will no longer be called for this
record. Thus error storms will not occur.
=item 2.
Call device support write routine C<write_aao>.
=item 3.
If PACT has been changed to TRUE, the device support read routine has started
but has not completed writing the new value. In this case, the processing
routine merely returns, leaving PACT TRUE.
=item 4.
Check to see if monitors should be invoked.
=over
=item *
Alarm monitors are invoked if the alarm status or severity has changed.
=item *
Archive and value change monitors are invoked if APST or MPST are Always or if
the result of the hash calculation is different.
=item *
NSEV and NSTA are reset to 0.
=back
=item 5.
Scan forward link if necessary, set PACT FALSE, and return.
=back
=begin html
<br>
<hr>
<br>
=end html
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct aaoRecord;
%typedef struct aaodset {
% dset common; /*init_record returns: (-1,0)=>(failure,success)*/
% long (*write_aao)(struct aaoRecord *prec); /*returns: (-1,0)=>(failure,success)*/
%} aaodset;
%#define HAS_aaodset
%
field(VAL,DBF_NOACCESS) {
prompt("Value")
asl(ASL0)
special(SPC_DBADDR)
pp(TRUE)
extra("void * val")
#=type DOUBLE[]
#=read Yes
#=write Yes
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(OUT,DBF_OUTLINK) {
prompt("Output Specification")
promptgroup("50 - Output")
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup("80 - Display")
interest(1)
size(16)
prop(YES)
}
field(HOPR,DBF_DOUBLE) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_DOUBLE) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(NELM,DBF_ULONG) {
prompt("Number of Elements")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(FTVL,DBF_MENU) {
prompt("Field Type of Value")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
menu(menuFtype)
}
field(NORD,DBF_ULONG) {
prompt("Number elements read")
special(SPC_NOMOD)
}
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
interest(4)
extra("void * bptr")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(SIOL,DBF_OUTLINK) {
prompt("Simulation Output Link")
promptgroup("90 - Simulate")
interest(1)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
}
field(MPST,DBF_MENU) {
prompt("Post Value Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaoPOST)
}
field(APST,DBF_MENU) {
prompt("Post Archive Monitors")
promptgroup("80 - Display")
interest(1)
menu(aaoPOST)
}
field(HASH,DBF_ULONG) {
prompt("Hash of OnChange data.")
interest(3)
}
=head2 Device Support
=head3 Fields Of Interest To Device Support
Each array analog output record record must have an associated set of device
support routines. The primary responsibility of the device support routines is to
write the array data value whenever C<write_aao()> is called. The device support
routines are primarily interested in the following fields:
=fields PACT, DPVT, NSEV, NSTA, OUT, NELM, FTVL, BPTR, NORD
=head3 Device Support Routines
Device support consists of the following routines:
=head4 report
long report(int level)
This optional routine is called by the IOC command C<dbior> and is passed the
report level that was requested by the user.
It should print a report on the state of the device support to stdout.
The C<level> parameter may be used to output increasingly more detailed
information at higher levels, or to select different types of information with
different levels.
Level zero should print no more than a small summary.
=head4 init
long init(int after)
This optional routine is called twice at IOC initialization time.
The first call happens before any of the C<init_record()> calls are made, with
the integer parameter C<after> set to 0.
The second call happens after all of the C<init_record()> calls have been made,
with C<after> set to 1.
=head4 init_record
long init_record(dbCommon *precord)
This routine is optional. If provided, it is called by the record support
C<init_record()> routine.
=head4 get_ioint_info
long get_ioint_info(int cmd, dbCommon *precord, IOSCANPVT *ppvt)
This routine is called by the ioEventScan system each time the record is added
or deleted from an I/O event scan list. C<cmd> has the value (0,1) if the
record is being (added to, deleted from) an I/O event list. It must be
provided for any device type that can use the ioEvent scanner.
=head4 write_aao
long write_aao(dbCommon *precord)
This routine must write the array data to output. It returns the following values:
=over
=item *
0: Success.
=item *
Other: Error.
=back
=head3 Device Support For Soft Records
The C<<< Soft Channel >>> device support module is provided to write values to
other records and store them in arrays. If OUT is a constant link, then
C<write_aao()> does nothing. In this case, the record can be used to hold arrays
written via dbPuts. If OUT is a database or channel access link, the array value
is written to the link. NORD is set to the number of items in the array.
If the OUT link type is constant, then NORD is set to zero.
=cut
}
+134 -145
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* aiRecord.c - Record Support Routines for Analog Input records */
@@ -63,40 +63,29 @@ static long get_precision(const DBADDR *, long *);
static long get_graphic_double(DBADDR *, struct dbr_grDouble *);
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
rset aiRSET={
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
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,aiRSET);
typedef struct aidset { /* analog input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_ai;/*(0,2)=> success and convert,don't convert)*/
/* if convert then raw value stored in rval */
DEVSUPFUN special_linconv;
}aidset;
static void checkAlarms(aiRecord *prec, epicsTimeStamp *lastTime);
static void convert(aiRecord *prec);
static void monitor(aiRecord *prec);
@@ -105,8 +94,8 @@ static long readValue(aiRecord *prec);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct aiRecord *prec = (struct aiRecord *)pcommon;
aidset *pdset;
double eoff = prec->eoff, eslo = prec->eslo;
aidset *pdset;
double eoff = prec->eoff, eslo = prec->eslo;
if (pass == 0) return 0;
@@ -114,27 +103,27 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitConstantLink(&prec->siol, DBF_DOUBLE, &prec->sval);
if(!(pdset = (aidset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"ai: init_record");
return(S_dev_noDSET);
recGblRecordError(S_dev_noDSET,(void *)prec,"ai: init_record");
return(S_dev_noDSET);
}
/* must have read_ai function defined */
if( (pdset->number < 6) || (pdset->read_ai == NULL) ) {
recGblRecordError(S_dev_missingSup,(void *)prec,"ai: init_record");
return(S_dev_missingSup);
if ((pdset->common.number < 6) || (pdset->read_ai == NULL)) {
recGblRecordError(S_dev_missingSup,(void *)prec,"ai: init_record");
return(S_dev_missingSup);
}
prec->init = TRUE;
/*The following is for old device support that doesnt know about eoff*/
if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
prec->eoff = prec->egul;
prec->eoff = prec->egul;
}
if( pdset->init_record ) {
long status=(*pdset->init_record)(prec);
if (prec->linr == menuConvertSLOPE) {
prec->eoff = eoff;
prec->eslo = eslo;
}
return (status);
if (pdset->common.init_record) {
long status = pdset->common.init_record(pcommon);
if (prec->linr == menuConvertSLOPE) {
prec->eoff = eoff;
prec->eslo = eslo;
}
return (status);
}
prec->mlst = prec->val;
prec->alst = prec->val;
@@ -146,51 +135,51 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct aiRecord *prec = (struct aiRecord *)pcommon;
aidset *pdset = (aidset *)(prec->dset);
long status;
aidset *pdset = (aidset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
epicsTimeStamp timeLast;
epicsTimeStamp timeLast;
if( (pdset==NULL) || (pdset->read_ai==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_ai");
return(S_dev_missingSup);
}
timeLast = prec->time;
if( (pdset==NULL) || (pdset->read_ai==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_ai");
return(S_dev_missingSup);
}
timeLast = prec->time;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
if (status==0) convert(prec);
else if (status==2) status=0;
if (status==0) convert(prec);
else if (status==2) status=0;
if (status == 0) prec->udf = isnan(prec->val);
/* check for alarms */
checkAlarms(prec,&timeLast);
/* check event list */
monitor(prec);
/* process the forward scan link record */
/* check for alarms */
checkAlarms(prec,&timeLast);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->init=FALSE;
prec->pact=FALSE;
return(status);
prec->init=FALSE;
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr,int after)
{
aiRecord *prec = (aiRecord *)(paddr->precord);
aidset *pdset = (aidset *) (prec->dset);
aiRecord *prec = (aiRecord *)(paddr->precord);
aidset *pdset = (aidset *) (prec->dset);
int special_type = paddr->special;
switch(special_type) {
case(SPC_LINCONV):
if(pdset->number<6) {
if (pdset->common.number < 6) {
recGblDbaddrError(S_db_noMod,paddr,"ai: special");
return(S_db_noMod);
}
@@ -226,7 +215,7 @@ static long special(DBADDR *paddr,int after)
static long get_units(DBADDR *paddr, char *units)
{
aiRecord *prec=(aiRecord *)paddr->precord;
aiRecord *prec=(aiRecord *)paddr->precord;
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
switch (dbGetFieldIndex(paddr)) {
@@ -243,7 +232,7 @@ static long get_units(DBADDR *paddr, char *units)
static long get_precision(const DBADDR *paddr, long *precision)
{
aiRecord *prec=(aiRecord *)paddr->precord;
aiRecord *prec=(aiRecord *)paddr->precord;
*precision = prec->prec;
if (dbGetFieldIndex(paddr) == indexof(VAL)) return(0);
@@ -253,7 +242,7 @@ static long get_precision(const DBADDR *paddr, long *precision)
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
{
aiRecord *prec=(aiRecord *)paddr->precord;
aiRecord *prec=(aiRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
@@ -276,7 +265,7 @@ static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
{
aiRecord *prec=(aiRecord *)paddr->precord;
aiRecord *prec=(aiRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
@@ -288,8 +277,8 @@ static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
case indexof(ALST):
case indexof(MLST):
case indexof(SVAL):
pcd->upper_ctrl_limit = prec->hopr;
pcd->lower_ctrl_limit = prec->lopr;
pcd->upper_ctrl_limit = prec->hopr;
pcd->lower_ctrl_limit = prec->lopr;
break;
default:
recGblGetControlDouble(paddr,pcd);
@@ -299,7 +288,7 @@ static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
{
aiRecord *prec=(aiRecord *)paddr->precord;
aiRecord *prec=(aiRecord *)paddr->precord;
if (dbGetFieldIndex(paddr) == indexof(VAL)) {
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
@@ -380,7 +369,7 @@ static void checkAlarms(aiRecord *prec, epicsTimeStamp *lastTime)
* level, otherwise to a higher.
*/
afvl = alpha * afvl +
((afvl > 0) ? (1 - alpha) : (alpha - 1)) * alarmRange;
((afvl > 0) ? (1 - alpha) : (alpha - 1)) * alarmRange;
if (afvl - floor(afvl) > THRESHOLD)
afvl = -afvl; /* reverse rounding */
@@ -422,38 +411,38 @@ static void checkAlarms(aiRecord *prec, epicsTimeStamp *lastTime)
static void convert(aiRecord *prec)
{
double val;
double val;
val = (double)prec->rval + (double)prec->roff;
/* adjust slope and offset */
if(prec->aslo!=0.0) val*=prec->aslo;
val+=prec->aoff;
val = (double)prec->rval + (double)prec->roff;
/* adjust slope and offset */
if(prec->aslo!=0.0) val*=prec->aslo;
val+=prec->aoff;
/* convert raw to engineering units and signal units */
switch (prec->linr) {
case menuConvertNO_CONVERSION:
break; /* do nothing*/
case menuConvertLINEAR:
case menuConvertSLOPE:
val = (val * prec->eslo) + prec->eoff;
break;
default: /* must use breakpoint table */
if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) {
recGblSetSevr(prec,SOFT_ALARM,MAJOR_ALARM);
}
}
/* convert raw to engineering units and signal units */
switch (prec->linr) {
case menuConvertNO_CONVERSION:
break; /* do nothing*/
/* apply smoothing algorithm */
case menuConvertLINEAR:
case menuConvertSLOPE:
val = (val * prec->eslo) + prec->eoff;
break;
default: /* must use breakpoint table */
if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) {
recGblSetSevr(prec,SOFT_ALARM,MAJOR_ALARM);
}
}
/* apply smoothing algorithm */
if (prec->smoo != 0.0 && finite(prec->val)){
if (prec->init) prec->val = val; /* initial condition */
prec->val = val * (1.00 - prec->smoo) + (prec->val * prec->smoo);
}else{
prec->val = val;
}
return;
if (prec->init) prec->val = val; /* initial condition */
prec->val = val * (1.00 - prec->smoo) + (prec->val * prec->smoo);
}else{
prec->val = val;
}
return;
}
static void monitor(aiRecord *prec)
@@ -466,15 +455,15 @@ static void monitor(aiRecord *prec)
/* check for archive change */
recGblCheckDeadband(&prec->alst, prec->val, prec->adel, &monitor_mask, DBE_ARCHIVE);
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(prec,&prec->val,monitor_mask);
if(prec->oraw != prec->rval) {
db_post_events(prec,&prec->rval,monitor_mask);
prec->oraw = prec->rval;
}
}
return;
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(prec,&prec->val,monitor_mask);
if(prec->oraw != prec->rval) {
db_post_events(prec,&prec->rval,monitor_mask);
prec->oraw = prec->rval;
}
}
return;
}
static long readValue(aiRecord *prec)
@@ -488,40 +477,40 @@ static long readValue(aiRecord *prec)
}
switch (prec->simm) {
case menuSimmNO:
status = pdset->read_ai(prec);
break;
case menuSimmNO:
status = pdset->read_ai(prec);
break;
case menuSimmYES:
case menuSimmRAW: {
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
if (prec->pact || (prec->sdly < 0.)) {
status = dbGetLink(&prec->siol, DBR_DOUBLE, &prec->sval, 0, 0);
if (status == 0) {
if (prec->simm == menuSimmYES) {
prec->val = prec->sval;
status = 2; /* don't convert */
} else {
prec->rval = (long)floor(prec->sval);
status = 0; /* convert RVAL */
case menuSimmYES:
case menuSimmRAW: {
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
if (prec->pact || (prec->sdly < 0.)) {
status = dbGetLink(&prec->siol, DBR_DOUBLE, &prec->sval, 0, 0);
if (status == 0) {
if (prec->simm == menuSimmYES) {
prec->val = prec->sval;
status = 2; /* don't convert */
} else {
prec->rval = (long)floor(prec->sval);
status = 0; /* convert RVAL */
}
}
prec->pact = FALSE;
} else { /* !prec->pact && delay >= 0. */
epicsCallback *pvt = prec->simpvt;
if (!pvt) {
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
prec->simpvt = pvt;
}
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
prec->pact = TRUE;
}
prec->pact = FALSE;
} else { /* !prec->pact && delay >= 0. */
epicsCallback *pvt = prec->simpvt;
if (!pvt) {
pvt = calloc(1, sizeof(epicsCallback)); /* very lazy allocation of callback structure */
prec->simpvt = pvt;
}
if (pvt) callbackRequestProcessCallbackDelayed(pvt, prec->prio, prec, prec->sdly);
prec->pact = TRUE;
break;
}
break;
}
default:
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
status = -1;
default:
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
status = -1;
}
return status;
+29 -26
View File
@@ -190,7 +190,13 @@ noise.
The AFTC field sets the time constant on a low-pass filter that delays the
reporting of limit alarms until the signal has been within the alarm range for
that number of seconds (the default AFTC value of zero retains the previous
behavior).
behavior). The record must be scanned often enough for the filtering action to
work effectively and the alarm severity can only change when the record is
processed, but that processing does not have to be regular; the filter uses the
time since the record last processed in its calculation. Setting AFTC to a
positive number of seconds will delay the record going into or out of a minor
alarm severity or from minor to major severity until the input signal has been
in the alarm range for that number of seconds.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, AFTC, LALM
@@ -215,6 +221,16 @@ monitoring functionality.
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct aiRecord;
%typedef struct aidset {
% dset common;
% long (*read_ai)(struct aiRecord *prec);
% long (*special_linconv)(struct aiRecord *prec, int after);
%} aidset;
%#define HAS_aidset
%
field(VAL,DBF_DOUBLE) {
prompt("Current EGU Value")
promptgroup("40 - Input")
@@ -435,35 +451,22 @@ monitoring functionality.
interest(3)
}
=head3 Simulation Mode
=head3 Simulation Mode Parameters
The record provides several fields to support simulation of absent hardware.
If the SIML field is set it is used to read a value into the SIMM field, which
controls whether simulation is used or not:
The following fields are used to operate the record in simulation mode.
=over
If SIMM (fetched through SIML) is YES or RAW, the record is put in SIMS
severity and the value is fetched through SIOL (buffered in SVAL).
If SIMM is YES, SVAL is written to VAL without conversion,
if SIMM is RAW, SVAL is trancated to RVAL and converted.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
=item *
SIMM must be zero (C<NO>) for the record to request a value from the device
support.
See L<Input Simulation Fields|dbCommonInput/Input Simulation Fields>
for more information on simulation mode and its fields.
=item *
If SIMM is C<YES> and the SIOL link field is set, a simlated value in
engineering units is read using the link into the SVAL field, from where it will
subsequently be copied into the VAL field.
=item *
If SIMM is C<RAW> the SIOL link is still read into SVAL, but is then truncated
and copied into the RVAL field.
The L</Units Conversion> process described above is then followed to transform
the simulated raw value into engineering units.
=back
The SIMS field can be set to give the record an alarm severity while it is in
simulation mode.
=fields SIML, SIMM, SIOL, SVAL, SIMS
=fields SIML, SIMM, SIOL, SVAL, SIMS, SDLY, SSCN
=cut
+158 -168
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* aoRecord.c - Record Support Routines for Analog Output records */
@@ -64,37 +64,27 @@ static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
rset aoRSET={
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 };
struct aodset { /* analog input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (0,2)=>(success,success no convert)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_ao;/*(0)=>(success ) */
DEVSUPFUN special_linconv;
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,aoRSET);
static void checkAlarms(aoRecord *);
static long fetch_value(aoRecord *, double *);
static void convert(aoRecord *, double);
@@ -104,62 +94,62 @@ static long writeValue(aoRecord *);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct aoRecord *prec = (struct aoRecord *)pcommon;
struct aodset *pdset;
double eoff = prec->eoff, eslo = prec->eslo;
double value;
long status = 0;
aodset *pdset;
double eoff = prec->eoff, eslo = prec->eslo;
double value;
long status = 0;
if (pass == 0) return 0;
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
if(!(pdset = (struct aodset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"ao: init_record");
return(S_dev_noDSET);
if(!(pdset = (aodset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"ao: init_record");
return(S_dev_noDSET);
}
/* get the initial value if dol is a constant*/
if (recGblInitConstantLink(&prec->dol,DBF_DOUBLE,&prec->val))
prec->udf = isnan(prec->val);
/* must have write_ao function defined */
if ((pdset->number < 6) || (pdset->write_ao ==NULL)) {
recGblRecordError(S_dev_missingSup,(void *)prec,"ao: init_record");
return(S_dev_missingSup);
if ((pdset->common.number < 6) || (pdset->write_ao ==NULL)) {
recGblRecordError(S_dev_missingSup,(void *)prec,"ao: init_record");
return(S_dev_missingSup);
}
prec->init = TRUE;
/*The following is for old device support that doesnt know about eoff*/
if ((prec->eslo==1.0) && (prec->eoff==0.0)) {
prec->eoff = prec->egul;
prec->eoff = prec->egul;
}
if (pdset->init_record) {
status = (*pdset->init_record)(prec);
if (prec->linr == menuConvertSLOPE) {
prec->eoff = eoff;
prec->eslo = eslo;
}
if (pdset->common.init_record) {
status = pdset->common.init_record(pcommon);
if (prec->linr == menuConvertSLOPE) {
prec->eoff = eoff;
prec->eslo = eslo;
}
switch(status){
case(0): /* convert */
value = (double)prec->rval + (double)prec->roff;
if(prec->aslo!=0.0) value *= prec->aslo;
value += prec->aoff;
value = (double)prec->rval + (double)prec->roff;
if(prec->aslo!=0.0) value *= prec->aslo;
value += prec->aoff;
if (prec->linr == menuConvertNO_CONVERSION){
; /*do nothing*/
; /*do nothing*/
} else if ((prec->linr == menuConvertLINEAR) ||
(prec->linr == menuConvertSLOPE)) {
(prec->linr == menuConvertSLOPE)) {
value = value*prec->eslo + prec->eoff;
}else{
if(cvtRawToEngBpt(&value,prec->linr,prec->init,
(void *)&prec->pbrk,&prec->lbrk)!=0) break;
(void *)&prec->pbrk,&prec->lbrk)!=0) break;
}
prec->val = value;
prec->udf = isnan(value);
prec->val = value;
prec->udf = isnan(value);
break;
case(2): /* no convert */
break;
default:
recGblRecordError(S_dev_badInitRet,(void *)prec,"ao: init_record");
return(S_dev_badInitRet);
recGblRecordError(S_dev_badInitRet,(void *)prec,"ao: init_record");
return(S_dev_badInitRet);
}
}
prec->oval = prec->pval = prec->val;
@@ -174,19 +164,19 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct aoRecord *prec = (struct aoRecord *)pcommon;
struct aodset *pdset = (struct aodset *)(prec->dset);
long status=0;
unsigned char pact=prec->pact;
double value;
aodset *pdset = (aodset *)(prec->dset);
long status=0;
unsigned char pact=prec->pact;
double value;
if ((pdset==NULL) || (pdset->write_ao==NULL)) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_ao");
return(S_dev_missingSup);
}
if ((pdset==NULL) || (pdset->write_ao==NULL)) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_ao");
return(S_dev_missingSup);
}
/* fetch value and convert*/
if (prec->pact == FALSE) {
/* fetch value and convert*/
if (prec->pact == FALSE) {
if (!dbLinkIsConstant(&prec->dol) &&
prec->omsl == menuOmslclosed_loop) {
status = fetch_value(prec, &value);
@@ -194,80 +184,80 @@ static long process(struct dbCommon *pcommon)
else {
value = prec->val;
}
if(!status) convert(prec, value);
prec->udf = isnan(prec->val);
}
if(!status) convert(prec, value);
prec->udf = isnan(prec->val);
}
/* check for alarms */
checkAlarms(prec);
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
prec->val=prec->ivov;
value=prec->ivov;
convert(prec,value);
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"ao:process Illegal IVOA field");
}
}
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
prec->val=prec->ivov;
value=prec->ivov;
convert(prec,value);
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"ao:process Illegal IVOA field");
}
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, NULL);
/* check event list */
monitor(prec);
/* check event list */
monitor(prec);
/* process the forward scan link record */
/* process the forward scan link record */
recGblFwdLink(prec);
prec->init=FALSE;
prec->pact=FALSE;
return(status);
prec->init=FALSE;
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
{
aoRecord *prec = (aoRecord *)(paddr->precord);
struct aodset *pdset = (struct aodset *) (prec->dset);
aodset *pdset = (aodset *) (prec->dset);
int special_type = paddr->special;
switch(special_type) {
case(SPC_LINCONV):
if(pdset->number<6 ) {
if(pdset->common.number<6 ) {
recGblDbaddrError(S_db_noMod,paddr,"ao: special");
return(S_db_noMod);
}
prec->init=TRUE;
prec->init=TRUE;
if ((prec->linr == menuConvertLINEAR) && pdset->special_linconv) {
double eoff = prec->eoff;
double eslo = prec->eslo;
long status;
prec->eoff = prec->egul;
status = (*pdset->special_linconv)(prec,after);
if (eoff != prec->eoff)
db_post_events(prec, &prec->eoff, DBE_VALUE|DBE_LOG);
double eoff = prec->eoff;
double eslo = prec->eslo;
long status;
prec->eoff = prec->egul;
status = (*pdset->special_linconv)(prec,after);
if (eoff != prec->eoff)
db_post_events(prec, &prec->eoff, DBE_VALUE|DBE_LOG);
if (eslo != prec->eslo)
db_post_events(prec, &prec->eslo, DBE_VALUE|DBE_LOG);
return (status);
}
return (0);
db_post_events(prec, &prec->eslo, DBE_VALUE|DBE_LOG);
return (status);
}
return (0);
case(SPC_MOD):
if (dbGetFieldIndex(paddr) == aoRecordSIMM) {
if (!after)
@@ -286,7 +276,7 @@ static long special(DBADDR *paddr, int after)
static long get_units(DBADDR * paddr,char *units)
{
aoRecord *prec=(aoRecord *)paddr->precord;
aoRecord *prec=(aoRecord *)paddr->precord;
if(paddr->pfldDes->field_type == DBF_DOUBLE) {
switch (dbGetFieldIndex(paddr)) {
@@ -302,7 +292,7 @@ static long get_units(DBADDR * paddr,char *units)
static long get_precision(const DBADDR *paddr,long *precision)
{
aoRecord *prec=(aoRecord *)paddr->precord;
aoRecord *prec=(aoRecord *)paddr->precord;
*precision = prec->prec;
switch (dbGetFieldIndex(paddr)) {
@@ -318,7 +308,7 @@ static long get_precision(const DBADDR *paddr,long *precision)
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
{
aoRecord *prec=(aoRecord *)paddr->precord;
aoRecord *prec=(aoRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
@@ -343,7 +333,7 @@ static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
{
aoRecord *prec=(aoRecord *)paddr->precord;
aoRecord *prec=(aoRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
@@ -366,7 +356,7 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
}
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
{
aoRecord *prec=(aoRecord *)paddr->precord;
aoRecord *prec=(aoRecord *)paddr->precord;
if(dbGetFieldIndex(paddr) == indexof(VAL)){
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
@@ -435,27 +425,27 @@ static void checkAlarms(aoRecord *prec)
static long fetch_value(aoRecord *prec,double *pvalue)
{
short save_pact;
long status;
short save_pact;
long status;
save_pact = prec->pact;
prec->pact = TRUE;
save_pact = prec->pact;
prec->pact = TRUE;
/* don't allow dbputs to val field */
prec->val=prec->pval;
/* don't allow dbputs to val field */
prec->val=prec->pval;
status = dbGetLink(&prec->dol,DBR_DOUBLE,pvalue,0,0);
prec->pact = save_pact;
status = dbGetLink(&prec->dol,DBR_DOUBLE,pvalue,0,0);
prec->pact = save_pact;
if (status) {
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
return(status);
}
if (status) {
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
return(status);
}
if (prec->oif == aoOIF_Incremental)
*pvalue += prec->val;
if (prec->oif == aoOIF_Incremental)
*pvalue += prec->val;
return(0);
return(0);
}
static void convert(aoRecord *prec, double value)
@@ -487,19 +477,19 @@ static void convert(aoRecord *prec, double value)
/* convert */
switch (prec->linr) {
case menuConvertNO_CONVERSION:
break; /* do nothing*/
case menuConvertLINEAR:
case menuConvertSLOPE:
if (prec->eslo == 0.0) value = 0;
else value = (value - prec->eoff) / prec->eslo;
break;
default:
if (cvtEngToRawBpt(&value, prec->linr, prec->init,
(void *)&prec->pbrk, &prec->lbrk) != 0) {
recGblSetSevr(prec, SOFT_ALARM, MAJOR_ALARM);
return;
}
case menuConvertNO_CONVERSION:
break; /* do nothing*/
case menuConvertLINEAR:
case menuConvertSLOPE:
if (prec->eslo == 0.0) value = 0;
else value = (value - prec->eoff) / prec->eslo;
break;
default:
if (cvtEngToRawBpt(&value, prec->linr, prec->init,
(void *)&prec->pbrk, &prec->lbrk) != 0) {
recGblSetSevr(prec, SOFT_ALARM, MAJOR_ALARM);
return;
}
}
value -= prec->aoff;
if (prec->aslo != 0) value /= prec->aslo;
@@ -535,27 +525,27 @@ static void monitor(aoRecord *prec)
db_post_events(prec,&prec->val,monitor_mask);
}
if(prec->omod) monitor_mask |= (DBE_VALUE|DBE_LOG);
if(monitor_mask) {
prec->omod = FALSE;
db_post_events(prec,&prec->oval,monitor_mask);
if(prec->oraw != prec->rval) {
db_post_events(prec,&prec->rval,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->oraw = prec->rval;
}
if(prec->orbv != prec->rbv) {
db_post_events(prec,&prec->rbv,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->orbv = prec->rbv;
}
}
return;
if(prec->omod) monitor_mask |= (DBE_VALUE|DBE_LOG);
if(monitor_mask) {
prec->omod = FALSE;
db_post_events(prec,&prec->oval,monitor_mask);
if(prec->oraw != prec->rval) {
db_post_events(prec,&prec->rval,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->oraw = prec->rval;
}
if(prec->orbv != prec->rbv) {
db_post_events(prec,&prec->rbv,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->orbv = prec->rbv;
}
}
return;
}
static long writeValue(aoRecord *prec)
{
struct aodset *pdset = (struct aodset *) prec->dset;
aodset *pdset = (aodset *) prec->dset;
long status = 0;
if (!prec->pact) {
+69 -31
View File
@@ -4,7 +4,7 @@
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Analog Output Record (ao)
@@ -104,33 +104,32 @@ The LINR field can specify C<LINEAR> or C<SLOPE> for linear conversions,
C<NO CONVERSION> for no conversions at all, or the name of a breakpoint table
such as C<typeKdegC> for breakpoint conversions.
Note that the ESLO, EOFF, EGUF, and EGUL fields are only used for linear
conversions.
Also note that none of these fields have any significance for records that use
the Soft Channel device support module.
The EGUF and EGUL fields should be set for C<LINEAR> conversions, and the ESLO
and EOFF fields for C<SLOPE> conversion. Note that none of these fields have any
significance for records that use the Soft Channel device support module.
=over
=item EGUF, EGUF
The user must calculate these fields when configuring the database for records
The user must set these fields when configuring the database for records
that use C<LINEAR> conversions.
They are used to calculate the values for ESLO and EOFF.
See Conversion Specification for more information on how to calculate these
fields.
=item ESLO, EOFF
Computed by device support from EGUF and EGUL when LINR specifies C<LINEAR>.
These values must be supplied by the user when LINR specifies C<SLOPE>.
Used only when LINR is C<LINEAR> or C<SLOPE>.
=item AOFF, ASLO
These fields are adjustment parameters for the raw output values.
They are applied to the raw output value after conversion from engineering
units.
=item ESLO, EOFF
Computed by device support using EGUF and EGUL when LINR specifies C<LINEAR>.
These values must be supplied by the user when LINR specifies C<SLOPE>.
Used only when LINR is C<LINEAR> or C<SLOPE>.
=item ROFF
This field can be used to offset the raw value generated by the conversion
@@ -168,8 +167,7 @@ addresses.
For soft records the output link can be a database link, a channel
access link, or a constant value. If the link is a constant, no output
is sent. See Address Specification for information on the format of
database and channel access addresses.
is sent.
=fields DTYP, OUT
@@ -193,8 +191,8 @@ The PREC field determines the floating point precision with which to
display VAL, OVAL and PVAL. It is used whenever the get_precision
record support routine is called.
See Fields Common to All Record Types for more on the record name
(NAME) and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, HOPR, LOPR, PREC, NAME, DESC
@@ -209,9 +207,10 @@ and LOW fields, which must be floating-point values. For each of these
fields, there is a corresponding severity field which can be either
NO_ALARM, MINOR, or MAJOR.
See Alarm Specification for a complete explanation of alarms and these
fields. See Invalid Alarm Output Action for more information on the
IVOA and IVOV fields. Alarm Fields lists other fields related to a
See L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields>
for more information on the IVOA and IVOV fields.
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related to a
alarms that are common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, IVOA, IVOV
@@ -229,7 +228,7 @@ a complete explanation of monitors.
=fields ADEL, MDEL
=head3 Run-time and Simulation Mode Parameters
=head3 Run-time Parameters
These parameters are used by the run-time code for processing the
analog output. They are not configurable. They represent the current
@@ -260,15 +259,34 @@ processing.
=fields ORAW, RBV, ORBV, LALM, ALST, MLST, INIT, PBRK, LBRK, PVAL, OMOD
The following fields are used to operate the analog output in the
simulation mode. See Fields Common to Many Record Types for more
information on these fields.
=head3 Simulation Mode Parameters
=fields SIOL, SIML, SIMM, SIMS
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is written through SIOL, without conversion.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Output Simulation Fields|dbCommonOutput/Output Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SIMS, SDLY, SSCN
=cut
include "dbCommon.dbd"
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct aoRecord;
%typedef struct aodset {
% dset common; /*init_record returns: (0,2)=>(success,success no convert)*/
% long (*write_ao)(struct aoRecord *prec); /*(0)=>(success ) */
% long (*special_linconv)(struct aoRecord *prec, int after);
%} aodset;
%#define HAS_aodset
%
field(VAL,DBF_DOUBLE) {
prompt("Desired Output")
promptgroup("50 - Output")
@@ -602,6 +620,8 @@ get_precision, get_graphic_double, and get_control_double routines.
=item init_record
C<long init_record(aoRecord *prec, int pass);>
This routine initializes SIMM if SIML is a constant or creates a
channel access link if SIML is PV_LINK. If SIOL is PV_LINK a channel
access link is created.
@@ -633,10 +653,14 @@ then set to FALSE. PVAL is set to VAL.
=item process
C<long process(aoRecord *prec);>
See next section.
=item special
C<long special(DBADDR *paddr, int after);>
The only special processing for analog output records is SPC_LINCONV
which is invoked whenever either of the fields LINR, EGUF, EGUL or ROFF
is changed If the device support routine special_linconv exists it is
@@ -647,6 +671,8 @@ re-initialized.
=item get_alarm_double
C<long get_alarm_double(DBADDR *, struct dbr_alDouble *);>
Sets the following values:
upper_alarm_limit = HIHI
@@ -796,7 +822,9 @@ Device support consists of the following routines:
=over
=item C<long report(int level)>
=item report
C<long report(int level);>
This optional routine is called by the IOC command C<dbior> and is passed the
report level that was requested by the user.
@@ -806,7 +834,9 @@ information at higher levels, or to select different types of information with
different levels.
Level zero should print no more than a small summary.
=item C<long init(int after)>
=item init
C<long init(int after);>
This optional routine is called twice at IOC initialization time.
The first call happens before any of the C<init_record()> calls are made, with
@@ -814,7 +844,9 @@ the integer parameter C<after> set to 0.
The second call happens after all of the C<init_record()> calls have been made,
with C<after> set to 1.
=item C<long init_record(aoRecord *prec)>
=item init_record
C<long init_record(aoRecord *prec);>
This optional routine is called by the record initialization code for each ao
record instance that has its DTYP field set to use this device support.
@@ -836,7 +868,9 @@ should also fetch that value and put it into the record's RVAL or VAL field. The
return value should be zero if the RVAL field has been set, or 2 if either the
VAL field has been set or if the last output value cannot be retrieved.
=item C<long get_ioint_info(int cmd, aoRecord *prec, IOSCANPVT *piosl)>
=item get_ioint_info
C<long get_ioint_info(int cmd, aoRecord *prec, IOSCANPVT *piosl);>
This optional routine is called whenever the record's SCAN field is being
changed to or from the value C<I/O Intr> to find out which I/O Interrupt Scan
@@ -864,7 +898,9 @@ thread.
The C<scanIoRequest()> routine is safe to call from an interrupt service routine
on embedded architectures (vxWorks and RTEMS).
=item C<long write_ao(aoRecord *prec)>
=item write_ao
C<long write_ao(aoRecord *prec);>
This essential routine is called whenever the record has a new output value to
send to the device. It is responsible for performing the write operation, using
@@ -883,7 +919,9 @@ that happens the C<write_ao()> routine will be called again with PACT still set
to TRUE; it should then set it to FALSE to indicate the write has completed, and
return.
=item C<long special_linconv(aoRecord *prec, int after)>
=item special_linconv
C<long special_linconv(aoRecord *prec, int after);>
This optional routine should be provided if the record type's unit conversion
features are used by the device support's C<write_ao()> routine utilizing the
+99 -106
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recBi.c - Record Support Routines for Binary Input records */
@@ -58,34 +58,27 @@ static long put_enum_str(const DBADDR *, const char *);
#define get_control_double NULL
#define get_alarm_double NULL
rset biRSET={
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 };
struct bidset { /* binary input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;/*(0,2)=> success and convert, don't convert)*/
/* if convert then raw value stored in rval */
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,biRSET);
static void checkAlarms(biRecord *);
static void monitor(biRecord *);
static long readValue(biRecord *);
@@ -93,7 +86,7 @@ static long readValue(biRecord *);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct biRecord *prec = (struct biRecord *)pcommon;
struct bidset *pdset;
bidset *pdset;
long status;
if (pass == 0) return 0;
@@ -101,17 +94,17 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
recGblInitConstantLink(&prec->siol, DBF_USHORT, &prec->sval);
if(!(pdset = (struct bidset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"bi: init_record");
return(S_dev_noDSET);
if(!(pdset = (bidset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"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,(void *)prec,"bi: init_record");
return(S_dev_missingSup);
if( (pdset->common.number < 5) || (pdset->read_bi == NULL) ) {
recGblRecordError(S_dev_missingSup,(void *)prec,"bi: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(prec))) return(status);
if( pdset->common.init_record ) {
if((status=(*pdset->common.init_record)(pcommon))) return(status);
}
prec->mlst = prec->val;
prec->lalm = prec->val;
@@ -122,38 +115,38 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct biRecord *prec = (struct biRecord *)pcommon;
struct bidset *pdset = (struct bidset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
bidset *pdset = (bidset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
if( (pdset==NULL) || (pdset->read_bi==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_bi");
return(S_dev_missingSup);
}
if( (pdset==NULL) || (pdset->read_bi==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_bi");
return(S_dev_missingSup);
}
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
if(status==0) { /* convert rval to val */
if(prec->rval==0) prec->val =0;
else prec->val = 1;
prec->udf = FALSE;
}
else if(status==2) status=0;
/* check for alarms */
checkAlarms(prec);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
if(prec->rval==0) prec->val =0;
else prec->val = 1;
prec->udf = FALSE;
}
else if(status==2) status=0;
/* check for alarms */
checkAlarms(prec);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
@@ -178,29 +171,29 @@ static long special(DBADDR *paddr, int after)
static long get_enum_str(const DBADDR *paddr, char *pstring)
{
biRecord *prec=(biRecord *)paddr->precord;
int index;
unsigned short *pfield = (unsigned short *)paddr->pfield;
biRecord *prec=(biRecord *)paddr->precord;
int index;
unsigned short *pfield = (unsigned short *)paddr->pfield;
index = dbGetFieldIndex(paddr);
if(index!=biRecordVAL) {
strcpy(pstring,"Illegal_Value");
strcpy(pstring,"Illegal_Value");
} else if(*pfield==0) {
strncpy(pstring,prec->znam,sizeof(prec->znam));
pstring[sizeof(prec->znam)] = 0;
strncpy(pstring,prec->znam,sizeof(prec->znam));
pstring[sizeof(prec->znam)] = 0;
} else if(*pfield==1) {
strncpy(pstring,prec->onam,sizeof(prec->onam));
pstring[sizeof(prec->onam)] = 0;
strncpy(pstring,prec->onam,sizeof(prec->onam));
pstring[sizeof(prec->onam)] = 0;
} else {
strcpy(pstring,"Illegal_Value");
strcpy(pstring,"Illegal_Value");
}
return(0);
}
static long get_enum_strs(const DBADDR *paddr,struct dbr_enumStrs *pes)
{
biRecord *prec=(biRecord *)paddr->precord;
biRecord *prec=(biRecord *)paddr->precord;
pes->no_str = 2;
memset(pes->strs,'\0',sizeof(pes->strs));
@@ -225,57 +218,57 @@ static long put_enum_str(const DBADDR *paddr, const char *pstring)
static void checkAlarms(biRecord *prec)
{
unsigned short val = prec->val;
unsigned short val = prec->val;
if(prec->udf == TRUE){
recGblSetSevr(prec,UDF_ALARM,prec->udfs);
return;
}
if(prec->udf == TRUE){
recGblSetSevr(prec,UDF_ALARM,prec->udfs);
return;
}
if(val>1)return;
/* check for state alarm */
if (val == 0){
recGblSetSevr(prec,STATE_ALARM,prec->zsv);
}else{
recGblSetSevr(prec,STATE_ALARM,prec->osv);
}
if(val>1)return;
/* check for state alarm */
if (val == 0){
recGblSetSevr(prec,STATE_ALARM,prec->zsv);
}else{
recGblSetSevr(prec,STATE_ALARM,prec->osv);
}
/* check for cos alarm */
if(val == prec->lalm) return;
if(val == prec->lalm) return;
recGblSetSevr(prec,COS_ALARM,prec->cosv);
prec->lalm = val;
return;
prec->lalm = val;
return;
}
static void monitor(biRecord *prec)
{
unsigned short monitor_mask;
unsigned short monitor_mask;
monitor_mask = recGblResetAlarms(prec);
/* check for value change */
if (prec->mlst != prec->val){
/* post events for value change and archive change */
monitor_mask |= (DBE_VALUE | DBE_LOG);
/* update last value monitored */
prec->mlst = prec->val;
}
monitor_mask = recGblResetAlarms(prec);
/* check for value change */
if (prec->mlst != prec->val){
/* post events for value change and archive change */
monitor_mask |= (DBE_VALUE | DBE_LOG);
/* update last value monitored */
prec->mlst = prec->val;
}
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(prec,&prec->val,monitor_mask);
}
if(prec->oraw!=prec->rval) {
db_post_events(prec,&prec->rval,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->oraw = prec->rval;
}
return;
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(prec,&prec->val,monitor_mask);
}
if(prec->oraw!=prec->rval) {
db_post_events(prec,&prec->rval,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->oraw = prec->rval;
}
return;
}
static long readValue(biRecord *prec)
{
struct bidset *pdset = (struct bidset *)prec->dset;
bidset *pdset = (bidset *)prec->dset;
long status = 0;
if (!prec->pact) {
+37 -38
View File
@@ -23,26 +23,7 @@ value into RVAL just like normal hardware modules.
=head2 Parameter Fields
The binary input's fields fall into the following categories:
=over
=item *
scan Parameters
=item *
read and convert parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
run-time parameters
=back
The record-specific fields are described below, grouped by functionality.
=recordtype bi
@@ -53,12 +34,8 @@ recordtype(bi) {
=head3 Scan Parameters
The binary input record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Note that I/O event scanning is only supported for those
card types that interrupt.
=fields SCAN
circumstances the record will be processed.
These fields are described in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Read and Convert Parameters
@@ -106,8 +83,8 @@ corresponding to the VAL's state. If the value is 1, C<get_enum_str()> will
return the string in the ONAM field; and if 0, C<get_enum_str()> will return
the ZNAM string.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields ZNAM, ONAM, NAME, DESC
@@ -126,12 +103,12 @@ the one state. COSV causes an alarm whenever the state changes between
0 and 1 and the severity is configured as MINOR or MAJOR.
See L<Alarm Specification> for a complete explanation of the discrete alarm
states. L<Alarm Fields> lists other fields related to alarms that are
states. L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related to alarms that are
common to all record types.
=fields ZSV, OSV, COSV
=head3 Run-time Parameters and Simulation Mode Parameters
=head3 Run-time Parameters
These parameters are used by the run-time code for processing the binary
input. They are not configured using a database configuration tool.
@@ -153,16 +130,18 @@ is not equal to VAL.
=fields ORAW, MASK, LALM, MLST
The following fields are used to operate the binary input in simulation
mode. See L<Fields Common to Many Record Types> for more information on
these fields.
=fields SIOL, SVAL, SIML, SIMM, SIMS
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct biRecord;
%typedef struct bidset {
% dset common;
% long (*read_bi)(struct biRecord *prec);
%} bidset;
%#define HAS_bidset
%
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup("40 - Input")
@@ -235,6 +214,26 @@ these fields.
special(SPC_NOMOD)
interest(3)
}
=head3 Simulation Mode Parameters
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES or RAW, the record is put in SIMS
severity and the value is fetched through SIOL (buffered in SVAL).
If SIMM is YES, SVAL is written to VAL without conversion,
if SIMM is RAW, SVAL is trancated to RVAL and converted.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Input Simulation Fields|dbCommonInput/Input Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SVAL, SIMS, SDLY, SSCN
=cut
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
@@ -305,7 +304,7 @@ If device support includes C<init_record()>, it is called.
long process(struct dbCommon *precord);
See L<Record Processing> below.
See L</Record Processing> below.
long get_enum_str(const struct dbAddr *paddr, char *pbuffer);
+170 -180
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recBo.c - Record Support Routines for Binary Output records */
@@ -60,24 +60,24 @@ static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
#define get_alarm_double NULL
rset boRSET={
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
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,boRSET);
@@ -86,16 +86,6 @@ epicsExportAddress(int, boHIGHprecision);
double boHIGHlimit = 100000;
epicsExportAddress(double, boHIGHlimit);
struct bodset { /* binary output dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns:(0,2)=>(success,success no convert*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;/*returns: (-1,0)=>(failure,success)*/
};
/* control block for callback*/
typedef struct myCallback {
epicsCallback callback;
@@ -115,15 +105,15 @@ static void myCallbackFunc(epicsCallback *arg)
prec=(boRecord *)pcallback->precord;
dbScanLock((struct dbCommon *)prec);
if(prec->pact) {
if((prec->val==1) && (prec->high>0)){
myCallback *pcallback;
pcallback = (myCallback *)(prec->rpvt);
if((prec->val==1) && (prec->high>0)){
myCallback *pcallback;
pcallback = (myCallback *)(prec->rpvt);
callbackSetPriority(prec->prio, &pcallback->callback);
callbackRequestDelayed(&pcallback->callback,(double)prec->high);
}
}
} else {
prec->val = 0;
dbProcess((struct dbCommon *)prec);
prec->val = 0;
dbProcess((struct dbCommon *)prec);
}
dbScanUnlock((struct dbCommon *)prec);
}
@@ -131,7 +121,7 @@ static void myCallbackFunc(epicsCallback *arg)
static long init_record(struct dbCommon *pcommon,int pass)
{
struct boRecord *prec = (struct boRecord *)pcommon;
struct bodset *pdset = (struct bodset *) prec->dset;
bodset *pdset = (bodset *) prec->dset;
unsigned short ival = 0;
long status = 0;
myCallback *pcallback;
@@ -146,7 +136,7 @@ static long init_record(struct dbCommon *pcommon,int pass)
}
/* must have write_bo functions defined */
if ((pdset->number < 5) || (pdset->write_bo == NULL)) {
if ((pdset->common.number < 5) || (pdset->write_bo == NULL)) {
recGblRecordError(S_dev_missingSup, prec, "bo: init_record");
return S_dev_missingSup;
}
@@ -163,19 +153,19 @@ static long init_record(struct dbCommon *pcommon,int pass)
callbackSetUser(pcallback, &pcallback->callback);
pcallback->precord = (struct dbCommon *) prec;
if (pdset->init_record) {
status=(*pdset->init_record)(prec);
if(status==0) {
if(prec->rval==0) prec->val = 0;
else prec->val = 1;
prec->udf = FALSE;
} else if (status==2) status=0;
if (pdset->common.init_record) {
status=(*pdset->common.init_record)(pcommon);
if(status==0) {
if(prec->rval==0) prec->val = 0;
else prec->val = 1;
prec->udf = FALSE;
} else if (status==2) status=0;
}
prec->mlst = prec->val;
/* convert val to rval */
if ( prec->mask != 0 ) {
if(prec->val==0) prec->rval = 0;
else prec->rval = prec->mask;
if(prec->val==0) prec->rval = 0;
else prec->rval = prec->mask;
} else prec->rval = (epicsUInt32)prec->val;
prec->mlst = prec->val;
@@ -188,87 +178,87 @@ static long init_record(struct dbCommon *pcommon,int pass)
static long process(struct dbCommon *pcommon)
{
struct boRecord *prec = (struct boRecord *)pcommon;
struct bodset *pdset = (struct bodset *)(prec->dset);
long status=0;
unsigned char pact=prec->pact;
bodset *pdset = (bodset *)(prec->dset);
long status=0;
unsigned char pact=prec->pact;
if( (pdset==NULL) || (pdset->write_bo==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_bo");
return(S_dev_missingSup);
}
if (!prec->pact) {
if (!dbLinkIsConstant(&prec->dol) &&
prec->omsl == menuOmslclosed_loop) {
unsigned short val;
if( (pdset==NULL) || (pdset->write_bo==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_bo");
return(S_dev_missingSup);
}
if (!prec->pact) {
if (!dbLinkIsConstant(&prec->dol) &&
prec->omsl == menuOmslclosed_loop) {
unsigned short val;
prec->pact = TRUE;
status=dbGetLink(&prec->dol,DBR_USHORT, &val,0,0);
prec->pact = FALSE;
if(status==0){
prec->val = val;
prec->udf = FALSE;
}else {
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
}
}
/* convert val to rval */
if ( prec->mask != 0 ) {
if(prec->val==0) prec->rval = 0;
else prec->rval = prec->mask;
} else prec->rval = (epicsUInt32)prec->val;
}
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
/* convert val to rval */
prec->val=prec->ivov;
if ( prec->mask != 0 ) {
if(prec->val==0) prec->rval = 0;
else prec->rval = prec->mask;
} else prec->rval = (epicsUInt32)prec->val;
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"bo:process Illegal IVOA field");
}
prec->pact = TRUE;
status=dbGetLink(&prec->dol,DBR_USHORT, &val,0,0);
prec->pact = FALSE;
if(status==0){
prec->val = val;
prec->udf = FALSE;
}else {
recGblSetSevr(prec,LINK_ALARM,INVALID_ALARM);
}
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
/* convert val to rval */
if ( prec->mask != 0 ) {
if(prec->val==0) prec->rval = 0;
else prec->rval = prec->mask;
} else prec->rval = (epicsUInt32)prec->val;
}
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
/* convert val to rval */
prec->val=prec->ivov;
if ( prec->mask != 0 ) {
if(prec->val==0) prec->rval = 0;
else prec->rval = prec->mask;
} else prec->rval = (epicsUInt32)prec->val;
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"bo:process Illegal IVOA field");
}
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, NULL);
if((prec->val==1) && (prec->high>0)){
myCallback *pcallback;
pcallback = (myCallback *)(prec->rpvt);
callbackSetPriority(prec->prio, &pcallback->callback);
callbackRequestDelayed(&pcallback->callback,(double)prec->high);
}
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
if((prec->val==1) && (prec->high>0)){
myCallback *pcallback;
pcallback = (myCallback *)(prec->rpvt);
callbackSetPriority(prec->prio, &pcallback->callback);
callbackRequestDelayed(&pcallback->callback,(double)prec->high);
}
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
@@ -277,17 +267,17 @@ static long special(DBADDR *paddr, int after)
int special_type = paddr->special;
switch(special_type) {
case(SPC_MOD):
if (dbGetFieldIndex(paddr) == boRecordSIMM) {
if (!after)
recGblSaveSimm(prec->sscn, &prec->oldsimm, prec->simm);
else
recGblCheckSimm((dbCommon *)prec, &prec->sscn, prec->oldsimm, prec->simm);
return(0);
}
default:
recGblDbaddrError(S_db_badChoice, paddr, "bo: special");
return(S_db_badChoice);
case(SPC_MOD):
if (dbGetFieldIndex(paddr) == boRecordSIMM) {
if (!after)
recGblSaveSimm(prec->sscn, &prec->oldsimm, prec->simm);
else
recGblCheckSimm((dbCommon *)prec, &prec->sscn, prec->oldsimm, prec->simm);
return(0);
}
default:
recGblDbaddrError(S_db_badChoice, paddr, "bo: special");
return(S_db_badChoice);
}
}
@@ -321,29 +311,29 @@ static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
static long get_enum_str(const DBADDR *paddr, char *pstring)
{
boRecord *prec=(boRecord *)paddr->precord;
int index;
unsigned short *pfield = (unsigned short *)paddr->pfield;
boRecord *prec=(boRecord *)paddr->precord;
int index;
unsigned short *pfield = (unsigned short *)paddr->pfield;
index = dbGetFieldIndex(paddr);
if(index!=indexof(VAL)) {
strcpy(pstring,"Illegal_Value");
strcpy(pstring,"Illegal_Value");
} else if(*pfield==0) {
strncpy(pstring,prec->znam,sizeof(prec->znam));
pstring[sizeof(prec->znam)] = 0;
strncpy(pstring,prec->znam,sizeof(prec->znam));
pstring[sizeof(prec->znam)] = 0;
} else if(*pfield==1) {
strncpy(pstring,prec->onam,sizeof(prec->onam));
pstring[sizeof(prec->onam)] = 0;
strncpy(pstring,prec->onam,sizeof(prec->onam));
pstring[sizeof(prec->onam)] = 0;
} else {
strcpy(pstring,"Illegal_Value");
strcpy(pstring,"Illegal_Value");
}
return(0);
}
static long get_enum_strs(const DBADDR *paddr,struct dbr_enumStrs *pes)
{
boRecord *prec=(boRecord *)paddr->precord;
boRecord *prec=(boRecord *)paddr->precord;
/*SETTING no_str=0 breaks channel access clients*/
pes->no_str = 2;
@@ -367,60 +357,60 @@ static long put_enum_str(const DBADDR *paddr, const char *pstring)
static void checkAlarms(boRecord *prec)
{
unsigned short val = prec->val;
unsigned short val = prec->val;
/* check for udf alarm */
if(prec->udf == TRUE ){
recGblSetSevr(prec,UDF_ALARM,prec->udfs);
}
/* check for udf alarm */
if(prec->udf == TRUE ){
recGblSetSevr(prec,UDF_ALARM,prec->udfs);
}
/* check for state alarm */
if (val == 0){
recGblSetSevr(prec,STATE_ALARM,prec->zsv);
}else{
recGblSetSevr(prec,STATE_ALARM,prec->osv);
}
/* check for state alarm */
if (val == 0){
recGblSetSevr(prec,STATE_ALARM,prec->zsv);
}else{
recGblSetSevr(prec,STATE_ALARM,prec->osv);
}
/* check for cos alarm */
if(val == prec->lalm) return;
recGblSetSevr(prec,COS_ALARM,prec->cosv);
prec->lalm = val;
return;
if(val == prec->lalm) return;
recGblSetSevr(prec,COS_ALARM,prec->cosv);
prec->lalm = val;
return;
}
static void monitor(boRecord *prec)
{
unsigned short monitor_mask;
unsigned short monitor_mask;
monitor_mask = recGblResetAlarms(prec);
/* check for value change */
if (prec->mlst != prec->val){
/* post events for value change and archive change */
monitor_mask |= (DBE_VALUE | DBE_LOG);
/* update last value monitored */
prec->mlst = prec->val;
}
monitor_mask = recGblResetAlarms(prec);
/* check for value change */
if (prec->mlst != prec->val){
/* post events for value change and archive change */
monitor_mask |= (DBE_VALUE | DBE_LOG);
/* update last value monitored */
prec->mlst = prec->val;
}
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(prec,&prec->val,monitor_mask);
}
if(prec->oraw!=prec->rval) {
db_post_events(prec,&prec->rval,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->oraw = prec->rval;
}
if(prec->orbv!=prec->rbv) {
db_post_events(prec,&prec->rbv,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->orbv = prec->rbv;
}
return;
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(prec,&prec->val,monitor_mask);
}
if(prec->oraw!=prec->rval) {
db_post_events(prec,&prec->rval,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->oraw = prec->rval;
}
if(prec->orbv!=prec->rbv) {
db_post_events(prec,&prec->rbv,
monitor_mask|DBE_VALUE|DBE_LOG);
prec->orbv = prec->rbv;
}
return;
}
static long writeValue(boRecord *prec)
{
struct bodset *pdset = (struct bodset *) prec->dset;
bodset *pdset = (bodset *) prec->dset;
long status = 0;
if (!prec->pact) {
+30 -11
View File
@@ -48,7 +48,8 @@ recordtype(bo) {
The binary output record has the standard fields for specifying under what
circumstances the record will be processed. The fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
L<Scan Fields|dbCommonRecord/Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Note that I/O event scanning is only supported for those card
types that interrupt.
@@ -147,8 +148,8 @@ corresponding to the VAL's state. So, if the value is 1, C<get_enum_str()>
will return the string in the ONAM field: and if 0, C<get_enum_str()> will
return the ZNAM string.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields ZNAM, ONAM, NAME, DESC
@@ -164,13 +165,13 @@ C<MAJOR>. The ZSV holds the severity for the zero state; OSV for the one
state. COSV is used to cause an alarm whenever the state changes between
states (0-1, 1-0) and its severity is configured as MINOR or MAJOR.
See L<Invalid Alarm Output Action> for more information on the IVOA and
IVOV fields. L<Alarm Fields> lists other fields related to alarms that are
See L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields> for more information on the IVOA and
IVOV fields. L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related to alarms that are
common to all record types.
=fields ZSV, OSV, COSV, IVOA, IVOV
=head3 Run-Time and Simulation Mode Parameters
=head3 Run-Time Parameters
These parameters are used by the run-time code for processiong the binary
output. They are not configurable using a configuration tool. They
@@ -201,15 +202,33 @@ The WPDT field is a private field for honoring seconds to hold HIGH.
=fields ORAW, MASK, RBV, ORBV, LALM, MLST, RPVT, WDPT
The following fields are used to operate the binary output in the
simulation mode. See L<Fields Common to Many Record Types> for more
information on these fields.
=head3 Simulation Mode Parameters
=fields SIOL, SIML, SIMM, SIMS
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is written through SIOL.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Output Simulation Fields|dbCommonOutput/Output Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SIMS, SDLY, SSCN
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct boRecord;
%typedef struct bodset {
% dset common; /*init_record returns:(0,2)=>(success,success no convert*/
% long (*write_bo)(struct boRecord *prec); /*returns: (-1,0)=>(failure,success)*/
%} bodset;
%#define HAS_bodset
%
field(VAL,DBF_ENUM) {
prompt("Current Value")
promptgroup("50 - Output")
@@ -475,7 +494,7 @@ Check alarms: This routine checks to see if the new VAL causes the alarm
status and severity to change. If so, NSEV, NSTA, and LALM are set.
=item 4.
Check severity and write the new value. See L<Invalid Alarm Output Action>
Check severity and write the new value. See L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields>
for more information on how INVALID alarms affect output.
=item 5.
+16 -16
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Record Support Routines for Calculation records */
@@ -43,7 +43,7 @@
#define report NULL
#define initialize NULL
static long init_record(struct dbCommon *prec, int pass);
static long init_record(struct dbCommon *pcommon, int pass);
static long process(struct dbCommon *prec);
static long special(DBADDR *paddr, int after);
#define get_value NULL
@@ -206,7 +206,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
calcRecord *prec = (calcRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
int linkNumber;
switch (fieldIndex) {
case indexof(VAL):
case indexof(HIHI):
@@ -234,7 +234,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
{
calcRecord *prec = (calcRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
case indexof(HIHI):
@@ -281,24 +281,24 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
static void checkAlarms(calcRecord *prec, epicsTimeStamp *timeLast)
{
enum {
range_Lolo = 1,
range_Low,
range_Normal,
range_High,
range_Hihi
} alarmRange;
static const epicsEnum16 range_stat[] = {
SOFT_ALARM, LOLO_ALARM, LOW_ALARM,
NO_ALARM, HIGH_ALARM, HIHI_ALARM
};
enum {
range_Lolo = 1,
range_Low,
range_Normal,
range_High,
range_Hihi
} alarmRange;
static const epicsEnum16 range_stat[] = {
SOFT_ALARM, LOLO_ALARM, LOW_ALARM,
NO_ALARM, HIGH_ALARM, HIHI_ALARM
};
double val, hyst, lalm, alev, aftc, afvl;
epicsEnum16 asev;
if (prec->udf) {
recGblSetSevr(prec, UDF_ALARM, prec->udfs);
prec->afvl = 0;
prec->afvl = 0;
return;
}
+11 -38
View File
@@ -16,32 +16,7 @@ then be used.
=head2 Parameter Fields
The fields in the record fall into the following categories:
=over 1
=item *
scan parameters
=item *
read parameters
=item *
expression parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
monitor parameters
=item *
run-time parameters
=back
The record-specific fields are described below, grouped by functionality.
=recordtype calc
@@ -52,13 +27,8 @@ recordtype(calc) {
=head3 Scan Parameters
The Calc record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Since the Calc record supports no direct interfaces to
hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot
be C<I/O Intr>.
=fields SCAN
circumstances the record will be processed.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Read Parameters
@@ -318,10 +288,13 @@ XOR : Bitwise Exclusive Or
C<~> : One's Complement
=item *
C<<< << >>> : Left shift
C<<< << >>> : Arithmetic Left Shift
=item *
C<<< >> >>> : Right shift
C<<< >> >>> : Arithmetic Right Shift
=item *
C<<<< >>> >>>> : Logical Right Shift
=back
@@ -463,8 +436,8 @@ solely for an operator's sake and does not have to be used.
The HOPR and LOPR fields only refer to the limits of the VAL, HIHI, HIGH,
LOW and LOLO fields. PREC controls the precision of the VAL field.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, PREC, HOPR, LOPR, NAME, DESC
@@ -481,7 +454,7 @@ limit alarms for the VAL field and the severity corresponding to those
conditions.
The HYST field defines an alarm deadband for each limit. See L<Alarm Specification>
for a complete explanation of alarms of these fields. L<Alarm Fields>
for a complete explanation of alarms of these fields. L<Alarm Fields|dbCommonRecord/Alarm Fields>
lists other fields related to alarms that are common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
+10 -20
View File
@@ -90,16 +90,6 @@ epicsExportAddress(int, calcoutODLYprecision);
double calcoutODLYlimit = 100000;
epicsExportAddress(double, calcoutODLYlimit);
typedef struct calcoutDSET {
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write;
}calcoutDSET;
/* To provide feedback to the user as to the connection status of the
* links (.INxV and .OUTV), the following algorithm has been implemented ...
*
@@ -142,7 +132,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
double *pvalue;
epicsEnum16 *plinkValid;
short error_number;
calcoutDSET *pcalcoutDSET;
calcoutdset *pcalcoutDSET;
rpvtStruct *prpvt;
if (pass == 0) {
@@ -150,13 +140,13 @@ static long init_record(struct dbCommon *pcommon, int pass)
return 0;
}
if (!(pcalcoutDSET = (calcoutDSET *)prec->dset)) {
if (!(pcalcoutDSET = (calcoutdset *)prec->dset)) {
recGblRecordError(S_dev_noDSET, (void *)prec, "calcout:init_record");
return S_dev_noDSET;
}
/* must have write defined */
if ((pcalcoutDSET->number < 5) || (pcalcoutDSET->write ==NULL)) {
if ((pcalcoutDSET->common.number < 5) || (pcalcoutDSET->write ==NULL)) {
recGblRecordError(S_dev_missingSup, (void *)prec, "calcout:init_record");
return S_dev_missingSup;
}
@@ -220,8 +210,8 @@ static long init_record(struct dbCommon *pcommon, int pass)
prpvt->cbScheduled = 0;
prec->epvt = eventNameToHandle(prec->oevt);
if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
if (pcalcoutDSET->common.init_record) pcalcoutDSET->common.init_record(pcommon);
prec->pval = prec->val;
prec->mlst = prec->val;
prec->alst = prec->val;
@@ -271,7 +261,7 @@ static long process(struct dbCommon *pcommon)
doOutput = (prec->val != 0.0);
break;
default:
doOutput = 0;
doOutput = 0;
break;
}
prec->pval = prec->val;
@@ -468,7 +458,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
int linkNumber;
switch (fieldIndex) {
case indexof(VAL):
case indexof(HIHI):
@@ -484,7 +474,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
case indexof(ODLY):
recGblGetGraphicDouble(paddr,pgd);
pgd->lower_disp_limit = 0.0;
break;
break;
default:
linkNumber = get_linkNumber(fieldIndex);
if (linkNumber >= 0) {
@@ -500,7 +490,7 @@ static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
{
calcoutRecord *prec = (calcoutRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
case indexof(HIHI):
@@ -768,7 +758,7 @@ static void checkLinks(calcoutRecord *prec)
static long writeValue(calcoutRecord *prec)
{
calcoutDSET *pcalcoutDSET = (calcoutDSET *)prec->dset;
calcoutdset *pcalcoutDSET = (calcoutdset *)prec->dset;
if (!pcalcoutDSET || !pcalcoutDSET->write) {
@@ -22,35 +22,7 @@ Wait record.
=head2 Parameter Fields
The fields in this record fall into these categories:
=over 1
=item *
scan parameters
=item *
read parameters
=item *
expression parameters
=item *
output parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
monitor parameters
=item *
run-time parameters
=back
The record-specific fields are described below, grouped by functionality.
=recordtype calcout
@@ -80,11 +52,8 @@ recordtype(calcout) {
=head3 Scan Parameters
The Calcout record has the standard fields for specifying under what
circumstances the record will be processed. The fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Since the Calcout record supports no direct interfaces to
hardware, it cannot be scanned on I/O interrupt, so its SCAN field cannot
be C<I/O Intr>.
circumstances the record will be processed.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Read Parameters
@@ -99,9 +68,6 @@ example, whether or not the specified PV was found and a link to it
established. See L<Operator Display Parameters> for an explanation of these
fields.
See L<Address Specification> for information on how to specify database
links.
=fields INPA, INPB, INPC, INPD, INPE, INPF, INPG, INPH, INPI, INPJ, INPK, INPL
=head3 Expression
@@ -350,10 +316,13 @@ XOR : Bitwise Exclusive Or
C<~> : One's Complement
=item *
C<<< << >>> : Left shift
C<<< << >>> : Arithmetic Left Shift
=item *
C<<< >> >>> : Right shift
C<<< >> >>> : Arithmetic Right Shift
=item *
C<<<< >>> >>>> : Logical Right Shift
=back
@@ -604,8 +573,8 @@ is set to one.
The DLYA field is set to one during the delay specified in ODLY.
See L<Fields Common to All Record Types> for more information on the record
name (NAME) and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, PREC, HOPR, LOPR, INAV, INBV, INCV, INDV, INEV, INFV, INGV, INHV, INIV, INJV, INKV, INLV, OUTV, CLCV, OCLV, DLYA, NAME, DESC
@@ -659,6 +628,14 @@ manner for the VAL field.
=cut
include "dbCommon.dbd"
%/* Declare Device Support Entry Table */
%struct calcoutRecord;
%typedef struct calcoutdset {
% dset common;
% long (*write)(struct calcoutRecord *prec);
%} calcoutdset;
%#define HAS_calcoutdset
%
field(RPVT,DBF_NOACCESS) {
prompt("Record Private")
special(SPC_NOMOD)
@@ -44,8 +44,6 @@ The record-specific fields are described below.
=recordtype compress
...
=cut
menu(compressALG) {
@@ -70,7 +68,8 @@ The record-specific fields are described below, grouped by functionality.
The compression record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification>
L<Scan Fields|dbCommonRecord/Scan Fields>. In addition, L<Scanning Specification>
explains how these fields are used. Since the compression record supports no
direct interfaces to hardware, its SCAN field cannot specify C<<< I/O Intr >>>.
@@ -197,14 +196,14 @@ PREC controls the floating-point precision whenever C<<< get_precision >>> is
called, and the field being referenced is the VAL field (i.e., one of the values
contained in the circular buffer).
See L<Fields Common to All Record Types>
for more on the record name (NAME) and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=head3 Alarm Parameters
The compression record has the alarm parameters common to all record types
described in L<Alarm Fields>.
described in L<Alarm Fields|dbCommonRecord/Alarm Fields>.
=head3 Run-time Parameters
@@ -234,7 +233,7 @@ appropriate fields in the record.
long process(struct dbCommon *precord)
See L<Record Processing> below.
See L</"Record Processing"> below.
long special(struct dbAddr *paddr, int after)
+24 -24
View File
@@ -2,17 +2,17 @@
* Copyright (c) 2002 Southeastern Universities Research Association, as
* Operator of Thomas Jefferson National Accelerator Facility.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recDfanout.c - Record Support Routines for Dfanout records */
/*
* Original Author: Matt Bickley (Sometime in 1994)
* Original Author: Matt Bickley (Sometime in 1994)
*
* Modification Log:
* -----------------
* .01 1994 mhb Started with longout record to make the data fanout
* .02 May 10, 96 jt Bug Fix
* .02 May 10, 96 jt Bug Fix
* .03 11SEP2000 mrk LONG=>DOUBLE, add SELL,SELN,SELM
*/
@@ -62,24 +62,24 @@ static long get_control_double(DBADDR *,struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *,struct dbr_alDouble *);
rset dfanoutRSET={
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
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,dfanoutRSET);
@@ -183,8 +183,8 @@ static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
case indexof(LALM):
case indexof(ALST):
case indexof(MLST):
pcd->upper_ctrl_limit = prec->hopr;
pcd->lower_ctrl_limit = prec->lopr;
pcd->upper_ctrl_limit = prec->hopr;
pcd->lower_ctrl_limit = prec->lopr;
break;
default:
recGblGetControlDouble(paddr,pcd);
@@ -194,7 +194,7 @@ static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
{
dfanoutRecord *prec=(dfanoutRecord *)paddr->precord;
if(dbGetFieldIndex(paddr) == indexof(VAL)) {
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
@@ -16,32 +16,7 @@ device support.
=head2 Parameter Fields
The fields in this record can be classified into the following categories:
=over
=item *
scan parameters
=item *
desired output parameters
=item *
write parameters
=item *
operator display parameters
=item *
alarm parameters
=item *
monitor parameters
=item *
run-time and simulation mode parameters
=back
The record-specific fields are described below, grouped by functionality.
=recordtype dfanout
@@ -58,11 +33,8 @@ recordtype(dfanout) {
=head3 Scan Parameters
The data fanout record has the standard fields for specifying under what
circumstances it will be processed. These fields are listed in
L<Scan Fields>. In addition, L<Scanning Specification> explains how these
fields are used. Since the data fanout record supports no direct interfaces
to hardware, it cannot be scanned on I/O interrupt, so its SCAN field
cannot be C<I/O Intr>.
circumstances it will be processed.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Desired Output Parameters
@@ -131,8 +103,8 @@ displays. They apply to the VAL, HIHI, HIGH, LOW, and LOLO fields. The
record support routines C<get_graphic_double()> and C<get_control_double()>
retrieve HOPR and LOPR.
See L<Fields Common to All Record Types> for more on the record name (NAME)
and description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, HOPR, LOPR, NAME, DESC
@@ -148,7 +120,7 @@ NO_ALARM, MINOR, or MAJOR. In the hysteresis field (HYST) can be entered a
number which serves as the deadband on the limit alarms.
See L<Alarm Specification> for a complete explanation of alarms and these
fields. L<Alarm Fields> lists other fields related to alarms that are
fields. L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related to alarms that are
common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
+39 -47
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recEvent.c - Record Support Routines for Event records */
@@ -59,35 +59,27 @@ static long special(DBADDR *, int);
#define get_alarm_double NULL
rset eventRSET={
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
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,eventRSET);
struct eventdset { /* event input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_event;/*(0)=> success */
};
static void monitor(eventRecord *);
static long readValue(eventRecord *);
@@ -95,7 +87,7 @@ static long readValue(eventRecord *);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct eventRecord *prec = (struct eventRecord *)pcommon;
struct eventdset *pdset;
eventdset *pdset;
long status=0;
if (pass == 0) return 0;
@@ -103,8 +95,8 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
recGblInitConstantLink(&prec->siol, DBF_STRING, &prec->sval);
if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) )
status=(*pdset->init_record)(prec);
if( (pdset=(eventdset *)(prec->dset)) && (pdset->common.init_record) )
status=(*pdset->common.init_record)(pcommon);
prec->epvt = eventNameToHandle(prec->val);
@@ -114,28 +106,28 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct eventRecord *prec = (struct eventRecord *)pcommon;
struct eventdset *pdset = (struct eventdset *)(prec->dset);
long status=0;
unsigned char pact=prec->pact;
eventdset *pdset = (eventdset *)(prec->dset);
long status=0;
unsigned char pact=prec->pact;
if((pdset!=NULL) && (pdset->number >= 5) && pdset->read_event )
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
postEvent(prec->epvt);
if((pdset!=NULL) && (pdset->common.number >= 5) && pdset->read_event )
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
postEvent(prec->epvt);
recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
/* check event list */
monitor(prec);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
@@ -173,7 +165,7 @@ static void monitor(eventRecord *prec)
static long readValue(eventRecord *prec)
{
struct eventdset *pdset = (struct eventdset *) prec->dset;
eventdset *pdset = (eventdset *) prec->dset;
long status = 0;
if (!prec->pact) {
@@ -15,27 +15,7 @@ handler routine for I/O Event-scanned records.
=head2 Parameter Fields
The records in this field fall into the following groups of parameters:
=over
=item *
scan parameters
=item *
read parameters
=item *
event number parameters
=item *
simulation mode parameters
=back
The record-specific fields are described below, grouped by functionality.
=recordtype event
@@ -44,14 +24,23 @@ simulation mode parameters
recordtype(event) {
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct eventRecord;
%typedef struct eventdset {
% dset common; /*init_record returns: (-1,0)=>(failure,success)*/
% long (*read_event)(struct eventRecord *prec); /*(0)=> success */
%} eventdset;
%#define HAS_eventdset
%
=head3 Scan Parameters
The event record has the standard fields for specifying under what circumstances
it will be processed. If the SCAN field specifies C<I/O Intr>, then device
support will provide an interrupt handler, posting an event number when an I/O
interrupt occurs. These fields are listed in L<Scan Fields>. In addition,
L<Scanning Specification> explains how the scanning fields work. Note that I/O
event scanning is only supported for those card types that interrupt.
interrupt occurs.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Event Number Parameters
@@ -102,8 +91,9 @@ access link. For soft records, the DTYP field should specify C<Soft Channel>.
=head3 Operator Display Parameters
See L<Fields Common to All Record Types> for more on the record name (NAME) and
description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields NAME, DESC
@@ -266,7 +256,7 @@ C<init_record()> routine.
get_ioint_info(int cmd, struct dbCommon *precord, IOSCANPVT *ppvt)
This routine is called by the ioEventScan system each time the record is added
or deleted from an I/O event scan list. cmd has the value (0,1) if the record is
or deleted from an I/O event scan list. C<cmd> has the value (0,1) if the record is
being (added to, deleted from) an I/O event list. It must be provided for any
device type that can use the ioEvent scanner.
+1 -1
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -17,27 +17,11 @@ process. If more than sixteen are needed, one of the forward links in the fanout
record (or its FLNK field) can point to another fanout record.
B<NOTE: Fanout records only propagate processing, not data.> The dfanout or
data fanout record can, on the other hand, send data to other records.
Data Fanout record can, on the other hand, send data to other records.
=head2 Parameter Fields
The fanout record's fields fall into the following categories:
=over
=item *
scan parameters
=item *
operator display parameters
=item *
run-time parameters.
=back
The record-specific fields are described below, grouped by functionality.
=recordtype fanout
@@ -113,9 +97,7 @@ retrieved from SELL each time the record is processed and can also be changed
via dbPuts.
The Fanout record also has the standard scanning fields common to all records.
These fields are listed in L<Scan Fields>. In addition,
L<Scanning Specification> explains in more detail how forward links and the
scanning algorithms work.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=fields SELM, SELN, SELL, OFFS, SHFT, LNK0, LNK1, LNK2, LNK3, LNK4, LNK5, LNK6, LNK7, LNK8, LNK9, LNKA, LNKB, LNKC, LNKD, LNKE, LNKF
@@ -238,15 +220,16 @@ scanning algorithms work.
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. See
L<Fields Common to All Record Types> for more on these fields.
L<Fields Common to All Record Types|dbCommonRecord/Operator Display Parameters>
for more on these fields.
=fields NAME, DESC
=head3 Alarm Parameters
The Fanout record has the alarm parameters common to all record types.
L<Alarm Fields> lists other fields related to a alarms that are common to all
record types.
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists the fields related to
alarms that are common to all record types.
=head3 Run-time Parameters
+25 -41
View File
@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* histogramRecord.c - Record Support Routines for Histogram records */
@@ -87,17 +87,6 @@ epicsExportAddress(rset,histogramRSET);
int histogramSDELprecision = 2;
epicsExportAddress(int, histogramSDELprecision);
struct histogramdset { /* histogram input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_histogram;/*(0,2)=> success and add_count, don't add_count)*/
/* if add_count then sgnl added to array */
DEVSUPFUN special_linconv;
};
/* control block for callback*/
typedef struct myCallback {
epicsCallback callback;
@@ -133,39 +122,34 @@ static void wdogCallback(epicsCallback *arg)
return;
}
static long wdogInit(histogramRecord *prec)
static void wdogInit(histogramRecord *prec)
{
myCallback *pcallback;
if (!prec->wdog && prec->sdel > 0) {
/* initialize a callback object */
pcallback = calloc(1, sizeof(myCallback));
pcallback->prec = prec;
if (!pcallback)
return -1;
callbackSetCallback(wdogCallback, &pcallback->callback);
callbackSetUser(pcallback, &pcallback->callback);
callbackSetPriority(priorityLow, &pcallback->callback);
prec->wdog = pcallback;
}
if (!prec->wdog)
return -1;
pcallback = prec->wdog;
if (!pcallback)
return -1;
if (prec->sdel > 0) {
myCallback *pcallback = prec->wdog;
if (!pcallback) {
/* initialize a callback object */
pcallback = calloc(1, sizeof(myCallback));
if (!pcallback)
return;
pcallback->prec = prec;
callbackSetCallback(wdogCallback, &pcallback->callback);
callbackSetUser(pcallback, &pcallback->callback);
callbackSetPriority(priorityLow, &pcallback->callback);
prec->wdog = pcallback;
}
/* start new timer on monitor */
callbackRequestDelayed(&pcallback->callback, prec->sdel);
}
return 0;
}
static long init_record(struct dbCommon *pcommon, int pass)
{
struct histogramRecord *prec = (struct histogramRecord *)pcommon;
struct histogramdset *pdset;
histogramdset *pdset;
if (pass == 0) {
/* allocate space for histogram array */
@@ -186,21 +170,21 @@ static long init_record(struct dbCommon *pcommon, int pass)
recGblInitConstantLink(&prec->siol, DBF_DOUBLE, &prec->sval);
/* must have device support defined */
pdset = (struct histogramdset *) prec->dset;
pdset = (histogramdset *) prec->dset;
if (!pdset) {
recGblRecordError(S_dev_noDSET, prec, "histogram: init_record");
return S_dev_noDSET;
}
/* must have read_histogram function defined */
if (pdset->number < 6 || !pdset->read_histogram) {
if (pdset->common.number < 6 || !pdset->read_histogram) {
recGblRecordError(S_dev_missingSup, prec, "histogram: init_record");
return S_dev_missingSup;
}
/* call device support init_record */
if (pdset->init_record) {
long status = pdset->init_record(prec);
if (pdset->common.init_record) {
long status = pdset->common.init_record(pcommon);
if (status)
return status;
@@ -211,7 +195,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct histogramRecord *prec = (struct histogramRecord *)pcommon;
struct histogramdset *pdset = (struct histogramdset *) prec->dset;
histogramdset *pdset = (histogramdset *) prec->dset;
int pact = prec->pact;
long status;
@@ -380,7 +364,7 @@ static long clear_histogram(histogramRecord *prec)
static long readValue(histogramRecord *prec)
{
struct histogramdset *pdset = (struct histogramdset *) prec->dset;
histogramdset *pdset = (histogramdset *) prec->dset;
long status = 0;
if (!prec->pact) {
@@ -1,173 +0,0 @@
#*************************************************************************
# 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 is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(histogramCMD) {
choice(histogramCMD_Read,"Read")
choice(histogramCMD_Clear,"Clear")
choice(histogramCMD_Start,"Start")
choice(histogramCMD_Stop,"Stop")
}
recordtype(histogram) {
include "dbCommon.dbd"
field(VAL,DBF_NOACCESS) {
prompt("Value")
asl(ASL0)
special(SPC_DBADDR)
extra("void * val")
#=type ULONG[]
#=read Yes
#=write Yes
}
field(NELM,DBF_USHORT) {
prompt("Num of Array Elements")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(CSTA,DBF_SHORT) {
prompt("Collection Status")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(CMD,DBF_MENU) {
prompt("Collection Control")
asl(ASL0)
special(SPC_CALC)
interest(1)
menu(histogramCMD)
}
field(ULIM,DBF_DOUBLE) {
prompt("Upper Signal Limit")
promptgroup("30 - Action")
special(SPC_RESET)
interest(1)
prop(YES)
}
field(LLIM,DBF_DOUBLE) {
prompt("Lower Signal Limit ")
promptgroup("30 - Action")
special(SPC_RESET)
interest(1)
prop(YES)
}
field(WDTH,DBF_DOUBLE) {
prompt("Element Width")
special(SPC_NOMOD)
interest(3)
}
field(SGNL,DBF_DOUBLE) {
prompt("Signal Value")
special(SPC_MOD)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(SVL,DBF_INLINK) {
prompt("Signal Value Location")
promptgroup("40 - Input")
interest(1)
}
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
interest(4)
extra("epicsUInt32 *bptr")
}
field(WDOG,DBF_NOACCESS) {
prompt("Watchdog callback")
special(SPC_NOMOD)
interest(4)
extra("void * wdog")
}
field(MDEL,DBF_SHORT) {
prompt("Monitor Count Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MCNT,DBF_SHORT) {
prompt("Counts Since Monitor")
special(SPC_NOMOD)
interest(3)
}
field(SDEL,DBF_DOUBLE) {
prompt("Monitor Seconds Dband")
promptgroup("80 - Display")
special(SPC_RESET)
interest(1)
}
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SVAL,DBF_DOUBLE) {
prompt("Simulation Value")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
}
field(HOPR,DBF_ULONG) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_ULONG) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
}
variable(histogramSDELprecision, int)
@@ -0,0 +1,456 @@
#*************************************************************************
# 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 is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
=title Histogram Record (histogram)
The histogram record is used to store frequency counts of a signal into an array
of arbitrary length. The user can configure the range of the signal value that
the array will store. Anything outside this range will be ignored.
=head2 Parameter Fields
The record-specific fields are described below.
=recordtype histogram
=cut
menu(histogramCMD) {
choice(histogramCMD_Read,"Read")
choice(histogramCMD_Clear,"Clear")
choice(histogramCMD_Start,"Start")
choice(histogramCMD_Stop,"Stop")
}
recordtype(histogram) {
=head3 Read Parameters
The SVL is the input link where the record reads its value. It can be a
constant, a database link, or a channel access link. If SVL is a database or
channel access link, then SGNL is read from SVL. If SVL is a constant, then SGNL
is initialized with the constant value but can be changed via dbPuts. The C<Soft
Channel> device support module can be specified in the DTYP field.
The ULIM and LLIM fields determine the usable range of signal values. Any value
of SGNL below LLIM or above ULIM is outside the range and will not be stored in
the array. In the NELM field the user must specify the array size, e.g., the
number of array elements. Each element in the NELM field holds the counts for an
interval of the range of signal counts, the range specified by ULIM and LLIM.
These intervals are determined by dividing the range by NELM:
(ULIM - LLIM) / NELM.
=fields SVL, SGNL, DTYP, NELM, ULIM, LLIM
=head3 Operator Display Parameters
These parameters are used to present meaningful data to the operator. These
fields are used to display the value and other parameters of the histogram
either textually or graphically. See
L<Fields Common to All Record Types|dbCommonRecord/Operator Display Parameters>
for more on the record name (NAME) and description (DESC) fields.
=fields NAME, DESC
=head3 Alarm Parameters
The Histogram record has the alarm parameters common to all record types.
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists the fields related to
alarms that are common to all record types.
=head3 Monitor Parameters
The MDEL field implements the monitor count deadband. Only when MCNT is greater
than the value given to MDEL are monitors triggered, MCNT being the number of
counts since the last time the record was processed. If MDEL is -1, everytime
the record is processed, a monitor is triggered regardless.
If SDEL is greater than 0, it causes a callback routine to be called. The number
specified in SDEL is the callback routines interval. The callback routine is
called every SDEL seconds. The callback routine posts an event if MCNT is
greater than 0.
=fields MDEL, SDEL
=head3 Run-time and Simulation Mode Parameters
These parameters are used by the run-time code for processing the histogram.
They are not configurable by the user prior to run-time. They represent the
current state of the record. Many of them are used to process the histogram more
efficiently.
The BPTR field contains a pointer to the unsigned long array of frequency
values. The VAL field references this array as well. However, the BPTR field is
not accessible at run-time.
The MCNT field keeps counts the number of signal counts since the last monitor
was invoked.
The collections controls field (CMD) is a menu field with five choices:
=menu histogramCMD
When CMD is C<Read>, the record retrieves its values and adds them to the signal
array. This command will first clear the signal counts which have already been
read when it is first invoked.
The C<Clear> command erases the signal counts, setting the elements in the array
back to zero. Afterwards, the CMD field is set back to C<Read>.
The C<Start> command simply causes the record to read signal values into the
array. Unlike C<Read>, it doesn't clear the array first.
The C<Stop> command disables the reading of signal values into the array.
The C<Setup> command waits until the C<start> or C<read> command has been issued
to start counting.
The CSTA or collections status field implements the CMD field choices by
enabling or disabling the reading of values into the histogram array. While
FALSE, no signals are added to the array. While TRUE, signals are read and added
to the array. The field is initialized to TRUE. The C<Stop> command is the only
command that sets CSTA to FALSE. On the other hand, the C<Start> command is the
only command that sets it to TRUE. Thus, C<Start> must be invoked after each
C<Stop> command in order to enable counting; invoking C<Read> will not enable
signal counting after C<Stop> has been invoked.
A typical use of these fields would be to initialize the CMD field to C<Read>
(it is initialized to this command by default), to use the C<Stop> command to
disable counting when necessary, after which the C<Start> command can be invoked
to re-start the signal count.
The WDTH field is a private field that holds the signal width of the array
elements. For instance, if the LLIM was configured to be 4.0 and ULIM was
configured to be 12.0 and the NELM was set to 4, then the WDTH for each array
would be 2. Thus, it is (ULIM - LLIM) / NELM.
=fields BPTR, VAL, MCNT, CMD, CSTA, WDTH
The following fields are used to operate the histogram record in simulation
mode. See L<Fields Common to Many Record Types> for more information on the
simulation mode fields.
=fields SIOL, SVAL, SIML, SIMM, SIMS
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct histogramRecord;
%typedef struct histogramdset {
% dset common; /*init_record returns: (-1,0)=>(failure,success)*/
% long (*read_histogram)(struct histogramRecord *prec); /*(0,2)=> success and add_count, don't add_count); if add_count then sgnl added to array*/
% long (*special_linconv)(struct histogramRecord *prec, int after);
%} histogramdset;
%#define HAS_histogramdset
%
field(VAL,DBF_NOACCESS) {
prompt("Value")
asl(ASL0)
special(SPC_DBADDR)
extra("void * val")
#=type ULONG[]
#=read Yes
#=write Yes
}
field(NELM,DBF_USHORT) {
prompt("Num of Array Elements")
promptgroup("30 - Action")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(CSTA,DBF_SHORT) {
prompt("Collection Status")
special(SPC_NOMOD)
interest(1)
initial("1")
}
field(CMD,DBF_MENU) {
prompt("Collection Control")
asl(ASL0)
special(SPC_CALC)
interest(1)
menu(histogramCMD)
}
field(ULIM,DBF_DOUBLE) {
prompt("Upper Signal Limit")
promptgroup("30 - Action")
special(SPC_RESET)
interest(1)
prop(YES)
}
field(LLIM,DBF_DOUBLE) {
prompt("Lower Signal Limit ")
promptgroup("30 - Action")
special(SPC_RESET)
interest(1)
prop(YES)
}
field(WDTH,DBF_DOUBLE) {
prompt("Element Width")
special(SPC_NOMOD)
interest(3)
}
field(SGNL,DBF_DOUBLE) {
prompt("Signal Value")
special(SPC_MOD)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(SVL,DBF_INLINK) {
prompt("Signal Value Location")
promptgroup("40 - Input")
interest(1)
}
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
interest(4)
extra("epicsUInt32 *bptr")
}
field(WDOG,DBF_NOACCESS) {
prompt("Watchdog callback")
special(SPC_NOMOD)
interest(4)
extra("void * wdog")
}
field(MDEL,DBF_SHORT) {
prompt("Monitor Count Deadband")
promptgroup("80 - Display")
interest(1)
}
field(MCNT,DBF_SHORT) {
prompt("Counts Since Monitor")
special(SPC_NOMOD)
interest(3)
}
field(SDEL,DBF_DOUBLE) {
prompt("Monitor Seconds Dband")
promptgroup("80 - Display")
special(SPC_RESET)
interest(1)
}
field(SIOL,DBF_INLINK) {
prompt("Simulation Input Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SVAL,DBF_DOUBLE) {
prompt("Simulation Value")
}
field(SIML,DBF_INLINK) {
prompt("Simulation Mode Link")
promptgroup("90 - Simulate")
interest(1)
}
field(SIMM,DBF_MENU) {
prompt("Simulation Mode")
special(SPC_MOD)
interest(1)
menu(menuYesNo)
}
field(SIMS,DBF_MENU) {
prompt("Simulation Mode Severity")
promptgroup("90 - Simulate")
interest(2)
menu(menuAlarmSevr)
}
field(OLDSIMM,DBF_MENU) {
prompt("Prev. Simulation Mode")
special(SPC_NOMOD)
interest(4)
menu(menuSimm)
}
field(SSCN,DBF_MENU) {
prompt("Sim. Mode Scan")
promptgroup("90 - Simulate")
interest(1)
menu(menuScan)
initial("65535")
}
field(SDLY,DBF_DOUBLE) {
prompt("Sim. Mode Async Delay")
promptgroup("90 - Simulate")
interest(2)
initial("-1.0")
}
%#include "callback.h"
field(SIMPVT,DBF_NOACCESS) {
prompt("Sim. Mode Private")
special(SPC_NOMOD)
interest(4)
extra("epicsCallback *simpvt")
}
field(HOPR,DBF_ULONG) {
prompt("High Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
field(LOPR,DBF_ULONG) {
prompt("Low Operating Range")
promptgroup("80 - Display")
interest(1)
prop(YES)
}
=head2 Record Support
=head3 Record Support Routines
=head4 init_record
Using NELM, space for the unsigned long array is allocated and the width WDTH of
the array is calculated.
This routine initializes SIMM with the value of SIML if SIML type is CONSTANT
link or creates a channel access link if SIML type is PV_LINK. SVAL is likewise
initialized if SIOL is CONSTANT or PV_LINK.
This routine next checks to see that device support and a device support read
routine are available. If device support includes C<init_record()>, it is
called.
=head4 process
See next section.
=head4 special
Special is invoked whenever the fields CMD, SGNL, ULIM, or LLIM are changed.
If SGNL is changed, add_count is called.
If ULIM or LLIM are changed, WDTH is recalculated and clear_histogram is called.
If CMD is less or equal to 1, clear_histogram is called and CMD is reset to 0.
If CMD is 2, CSTA is set to TRUE and CMD is reset to 0. If CMD is 3, CSTA is set
to FALSE and CMD is reset to 0.
clear_histogram zeros out the histogram array. add_count increments the
frequency in the histogram array.
=head4 cvt_dbaddr
This is called by dbNameToAddr. It makes the dbAddr structure refer to the
actual buffer holding the array.
=head4 get_array_info
Obtains values from the array referenced by VAL.
=head4 put_array_info
Writes values into the array referenced by VAL.
=head3 Record Processing
Routine process implements the following algorithm:
=over
=item 1.
Check to see that the appropriate device support module exists. If it doesn't,
an error message is issued and processing is terminated with the PACT field set
to TRUE. This ensures that processes will no longer be called for this record.
Thus error storms will not occur.
=item 2.
readValue is called. See L<Input Records> for more information
=item 3.
If PACT has been changed to TRUE, the device support read routine has started
but has not completed writing the new value. In this case, the processing
routine merely returns, leaving PACT TRUE.
=item 4.
Add count to histogram array.
=item 5.
Check to see if monitors should be invoked. Alarm monitors are invoked if the
alarm status or severity has changed. Archive and value change monitors are
invoked if MDEL conditions are met. NSEV and NSTA are reset to 0.
=item 6.
Scan forward link if necessary, set PACT and INIT to FALSE, and return.
=back
=head2 Device Support
=head3 Fields Of Interest To Device Support
The device support routines are primarily interested in the following fields:
=fields PACT, DPVT, UDF, NSEV, NSTA, SVL, SGNL
=head3 Device Support Routines
Device support consists of the following routines:
=head4 long report(int level)
This optional routine is called by the IOC command C<dbior> and is passed the
report level that was requested by the user.
It should print a report on the state of the device support to stdout.
The C<level> parameter may be used to output increasingly more detailed
information at higher levels, or to select different types of information with
different levels.
Level zero should print no more than a small summary.
=head4 long init(int after)
This optional routine is called twice at IOC initialization time.
The first call happens before any of the C<init_record()> calls are made, with
the integer parameter C<after> set to 0.
The second call happens after all of the C<init_record()> calls have been made,
with C<after> set to 1.
=head4 init_record
init_record(precord)
This routine is called by the record support C<init_record()> routine. It makes
sure that SGNL is a CONSTANT, PV_LINK, DB_LINK, or CA_LINK. It also retrieves a
value for SVL from SGNL. If SGNL is none of the above, an error is generated.
=head4 read_histogram
read_histogram(*precord)
This routine is called by the record support routines. It retrieves a value for
SVL from SGNL.
=head3 Device Support For Soft Records
Only the device support module C<Soft Channel> is currently provided, though
other device support modules may be provided at the user's site.
=head4 Soft Channel
The C<Soft Channel> device support routine retrieves a value from SGNL. SGNL
must be CONSTANT, PV_LINK, DB_LINK, or CA_LINK.
=cut
}
variable(histogramSDELprecision, int)
+55 -63
View File
@@ -4,13 +4,13 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* int64inRecord.c - Record Support Routines for int64in records */
/*
* Original Author: Janet Anderson
* Date: 9/23/91
* Date: 9/23/91
*/
#include <stddef.h>
@@ -58,39 +58,31 @@ static long get_units(DBADDR *, char *);
#define put_enum_str NULL
static long get_graphic_double(DBADDR *, struct dbr_grDouble *);
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
rset int64inRSET={
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
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,int64inRSET);
struct int64indset { /* int64in input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_int64in; /*returns: (-1,0)=>(failure,success)*/
};
static void checkAlarms(int64inRecord *prec, epicsTimeStamp *timeLast);
static void monitor(int64inRecord *prec);
static long readValue(int64inRecord *prec);
@@ -99,7 +91,7 @@ static long readValue(int64inRecord *prec);
static long init_record(dbCommon *pcommon, int pass)
{
int64inRecord *prec = (int64inRecord*)pcommon;
struct int64indset *pdset;
int64indset *pdset;
long status;
if (pass == 0) return 0;
@@ -108,17 +100,17 @@ static long init_record(dbCommon *pcommon, int pass)
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
recGblInitConstantLink(&prec->siol, DBF_INT64, &prec->sval);
if(!(pdset = (struct int64indset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"int64in: init_record");
return(S_dev_noDSET);
if(!(pdset = (int64indset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"int64in: init_record");
return(S_dev_noDSET);
}
/* must have read_int64in function defined */
if( (pdset->number < 5) || (pdset->read_int64in == NULL) ) {
recGblRecordError(S_dev_missingSup,(void *)prec,"int64in: init_record");
return(S_dev_missingSup);
if ((pdset->common.number < 5) || (pdset->read_int64in == NULL)) {
recGblRecordError(S_dev_missingSup,(void *)prec,"int64in: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(prec))) return(status);
if (pdset->common.init_record) {
if ((status = pdset->common.init_record(pcommon))) return status;
}
prec->mlst = prec->val;
prec->alst = prec->val;
@@ -129,36 +121,36 @@ static long init_record(dbCommon *pcommon, int pass)
static long process(dbCommon *pcommon)
{
int64inRecord *prec = (int64inRecord*)pcommon;
struct int64indset *pdset = (struct int64indset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
epicsTimeStamp timeLast;
int64indset *pdset = (int64indset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
epicsTimeStamp timeLast;
if( (pdset==NULL) || (pdset->read_int64in==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_int64in");
return(S_dev_missingSup);
}
timeLast = prec->time;
if( (pdset==NULL) || (pdset->read_int64in==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_int64in");
return(S_dev_missingSup);
}
timeLast = prec->time;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
if (status==0) prec->udf = FALSE;
/* check for alarms */
checkAlarms(prec, &timeLast);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
/* check for alarms */
checkAlarms(prec, &timeLast);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
@@ -239,7 +231,7 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
return(0);
}
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
{
int64inRecord *prec=(int64inRecord *)paddr->precord;
@@ -265,7 +257,7 @@ static void checkAlarms(int64inRecord *prec, epicsTimeStamp *timeLast)
SOFT_ALARM, LOLO_ALARM, LOW_ALARM,
NO_ALARM, HIGH_ALARM, HIHI_ALARM
};
double aftc, afvl;
epicsInt64 val, hyst, lalm;
epicsInt64 alev;
@@ -397,7 +389,7 @@ static void monitor(int64inRecord *prec)
static long readValue(int64inRecord *prec)
{
struct int64indset *pdset = (struct int64indset *) prec->dset;
int64indset *pdset = (int64indset *) prec->dset;
long status = 0;
if (!prec->pact) {
@@ -43,10 +43,7 @@ that comes with Base.
The INP link field contains a database or channel access link or provides
hardware address information that the device support uses to determine where the
input data should come from.
The format for the INP field value depends on the device support layer that is
selected by the DTYP field.
See L<Address Specification|...> for a description of the various hardware
address formats supported.
=head3 Operator Display Parameters
@@ -111,6 +108,15 @@ monitoring deadband functionality.
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct int64inRecord;
%typedef struct int64indset {
% dset common;
% long (*read_int64in)(struct int64inRecord *prec);
%} int64indset;
%#define HAS_int64indset
%
field(VAL,DBF_INT64) {
prompt("Current value")
promptgroup("40 - Input")
@@ -238,29 +244,20 @@ monitoring deadband functionality.
interest(3)
}
=head3 Simulation Mode
=head3 Simulation Mode Parameters
The record provides several fields to support simulation of absent hardware.
If the SIML field is set it is used to read a value into the SIMM field, which
controls whether simulation is used or not:
The following fields are used to operate the record in simulation mode.
=over
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is fetched through SIOL (buffered in SVAL).
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
=item *
SIMM must be zero (C<NO>) for the record to request a value from the device
support.
See L<Input Simulation Fields|dbCommonInput/Input Simulation Fields>
for more information on simulation mode and its fields.
=item *
If SIMM is C<YES> and the SIOL link field is set, a simulated value in
engineering units is read using the link into the SVAL field, from where it will
subsequently be copied into the VAL field.
=back
The SIMS field can be set to give the record an alarm severity while it is in
simulation mode.
=fields SIML, SIMM, SIOL, SVAL, SIMS
=fields SIML, SIMM, SIOL, SVAL, SIMS, SDLY, SSCN
=cut
@@ -375,14 +372,30 @@ If PACT is FALSE, read the value, honoring simulation mode:
=item * If SIMM is C<NO>,
call the device support C<read_int64in> routine and return.
=item * If SIMM is C<YES>,
read the simulated value into SVAL using the SIOL link,
then copy the value into VAL and set UDF to 0 on success.
=item * If SIMM is C<YES>, then
=over
=item *
Set alarm status to SIMM_ALARM and severity to SIMS,
if SIMS is greater than zero.
=item *
If the record simulation processing is synchronous (SDLY < 0) or the record is
in the second phase of an asynchronous processing, call C<dbGetLink()>
to read the input value from SIOL into SVAL.
Set status to the return code from C<dbGetLink()>.
If the call succeeded, write the value to VAL and set UDF to 0.
Otherwise (record is in first phase of an asynchronous processing), set up a
callback processing with the delay specified in SDLY.
=back
=item * Raise an alarm for other values of SIMM.
=item * Set the record to the severity configured in SIMS.
=back
=item 3.
+92 -100
View File
@@ -9,8 +9,8 @@
/*
* Original Author: Janet Anderson
* Date: 9/23/91
*/
* Date: 9/23/91
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -58,36 +58,28 @@ static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
rset int64outRSET={
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
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,int64outRSET);
struct int64outdset { /* int64out input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_int64out;/*(-1,0)=>(failure,success*/
};
static void checkAlarms(int64outRecord *prec);
static void monitor(int64outRecord *prec);
static long writeValue(int64outRecord *prec);
@@ -97,28 +89,28 @@ static void convert(int64outRecord *prec, epicsInt64 value);
static long init_record(dbCommon *pcommon, int pass)
{
int64outRecord *prec = (int64outRecord*)pcommon;
struct int64outdset *pdset;
int64outdset *pdset;
long status=0;
if (pass == 0) return 0;
recGblInitSimm(pcommon, &prec->sscn, &prec->oldsimm, &prec->simm, &prec->siml);
if(!(pdset = (struct int64outdset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"int64out: init_record");
return(S_dev_noDSET);
if(!(pdset = (int64outdset *)(prec->dset))) {
recGblRecordError(S_dev_noDSET,(void *)prec,"int64out: init_record");
return(S_dev_noDSET);
}
/* must have write_int64out functions defined */
if( (pdset->number < 5) || (pdset->write_int64out == NULL) ) {
recGblRecordError(S_dev_missingSup,(void *)prec,"int64out: init_record");
return(S_dev_missingSup);
if ((pdset->common.number < 5) || (pdset->write_int64out == NULL)) {
recGblRecordError(S_dev_missingSup,(void *)prec,"int64out: init_record");
return(S_dev_missingSup);
}
if (prec->dol.type == CONSTANT) {
if(recGblInitConstantLink(&prec->dol,DBF_INT64,&prec->val))
prec->udf=FALSE;
if(recGblInitConstantLink(&prec->dol,DBF_INT64,&prec->val))
prec->udf=FALSE;
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(prec))) return(status);
if (pdset->common.init_record) {
if ((status = pdset->common.init_record(pcommon))) return status;
}
prec->mlst = prec->val;
prec->alst = prec->val;
@@ -129,69 +121,69 @@ static long init_record(dbCommon *pcommon, int pass)
static long process(dbCommon *pcommon)
{
int64outRecord *prec = (int64outRecord*)pcommon;
struct int64outdset *pdset = (struct int64outdset *)(prec->dset);
long status=0;
epicsInt64 value;
unsigned char pact=prec->pact;
int64outdset *pdset = (int64outdset *)(prec->dset);
long status=0;
epicsInt64 value;
unsigned char pact=prec->pact;
if( (pdset==NULL) || (pdset->write_int64out==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_int64out");
return(S_dev_missingSup);
}
if (!prec->pact) {
if((prec->dol.type != CONSTANT)
if( (pdset==NULL) || (pdset->write_int64out==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_int64out");
return(S_dev_missingSup);
}
if (!prec->pact) {
if((prec->dol.type != CONSTANT)
&& (prec->omsl == menuOmslclosed_loop)) {
status = dbGetLink(&(prec->dol),DBR_INT64,
&value,0,0);
if (prec->dol.type!=CONSTANT && RTN_SUCCESS(status))
prec->udf=FALSE;
}
else {
value = prec->val;
}
if (!status) convert(prec,value);
}
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
prec->val=prec->ivov;
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"int64out:process Illegal IVOA field");
}
status = dbGetLink(&(prec->dol),DBR_INT64,
&value,0,0);
if (prec->dol.type!=CONSTANT && RTN_SUCCESS(status))
prec->udf=FALSE;
}
else {
value = prec->val;
}
if (!status) convert(prec,value);
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
prec->val=prec->ivov;
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"int64out:process Illegal IVOA field");
}
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, NULL);
/* check event list */
monitor(prec);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
@@ -229,7 +221,7 @@ static long get_units(DBADDR *paddr,char *units)
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
{
int64outRecord *prec=(int64outRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
case indexof(HIHI):
@@ -377,7 +369,7 @@ static void monitor(int64outRecord *prec)
static long writeValue(int64outRecord *prec)
{
struct int64outdset *pdset = (struct int64outdset *) prec->dset;
int64outdset *pdset = (int64outdset *) prec->dset;
long status = 0;
if (!prec->pact) {
@@ -418,9 +410,9 @@ static long writeValue(int64outRecord *prec)
static void convert(int64outRecord *prec, epicsInt64 value)
{
/* check drive limits */
if(prec->drvh > prec->drvl) {
if (value > prec->drvh) value = prec->drvh;
else if (value < prec->drvl) value = prec->drvl;
}
prec->val = value;
if(prec->drvh > prec->drvl) {
if (value > prec->drvh) value = prec->drvh;
else if (value < prec->drvl) value = prec->drvl;
}
prec->val = value;
}
@@ -74,10 +74,6 @@ that comes with Base.
The OUT link field contains a database or channel access link or provides
hardware address information that the device support uses to determine where the
output data should be sent to.
The format for the OUT field value depends on the device support layer that is
selected by the DTYP field.
See L<Address Specification|...> for a description of the various hardware
address formats supported.
=head3 Operator Display Parameters
@@ -137,6 +133,15 @@ monitoring deadband functionality.
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct int64outRecord;
%typedef struct int64outdset {
% dset common;
% long (*write_int64out)(struct int64outRecord *prec);
%} int64outdset;
%#define HAS_int64outdset
%
field(VAL,DBF_INT64) {
prompt("Desired Output")
promptgroup("50 - Output")
@@ -279,28 +284,20 @@ monitoring deadband functionality.
interest(3)
}
=head3 Simulation Mode
=head3 Simulation Mode Parameters
The record provides several fields to support simulation of absent hardware.
If the SIML field is set it is used to read a value into the SIMM field,
which controls whether simulation is used or not:
The following fields are used to operate the record in simulation mode.
=over
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is written through SIOL.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
=item *
SIMM must be zero (C<NO>) for the record to write a value to the device
support.
See L<Output Simulation Fields|dbCommonOutput/Output Simulation Fields>
for more information on simulation mode and its fields.
=item *
If SIMM is C<YES> and the SIOL link field is set, the value in engineering
units is written using the link.
=back
The SIMS field can be set to give the record an alarm severity while it is in
simulation mode.
=fields SIML, SIMM, SIOL, SIMS
=fields SIML, SIMM, SIOL, SIMS, SDLY, SSCN
=cut
@@ -462,7 +459,7 @@ by at least HYST between level alarm status and severity changes.
=item 4.
Check severity and write the new value. See L<Invalid Alarm Output Action>
Check severity and write the new value. See L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields>
for details on how invalid alarms affect output records.
=item 5.
+52 -61
View File
@@ -4,13 +4,13 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recLongin.c - Record Support Routines for Longin records */
/*
* Author: Janet Anderson
* Date: 9/23/91
* Author: Janet Anderson
* Date: 9/23/91
*/
#include <stddef.h>
@@ -59,39 +59,30 @@ static long get_units(DBADDR *, char *);
#define put_enum_str NULL
static long get_graphic_double(DBADDR *, struct dbr_grDouble *);
static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
rset longinRSET={
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
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,longinRSET);
struct longindset { /* longin input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_longin; /*returns: (-1,0)=>(failure,success)*/
};
static void checkAlarms(longinRecord *prec, epicsTimeStamp *timeLast);
static void monitor(longinRecord *prec);
static long readValue(longinRecord *prec);
@@ -100,7 +91,7 @@ static long readValue(longinRecord *prec);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct longinRecord *prec = (struct longinRecord *)pcommon;
struct longindset *pdset = (struct longindset *) prec->dset;
longindset *pdset = (longindset *) prec->dset;
if (pass == 0) return 0;
@@ -113,13 +104,13 @@ static long init_record(struct dbCommon *pcommon, int pass)
}
/* must have read_longin function defined */
if ((pdset->number < 5) || (pdset->read_longin == NULL)) {
if ((pdset->common.number < 5) || (pdset->read_longin == NULL)) {
recGblRecordError(S_dev_missingSup, prec, "longin: init_record");
return S_dev_missingSup;
}
if (pdset->init_record) {
long status = pdset->init_record(prec);
if (pdset->common.init_record) {
long status = pdset->common.init_record(pcommon);
if (status)
return status;
@@ -134,36 +125,36 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct longinRecord *prec = (struct longinRecord *)pcommon;
struct longindset *pdset = (struct longindset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
epicsTimeStamp timeLast;
longindset *pdset = (longindset *)(prec->dset);
long status;
unsigned char pact=prec->pact;
epicsTimeStamp timeLast;
if( (pdset==NULL) || (pdset->read_longin==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_longin");
return(S_dev_missingSup);
}
timeLast = prec->time;
if( (pdset==NULL) || (pdset->read_longin==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"read_longin");
return(S_dev_missingSup);
}
timeLast = prec->time;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
status=readValue(prec); /* read the new value */
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
if (status==0) prec->udf = FALSE;
/* check for alarms */
checkAlarms(prec, &timeLast);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
/* check for alarms */
checkAlarms(prec, &timeLast);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
@@ -245,7 +236,7 @@ static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
return(0);
}
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
{
longinRecord *prec=(longinRecord *)paddr->precord;
@@ -262,7 +253,7 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
static void checkAlarms(longinRecord *prec, epicsTimeStamp *timeLast)
{
enum {
enum {
range_Lolo = 1,
range_Low,
range_Normal,
@@ -273,7 +264,7 @@ static void checkAlarms(longinRecord *prec, epicsTimeStamp *timeLast)
SOFT_ALARM, LOLO_ALARM, LOW_ALARM,
NO_ALARM, HIGH_ALARM, HIHI_ALARM
};
double aftc, afvl;
epicsInt32 val, hyst, lalm;
epicsInt32 alev;
@@ -405,7 +396,7 @@ static void monitor(longinRecord *prec)
static long readValue(longinRecord *prec)
{
struct longindset *pdset = (struct longindset *) prec->dset;
longindset *pdset = (longindset *) prec->dset;
long status = 0;
if (!prec->pact) {
@@ -28,10 +28,8 @@ The record-specific fields are described below, grouped by functionality.
=head3 Scan Parameters
The long input record has the standard fields for specifying under what
circumstances the record will be processed. These fields are listed in L<Scan
Fields>. In addition, L<Scanning Specification> explains how these fields are
used. Note that I/O event scanning is only supported for those card types
that interrupt.
circumstances the record will be processed.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Read Parameters
@@ -43,9 +41,7 @@ I/O bus used.
For soft records, the INP can be a constant, a database link, or a channel
access link. The value is read directly into VAL. The C<<< Soft Channel >>>
device support module is available for longin records. See L<Address
Specification> for information on the format of hardware addresses and a
database links.
device support module is available for longin records.
=fields VAL, INP, DTYP
@@ -62,8 +58,9 @@ The HOPR and LOPR fields set the upper and lower display limits for the VAL,
HIHI, HIGH, LOW, and LOLO fields. Both the C<<< get_graphic_double >>> and C<<<
get_control_double >>> record support routines retrieve these fields.
See L<Fields Common to All Record Types> for more on the record name (NAME) and
description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, HOPR, LOPR, NAME, DESC
@@ -76,10 +73,9 @@ routines.
The limit alarms are configured by the user in the HIHI, LOLO, HIGH, and LOW
fields using numerical values. For each of these fields, there is a
corresponding severity field which can be either NO_ALARM, MINOR, or MAJOR. The
HYST field can be used to specify a deadband around each limit. See L<Alarm
Specification> for a complete explanation of alarms and these fields. L<Alarm
Fields> lists other fields related to a alarms that are common to all record
types.
HYST field can be used to specify a deadband around each limit.
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists the fields related to
alarms that are common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST
@@ -91,24 +87,34 @@ field (see the next section) by the appropriate deadband. If these fields have a
value of zero, everytime the value changes, a monitor will be triggered; if they
have a value of -1, everytime the record is scanned, monitors are triggered. The
ADEL field is used by archive monitors and the MDEL field for all other types of
monitors. See L<Monitor Specification> for a complete explanation of monitors.
monitors.
=fields ADEL, MDEL
=head3 Run-time and Simulation Mode Parameters
=head3 Run-time Parameters
The LALM, MLST, and ALST fields are used to implement the hysteresis factors for
monitor callbacks. Only if the difference between these fields and the
corresponding value field is greater than the appropriate delta (MDEL, ADEL,
HYST)--only then are monitors triggered. For instance, only if the difference
HYST) will monitors be triggered. For instance, only if the difference
between VAL and MLST is greater than MDEL are the monitors triggered for VAL.
=fields LALM, ALST, MLST
The following fields are used to operate the long input in the simulation mode.
See L<Fields Common to Many Record Types> for more information on these fields.
=head3 Simulation Mode Parameters
=fields SIOL, SVAL, SIML, SIMM, SIMS
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is fetched through SIOL (buffered in SVAL).
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Input Simulation Fields|dbCommonInput/Input Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SVAL, SIMS, SDLY, SSCN
=head2 Record Support
@@ -265,7 +271,7 @@ C<init_record()> routine.
get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt)
This routine is called by the ioEventScan system each time the record is added
or deleted from an I/O event scan list. cmd has the value (0,1) if the
or deleted from an I/O event scan list. C<cmd> has the value (0,1) if the
record is being (added to, deleted from) an I/O event list. It must be
provided for any device type that can use the ioEvent scanner.
@@ -305,6 +311,15 @@ sets UDF to FALSE. read_longin returns the status of C<recGblGetLinkValue>.
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct longinRecord;
%typedef struct longindset {
% dset common; /*init_record returns: (-1,0)=>(failure,success)*/
% long (*read_longin)(struct longinRecord *prec); /*returns: (-1,0)=>(failure,success)*/
%} longindset;
%#define HAS_longindset
%
field(VAL,DBF_LONG) {
prompt("Current value")
promptgroup("40 - Input")
+87 -96
View File
@@ -4,13 +4,13 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Janet Anderson
* Date: 9/23/91
*/
* Author: Janet Anderson
* Date: 9/23/91
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -59,36 +59,27 @@ static long get_control_double(DBADDR *, struct dbr_ctrlDouble *);
static long get_alarm_double(DBADDR *, struct dbr_alDouble *);
rset longoutRSET={
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
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,longoutRSET);
struct longoutdset { /* longout input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;/*(-1,0)=>(failure,success*/
};
static void checkAlarms(longoutRecord *prec);
static void monitor(longoutRecord *prec);
static long writeValue(longoutRecord *prec);
@@ -97,7 +88,7 @@ static void convert(longoutRecord *prec, epicsInt32 value);
static long init_record(struct dbCommon *pcommon, int pass)
{
struct longoutRecord *prec = (struct longoutRecord *)pcommon;
struct longoutdset *pdset = (struct longoutdset *) prec->dset;
longoutdset *pdset = (longoutdset *) prec->dset;
if (pass == 0) return 0;
@@ -109,7 +100,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
}
/* must have write_longout functions defined */
if ((pdset->number < 5) || (pdset->write_longout == NULL)) {
if ((pdset->common.number < 5) || (pdset->write_longout == NULL)) {
recGblRecordError(S_dev_missingSup, prec, "longout: init_record");
return S_dev_missingSup;
}
@@ -117,8 +108,8 @@ static long init_record(struct dbCommon *pcommon, int pass)
if (recGblInitConstantLink(&prec->dol, DBF_LONG, &prec->val))
prec->udf=FALSE;
if (pdset->init_record) {
long status = pdset->init_record(prec);
if (pdset->common.init_record) {
long status = pdset->common.init_record(pcommon);
if (status)
return status;
@@ -133,68 +124,68 @@ static long init_record(struct dbCommon *pcommon, int pass)
static long process(struct dbCommon *pcommon)
{
struct longoutRecord *prec = (struct longoutRecord *)pcommon;
struct longoutdset *pdset = (struct longoutdset *)(prec->dset);
long status=0;
epicsInt32 value;
unsigned char pact=prec->pact;
longoutdset *pdset = (longoutdset *)(prec->dset);
long status=0;
epicsInt32 value;
unsigned char pact=prec->pact;
if( (pdset==NULL) || (pdset->write_longout==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_longout");
return(S_dev_missingSup);
}
if (!prec->pact) {
if (!dbLinkIsConstant(&prec->dol) &&
prec->omsl == menuOmslclosed_loop) {
status = dbGetLink(&prec->dol, DBR_LONG, &value, 0, 0);
if (!dbLinkIsConstant(&prec->dol) && !status)
prec->udf=FALSE;
}
else {
value = prec->val;
}
if (!status) convert(prec,value);
}
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
prec->val=prec->ivov;
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"longout:process Illegal IVOA field");
}
if( (pdset==NULL) || (pdset->write_longout==NULL) ) {
prec->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)prec,"write_longout");
return(S_dev_missingSup);
}
if (!prec->pact) {
if (!dbLinkIsConstant(&prec->dol) &&
prec->omsl == menuOmslclosed_loop) {
status = dbGetLink(&prec->dol, DBR_LONG, &value, 0, 0);
if (!dbLinkIsConstant(&prec->dol) && !status)
prec->udf=FALSE;
}
else {
value = prec->val;
}
if (!status) convert(prec,value);
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
/* check for alarms */
checkAlarms(prec);
if (prec->nsev < INVALID_ALARM )
status=writeValue(prec); /* write the new value */
else {
switch (prec->ivoa) {
case (menuIvoaContinue_normally) :
status=writeValue(prec); /* write the new value */
break;
case (menuIvoaDon_t_drive_outputs) :
break;
case (menuIvoaSet_output_to_IVOV) :
if(prec->pact == FALSE){
prec->val=prec->ivov;
}
status=writeValue(prec); /* write the new value */
break;
default :
status=-1;
recGblRecordError(S_db_badField,(void *)prec,
"longout:process Illegal IVOA field");
}
}
/* check if device support set pact */
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
recGblGetTimeStampSimm(prec, prec->simm, NULL);
/* check event list */
monitor(prec);
/* check event list */
monitor(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
/* process the forward scan link record */
recGblFwdLink(prec);
prec->pact=FALSE;
return(status);
prec->pact=FALSE;
return(status);
}
static long special(DBADDR *paddr, int after)
@@ -232,7 +223,7 @@ static long get_units(DBADDR *paddr,char *units)
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
{
longoutRecord *prec=(longoutRecord *)paddr->precord;
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
case indexof(HIHI):
@@ -382,7 +373,7 @@ static void monitor(longoutRecord *prec)
static long writeValue(longoutRecord *prec)
{
struct longoutdset *pdset = (struct longoutdset *) prec->dset;
longoutdset *pdset = (longoutdset *) prec->dset;
long status = 0;
if (!prec->pact) {
@@ -423,9 +414,9 @@ static long writeValue(longoutRecord *prec)
static void convert(longoutRecord *prec, epicsInt32 value)
{
/* check drive limits */
if(prec->drvh > prec->drvl) {
if (value > prec->drvh) value = prec->drvh;
else if (value < prec->drvl) value = prec->drvl;
}
prec->val = value;
if(prec->drvh > prec->drvl) {
if (value > prec->drvh) value = prec->drvh;
else if (value < prec->drvl) value = prec->drvl;
}
prec->val = value;
}
@@ -24,33 +24,13 @@ recordtype(longout) {
=head2 Parameter Fields
The fields in this record fall into the following categories:
=over
=item * L<Scan Parameters>
=item * L<Desired Output Parameters>
=item * L<Write Parameters>
=item * L<Operator Display Parameters>
=item * L<Alarm Parameters>
=item * L<Monitor Parameters>
=item * L<Simulation Mode Parameters>
=back
The record-specific fields are described below, grouped by functionality.
=head3 Scan Parameters
The longout record has the standard fields for specifying under what
circumstances it will be processed. These fields are listed in L<Scan Fields>.
In addition, L<Scanning Specification> explains how these fields are used. Note
that I/O event scanning is only supported for those card types that
interrupt.
circumstances it will be processed.
These fields are listed in L<Scan Fields|dbCommonRecord/Scan Fields>.
=head3 Desired Output Parameters
@@ -96,6 +76,15 @@ and database links.
=cut
include "dbCommon.dbd"
%
%/* Declare Device Support Entry Table */
%struct longoutRecord;
%typedef struct longoutdset {
% dset common; /*init_record returns: (-1,0)=>(failure,success)*/
% long (*write_longout)(struct longoutRecord *prec); /*(-1,0)=>(failure,success*/
%} longoutdset;
%#define HAS_longoutdset
%
field(VAL,DBF_LONG) {
prompt("Desired Output")
promptgroup("50 - Output")
@@ -132,8 +121,8 @@ The HOPR and LOPR fields set the upper and lower display limits for the VAL,
HIHI, HIGH, LOW, and LOLO fields. Both the C<<< get_graphic_double >>> and C<<<
get_control_double >>> record support routines retrieve these fields.
See L<Fields Common to All Record Types> for more on the record name (NAME) and
description (DESC) fields.
See L<Fields Common to All Record Types|dbCommonRecord/Operator Display
Parameters> for more on the record name (NAME) and description (DESC) fields.
=fields EGU, HOPR, LOPR, NAME, DESC
@@ -186,10 +175,10 @@ fields using floating-point values. For each of these fields, there is a
corresponding severity field which can be either NO_ALARM, MINOR, or MAJOR. The
HYST field contains the alarm deadband around each limit alarm.
See the See L<Alarm Specification> for a complete explanation of alarms and
See L<Alarm Specification> for a complete explanation of alarms and
these fields. For an explanation of the IVOA and IVOV fields, see L<Output
Records>. L<Alarm Fields> lists other fields related to a alarms that are common
to all record types.
Records>. L<Alarm Fields|dbCommonRecord/Alarm Fields> lists the fields related to
alarms that are common to all record types.
=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, IVOA, IVOV
@@ -298,7 +287,7 @@ monitors.
interest(3)
}
=head3 Run-time and Simulation Mode Parameters
=head3 Run-time Parameters
The LALM, MLST, and ALST fields are used to implement the hysteresis factors for
monitor callbacks. Only if the difference between these fields and the
@@ -308,15 +297,24 @@ between VAL and MLST is greater than MDEL are the monitors triggered for VAL.
=fields LALM, ALST, MLST
The following fields are used to operate the long output in the simulation mode.
See L<Fields Common to Many Record Types> for more information on the simulation
mode fields
=head3 Simulation Mode Parameters
=fields SIOL, SIML, SIMM, SIMS
The following fields are used to operate the record in simulation mode.
If SIMM (fetched through SIML) is YES, the record is put in SIMS
severity and the value is written through SIOL.
SSCN sets a different SCAN mechanism to use in simulation mode.
SDLY sets a delay (in sec) that is used for asynchronous simulation
processing.
See L<Output Simulation Fields|dbCommonOutput/Output Simulation Fields>
for more information on simulation mode and its fields.
=fields SIML, SIMM, SIOL, SIMS, SDLY, SSCN
=cut
field(SIOL,DBF_OUTLINK) {
field(SIOL,DBF_OUTLINK) {
prompt("Sim Output Specifctn")
promptgroup("90 - Simulate")
interest(1)
@@ -464,7 +462,8 @@ before the alarm status and severity is lowered.
=item 4.
Check severity and write the new value. See L<Invalid Alarm Output Action> for
Check severity and write the new value. See
L<Invalid Output Action Fields|dbCommonOutput/Invalid Output Action Fields> for
information on how INVALID alarms affect output records.
=item 5.
@@ -551,7 +550,7 @@ C<init_record()> routine.
get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt)
This routine is called by the ioEventScan system each time the record is added
or deleted from an I/O event scan list. cmd has the value (0,1) if the
or deleted from an I/O event scan list. C<cmd> has the value (0,1) if the
record is being (added to, deleted from) an I/O event list. It must be
provided for any device type that can use the ioEvent scanner.
+4 -4
View File
@@ -66,13 +66,13 @@ static long init_record(struct dbCommon *pcommon, int pass)
}
/* must have a read_string function */
if (pdset->number < 5 || !pdset->read_string) {
if (pdset->common.number < 5 || !pdset->read_string) {
recGblRecordError(S_dev_missingSup, prec, "lsi: init_record");
return S_dev_missingSup;
}
if (pdset->init_record) {
long status = pdset->init_record(prec);
if (pdset->common.init_record) {
long status = pdset->common.init_record(pcommon);
if (status)
return status;
@@ -221,7 +221,7 @@ static void monitor(lsiRecord *prec)
static long readValue(lsiRecord *prec)
{
struct lsidset *pdset = (struct lsidset *) prec->dset;
lsidset *pdset = (lsidset *) prec->dset;
long status = 0;
if (!prec->pact) {

Some files were not shown because too many files have changed in this diff Show More