Merge changes from 3.15 branch into 7.0
This commit is contained in:
@@ -42,14 +42,18 @@ environment:
|
||||
matrix:
|
||||
- TOOLCHAIN: mingw
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLCHAIN: 2019
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLCHAIN: 2017
|
||||
- TOOLCHAIN: 2019
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- TOOLCHAIN: 2017
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
- TOOLCHAIN: 14.0
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLCHAIN: 12.0
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLCHAIN: 11.0
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- TOOLCHAIN: 10.0
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
||||
# Platform: architecture
|
||||
platform:
|
||||
@@ -62,19 +66,21 @@ matrix:
|
||||
# VS Express installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
TOOLCHAIN: 10.0
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
# Exclude to reduce total job runtime
|
||||
# skip 64-bit for older and 32-bit for newer
|
||||
- platform: x64
|
||||
TOOLCHAIN: 11.0
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- platform: x86
|
||||
TOOLCHAIN: mingw
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
- platform: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLCHAIN: 2019
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- platform: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLCHAIN: 2017
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
|
||||
#---------------------------------#
|
||||
|
||||
@@ -30,7 +30,7 @@ ARCH_DEP_LDFLAGS += -m32
|
||||
# Compiler does not define __unix __unix__ unix
|
||||
|
||||
# Override for -DUNIX from CONFIG.Common.UnixCommon
|
||||
OP_SYS_CPPFLAGS = -D_MINGW -Wno-format
|
||||
OP_SYS_CPPFLAGS = -D_MINGW -D__USE_MINGW_ANSI_STDIO
|
||||
|
||||
EXE = .exe
|
||||
RES = .coff
|
||||
|
||||
@@ -36,7 +36,7 @@ and can be adjusted locally if necessary.
|
||||
|
||||
### caRepeater /dev/null
|
||||
|
||||
On *NIX targets caRepeater will now partially daemonize by redirecting
|
||||
On \*NIX targets caRepeater will now partially daemonize by redirecting
|
||||
stdin/out/err to /dev/null. This prevents caRepeater from inheriting
|
||||
the stdin/out of a process, like caget, which has spawned it in the
|
||||
background. This has been known to cause problems in some cases when
|
||||
@@ -195,7 +195,7 @@ set to their default values.
|
||||
void startitup(void) {
|
||||
epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT;
|
||||
epicsThreadId tid;
|
||||
|
||||
|
||||
opts.priority = epicsThreadPriorityMedium;
|
||||
tid = epicsThreadCreateOpt("my thread", &threadMain, NULL, &opts);
|
||||
}
|
||||
@@ -662,14 +662,14 @@ number instead, like this:
|
||||
|
||||
```
|
||||
#include <epicsVersion.h>
|
||||
|
||||
|
||||
#ifndef VERSION_INT
|
||||
# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
|
||||
#endif
|
||||
#ifndef EPICS_VERSION_INT
|
||||
# define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
|
||||
#endif
|
||||
|
||||
|
||||
#if EPICS_VERSION_INT >= VERSION_INT(3,16,1,0)
|
||||
/* Code where Base has INT64 support */
|
||||
#else
|
||||
@@ -995,7 +995,7 @@ excerpts from a database file:
|
||||
record(ai, math:pi) {
|
||||
field(INP, {const: 3.14159265358979}) # Correct
|
||||
field(SIOL, "{const: 3.142857}") # Wrong
|
||||
|
||||
|
||||
info(autosave, { # White-space and comments are allowed
|
||||
fields:[DESC, SIMM],
|
||||
pass0:[VAL]
|
||||
@@ -1143,7 +1143,7 @@ this:
|
||||
|
||||
```
|
||||
#include "epicsTime.h"
|
||||
|
||||
|
||||
#ifndef M_time
|
||||
/* S_time_... status values were not provided before Base 3.16 */
|
||||
#define S_time_unsynchronized epicsTimeERROR
|
||||
@@ -1168,9 +1168,49 @@ Added a new macro `callbackGetPriority(prio, callback)` to the callback.h
|
||||
header and removed the need for dbScan.c to reach into the internals of its
|
||||
`CALLBACK` objects.
|
||||
|
||||
|
||||
## Changes from the 3.15 branch since 3.15.7
|
||||
|
||||
> None.
|
||||
### epicsThread: Main thread defaults to allow blocking I/O
|
||||
|
||||
VxWorks IOCs (and potentially RTEMS IOCs running GeSys) have had problems with
|
||||
garbled error messages from dbStaticLib routines for some time — messages
|
||||
printed before `iocInit` were being queued through the errlog thread instead of
|
||||
being output immediately. This has been fixed by initializing the main thread
|
||||
with its `OkToBlock` flag set instead of cleared. IOCs running on other
|
||||
operating systems that use iocsh to execute the startup script previously had
|
||||
that set anyway in iocsh so were not affected, but this change might cause other
|
||||
programs that don't use iocsh to change their behavior slightly if they use
|
||||
`errlogPrintf()`, `epicsPrintf()` or `errPrintf()`.
|
||||
|
||||
### catools: Handle data type changes in camonitor
|
||||
|
||||
The camonitor program didn't properly cope if subscribed to a channel whose data
|
||||
type changed when its IOC was rebooted without restarting the camonitor program.
|
||||
This has now been fixed.
|
||||
|
||||
### More Record Reference Documentation
|
||||
|
||||
The remaining record types have had their reference pages moved from the Wiki,
|
||||
and some new reference pages have been written to cover the analog array and
|
||||
long string input and output record types plus the printf recor type, none of
|
||||
which were previously documented. The wiki reference pages covering the fields
|
||||
common to all, input, and output record types have also been added, thanks to
|
||||
Rolf Keitel. The POD conversion scripts have also been improved and they now
|
||||
properly support linking to subsections in a different document, although the
|
||||
POD changes to add the cross-links that appeared in the original wiki pages
|
||||
still needs to be done in most cases.
|
||||
|
||||
### Fix build issues with newer MinGW versions
|
||||
|
||||
The `clock_gettime()` routine is no longer used under MinGW since newer versions
|
||||
don't provide it any more.
|
||||
|
||||
### Fix race for port in RSRV when multiple IOCs start simultaneously
|
||||
|
||||
If multiple IOCs were started at the same time, by systemd say, they could race
|
||||
to obtain the Channel Access TCP port number 5064. This issue has been fixed.
|
||||
|
||||
|
||||
## Changes made between 3.15.6 and 3.15.7
|
||||
|
||||
@@ -1887,4 +1927,3 @@ Simpler versions of the `epicsTime_gmtime()` and `epicsTime_localtime()`
|
||||
routines have been included in the Windows implementations, and a new test
|
||||
program added. The original versions do not report DST status properly. Fixes
|
||||
[Launchpad bug 1528284](https://bugs.launchpad.net/bugs/1528284).
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
# Record Reference Documentation
|
||||
|
||||
The following documentation for the record types and menus include with Base was converted from the old EPICS Wiki pages and updated. This list does not include all of the available record types as some have not been documented yet.
|
||||
The following documentation for the record types and menus include with Base was
|
||||
converted from the old EPICS Wiki pages and updated. This list only includes the
|
||||
record types supplied with Base.
|
||||
|
||||
* [Fields Common to All Record Types](dbCommonRecord.html)
|
||||
* [Fields Common to Input Record Types](dbCommonInputs.html)
|
||||
* [Fields Common to Output Record Types](dbCommonOutputs.html)
|
||||
|
||||
## Record Types
|
||||
|
||||
* [Analog Array Input Record (aai)](aaiRecord.html)
|
||||
* [Analog Array Output Record (aao)](aaoRecord.html)
|
||||
* [Analog Input Record (ai)](aiRecord.html)
|
||||
* [Analog Output Record (ao)](aoRecord.html)
|
||||
* [Array Subroutine Record (aSub)](aSubRecord.html)
|
||||
@@ -15,15 +23,19 @@ The following documentation for the record types and menus include with Base was
|
||||
* [Data Fanout Record (dfanout)](dfanoutRecord.html)
|
||||
* [Event Record (event)](eventRecord.html)
|
||||
* [Fanout Record (fanout)](fanoutRecord.html)
|
||||
* [Histogram Record (histogram)](histogramRecord.html)
|
||||
* [64bit Integer Input Record (int64in)](int64inRecord.html)
|
||||
* [64bit Integer Output Record (int64out)](int64outRecord.html)
|
||||
* [Long Input Record (longin)](longinRecord.html)
|
||||
* [Long Output Record (longout)](longoutRecord.html)
|
||||
* [Long String Input Record (lsi)](lsiRecord.html)
|
||||
* [Long String Output Record (lso)](lsoRecord.html)
|
||||
* [Multi-Bit Binary Input Direct Record (mbbiDirect)](mbbiDirectRecord.html)
|
||||
* [Multi-Bit Binary Input Record (mbbi)](mbbiRecord.html)
|
||||
* [Multi-Bit Binary Output Direct Record (mbboDirect)](mbboDirectRecord.html)
|
||||
* [Multi-Bit Binary Output Record (mbbo)](mbboRecord.html)
|
||||
* [Permissive Record (permissive)](permissiveRecord.html)
|
||||
* [Printf Record (prinf)](printfRecord.html)
|
||||
* [Select Record (sel)](selRecord.html)
|
||||
* [Sequence Record (seq)](seqRecord.html)
|
||||
* [State Record (state)](stateRecord.html)
|
||||
@@ -47,4 +59,10 @@ The following documentation for the record types and menus include with Base was
|
||||
|
||||
## Corrections and Updates
|
||||
|
||||
Corrections to these documents can be submitted as patch files to the EPICS core developers, or as merge requests or pull requests to the 7.0 branch of epics-base. The document sources can be found in the `modules/database/src/std/rec` and `modules/database/src/ioc/db` directories in files with extension `.dbd.pod`. The documentation format is an extended version of Perl POD, run `perldoc pod` for details.
|
||||
Corrections to these documents can be submitted as patch files to the EPICS core
|
||||
developers, or as merge requests or pull requests to the 7.0 branch of Base.
|
||||
The document sources can be found in the `modules/database/src/std/rec` and
|
||||
`modules/database/src/ioc/db` directories in files with extension `.dbd.pod`.
|
||||
The documentation source format is a combination of the EPICS DBD file format
|
||||
with an extended version of Perl's POD (plain old documentation); run `perldoc
|
||||
pod` for details of POD.
|
||||
|
||||
@@ -138,7 +138,14 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
pv *ppv = ( pv * ) ca_puser ( args.chid );
|
||||
if ( args.op == CA_OP_CONN_UP ) {
|
||||
nConn++;
|
||||
if (!ppv->onceConnected) {
|
||||
|
||||
if (ppv->onceConnected && ppv->dbfType != ca_field_type(ppv->chid)) {
|
||||
/* Data type has changed. Rebuild connection with new type. */
|
||||
ca_clear_subscription(ppv->evid);
|
||||
ppv->evid = NULL;
|
||||
}
|
||||
|
||||
if (!ppv->evid) {
|
||||
ppv->onceConnected = 1;
|
||||
/* Set up pv structure */
|
||||
/* ------------------- */
|
||||
@@ -169,7 +176,7 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
eventMask,
|
||||
event_handler,
|
||||
(void*)ppv,
|
||||
NULL);
|
||||
&ppv->evid);
|
||||
}
|
||||
}
|
||||
else if ( args.op == CA_OP_CONN_DOWN ) {
|
||||
|
||||
@@ -78,6 +78,7 @@ typedef struct
|
||||
epicsTimeStamp tsPreviousS;
|
||||
char firstStampPrinted;
|
||||
char onceConnected;
|
||||
evid evid;
|
||||
} pv;
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
#*************************************************************************
|
||||
|
||||
# This is a Makefile fragment, see src/ioc/Makefile.
|
||||
@@ -62,6 +62,9 @@ DBDINC += dbCommon
|
||||
|
||||
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
|
||||
HTMLS += $(patsubst %.dbd.pod,%.html,$(dbMenusPod))
|
||||
HTMLS += dbCommonRecord.html
|
||||
HTMLS += dbCommonInput.html
|
||||
HTMLS += dbCommonOutput.html
|
||||
|
||||
dbCore_SRCS += dbLock.c
|
||||
dbCore_SRCS += dbAccess.c
|
||||
@@ -96,4 +99,3 @@ dbCore_SRCS += chfPlugin.c
|
||||
dbCore_SRCS += dbState.c
|
||||
dbCore_SRCS += dbUnitTest.c
|
||||
dbCore_SRCS += dbServer.c
|
||||
|
||||
|
||||
@@ -6,21 +6,25 @@
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
# This is a Makefile fragment, see src/ioc/Makefile.
|
||||
|
||||
dbCommon.h$(DEP): $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES
|
||||
@$(RM) $@
|
||||
@$(DBTORECORDTYPEH) -D -I ../db -o $(COMMONDEP_TARGET) $< > $@
|
||||
THESE_RULES := $(IOCDIR)/db/RULES
|
||||
|
||||
$(COMMON_DIR)/dbCommon.h: $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES
|
||||
dbCommon.h$(DEP): $(COMMON_DIR)/dbCommonRecord.dbd $(THESE_RULES)
|
||||
@$(RM) $@
|
||||
@$(DBTORECORDTYPEH) -D -I ../db -I $(COMMON_DIR) -o $(COMMONDEP_TARGET) $< > $@
|
||||
|
||||
$(COMMON_DIR)/dbCommonRecord.html: ../db/dbCommon.dbd.pod
|
||||
|
||||
$(COMMON_DIR)/dbCommon.h: $(COMMON_DIR)/dbCommonRecord.dbd $(THESE_RULES)
|
||||
@$(RM) $(notdir $@)
|
||||
$(DBTORECORDTYPEH) -I ../db -o $(notdir $@) $<
|
||||
$(DBTORECORDTYPEH) -I ../db -I $(COMMON_DIR) -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/menuGlobal.dbd: $(IOCDIR)/db/Makefile $(IOCDIR)/db/RULES
|
||||
$(COMMON_DIR)/menuGlobal.dbd: $(IOCDIR)/db/Makefile $(THESE_RULES)
|
||||
|
||||
# This is a target-specific variable
|
||||
$(COMMON_DIR)/menuGlobal.dbd: DBDCAT_COMMAND = \
|
||||
|
||||
@@ -776,8 +776,19 @@ int dbLoadRecords(const char* file, const char* subs)
|
||||
return -1;
|
||||
}
|
||||
status = dbReadDatabase(&pdbbase, file, 0, subs);
|
||||
if (!status && dbLoadRecordsHook)
|
||||
dbLoadRecordsHook(file, subs);
|
||||
switch(status)
|
||||
{
|
||||
case 0:
|
||||
if(dbLoadRecordsHook)
|
||||
dbLoadRecordsHook(file, subs);
|
||||
break;
|
||||
case -2:
|
||||
errlogPrintf("dbLoadRecords: failed to load '%s'\n"
|
||||
" Records cannot be loaded after iocInit!\n", file);
|
||||
break;
|
||||
default:
|
||||
errlogPrintf("dbLoadRecords: failed to load '%s'\n", file);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -943,6 +954,11 @@ long dbGet(DBADDR *paddr, short dbrType,
|
||||
} else {
|
||||
DBADDR localAddr = *paddr; /* Structure copy */
|
||||
|
||||
if (pfl->no_elements < 1) {
|
||||
status = S_db_badField;
|
||||
goto done;
|
||||
}
|
||||
|
||||
localAddr.field_type = pfl->field_type;
|
||||
localAddr.field_size = pfl->field_size;
|
||||
localAddr.no_elements = pfl->no_elements;
|
||||
|
||||
@@ -1,268 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2007 UChicago Argonne LLC, 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.
|
||||
#*************************************************************************
|
||||
%#include "epicsTypes.h"
|
||||
%#include "link.h"
|
||||
field(NAME,DBF_STRING) {
|
||||
prompt("Record Name")
|
||||
special(SPC_NOMOD)
|
||||
size(61)
|
||||
}
|
||||
field(DESC,DBF_STRING) {
|
||||
prompt("Descriptor")
|
||||
promptgroup("10 - Common")
|
||||
size(41)
|
||||
}
|
||||
field(ASG,DBF_STRING) {
|
||||
prompt("Access Security Group")
|
||||
promptgroup("10 - Common")
|
||||
special(SPC_AS)
|
||||
size(29)
|
||||
}
|
||||
field(SCAN,DBF_MENU) {
|
||||
prompt("Scan Mechanism")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
}
|
||||
field(PINI,DBF_MENU) {
|
||||
prompt("Process at iocInit")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
menu(menuPini)
|
||||
}
|
||||
field(PHAS,DBF_SHORT) {
|
||||
prompt("Scan Phase")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
}
|
||||
field(EVNT,DBF_STRING) {
|
||||
prompt("Event Name")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
size(40)
|
||||
interest(1)
|
||||
}
|
||||
field(TSE,DBF_SHORT) {
|
||||
prompt("Time Stamp Event")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(TSEL,DBF_INLINK) {
|
||||
prompt("Time Stamp Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(DTYP,DBF_DEVICE) {
|
||||
prompt("Device Type")
|
||||
promptgroup("10 - Common")
|
||||
interest(1)
|
||||
}
|
||||
field(DISV,DBF_SHORT) {
|
||||
prompt("Disable Value")
|
||||
promptgroup("20 - Scan")
|
||||
initial("1")
|
||||
}
|
||||
field(DISA,DBF_SHORT) {
|
||||
prompt("Disable")
|
||||
}
|
||||
field(SDIS,DBF_INLINK) {
|
||||
prompt("Scanning Disable")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
%#include "epicsMutex.h"
|
||||
field(MLOK,DBF_NOACCESS) {
|
||||
prompt("Monitor lock")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsMutexId mlok")
|
||||
}
|
||||
%#include "ellLib.h"
|
||||
field(MLIS,DBF_NOACCESS) {
|
||||
prompt("Monitor List")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("ELLLIST mlis")
|
||||
}
|
||||
field(BKLNK,DBF_NOACCESS) {
|
||||
prompt("Backwards link tracking")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("ELLLIST bklnk")
|
||||
}
|
||||
field(DISP,DBF_UCHAR) {
|
||||
prompt("Disable putField")
|
||||
}
|
||||
field(PROC,DBF_UCHAR) {
|
||||
prompt("Force Processing")
|
||||
pp(TRUE)
|
||||
interest(3)
|
||||
}
|
||||
field(STAT,DBF_MENU) {
|
||||
prompt("Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmStat)
|
||||
initial("UDF")
|
||||
}
|
||||
field(SEVR,DBF_MENU) {
|
||||
prompt("Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(NSTA,DBF_MENU) {
|
||||
prompt("New Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmStat)
|
||||
}
|
||||
field(NSEV,DBF_MENU) {
|
||||
prompt("New Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKS,DBF_MENU) {
|
||||
prompt("Alarm Ack Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKT,DBF_MENU) {
|
||||
prompt("Alarm Ack Transient")
|
||||
promptgroup("70 - Alarm")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuYesNo)
|
||||
initial("YES")
|
||||
}
|
||||
field(DISS,DBF_MENU) {
|
||||
prompt("Disable Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LCNT,DBF_UCHAR) {
|
||||
prompt("Lock Count")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
}
|
||||
field(PACT,DBF_UCHAR) {
|
||||
prompt("Record active")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(PUTF,DBF_UCHAR) {
|
||||
prompt("dbPutField process")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(RPRO,DBF_UCHAR) {
|
||||
prompt("Reprocess ")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(ASP,DBF_NOACCESS) {
|
||||
prompt("Access Security Pvt")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct asgMember *asp")
|
||||
}
|
||||
field(PPN,DBF_NOACCESS) {
|
||||
prompt("pprocessNotify")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotify *ppn")
|
||||
}
|
||||
field(PPNR,DBF_NOACCESS) {
|
||||
prompt("pprocessNotifyRecord")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotifyRecord *ppnr")
|
||||
}
|
||||
field(SPVT,DBF_NOACCESS) {
|
||||
prompt("Scan Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct scan_element *spvt")
|
||||
}
|
||||
field(RSET,DBF_NOACCESS) {
|
||||
prompt("Address of RSET")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct typed_rset *rset")
|
||||
}
|
||||
%#include "devSup.h"
|
||||
field(DSET,DBF_NOACCESS) {
|
||||
prompt("DSET address")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("unambiguous_dset *dset")
|
||||
}
|
||||
field(DPVT,DBF_NOACCESS) {
|
||||
prompt("Device Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("void *dpvt")
|
||||
}
|
||||
field(RDES,DBF_NOACCESS) {
|
||||
prompt("Address of dbRecordType")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dbRecordType *rdes")
|
||||
}
|
||||
field(LSET,DBF_NOACCESS) {
|
||||
prompt("Lock Set")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct lockRecord *lset")
|
||||
}
|
||||
field(PRIO,DBF_MENU) {
|
||||
prompt("Scheduling Priority")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuPriority)
|
||||
}
|
||||
field(TPRO,DBF_UCHAR) {
|
||||
prompt("Trace Processing")
|
||||
}
|
||||
field(BKPT,DBF_NOACCESS) {
|
||||
prompt("Break Point")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
extra("char bkpt")
|
||||
}
|
||||
field(UDF,DBF_UCHAR) {
|
||||
prompt("Undefined")
|
||||
promptgroup("10 - Common")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
initial("1")
|
||||
}
|
||||
field(UDFS,DBF_MENU) {
|
||||
prompt("Undefined Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
initial("INVALID")
|
||||
}
|
||||
%#include "epicsTime.h"
|
||||
field(TIME,DBF_NOACCESS) {
|
||||
prompt("Time")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
extra("epicsTimeStamp time")
|
||||
}
|
||||
field(FLNK,DBF_FWDLINK) {
|
||||
prompt("Forward Process Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
521
modules/database/src/ioc/db/dbCommon.dbd.pod
Normal file
521
modules/database/src/ioc/db/dbCommon.dbd.pod
Normal file
@@ -0,0 +1,521 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2007 UChicago Argonne LLC, 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.
|
||||
#*************************************************************************
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
The B<NAME> field contains the record name which must be unique within an
|
||||
EPICS Channel Access name space. The name is supplied by the application
|
||||
developer and is the means of identifying a specific record. The name has a
|
||||
maximum length of 60 characters and should use only this limited set of
|
||||
characters:
|
||||
|
||||
a-z A-Z 0-9 _ - : [ ] < > ;
|
||||
|
||||
The B<DESC> field may be set to provide a meaningful description of the
|
||||
record's purpose. Maximum length is 40 characters.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=cut
|
||||
|
||||
%#include "epicsTypes.h"
|
||||
%#include "link.h"
|
||||
field(NAME,DBF_STRING) {
|
||||
prompt("Record Name")
|
||||
special(SPC_NOMOD)
|
||||
size(61)
|
||||
}
|
||||
field(DESC,DBF_STRING) {
|
||||
prompt("Descriptor")
|
||||
promptgroup("10 - Common")
|
||||
size(41)
|
||||
}
|
||||
field(ASG,DBF_STRING) {
|
||||
prompt("Access Security Group")
|
||||
promptgroup("10 - Common")
|
||||
special(SPC_AS)
|
||||
size(29)
|
||||
}
|
||||
|
||||
=head3 Scan Fields
|
||||
|
||||
These fields contain information related to how and when a record processes. A
|
||||
few records have unique fields that also affect how they process. These
|
||||
fields, if any, will be listed and explained in the section for each record.
|
||||
|
||||
The B<SCAN> field specifies the scanning period for periodic record scans or the
|
||||
scan type for non-periodic record scans. The default set of values for SCAN can
|
||||
be found in L<menuScan.dbd|menuScan>.
|
||||
|
||||
The choices provided by this menu are:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
C<Passive> for the record scan to be triggered by other records or Channel
|
||||
Access
|
||||
|
||||
=item *
|
||||
|
||||
C<Event> for event-driven scan
|
||||
|
||||
=item *
|
||||
|
||||
C<I/O Intr> for interrupt-driven scan
|
||||
|
||||
=item *
|
||||
|
||||
A set of periodic scan intervals
|
||||
|
||||
=back
|
||||
|
||||
Additional periodic scan rates may be defined for individual IOCs by making a
|
||||
local copy of menuScan.dbd and adding more choices as required. Scan rates
|
||||
should normally be defined in order, with the fastest rates appearing first.
|
||||
Scan periods may now be specified in seconds, minutes, hours or Hertz/Hz, and
|
||||
plural time units will also be accepted (seconds are used if no unit is
|
||||
mentioned in the choice string). For example the rates given below are all
|
||||
valid:
|
||||
|
||||
1 hour
|
||||
0.5 hours
|
||||
15 minutes
|
||||
3 seconds
|
||||
1 second
|
||||
2 Hertz
|
||||
|
||||
The B<PINI> field specifies record processing at initialization. If it is set
|
||||
to YES during database configuration, the record is processed once at IOC
|
||||
initialization (before the normal scan tasks are started).
|
||||
|
||||
The B<PHAS> field orders the records within a specific SCAN group. This is not
|
||||
meaningful for passive records. All records of a specified phase are processed
|
||||
before those with higher phase number. Whenever possible it is better to use
|
||||
linked passive records to enforce the order of processing rather than a phase
|
||||
number.
|
||||
|
||||
The B<EVNT> field specifies an event number. This event number is used if the
|
||||
SCAN field is set to C<Event>. All records with scan type C<Event> and the
|
||||
same EVNT value will be processed when a call to post_event for EVNT is made.
|
||||
The call to post_event is: post_event(short event_number).
|
||||
|
||||
The B<PRIO> field specifies the scheduling priority for processing records
|
||||
with SCAN=C<I/O Event> and asynchronous record completion tasks.
|
||||
|
||||
The B<DISV> field specifies a "disable value". Record processing is
|
||||
immediately terminated if the value of this field is equal to the value of the
|
||||
DISA field, i.e. the record is disabled. Note that field values of a record
|
||||
can be changed by database put or Channel Access, even if a record is
|
||||
disabled.
|
||||
|
||||
The B<DISA> field contains the value that is compared with DISV to determine
|
||||
if the record is disabled. The value of the DISA field is obtained via SDIS if
|
||||
SDIS is a database or channel access link. If SDIS is not a database or
|
||||
channel access link, then DISA can be set via dbPutField or dbPutLink.
|
||||
|
||||
If the B<PROC> field of a record is written to, the record is processed.
|
||||
|
||||
The B<DISS> field defines the record's "disable severity". If this field is
|
||||
not NO_ALARM and the record is disabled, the record will be put into alarm
|
||||
with this severity and a status of DISABLE_ALARM.
|
||||
|
||||
The B<LSET> field contains the lock set to which this record belongs. All
|
||||
records linked in any way via input, output, or forward database links belong
|
||||
to the same lock set. Lock sets are determined at IOC initialization time, and
|
||||
are updated whenever a database link is added, removed or altered.
|
||||
|
||||
The B<LCNT> field counts the number of times dbProcess finds the record active
|
||||
during successive scans, i.e. PACT is TRUE. If dbProcess finds the record
|
||||
active MAX_LOCK times (currently set to 10) it raises a SCAN_ALARM.
|
||||
|
||||
The B<PACT> field is TRUE while the record is being processed. For
|
||||
asynchronous records PACT can be TRUE from the time record processing is
|
||||
started until the asynchronous completion occurs. As long as PACT is TRUE,
|
||||
dbProcess will not call the record processing routine. See Application
|
||||
Developers Guide for details on usage of PACT.
|
||||
|
||||
The B<FLNK> field is a database link to another record (the "target" record).
|
||||
Processing a record with a specified FLNK field will force processing of the
|
||||
target record, provided the target record's SCAN field is set to C<Passive>.
|
||||
|
||||
The B<SPVT> field is for internal use by the scanning system.
|
||||
|
||||
=fields SCAN, PINI, PHAS, EVNT, PRIO, DISV, DISA, SDIS, PROC, DISS, LCNT, PACT, FLNK, SPVT
|
||||
|
||||
=cut
|
||||
|
||||
field(SCAN,DBF_MENU) {
|
||||
prompt("Scan Mechanism")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuScan)
|
||||
}
|
||||
field(PINI,DBF_MENU) {
|
||||
prompt("Process at iocInit")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
menu(menuPini)
|
||||
}
|
||||
field(PHAS,DBF_SHORT) {
|
||||
prompt("Scan Phase")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
}
|
||||
field(EVNT,DBF_STRING) {
|
||||
prompt("Event Name")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
size(40)
|
||||
interest(1)
|
||||
}
|
||||
field(TSE,DBF_SHORT) {
|
||||
prompt("Time Stamp Event")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(TSEL,DBF_INLINK) {
|
||||
prompt("Time Stamp Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
field(DTYP,DBF_DEVICE) {
|
||||
prompt("Device Type")
|
||||
promptgroup("10 - Common")
|
||||
interest(1)
|
||||
}
|
||||
field(DISV,DBF_SHORT) {
|
||||
prompt("Disable Value")
|
||||
promptgroup("20 - Scan")
|
||||
initial("1")
|
||||
}
|
||||
field(DISA,DBF_SHORT) {
|
||||
prompt("Disable")
|
||||
}
|
||||
field(SDIS,DBF_INLINK) {
|
||||
prompt("Scanning Disable")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
%#include "epicsMutex.h"
|
||||
field(MLOK,DBF_NOACCESS) {
|
||||
prompt("Monitor lock")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("epicsMutexId mlok")
|
||||
}
|
||||
%#include "ellLib.h"
|
||||
field(MLIS,DBF_NOACCESS) {
|
||||
prompt("Monitor List")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("ELLLIST mlis")
|
||||
}
|
||||
field(BKLNK,DBF_NOACCESS) {
|
||||
prompt("Backwards link tracking")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("ELLLIST bklnk")
|
||||
}
|
||||
field(DISP,DBF_UCHAR) {
|
||||
prompt("Disable putField")
|
||||
}
|
||||
field(PROC,DBF_UCHAR) {
|
||||
prompt("Force Processing")
|
||||
pp(TRUE)
|
||||
interest(3)
|
||||
}
|
||||
|
||||
=head3 Alarm Fields
|
||||
|
||||
These fields indicate the status and severity of alarms, or else determine the
|
||||
how and when alarms are triggered. Of course, many records have alarm-related
|
||||
fields not common to all records. These fields are listed and explained in the
|
||||
appropriate section on each record.
|
||||
|
||||
The B<STAT> field contains the current alarm status.
|
||||
|
||||
The B<SEVR> field contains the current alarm severity.
|
||||
|
||||
These two fields are seen outside database access. The B<NSTA> and B<NSEV>
|
||||
fields are used by the database access, record support, and device support
|
||||
routines to set new alarm status and severity values. Whenever any software
|
||||
component discovers an alarm condition, it uses the following macro function:
|
||||
recGblSetSevr(precord,new_status,new_severity) This ensures that the current
|
||||
alarm severity is set equal to the highest outstanding alarm. The file alarm.h
|
||||
defines all allowed alarm status and severity values.
|
||||
|
||||
The B<ACKS> field contains the highest unacknowledged alarm severity.
|
||||
|
||||
The B<ACKT> field specifies if it is necessary to acknowledge transient
|
||||
alarms.
|
||||
|
||||
The B<UDF> indicates if the record's value is B<U>nB<D>eB<F>ined. Typically
|
||||
this is caused by a failure in device support, the fact that the record has
|
||||
never been processed, or that the VAL field currently contains a NaN (not a
|
||||
number). UDF is initialized to TRUE at IOC initialization. Record and device
|
||||
support routines which write to the VAL field are responsible for setting UDF.
|
||||
|
||||
=fields STAT, SEVR, NSTA, NSEV, ACKS, ACKT, UDF
|
||||
|
||||
=cut
|
||||
|
||||
field(STAT,DBF_MENU) {
|
||||
prompt("Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmStat)
|
||||
initial("UDF")
|
||||
}
|
||||
field(SEVR,DBF_MENU) {
|
||||
prompt("Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(NSTA,DBF_MENU) {
|
||||
prompt("New Alarm Status")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmStat)
|
||||
}
|
||||
field(NSEV,DBF_MENU) {
|
||||
prompt("New Alarm Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKS,DBF_MENU) {
|
||||
prompt("Alarm Ack Severity")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(ACKT,DBF_MENU) {
|
||||
prompt("Alarm Ack Transient")
|
||||
promptgroup("70 - Alarm")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
menu(menuYesNo)
|
||||
initial("YES")
|
||||
}
|
||||
field(DISS,DBF_MENU) {
|
||||
prompt("Disable Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
}
|
||||
field(LCNT,DBF_UCHAR) {
|
||||
prompt("Lock Count")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
}
|
||||
field(PACT,DBF_UCHAR) {
|
||||
prompt("Record active")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(PUTF,DBF_UCHAR) {
|
||||
prompt("dbPutField process")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(RPRO,DBF_UCHAR) {
|
||||
prompt("Reprocess ")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
}
|
||||
field(ASP,DBF_NOACCESS) {
|
||||
prompt("Access Security Pvt")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct asgMember *asp")
|
||||
}
|
||||
field(PPN,DBF_NOACCESS) {
|
||||
prompt("pprocessNotify")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotify *ppn")
|
||||
}
|
||||
field(PPNR,DBF_NOACCESS) {
|
||||
prompt("pprocessNotifyRecord")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct processNotifyRecord *ppnr")
|
||||
}
|
||||
field(SPVT,DBF_NOACCESS) {
|
||||
prompt("Scan Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct scan_element *spvt")
|
||||
}
|
||||
|
||||
=head3 Device Fields
|
||||
|
||||
The B<RSET> field contains the address of the Record Support Entry Table. See
|
||||
the Application Developers Guide for details on usage.
|
||||
|
||||
The B<DSET> field contains the address of Device Support Entry Table. The
|
||||
value of this field is determined at IOC initialization time. Record support
|
||||
routines use this field to locate their device support routines.
|
||||
|
||||
The B<DPVT> field is is for private use of the device support modules.
|
||||
|
||||
=fields RSET, DSET, DPVT
|
||||
|
||||
=cut
|
||||
|
||||
field(RSET,DBF_NOACCESS) {
|
||||
prompt("Address of RSET")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct typed_rset *rset")
|
||||
}
|
||||
%#include "devSup.h"
|
||||
field(DSET,DBF_NOACCESS) {
|
||||
prompt("DSET address")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("unambiguous_dset *dset")
|
||||
}
|
||||
field(DPVT,DBF_NOACCESS) {
|
||||
prompt("Device Private")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("void *dpvt")
|
||||
}
|
||||
field(RDES,DBF_NOACCESS) {
|
||||
prompt("Address of dbRecordType")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct dbRecordType *rdes")
|
||||
}
|
||||
field(LSET,DBF_NOACCESS) {
|
||||
prompt("Lock Set")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("struct lockRecord *lset")
|
||||
}
|
||||
field(PRIO,DBF_MENU) {
|
||||
prompt("Scheduling Priority")
|
||||
promptgroup("20 - Scan")
|
||||
special(SPC_SCAN)
|
||||
interest(1)
|
||||
menu(menuPriority)
|
||||
}
|
||||
|
||||
=head3 Debugging Fields
|
||||
|
||||
The B<TPRO> field is used for trace processing. If this field is non-zero a
|
||||
message is printed whenever this record is processed, and when any other
|
||||
record in the same lock-set is processed by a database link from this record.
|
||||
|
||||
The B<BKPT> field indicates if there is a breakpoint set at this record. This
|
||||
supports setting a debug breakpoint in the record processing. STEP through
|
||||
database processing can be supported using this.
|
||||
|
||||
=fields TPRO, BKPT
|
||||
|
||||
|
||||
=head3 Miscellaneous Fields
|
||||
|
||||
The B<ASG> field contains a character string value defining the access
|
||||
security group for this record. If left empty, the record is placed in group
|
||||
DEFAULT.
|
||||
|
||||
The B<ASP> field is a field for private use of the access security system.
|
||||
|
||||
The B<DISP> field controls dbPutFields to this record which are normally
|
||||
issued by channel access. If the field is set to TRUE all dbPutFields
|
||||
directed to this record are ignored except to the field DISP itself.
|
||||
|
||||
The B<DTYP> field specifies the device type for the record. Each record type
|
||||
has its own set of device support routines which are specified in
|
||||
devSup.ASCII. If a record type does not have any associated device support,
|
||||
DTYP and DSET are meaningless.
|
||||
|
||||
The B<MLOK> field contains the monitor lock. The lock used by the monitor
|
||||
routines when the monitor list is being used. The list is locked whenever
|
||||
monitors are being scheduled, invoked, or when monitors are being added to or
|
||||
removed from the list. This field is accessed only by the dbEvent routines.
|
||||
|
||||
The B<MLIS> field is the head of the list of monitors connected to this
|
||||
record. Each record support module is responsible for triggering monitors for
|
||||
any fields that change as a result of record processing. Monitors are present
|
||||
if mlis count is greater than zero. The call to trigger monitors is:
|
||||
db_post_event(precord,&data,mask), where "mask" is some combination of
|
||||
DBE_ALARM, DBE_VALUE, and DBE_LOG.
|
||||
|
||||
The B<PPN> field contains the address of a putNotify callback.
|
||||
|
||||
The B<PPNR> field contains the next record for PutNotify.
|
||||
|
||||
The B<PUTF> field is set to TRUE if dbPutField caused the current record
|
||||
processing.
|
||||
|
||||
The B<RDES> field contains the address of dbRecordType
|
||||
|
||||
The B<RPRO> field specifies a reprocessing of the record when current
|
||||
processing completes.
|
||||
|
||||
The B<TIME> field contains the time when this record was last processed in
|
||||
standard format.
|
||||
|
||||
The B<TSE> field indicates the mechanism to use to get the time stamp. '0' -
|
||||
call get time as before '-1' - call the time stamp driver and use the best
|
||||
source available. '-2' - the device support provides the time stamp from the
|
||||
hardware. Values between 1-255 request the time of the last occurance of a
|
||||
generalTime event.
|
||||
|
||||
The B<TSEL> field contains an input link for obtaining the time stamp. If this
|
||||
link references the .TIME field of a record then the time stamp of the
|
||||
referenced record becomes the time stamp for this record as well. In this
|
||||
case, an internal flag is set and ".TIME" is then overwritten by ".VAL". If
|
||||
any other field is referenced, the field value is read and stored in the .TSE
|
||||
field which is then used to acquire a timestamp.
|
||||
|
||||
=fields ASG, ASP, DISP, DTYP, MLOK, MLIS, PPN, PPNR, PUTF, RDES, RPRO, TIME, TSE, TSEL
|
||||
|
||||
=cut
|
||||
|
||||
field(TPRO,DBF_UCHAR) {
|
||||
prompt("Trace Processing")
|
||||
}
|
||||
field(BKPT,DBF_NOACCESS) {
|
||||
prompt("Break Point")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
extra("char bkpt")
|
||||
}
|
||||
field(UDF,DBF_UCHAR) {
|
||||
prompt("Undefined")
|
||||
promptgroup("10 - Common")
|
||||
pp(TRUE)
|
||||
interest(1)
|
||||
initial("1")
|
||||
}
|
||||
field(UDFS,DBF_MENU) {
|
||||
prompt("Undefined Alarm Sevrty")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
menu(menuAlarmSevr)
|
||||
initial("INVALID")
|
||||
}
|
||||
%#include "epicsTime.h"
|
||||
field(TIME,DBF_NOACCESS) {
|
||||
prompt("Time")
|
||||
special(SPC_NOMOD)
|
||||
interest(2)
|
||||
extra("epicsTimeStamp time")
|
||||
}
|
||||
field(FLNK,DBF_FWDLINK) {
|
||||
prompt("Forward Process Link")
|
||||
promptgroup("20 - Scan")
|
||||
interest(1)
|
||||
}
|
||||
181
modules/database/src/ioc/db/dbCommonInput.pod
Normal file
181
modules/database/src/ioc/db/dbCommonInput.pod
Normal file
@@ -0,0 +1,181 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Fields Common to Input Record Types
|
||||
|
||||
This section describes fields that are found in many input record types.
|
||||
These fields usually have the same meaning whenever they are used.
|
||||
|
||||
See also L<Fields Common to All Record Types|dbCommonRecord> and L<Fields Common
|
||||
to Output Record Types|dbCommonOutput>.
|
||||
|
||||
=head3 Input and Value Fields
|
||||
|
||||
The B<INP> field specifies an input link. It is used by the device support
|
||||
routines to obtain input. For soft analog records it can be a constant, a
|
||||
database link, or a channel access link.
|
||||
|
||||
The B<DTYP> field specifies the name of the device support module that will
|
||||
input values. Each record type has its own set of device support routines. If
|
||||
a record type does not have any associated device support, DTYP is
|
||||
meaningless.
|
||||
|
||||
The B<RVAL> field contains - whenever possible - the raw data value exactly as
|
||||
it is obtained from the hardware or from the associated device driver and
|
||||
before it undergoes any conversions. The Soft Channel device support module
|
||||
reads values directly into VAL, bypassing this field.
|
||||
|
||||
The B<VAL> field contains the record's final value, after any needed
|
||||
conversions have been performed.
|
||||
|
||||
=head3 Device Input
|
||||
|
||||
A device input routine normally returns one of the following values to its
|
||||
associated record support routine:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0: Success and convert. The input value is in RVAL. The record support module
|
||||
will compute VAL from RVAL.
|
||||
|
||||
=item *
|
||||
|
||||
2: Success, but don't convert. The device support module can specify this
|
||||
value if it does not want any conversions. It might do this for two reasons:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
A hardware error is detected (in this case, it should also raise an alarm
|
||||
condition).
|
||||
|
||||
=item *
|
||||
|
||||
The device support routine reads values directly into the VAL field and then
|
||||
sets UDF to FALSE. For some record types the device support routine may have to
|
||||
do other record-specific processing as well such as applying a smoothing filter
|
||||
to the engineering units value.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head3 Device Support for Soft Records
|
||||
|
||||
In most cases, two soft output device support modules are provided: Soft Channel
|
||||
and Raw Soft Channel. Both allow INP to be a constant, a database link, or a
|
||||
channel access link. The Soft Channel device support module reads input directly
|
||||
into the VAL field and specifies that no value conversion should be performed.
|
||||
This allows the record to store values in the data type of its VAL field. Note
|
||||
that for Soft Channel input, the RVAL field is not used. The Raw Soft Channel
|
||||
support module reads input into RVAL and indicates that any specified unit
|
||||
conversions be performed.
|
||||
|
||||
The device support read routine normally calls C<dbGetLink()> which
|
||||
fetches a value from the link.
|
||||
|
||||
If a value was returned by the link the UDF field is set to FALSE. The device
|
||||
support read routine normally returns the status from C<dbGetLink()>.
|
||||
|
||||
|
||||
=head3 Input Simulation Fields
|
||||
|
||||
The B<SIMM> field controls simulation mode. It has either the value YES or NO.
|
||||
By setting this field to YES, the record can be switched into simulation mode
|
||||
of operation. While in simulation mode, input will be obtained from SIOL
|
||||
instead of INP.
|
||||
|
||||
Ths B<SIML> specifies the simulation mode location. This field can be a
|
||||
constant, a database link, or a channel access link. If SIML is a database or
|
||||
channel access link, then SIMM is read from SIML. If SIML is a constant link
|
||||
then SIMM is initialized with the constant value but can be changed via
|
||||
dbPuts.
|
||||
|
||||
Ths B<SVAL> field contains the simulation value. This is the record's input
|
||||
value, in engineering units, when the record is switched into simulation mode,
|
||||
i.e. when SIMM is set to YES.
|
||||
|
||||
The B<SIOL> field is a link that can be used to fetch the simulation value. The
|
||||
link can be a constant, a database link, or a channel access link. If SIOL is a
|
||||
database or channel access link, then SVAL is read from SIOL. If SIOL is a
|
||||
constant link then SVAL is initialized with the constant value but can be
|
||||
changed via dbPuts.
|
||||
|
||||
The B<SIMS> field specifies the simulation mode alarm severity. When this
|
||||
field is set to a value other than NO_ALARM and the record is in simulation
|
||||
mode, it will be put into alarm with this severity and a status of SIMM.
|
||||
|
||||
=head3 Simulation Mode for Input Records
|
||||
|
||||
An input record can be switched into simulation mode of operation by setting
|
||||
the value of SIMM to YES or RAW. During simulation, the record will be put
|
||||
into alarm with a severity of SIMS and a status of SIMM_ALARM. While in
|
||||
simulation mode, input values will be read from SIOL instead of INP:
|
||||
|
||||
-- (SIMM = NO?) INP (if supported and directed by device support, -> RVAL -- convert -> VAL), (else -> VAL)
|
||||
/
|
||||
|
||||
SIML -> SIMM
|
||||
|
||||
\
|
||||
-- (SIMM = YES?) SIOL -> SVAL -> VAL
|
||||
\
|
||||
-- (SIMM = RAW?) SIOL -> SVAL -> RVAL -- convert -> VAL
|
||||
|
||||
A record can be switched into simulation mode of operation by setting the
|
||||
value of SIMM to YES. During simulation, the record will be put into alarm
|
||||
with a severity of SIMS and a status of SIMM_ALARM. While in simulation mode,
|
||||
input values, in engineering units, will be obtained from SIOL instead of INP.
|
||||
Also, while the record is in simulation mode, there will be no raw value
|
||||
conversion and no calls to device support when the record is processed.
|
||||
|
||||
Normally input records contain a private readValue() routine which performs
|
||||
the following steps:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If PACT is TRUE, the device support read routine is called, status is set to
|
||||
its return code, and readValue returns.
|
||||
|
||||
=item *
|
||||
|
||||
Call C<dbGetLink()> to get a new value for SIMM from SIML.
|
||||
|
||||
=item *
|
||||
|
||||
Check value of SIMM.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is NO, then call the device support read routine, set status to its
|
||||
return code, and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is YES, then call C<dbGetLink()> to read the input value from SIOL
|
||||
into SVAL. If success, then set VAL to SVAL and UDF to FALSE and set status to
|
||||
2 (don't convert) if input record supports conversion. If SIMS is greater than
|
||||
zero, set alarm status to SIMM and severity to SIMS. Set status to the return
|
||||
code from recGblGetLinkValue and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is RAW, then call C<dbGetLink()> to read the input value from SIOL
|
||||
into SVAL. If success, then set RVAL to SVAL and UDF to FALSE and set status
|
||||
to 0 (convert) if input record supports conversion. If SIMS is greater than
|
||||
zero, set alarm status to SIMM and severity to SIMS. Set status to the return
|
||||
code from recGblGetLinkValue and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is not YES, NO or RAW, a SOFT alarm with a severity of INVALID is
|
||||
raised, and return status is set to -1.
|
||||
|
||||
=back
|
||||
211
modules/database/src/ioc/db/dbCommonOutput.pod
Normal file
211
modules/database/src/ioc/db/dbCommonOutput.pod
Normal file
@@ -0,0 +1,211 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Fields Common to Output Record Types
|
||||
|
||||
This section describes fields that are found in many output record types.
|
||||
These fields usually have the same meaning whenever they are used.
|
||||
|
||||
See also L<Fields Common to All Record Types|dbCommonRecord> and L<Fields Common to
|
||||
Input Records|dbCommonInput>.
|
||||
|
||||
=head3 Output and Value Fields
|
||||
|
||||
The B<OUT> field specifies an output link. It is used by the device support
|
||||
routines to decide where to send output. For soft records, it can be a
|
||||
constant, a database link, or a channel access link. If the link is a
|
||||
constant, the result is no output.
|
||||
|
||||
The B<DTYP> field specifies the name of the device support module that will
|
||||
input values. Each record type has its own set of device support routines. If
|
||||
a record type does not have any associated device support, DTYP is
|
||||
meaningless.
|
||||
|
||||
The B<VAL> field contains the desired value before any conversions to raw
|
||||
output have been performed.
|
||||
|
||||
The B<OVAL> field is used to decide when to invoke monitors. Archive and value
|
||||
change monitors are invoked if OVAL is not equal to VAL. If a record type
|
||||
needs to make adjustments, OVAL is used to enforce the maximum rate of change
|
||||
limit before converting the desired value to a raw value.
|
||||
|
||||
The B<RVAL> field contains - whenever possible - the actual value sent to the
|
||||
hardware itself or to the associated device driver.
|
||||
|
||||
The B<RBV> field contains - whenever possible - the actual read back value
|
||||
obtained from the hardware itself or from the associated device driver.
|
||||
|
||||
|
||||
=head3 Device Support for Soft Records
|
||||
|
||||
Normally two soft output device support modules are provided, Soft Channel and
|
||||
and Raw Soft Channel. Both write a value through the output link OUT.
|
||||
The Soft Channel module writes output from the value associated with OVAL or
|
||||
VAL (if OVAL does not exist). The Raw Soft Channel support module writes the
|
||||
value associated with the RVAL field after conversion has been performed.
|
||||
|
||||
The device support write routine normally calls C<dbPutLink()> which writes a
|
||||
value through the OUT link, and returns the status from that call.
|
||||
|
||||
|
||||
=head3 Input and Mode Select Fields
|
||||
|
||||
The B<DOL> field is a link from which the desired output value can be fetched.
|
||||
DOL can be a constant, a database link, or a channel access link. If DOL is a
|
||||
database or channel access link and OMSL is closed_loop, then VAL is obtained
|
||||
from DOL.
|
||||
|
||||
The B<OMSL> field selects the output mode. This field has either the value
|
||||
C<supervisory> or C<closed_loop>. DOL is used to fetch VAL only if OMSL has the
|
||||
value C<closed_loop>. By setting this field a record can be switched between
|
||||
supervisory and closed loop mode of operation. While in closed loop mode, the
|
||||
VAL field cannot be set via dbPuts.
|
||||
|
||||
=head3 Output Mode Selection
|
||||
|
||||
The fields DOL and OMSL are used to allow the output record to be part of a
|
||||
closed loop control algorithm. OMSL is meaningful only if DOL refers to a
|
||||
database or channel access link. It can have the values C<supervisory> or
|
||||
C<closed_loop>. If the mode is C<supervisory>, then nothing is done to VAL. If
|
||||
the mode is C<closed_loop> and the record type does not contain an OIF field,
|
||||
then each time the record is processed, VAL is set equal to the value obtained
|
||||
from the location referenced by DOL. If the mode is C<closed_loop> in record
|
||||
types with an OIF field and OIF is Full, VAL is set equal to the value obtained
|
||||
from the location referenced by DOL; if OIF is Incremental VAL is incremented by
|
||||
the value obtained from DOL.
|
||||
|
||||
=head3 Invalid Output Action Fields
|
||||
|
||||
The B<IVOA> field specifies the output action for the case that the record is
|
||||
put into an INVALID alarm severity. IVOA can be one of the following actions:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
C<Continue normally>
|
||||
|
||||
=item *
|
||||
|
||||
C<Don't drive outputs>
|
||||
|
||||
=item *
|
||||
|
||||
C<Set output to IVOV>
|
||||
|
||||
=back
|
||||
|
||||
The B<IVOV> field contains the value for the IVOA action C<Set output to IVOV>
|
||||
in engineering units. If a new severity has been set to INVALID and IVOA is
|
||||
C<Set output to IVOV>, then VAL is set to IVOV and converted to RVAL before
|
||||
device support is called.
|
||||
|
||||
=head3 Invalid Alarm Output Action
|
||||
|
||||
Whenever an output record is put into INVALID alarm severity, IVOA specifies
|
||||
an action to take. The record support process routine for each output record
|
||||
contains code which performs the following steps.
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If new severity is less than INVALID, then call C<writeValue()>:
|
||||
|
||||
=item *
|
||||
|
||||
Else do the following:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA is C<Continue normally> then call C<writeValue()>.
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA is C<Don't drive outputs> then do not write output.
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA is C<Set output to IVOV> then set VAL to IVOV, call C<convert()> if
|
||||
necessary, and then call C<writeValue()>.
|
||||
|
||||
=item *
|
||||
|
||||
If IVOA not one of the above, an error message is generated.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head3 Simulation Fields
|
||||
|
||||
The B<SIMM> field controls simulation mode. It has either the value YES or NO.
|
||||
By setting this field to YES, the record can be switched into simulation mode
|
||||
of operation. While in simulation mode, output will be forwarded through SIOL
|
||||
instead of OUT.
|
||||
|
||||
Ths B<SIML> specifies the simulation mode location. This field can be a
|
||||
constant, a database link, or a channel access link. If SIML is a database or
|
||||
channel access link, then SIMM is read from SIML. If SIML is a constant link
|
||||
then SIMM is initialized with the constant value but can be changed via
|
||||
dbPuts.
|
||||
|
||||
The B<SIOL> field is a link that the output value is written to when the record
|
||||
is in simulation mode.
|
||||
|
||||
The B<SIMS> field specifies the simulation mode alarm severity. When this
|
||||
field is set to a value other than NO_ALARM and the record is in simulation
|
||||
mode, it will be put into alarm with this severity and a status of SIMM.
|
||||
|
||||
=head3 Simulation Mode
|
||||
|
||||
An output record can be switched into simulation mode of operation by setting
|
||||
the value of SIMM to YES. During simulation, the record will be put into alarm
|
||||
with a severity of SIMS and a status of SIMM_ALARM. While in simulation mode,
|
||||
output values, in engineering units, will be written to SIOL instead of OUT.
|
||||
However, the output values are never converted. Also, while the record is in
|
||||
simulation mode, there will be no calls to device support during record
|
||||
processing.
|
||||
|
||||
Normally output records contain a private C<writeValue()> routine which performs
|
||||
the following steps:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If PACT is TRUE, the device support write routine is called, status is set to
|
||||
its return code, and readValue returns.
|
||||
|
||||
=item *
|
||||
|
||||
Call C<dbGetLink()> to get a new value for SIMM if SIML is a DB_LINK or a
|
||||
CA_LINK.
|
||||
|
||||
=item *
|
||||
|
||||
Check value of SIMM.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is NO, then call the device support write routine, set status to its
|
||||
return code, and return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM is YES, then call C<dbPutLink()> to write the output value from VAL or
|
||||
OVAL to SIOL. Set alarm status to SIMM and severity to SIMS, if SIMS is
|
||||
greater than zero. Set status to the return code from C<dbPutLink()> and
|
||||
return.
|
||||
|
||||
=item *
|
||||
|
||||
If SIMM not one of the above, a SOFT alarm with a severity of INVALID is
|
||||
raised, and return status is set to -1.
|
||||
|
||||
=back
|
||||
@@ -1,12 +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 Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
recordtype(dbCommon) {
|
||||
include "dbCommon.dbd"
|
||||
}
|
||||
20
modules/database/src/ioc/db/dbCommonRecord.dbd.pod
Normal file
20
modules/database/src/ioc/db/dbCommonRecord.dbd.pod
Normal file
@@ -0,0 +1,20 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Fields Common to All Record Types
|
||||
|
||||
This section contains a description of the fields that are common to all record
|
||||
types. These fields are defined in dbCommon.dbd.
|
||||
|
||||
See also L<Fields Common to Input Record Types|dbCommonInput> and L<Fields
|
||||
Common to Output Record Types|dbCommonOutput>.
|
||||
|
||||
=recordtype dbCommon
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(dbCommon) {
|
||||
include "dbCommon.dbd.pod"
|
||||
}
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "epicsExport.h"
|
||||
#include "link.h"
|
||||
#include "special.h"
|
||||
#include "iocInit.h"
|
||||
|
||||
|
||||
|
||||
@@ -216,10 +217,13 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
char *penv;
|
||||
char **macPairs;
|
||||
|
||||
if(ellCount(&tempList)) {
|
||||
if (ellCount(&tempList)) {
|
||||
epicsPrintf("dbReadCOM: Parser stack dirty %d\n", ellCount(&tempList));
|
||||
}
|
||||
|
||||
if (getIocState() != iocVoid)
|
||||
return -2;
|
||||
|
||||
if(*ppdbbase == 0) *ppdbbase = dbAllocBase();
|
||||
pdbbase = *ppdbbase;
|
||||
if(path && strlen(path)>0) {
|
||||
|
||||
@@ -70,9 +70,7 @@
|
||||
#include "registryJLinks.h"
|
||||
#include "registryRecordType.h"
|
||||
|
||||
static enum {
|
||||
iocVirgin, iocBuilding, iocBuilt, iocRunning, iocPaused, iocStopped
|
||||
} iocState = iocVirgin;
|
||||
static enum iocStateEnum iocState = iocVoid;
|
||||
static enum {
|
||||
buildServers, buildIsolated
|
||||
} iocBuildMode;
|
||||
@@ -99,6 +97,11 @@ static void iterateRecords(recIterFunc func, void *user);
|
||||
int dbThreadRealtimeLock = 1;
|
||||
epicsExportAddress(int, dbThreadRealtimeLock);
|
||||
|
||||
enum iocStateEnum getIocState(void)
|
||||
{
|
||||
return iocState;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize EPICS on the IOC.
|
||||
*/
|
||||
@@ -109,7 +112,7 @@ int iocInit(void)
|
||||
|
||||
static int iocBuild_1(void)
|
||||
{
|
||||
if (iocState != iocVirgin && iocState != iocStopped) {
|
||||
if (iocState != iocVoid) {
|
||||
errlogPrintf("iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -705,8 +708,7 @@ static void doFreeRecord(dbRecordType *pdbRecordType, dbCommon *precord,
|
||||
|
||||
int iocShutdown(void)
|
||||
{
|
||||
if (iocState == iocVirgin || iocState == iocStopped)
|
||||
return 0;
|
||||
if (iocState == iocVoid) return 0;
|
||||
|
||||
iterateRecords(doCloseLinks, NULL);
|
||||
|
||||
@@ -734,7 +736,7 @@ int iocShutdown(void)
|
||||
iocshFree();
|
||||
}
|
||||
|
||||
iocState = iocStopped;
|
||||
iocState = iocVoid;
|
||||
iocBuildMode = buildServers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,10 +13,15 @@
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
enum iocStateEnum {
|
||||
iocVoid, iocBuilding, iocBuilt, iocRunning, iocPaused
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc enum iocStateEnum getIocState(void);
|
||||
epicsShareFunc int iocInit(void);
|
||||
epicsShareFunc int iocBuild(void);
|
||||
epicsShareFunc int iocBuildIsolated(void);
|
||||
|
||||
@@ -68,17 +68,6 @@ static void req_server (void *pParm)
|
||||
|
||||
IOC_sock = conf->tcp;
|
||||
|
||||
/* listen and accept new connections */
|
||||
if ( listen ( IOC_sock, 20 ) < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf ( "CAS: Listen error: %s\n",
|
||||
sockErrBuf );
|
||||
epicsSocketDestroy (IOC_sock);
|
||||
epicsThreadSuspendSelf ();
|
||||
}
|
||||
|
||||
epicsEventSignal(castcp_startStopEvent);
|
||||
|
||||
while (TRUE) {
|
||||
@@ -198,7 +187,7 @@ SOCKET* rsrv_grab_tcp(unsigned short *port)
|
||||
|
||||
epicsSocketEnableAddressReuseDuringTimeWaitState ( tcpsock );
|
||||
|
||||
if(bind(tcpsock, &scratch.sa, sizeof(scratch))==0) {
|
||||
if(bind(tcpsock, &scratch.sa, sizeof(scratch))==0 && listen(tcpsock, 20)==0) {
|
||||
if(scratch.ia.sin_port==0) {
|
||||
/* use first socket to pick a random port */
|
||||
osiSocklen_t alen = sizeof(ifaceAddr);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
505
modules/database/src/std/rec/aaiRecord.dbd.pod
Normal file
505
modules/database/src/std/rec/aaiRecord.dbd.pod
Normal file
@@ -0,0 +1,505 @@
|
||||
#*************************************************************************
|
||||
# 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
|
||||
|
||||
include "menuFtype.dbd"
|
||||
|
||||
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 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.
|
||||
|
||||
=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. See L<Address Specification> for information on the format
|
||||
of hardware addresses and database links.
|
||||
|
||||
=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.
|
||||
|
||||
=fields DTYP, INP, NELM, FTVL
|
||||
|
||||
=head4 Possible data types for FTVL
|
||||
|
||||
=menu menuFtype
|
||||
|
||||
=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> 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 "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 choices for 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
|
||||
|
||||
The following fields are used to operate the array analog input record in the
|
||||
simulation mode. See L<Simulation Mode> for more information on the simulation
|
||||
mode fields.
|
||||
|
||||
=fields SIOL, SIML, SIMM, SIMS
|
||||
|
||||
=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"
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
=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. 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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
503
modules/database/src/std/rec/aaoRecord.dbd.pod
Normal file
503
modules/database/src/std/rec/aaoRecord.dbd.pod
Normal file
@@ -0,0 +1,503 @@
|
||||
#*************************************************************************
|
||||
# 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
|
||||
|
||||
include "menuFtype.dbd"
|
||||
|
||||
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.
|
||||
|
||||
=fields DTYP, OUT, NELM, FTVL
|
||||
|
||||
=head4 Possible data types for FTVL
|
||||
|
||||
=menu menuFtype
|
||||
|
||||
=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> 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 choices for 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
|
||||
|
||||
The following fields are used to operate the array analog output record in the
|
||||
simulation mode. See L<Simulation Mode> for more information on the simulation
|
||||
mode fields.
|
||||
|
||||
=fields SIOL, SIML, SIMM, SIMS
|
||||
|
||||
=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"
|
||||
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
|
||||
|
||||
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. 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -260,15 +259,15 @@ 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.
|
||||
The following fields are used when the record is in simulation mode. See
|
||||
L<Fields Common to Output Record Types|dbCommonOutput/Simulation Fields> for
|
||||
more information on these fields.
|
||||
|
||||
=fields SIOL, SIML, SIMM, SIMS
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
include "dbCommon.dbd"
|
||||
field(VAL,DBF_DOUBLE) {
|
||||
prompt("Desired Output")
|
||||
promptgroup("50 - Output")
|
||||
@@ -602,6 +601,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 +634,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 +652,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 +803,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 +815,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 +825,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 +849,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 +879,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 +900,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
|
||||
|
||||
@@ -318,10 +318,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
|
||||
|
||||
|
||||
@@ -350,10 +350,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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -103,7 +103,7 @@ 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) )
|
||||
if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) )
|
||||
status=(*pdset->init_record)(prec);
|
||||
|
||||
prec->epvt = eventNameToHandle(prec->val);
|
||||
@@ -118,12 +118,12 @@ static long process(struct dbCommon *pcommon)
|
||||
long status=0;
|
||||
unsigned char pact=prec->pact;
|
||||
|
||||
if((pdset!=NULL) && (pdset->number >= 5) && pdset->read_event )
|
||||
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);
|
||||
|
||||
recGblGetTimeStampSimm(prec, prec->simm, &prec->siol);
|
||||
|
||||
@@ -133,33 +133,28 @@ 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)
|
||||
|
||||
@@ -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)
|
||||
445
modules/database/src/std/rec/histogramRecord.dbd.pod
Normal file
445
modules/database/src/std/rec/histogramRecord.dbd.pod
Normal file
@@ -0,0 +1,445 @@
|
||||
#*************************************************************************
|
||||
# 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> 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> lists other fields related to a 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"
|
||||
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)
|
||||
@@ -1,115 +0,0 @@
|
||||
#*************************************************************************
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
recordtype(lsi) {
|
||||
include "dbCommon.dbd"
|
||||
%#include "devSup.h"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%typedef struct lsidset {
|
||||
% long number;
|
||||
% DEVSUPFUN report;
|
||||
% DEVSUPFUN init;
|
||||
% DEVSUPFUN init_record;
|
||||
% DEVSUPFUN get_ioint_info;
|
||||
% DEVSUPFUN read_string;
|
||||
%} lsidset;
|
||||
%
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Current Value")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
special(SPC_DBADDR)
|
||||
extra("char *val")
|
||||
}
|
||||
field(OVAL,DBF_NOACCESS) {
|
||||
prompt("Old Value")
|
||||
special(SPC_DBADDR)
|
||||
interest(3)
|
||||
extra("char *oval")
|
||||
}
|
||||
field(SIZV,DBF_USHORT) {
|
||||
prompt("Size of buffers")
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("41")
|
||||
}
|
||||
field(LEN,DBF_ULONG) {
|
||||
prompt("Length of VAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OLEN,DBF_ULONG) {
|
||||
prompt("Length of OVAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(MPST,DBF_MENU) {
|
||||
prompt("Post Value Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
field(APST,DBF_MENU) {
|
||||
prompt("Post Archive Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
234
modules/database/src/std/rec/lsiRecord.dbd.pod
Normal file
234
modules/database/src/std/rec/lsiRecord.dbd.pod
Normal file
@@ -0,0 +1,234 @@
|
||||
#*************************************************************************
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
|
||||
=title Long String Input Record (lsi)
|
||||
|
||||
The long string input record is used to retrieve an arbitrary ASCII string with
|
||||
a maximum length of 65535 characters.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=recordtype lsi
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(lsi) {
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The long string input 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.
|
||||
|
||||
=head3 Input Specification
|
||||
|
||||
The INP field determines where the long string input record obtains its string
|
||||
from. It can be a database or channel access link, or a constant. If constant,
|
||||
the VAL field is initialized with the constant and can be changed via dbPuts.
|
||||
Otherwise, the string is read from the specified location each time the record
|
||||
is processed and placed in the VAL field. The maximum number of characters in
|
||||
VAL is given by SIZV, and cannot be larger than 65535. In addition, the
|
||||
appropriate device support module must be entered into the DTYP field.
|
||||
|
||||
See L<Address Specification> for information on specifying links.
|
||||
|
||||
=fields VAL, OVAL, SIZV, INP, DTYP
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
%#include "devSup.h"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%typedef struct lsidset {
|
||||
% long number;
|
||||
% DEVSUPFUN report;
|
||||
% DEVSUPFUN init;
|
||||
% DEVSUPFUN init_record;
|
||||
% DEVSUPFUN get_ioint_info;
|
||||
% DEVSUPFUN read_string;
|
||||
%} lsidset;
|
||||
%
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Current Value")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
special(SPC_DBADDR)
|
||||
extra("char *val")
|
||||
#=type STRING[SIZV]
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
}
|
||||
field(OVAL,DBF_NOACCESS) {
|
||||
prompt("Old Value")
|
||||
special(SPC_DBADDR)
|
||||
interest(3)
|
||||
extra("char *oval")
|
||||
#=type STRING[SIZV]
|
||||
#=read Yes
|
||||
#=write No
|
||||
}
|
||||
field(SIZV,DBF_USHORT) {
|
||||
prompt("Size of buffers")
|
||||
promptgroup("40 - Input")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("41")
|
||||
}
|
||||
field(LEN,DBF_ULONG) {
|
||||
prompt("Length of VAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OLEN,DBF_ULONG) {
|
||||
prompt("Length of OVAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(INP,DBF_INLINK) {
|
||||
prompt("Input Specification")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
|
||||
=head3 Monitor Parameters
|
||||
|
||||
These parameters are used to specify when the monitor post should be sent by the
|
||||
C<monitor()> routine. There are two possible choices:
|
||||
|
||||
APST is used for archiver monitors and MPST for all other type of monitors.
|
||||
|
||||
=fields MPST, APST
|
||||
|
||||
=cut
|
||||
|
||||
field(MPST,DBF_MENU) {
|
||||
prompt("Post Value Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
field(APST,DBF_MENU) {
|
||||
prompt("Post Archive Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME) and
|
||||
description (DESC) fields.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The long string input 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.
|
||||
|
||||
=head3 Run-time and Simulation Mode Parameters
|
||||
|
||||
The old value field (OVAL) of the long string input record is used to implement
|
||||
value change monitors for VAL. If VAL is not equal to OVAL, then monitors are
|
||||
triggered. LEN contains the length of the string in VAL, OLEN contains the
|
||||
length of the string in OVAL.
|
||||
|
||||
=fields OVAL, LEN, OLEN
|
||||
|
||||
|
||||
The following fields are used to operate the string input in the simulation
|
||||
mode. See L<Simulation Mode> for more information on simulation mode fields.
|
||||
|
||||
=fields SIOL, SIML, SIMM, SIMS
|
||||
|
||||
=cut
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
=head2 Device Support Interface
|
||||
|
||||
The record requires device support to provide an entry table (dset) which
|
||||
defines the following members:
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
long (*report)(int level);
|
||||
long (*init)(int after);
|
||||
long (*init_record)(lsiRecord *prec);
|
||||
long (*get_ioint_info)(int cmd, lsiRecord *prec, IOSCANPVT *piosl);
|
||||
long (*read_string)(lsiRecord *prec);
|
||||
} lsidset;
|
||||
|
||||
The module must set C<number> to at least 5, and provide a pointer to its
|
||||
C<read_string()> routine; the other function pointers may be C<NULL> if their
|
||||
associated functionality is not required for this support layer.
|
||||
Most device supports also provide an C<init_record()> routine to configure the
|
||||
record instance and connect it to the hardware or driver support layer.
|
||||
|
||||
=head2 Device Support for Soft Records
|
||||
|
||||
A device support module for DTYP C<Soft Channel> is provided for retrieving
|
||||
values from other records or other software components.
|
||||
|
||||
Device support for DTYP C<getenv> is provided for retrieving strings from
|
||||
environment variables. C<INST_IO> addressing C<< @<environment variable> >> is
|
||||
used on the C<INP> link field to select the desired environment variable.
|
||||
|
||||
=cut
|
||||
@@ -1,139 +0,0 @@
|
||||
#*************************************************************************
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
recordtype(lso) {
|
||||
include "dbCommon.dbd"
|
||||
%#include "devSup.h"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%typedef struct lsodset {
|
||||
% long number;
|
||||
% DEVSUPFUN report;
|
||||
% DEVSUPFUN init;
|
||||
% DEVSUPFUN init_record;
|
||||
% DEVSUPFUN get_ioint_info;
|
||||
% DEVSUPFUN write_string;
|
||||
%} lsodset;
|
||||
%
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Current Value")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
special(SPC_DBADDR)
|
||||
extra("char *val")
|
||||
}
|
||||
field(OVAL,DBF_NOACCESS) {
|
||||
prompt("Previous Value")
|
||||
special(SPC_DBADDR)
|
||||
interest(3)
|
||||
extra("char *oval")
|
||||
}
|
||||
field(SIZV,DBF_USHORT) {
|
||||
prompt("Size of buffers")
|
||||
promptgroup("50 - Output")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("41")
|
||||
}
|
||||
field(LEN,DBF_ULONG) {
|
||||
prompt("Length of VAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OLEN,DBF_ULONG) {
|
||||
prompt("Length of OVAL")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
prompt("Desired Output Link")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID Output Action")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
menu(menuIvoa)
|
||||
}
|
||||
field(IVOV,DBF_STRING) {
|
||||
prompt("INVALID Output Value")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
size(40)
|
||||
}
|
||||
field(OMSL,DBF_MENU) {
|
||||
prompt("Output Mode Select")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
menu(menuOmsl)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(MPST,DBF_MENU) {
|
||||
prompt("Post Value Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
field(APST,DBF_MENU) {
|
||||
prompt("Post Archive Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
293
modules/database/src/std/rec/lsoRecord.dbd.pod
Normal file
293
modules/database/src/std/rec/lsoRecord.dbd.pod
Normal file
@@ -0,0 +1,293 @@
|
||||
#*************************************************************************
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
|
||||
=title Long String Output Record (lso)
|
||||
|
||||
The long string output record is used to write an arbitrary ASCII string with a
|
||||
maximum length of 65535 characters.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=recordtype lso
|
||||
|
||||
=cut
|
||||
|
||||
include "menuIvoa.dbd"
|
||||
|
||||
recordtype(lso) {
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The long string output 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.
|
||||
|
||||
=head3 Desired Output Parameters
|
||||
|
||||
The long string output record must specify from where it gets its desired output
|
||||
string. The first field that determines where the desired output originates is
|
||||
the output mode select (OMSL) field, which can have two possible value:
|
||||
C<closed_loop> or C<supervisory>. If C<supervisory> is specified, DOL is
|
||||
ignored, the current value of VAL is written, and VAL can be changed externally
|
||||
via dbPuts at run-time. If C<closed_loop> is specified, the VAL field's value is
|
||||
obtained from the address specified in the desired output location field (DOL)
|
||||
which can be either a database link or a channel access link.
|
||||
|
||||
The maximum number of characters in VAL is given by SIZV, and cannot be larger
|
||||
than 65535.
|
||||
|
||||
DOL can also be a constant in addition to a link, in which case VAL is
|
||||
initialized to the constant value. Your string constant, however, may be
|
||||
interpreted as a CA link name. If you want to initialize your string output
|
||||
record, it is therefore best to use the VAL field. Note that if DOL is a
|
||||
constant, OMSL cannot be C<closed_loop>.
|
||||
|
||||
See L<Address Specification> for information on specifying links.
|
||||
|
||||
=fields VAL, SIZV, DOL, OMSL
|
||||
|
||||
=head3 Output Specification
|
||||
|
||||
The output link specified in the OUT field specifies where the long string
|
||||
output record is to write its string. The link can be a database or channel
|
||||
access link. If the OUT field is a constant, no output will be written.
|
||||
|
||||
See L<Address Specification> for information on specifying links.
|
||||
|
||||
In addition, the appropriate device support module must be entered into the DTYP
|
||||
field.
|
||||
|
||||
|
||||
=fields OUT, DTYP
|
||||
|
||||
=head3 Monitor Parameters
|
||||
|
||||
These parameters are used to specify when the monitor post should be sent by the
|
||||
C<monitor()> routine. There are two possible choices:
|
||||
|
||||
APST is used for archiver monitors and MPST for all other type of monitors.
|
||||
|
||||
=fields MPST, APST
|
||||
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME) and
|
||||
description (DESC) fields.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The long string input 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.
|
||||
|
||||
The IVOA field specifies an action to take when the INVALID alarm is triggered.
|
||||
There are three possible actions:
|
||||
|
||||
=head4 Menu menuIvoa
|
||||
|
||||
=menu menuIvoa
|
||||
|
||||
When C<<< Set output to IVOV >>>, the value contained in the IVOV field is
|
||||
written to the output link during an alarm condition. See
|
||||
L<Invalid Alarm Output Action>
|
||||
for more information on the IVOA and IVOV fields.
|
||||
L<Alarm Fields>
|
||||
lists other fields related to a alarms that are common to all record types.
|
||||
|
||||
=fields IVOA, IVOV
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
%#include "devSup.h"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%typedef struct lsodset {
|
||||
% long number;
|
||||
% DEVSUPFUN report;
|
||||
% DEVSUPFUN init;
|
||||
% DEVSUPFUN init_record;
|
||||
% DEVSUPFUN get_ioint_info;
|
||||
% DEVSUPFUN write_string;
|
||||
%} lsodset;
|
||||
%
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Current Value")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
special(SPC_DBADDR)
|
||||
extra("char *val")
|
||||
}
|
||||
field(OVAL,DBF_NOACCESS) {
|
||||
prompt("Previous Value")
|
||||
special(SPC_DBADDR)
|
||||
interest(3)
|
||||
extra("char *oval")
|
||||
}
|
||||
field(SIZV,DBF_USHORT) {
|
||||
prompt("Size of buffers")
|
||||
promptgroup("50 - Output")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("41")
|
||||
}
|
||||
field(LEN,DBF_ULONG) {
|
||||
prompt("Length of VAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OLEN,DBF_ULONG) {
|
||||
prompt("Length of OVAL")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(DOL,DBF_INLINK) {
|
||||
prompt("Desired Output Link")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(IVOA,DBF_MENU) {
|
||||
prompt("INVALID Output Action")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
menu(menuIvoa)
|
||||
}
|
||||
field(IVOV,DBF_STRING) {
|
||||
prompt("INVALID Output Value")
|
||||
promptgroup("50 - Output")
|
||||
interest(2)
|
||||
size(40)
|
||||
}
|
||||
field(OMSL,DBF_MENU) {
|
||||
prompt("Output Mode Select")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
menu(menuOmsl)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(MPST,DBF_MENU) {
|
||||
prompt("Post Value Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
field(APST,DBF_MENU) {
|
||||
prompt("Post Archive Monitors")
|
||||
promptgroup("80 - Display")
|
||||
interest(1)
|
||||
menu(menuPost)
|
||||
}
|
||||
|
||||
|
||||
=head3 Run-time and Simulation Mode Parameters
|
||||
|
||||
The old value field (OVAL) of the long string input record is used to implement
|
||||
value change monitors for VAL. If VAL is not equal to OVAL, then monitors are
|
||||
triggered. LEN contains the length of the string in VAL, OLEN contains the
|
||||
length of the string in OVAL.
|
||||
|
||||
=fields OVAL, LEN, OLEN
|
||||
|
||||
The following fields are used to operate the string input in the simulation
|
||||
mode. See L<Simulation Mode> for more information on simulation mode fields.
|
||||
|
||||
=fields SIOL, SIML, SIMM, SIMS
|
||||
|
||||
=cut
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
=head2 Device Support Interface
|
||||
|
||||
The record requires device support to provide an entry table (dset) which
|
||||
defines the following members:
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
long (*report)(int level);
|
||||
long (*init)(int after);
|
||||
long (*init_record)(lsoRecord *prec);
|
||||
long (*get_ioint_info)(int cmd, lsoRecord *prec, IOSCANPVT *piosl);
|
||||
long (*write_string)(lsoRecord *prec);
|
||||
} lsodset;
|
||||
|
||||
The module must set C<number> to at least 5, and provide a pointer to its
|
||||
C<write_string()> routine; the other function pointers may be C<NULL> if their
|
||||
associated functionality is not required for this support layer.
|
||||
Most device supports also provide an C<init_record()> routine to configure the
|
||||
record instance and connect it to the hardware or driver support layer.
|
||||
|
||||
|
||||
=head2 Device Support for Soft Records
|
||||
|
||||
Device support for DTYP C<Soft Channel> is provided for writing values to other
|
||||
records or other software components.
|
||||
|
||||
Device support for DTYP C<stdio> is provided for writing values to the stdout,
|
||||
stderr, or errlog streams. C<INST_IO> addressing C<@stdout>, C<@stderr> or
|
||||
C<@errlog> is used on the OUT link field to select the desired stream.
|
||||
|
||||
=cut
|
||||
@@ -1,109 +0,0 @@
|
||||
#*************************************************************************
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
recordtype(printf) {
|
||||
include "dbCommon.dbd"
|
||||
%#include "devSup.h"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%typedef struct printfdset {
|
||||
% long number;
|
||||
% DEVSUPFUN report;
|
||||
% DEVSUPFUN init;
|
||||
% DEVSUPFUN init_record;
|
||||
% DEVSUPFUN get_ioint_info;
|
||||
% DEVSUPFUN write_string;
|
||||
%} printfdset;
|
||||
%
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Result")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
special(SPC_DBADDR)
|
||||
extra("char *val")
|
||||
}
|
||||
field(SIZV,DBF_USHORT) {
|
||||
prompt("Size of VAL buffer")
|
||||
promptgroup("30 - Action")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("41")
|
||||
}
|
||||
field(LEN,DBF_ULONG) {
|
||||
prompt("Length of VAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(FMT,DBF_STRING) {
|
||||
prompt("Format String")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
size(81)
|
||||
}
|
||||
field(IVLS,DBF_STRING) {
|
||||
prompt("Invalid Link String")
|
||||
promptgroup("30 - Action")
|
||||
size(16)
|
||||
initial("LNK")
|
||||
}
|
||||
field(INP0,DBF_INLINK) {
|
||||
prompt("Input 0")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP1,DBF_INLINK) {
|
||||
prompt("Input 1")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP2,DBF_INLINK) {
|
||||
prompt("Input 2")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP3,DBF_INLINK) {
|
||||
prompt("Input 3")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP4,DBF_INLINK) {
|
||||
prompt("Input 4")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP5,DBF_INLINK) {
|
||||
prompt("Input 5")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP6,DBF_INLINK) {
|
||||
prompt("Input 6")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP7,DBF_INLINK) {
|
||||
prompt("Input 7")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP8,DBF_INLINK) {
|
||||
prompt("Input 8")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP9,DBF_INLINK) {
|
||||
prompt("Input 9")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
%/* Number of INPx fields defined */
|
||||
%#define PRINTF_NLINKS 10
|
||||
}
|
||||
323
modules/database/src/std/rec/printfRecord.dbd.pod
Normal file
323
modules/database/src/std/rec/printfRecord.dbd.pod
Normal file
@@ -0,0 +1,323 @@
|
||||
#*************************************************************************
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
|
||||
=title Printf Record (printf)
|
||||
|
||||
The printf record is used to generate and write a string using a format
|
||||
specification and parameters, analogous to the C C<printf()> function.
|
||||
|
||||
=head2 Parameter Fields
|
||||
|
||||
The record-specific fields are described below, grouped by functionality.
|
||||
|
||||
=recordtype printf
|
||||
|
||||
=cut
|
||||
|
||||
recordtype(printf) {
|
||||
|
||||
=head3 Scan Parameters
|
||||
|
||||
The printf 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.
|
||||
|
||||
=head3 String Generation Parameters
|
||||
|
||||
The printf record must specify the desired output string with embedded format
|
||||
specifiers in the FMT field. Plain characters are copied directly to the output
|
||||
string. A pair of percent characters 'C<%%>' are converted into a single percent
|
||||
character in the output string. A single precent character 'C<%>' introduces a
|
||||
format specifier and is followed by zero or more of the standard C<printf()>
|
||||
format flags and modifiers:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Plus ('C<+>')
|
||||
|
||||
=item *
|
||||
|
||||
Minus ('C<->')
|
||||
|
||||
=item *
|
||||
|
||||
Space ('C< >')
|
||||
|
||||
=item *
|
||||
|
||||
Hash ('C<#>')
|
||||
|
||||
=item *
|
||||
|
||||
Minimum Field Width (decimal digits or 'C<*>')
|
||||
|
||||
=item *
|
||||
|
||||
Precision ('C<.>' followed by decimal digits or 'C<*>')
|
||||
|
||||
=item *
|
||||
|
||||
Length Modifier 'C<hh>' E<ndash> Reads link as DBR_CHAR or DBR_UCHAR
|
||||
|
||||
=item *
|
||||
|
||||
Length Modifier 'C<h>' E<ndash> Reads link as DBR_SHORT or DBR_USHORT for
|
||||
integer conversions, DBR_FLOAT for floating-point conversions.
|
||||
|
||||
=item *
|
||||
|
||||
Length Modifier 'C<l>' E<ndash> Reads link as DBR_LONG or DBR_ULONG for integer
|
||||
conversions, array of DBR_CHAR for string conversion.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
The following character specifies the conversion to perform, see your operating
|
||||
system's C<printf()> documentation for more details. These conversions
|
||||
ultimately call the C<snprintf()> routine for the actual string conversion
|
||||
process, so are subject to the behaviour of that routine.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
'C<c>' E<ndash> Convert to a character. Only single byte characters are
|
||||
permitted.
|
||||
|
||||
=item *
|
||||
|
||||
'C<d>' or 'C<i>' E<ndash> Convert to a decimal integer.
|
||||
|
||||
=item *
|
||||
|
||||
'C<o>' E<ndash> Convert to an unsigned octal integer.
|
||||
|
||||
=item *
|
||||
|
||||
'C<u>' E<ndash> Convert to an unsigned decimal integer.
|
||||
|
||||
=item *
|
||||
|
||||
'C<x>' E<ndash> Convert to an unsigned hexadecimal integer, using C<abcdef>.
|
||||
|
||||
=item *
|
||||
|
||||
'C<X>' E<ndash> Convert to an unsigned hexadecimal integer, using C<ABCDEF>.
|
||||
|
||||
=item *
|
||||
|
||||
'C<e>' or 'C<E>' E<ndash> Convert to floating-point in exponent style, reading
|
||||
the link as DBR_DOUBLE or DBR_FLOAT.
|
||||
|
||||
=item *
|
||||
|
||||
'C<f>' or 'C<F>' E<ndash> Convert to floating-point in fixed-point style,
|
||||
reading the link as DBR_DOUBLE or DBR_FLOAT.
|
||||
|
||||
=item *
|
||||
|
||||
'C<g>' or 'C<G>' E<ndash> Convert to floating-point in general style, reading
|
||||
the link as DBR_DOUBLE or DBR_FLOAT.
|
||||
|
||||
=item *
|
||||
|
||||
'C<s>' E<ndash> Insert string, reading the link as DBR_STRING or array of
|
||||
DBR_CHAR.
|
||||
|
||||
=back
|
||||
|
||||
The fields INP0 ... INP9 are input links that provide the parameter values to be
|
||||
formatted into the output. The format specifiers in the FMT string determine
|
||||
which type of the data is requested through the appropriate input link. As with
|
||||
C<printf()> a C<*> character may be used in the format to specify width and/or
|
||||
precision instead of numeric literals, in which case additional input links are
|
||||
used to provide the necessary integer parameter or parameters. See L<Address
|
||||
Specification> for information on specifying links.
|
||||
|
||||
The formatted string is written to the VAL field. The maximum number of
|
||||
characters in VAL is given by SIZV, and cannot be larger than 65535. The LEN
|
||||
field contains the length of the formatted string in the VAL field.
|
||||
|
||||
=fields FMT, INP0, INP1, INP2, INP3, INP4, INP5, INP6, INP7, INP8, INP9, VAL, SIZV, LEN
|
||||
|
||||
|
||||
=head3 Output Specification
|
||||
|
||||
The output link specified in the OUT field specifies where the printf record is
|
||||
to write the contents of its VAL field. The link can be a database or channel
|
||||
access link. If the OUT field is a constant, no output will be written.
|
||||
|
||||
See L<Address Specification> for information on specifying links.
|
||||
|
||||
In addition, the appropriate device support module must be entered into the DTYP
|
||||
field.
|
||||
|
||||
=fields OUT, DTYP
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
See L<Fields Common to All Record Types> for more on the record name (NAME) and
|
||||
description (DESC) fields.
|
||||
|
||||
=fields NAME, DESC
|
||||
|
||||
=cut
|
||||
|
||||
include "dbCommon.dbd"
|
||||
%#include "devSup.h"
|
||||
%
|
||||
%/* Declare Device Support Entry Table */
|
||||
%typedef struct printfdset {
|
||||
% long number;
|
||||
% DEVSUPFUN report;
|
||||
% DEVSUPFUN init;
|
||||
% DEVSUPFUN init_record;
|
||||
% DEVSUPFUN get_ioint_info;
|
||||
% DEVSUPFUN write_string;
|
||||
%} printfdset;
|
||||
%
|
||||
field(VAL,DBF_NOACCESS) {
|
||||
prompt("Result")
|
||||
asl(ASL0)
|
||||
pp(TRUE)
|
||||
special(SPC_DBADDR)
|
||||
extra("char *val")
|
||||
#=type STRING[SIZV]
|
||||
#=read Yes
|
||||
#=write Yes
|
||||
}
|
||||
field(SIZV,DBF_USHORT) {
|
||||
prompt("Size of VAL buffer")
|
||||
promptgroup("30 - Action")
|
||||
special(SPC_NOMOD)
|
||||
interest(1)
|
||||
initial("41")
|
||||
}
|
||||
field(LEN,DBF_ULONG) {
|
||||
prompt("Length of VAL")
|
||||
special(SPC_NOMOD)
|
||||
}
|
||||
field(OUT,DBF_OUTLINK) {
|
||||
prompt("Output Specification")
|
||||
promptgroup("50 - Output")
|
||||
interest(1)
|
||||
}
|
||||
field(FMT,DBF_STRING) {
|
||||
prompt("Format String")
|
||||
promptgroup("30 - Action")
|
||||
pp(TRUE)
|
||||
size(81)
|
||||
}
|
||||
|
||||
|
||||
=head3 Alarm Parameters
|
||||
|
||||
The printf 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.
|
||||
|
||||
The IVLS field specifies a string which is sent to the OUT link if if input
|
||||
link data are invalid.
|
||||
|
||||
=fields IVLS
|
||||
|
||||
=cut
|
||||
|
||||
field(IVLS,DBF_STRING) {
|
||||
prompt("Invalid Link String")
|
||||
promptgroup("30 - Action")
|
||||
size(16)
|
||||
initial("LNK")
|
||||
}
|
||||
field(INP0,DBF_INLINK) {
|
||||
prompt("Input 0")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP1,DBF_INLINK) {
|
||||
prompt("Input 1")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP2,DBF_INLINK) {
|
||||
prompt("Input 2")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP3,DBF_INLINK) {
|
||||
prompt("Input 3")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP4,DBF_INLINK) {
|
||||
prompt("Input 4")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP5,DBF_INLINK) {
|
||||
prompt("Input 5")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP6,DBF_INLINK) {
|
||||
prompt("Input 6")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP7,DBF_INLINK) {
|
||||
prompt("Input 7")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP8,DBF_INLINK) {
|
||||
prompt("Input 8")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
field(INP9,DBF_INLINK) {
|
||||
prompt("Input 9")
|
||||
promptgroup("40 - Input")
|
||||
interest(1)
|
||||
}
|
||||
%/* Number of INPx fields defined */
|
||||
%#define PRINTF_NLINKS 10
|
||||
}
|
||||
|
||||
|
||||
=head2 Device Support Interface
|
||||
|
||||
The record requires device support to provide an entry table (dset) which
|
||||
defines the following members:
|
||||
|
||||
typedef struct {
|
||||
long number;
|
||||
long (*report)(int level);
|
||||
long (*init)(int after);
|
||||
long (*init_record)(printfRecord *prec);
|
||||
long (*get_ioint_info)(int cmd, printfRecord *prec, IOSCANPVT *piosl);
|
||||
long (*write_string)(printfRecord *prec);
|
||||
} printfdset;
|
||||
|
||||
The module must set C<number> to at least 5, and provide a pointer to its
|
||||
C<write_string()> routine; the other function pointers may be C<NULL> if their
|
||||
associated functionality is not required for this support layer.
|
||||
Most device supports also provide an C<init_record()> routine to configure the
|
||||
record instance and connect it to the hardware or driver support layer.
|
||||
|
||||
=head2 Device Support for Soft Records
|
||||
|
||||
A soft device support module Soft Channel is provided for writing values to
|
||||
other records or other software components.
|
||||
|
||||
Device support for DTYP C<stdio> is provided for writing values to the stdout,
|
||||
stderr, or errlog streams. C<INST_IO> addressing C<@stdout>, C<@stderr> or
|
||||
C<@errlog> is used on the OUT link field to select the desired stream.
|
||||
|
||||
=cut
|
||||
@@ -48,7 +48,7 @@ The string input 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.
|
||||
|
||||
=head3 Read Parameters
|
||||
=head3 Input Specification
|
||||
|
||||
The INP field determines where the string input record gets its string. It can
|
||||
be a database or channel access link, or a constant. If constant, the VAL field
|
||||
@@ -118,7 +118,6 @@ monitors for VAL. If VAL is not equal to OVAL, then monitors are triggered.
|
||||
|
||||
=fields OVAL
|
||||
|
||||
|
||||
The following fields are used to operate the string input in the simulation
|
||||
mode. See L<Simulation Mode> for more information on simulation mode fields.
|
||||
|
||||
@@ -277,15 +276,48 @@ routines are primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, UDF, VAL, INP
|
||||
|
||||
=head3 Device Support Routines (devSiSoft.c)
|
||||
=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(stringinRecord *prec)
|
||||
long init_record(dbCommon *prec)
|
||||
|
||||
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_stringin
|
||||
|
||||
long read_stringin(stringinRecord *prec)
|
||||
@@ -302,17 +334,11 @@ This routine must provide a new input value. It returns the following values:
|
||||
|
||||
=head3 Device Support for Soft Records
|
||||
|
||||
The C<<< Soft Channel >>> module places a value directly in VAL.
|
||||
The C<<< Soft Channel >>> module reads a value directly into VAL.
|
||||
|
||||
If the INP link type is constant, the double constant, if non-zero, is converted
|
||||
to a string and stored into VAL by C<init_record()>, and UDF is set to FALSE. If
|
||||
the INP link type is PV_LINK, then dbCaAddInlink is called by C<init_record()>.
|
||||
|
||||
read_stringin calls recGblGetLinkValue to read the current value of VAL. See
|
||||
L<Soft Input>.
|
||||
|
||||
If the return status of recGblGetLinkValue is zero, then read_stringin sets UDF
|
||||
to FALSE. The status of recGblGetLinkValue is returned.
|
||||
Device support for DTYP C<getenv> is provided for retrieving strings from environment variables.
|
||||
C<INST_IO> addressing C!!@<environment variable> !!is used on the C<INP> link field to select the
|
||||
desired environment variable.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ explains how these fields are used.
|
||||
|
||||
The string output record must specify from where it gets its desired output
|
||||
string. The first field that determines where the desired output originates is
|
||||
the output mode select (OSML) field, which can have two possible value: C<<<
|
||||
the output mode select (OMSL) field, which can have two possible value: C<<<
|
||||
closed_loop >>> or C<<< supervisory >>>. If C<<< supervisory >>> is specified,
|
||||
DOL is ignored, the current value of VAL is written, and the VAL can be changed
|
||||
externally via dbPuts at run-time. If C<<< closed_loop >>> is specified, the VAL
|
||||
@@ -87,7 +87,7 @@ for information on specifying links.
|
||||
menu(menuOmsl)
|
||||
}
|
||||
|
||||
=head3 Write Parameters
|
||||
=head3 Output Specification
|
||||
|
||||
The output link specified in the OUT field specifies where the string output
|
||||
record is to write its string. The link can be a database or channel access
|
||||
@@ -353,7 +353,47 @@ primarily interested in the following fields:
|
||||
|
||||
=fields PACT, DPVT, NSEV, NSTA, VAL, OUT
|
||||
|
||||
=head3 Device Support Routines (devSoSoft.c)
|
||||
=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 *prec)
|
||||
|
||||
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_stringout
|
||||
|
||||
@@ -373,11 +413,9 @@ This routine must output a new value. It returns the following values:
|
||||
|
||||
The C<<< Soft Channel >>> device support module writes the current value of VAL.
|
||||
|
||||
If the OUT link type is PV_LINK, then dbCaAddInlink is called by
|
||||
C<init_record()>.
|
||||
|
||||
write_so calls recGblPutLinkValue to write the current value of VAL. See
|
||||
L<Soft Output>.
|
||||
Device support for DTYP C<stdio> is provided for writing values to the stdout,
|
||||
stderr, or errlog streams. C<INST_IO> addressing C<@stdout>, C<@stderr> or
|
||||
C<@errlog> is used on the OUT link field to select the desired stream.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ L<Address Specification>
|
||||
for information on specifying links.
|
||||
|
||||
In addition, the DTYP field must specify a device support module. Currently, the
|
||||
only device support module is C<<< Soft Channel >>>.
|
||||
only device support module is C<Soft Channel>.
|
||||
|
||||
=fields INP, DTYP
|
||||
|
||||
@@ -59,13 +59,13 @@ These parameters determine the number of array elements (the array length) and
|
||||
the data type of those elements. The Field Type of Value (FTVL) field determines
|
||||
the data type of the array.
|
||||
|
||||
The user specifies the maximum number of elements allowed in the subarray in the
|
||||
MALM field. Generally, the number should be equal to the number of elements of
|
||||
the Waveform array (found in the Waveform's NELM field). The MALM field is used
|
||||
to allocate memory. The subArray's Number of Elements (NELM) field is where the
|
||||
user specifies the actual number of elements that the subArray will contain. It
|
||||
should of course be no greater than MALM; if it is, the record processing
|
||||
routine sets it equal to MALM.
|
||||
The user specifies the maximum number of elements that can be read into the
|
||||
subarray in the MALM field. This number should normally be equal to the number
|
||||
of elements of the Waveform array (found in the Waveform's NELM field). The MALM
|
||||
field is used to allocate memory. The subArray's Number of Elements (NELM) field
|
||||
is where the user specifies the actual number of elements that the subArray will
|
||||
extract. It should of course be no greater than MALM; if it is, the record
|
||||
processing routine sets it equal to MALM.
|
||||
|
||||
The INDX field determines the offset of the subArray record's array in relation
|
||||
to the Waveform's. For instance, if INDX is 2, then the subArray will read NELM
|
||||
@@ -83,15 +83,15 @@ display the value and other parameters of the subarray record either textually
|
||||
or graphically.
|
||||
|
||||
EGU is a string of up to 16 characters describing the engineering units (if any)
|
||||
of the values which the subArray holds. It is retrieved by the C<<< get_units
|
||||
>>> record support routine.
|
||||
of the values which the subArray holds. It is retrieved by the C<get_units()>
|
||||
record support routine.
|
||||
|
||||
The HOPR and LOPR fields set the upper and lower display limits for the
|
||||
sub-array elements. Both the C<<< get_graphic_double >>> and C<<<
|
||||
get_control_double >>> record support routines retrieve these fields.
|
||||
sub-array elements. 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
|
||||
VAL. It is used whenever the C<<< get_precision >>> record support routine is
|
||||
VAL. It is used whenever the C<get_precision()> record support routine is
|
||||
called.
|
||||
|
||||
See L<Fields Common to All Record Types>
|
||||
@@ -110,9 +110,9 @@ record types.
|
||||
These fields are not configurable by the user. They are used for the record's
|
||||
internal processing or to represent the current state of the record.
|
||||
|
||||
The NORD field holds a counter of the number of elements read into the array. It
|
||||
can be less than NELM even after the array is full if NELM exceeds the number of
|
||||
existing elements in the referenced array, i.e., the Waveform's array.
|
||||
The NORD field holds the number of elements that were actually read into the
|
||||
array. It will be less than NELM whenever the sum of the NELM and INDX fields
|
||||
exceeds the number of existing elements found in the source array.
|
||||
|
||||
BPTR contains a pointer to the record's array.
|
||||
|
||||
@@ -150,14 +150,14 @@ See L<Record Processing>.
|
||||
|
||||
long (*cvt_dbaddr)(struct dbAddr *paddr)
|
||||
|
||||
This is called by dbNameToAddr. It makes the dbAddr structure refer to the
|
||||
This is called by C<dbNameToAddr()>. It makes the dbAddr structure refer to the
|
||||
actual buffer holding the result.
|
||||
|
||||
=head4 get_array_info
|
||||
|
||||
long (*get_array_info)(struct dbAddr *paddr, long *no_elements, long *offset)
|
||||
|
||||
Retrieves NELM.
|
||||
Retrieves NORD.
|
||||
|
||||
=head4 put_array_info
|
||||
|
||||
@@ -171,14 +171,14 @@ Sets NORD.
|
||||
|
||||
For the elements in the array, this routine routines HOPR and LOPR. For the INDX
|
||||
field, this routine returns MALM - 1 and 0. For NELM, it returns MALM and 1. For
|
||||
other fields, it calls C<<< recGblGetGraphicDouble() >>>.
|
||||
other fields, it calls C<recGblGetGraphicDouble()>.
|
||||
|
||||
=head4 get_control_double
|
||||
|
||||
long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p)
|
||||
|
||||
For array elements, this routine retrieves HOPR and LOPR. Otherwise, C<<<
|
||||
recGblGetControlDouble() >>> is called.
|
||||
For array elements, this routine retrieves HOPR and LOPR. Otherwise,
|
||||
C<recGblGetControlDouble()> is called.
|
||||
|
||||
=head4 get_units
|
||||
|
||||
@@ -212,13 +212,13 @@ INDX is greater than or equal to MALM it is set to MALM-1.
|
||||
|
||||
=item 3.
|
||||
|
||||
Call device support read routine. This routine is expected to place the desired
|
||||
sub-array at the beginning of the buffer and set NORD to the number of elements
|
||||
of the sub-array that were read.
|
||||
Call the device support's C<read_sa()> routine. This routine is expected to
|
||||
place the desired sub-array at the beginning of the buffer and set NORD to the
|
||||
number of elements of the sub-array that were read.
|
||||
|
||||
=item 4.
|
||||
|
||||
If PACT has been changed to TRUE, the device support read routine has started
|
||||
If PACT has been changed to TRUE, the device support read operation has started
|
||||
but has not completed writing the new value. In this case, the processing
|
||||
routine merely returns, leaving PACT TRUE. Otherwise, process sets PACT TRUE at
|
||||
this time. This asynchronous processing logic is not currently used but has been
|
||||
@@ -305,12 +305,11 @@ sub-array were acquired.
|
||||
|
||||
=head3 Device Support For Soft Records
|
||||
|
||||
Only the device support module C<<< Soft Channel >>> is currently provided. The
|
||||
INP link type must be either DB_LINK or CA_LINK.
|
||||
Only the device support module C<Soft Channel> is currently provided.
|
||||
|
||||
=head4 Soft Channel
|
||||
|
||||
INP is expected to point to a waveform record.
|
||||
INP is expected to point to an array field of a waveform record or similar.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -303,7 +303,9 @@ interested in the following fields:
|
||||
|
||||
Device support consists of the following routines:
|
||||
|
||||
=head4 long report(int level)
|
||||
=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.
|
||||
@@ -313,7 +315,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.
|
||||
|
||||
=head4 long init(int after)
|
||||
=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
|
||||
@@ -323,14 +327,14 @@ with C<after> set to 1.
|
||||
|
||||
=head4 init_record
|
||||
|
||||
init_record(precord)
|
||||
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
|
||||
|
||||
get_ioint_info(int cmd,struct dbCommon *precord,IOSCANPVT *ppvt)
|
||||
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. cmd has the value (0,1) if the
|
||||
@@ -339,7 +343,7 @@ provided for any device type that can use the ioEvent scanner.
|
||||
|
||||
=head4 read_wf
|
||||
|
||||
read_wf(precord)
|
||||
long read_wf(waveformRecord *prec)
|
||||
|
||||
This routine must provide a new input value. It returns the following values:
|
||||
|
||||
@@ -361,38 +365,11 @@ 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_wf
|
||||
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.
|
||||
from the link. NORD is set to the number of items in the array.
|
||||
|
||||
This module places a value directly in VAL.
|
||||
|
||||
If the INP link type is constant, then NORD is set to zero. If the INP link type
|
||||
is PV_LINK, then dbCaAddInlink is called by C<init_record()>.
|
||||
|
||||
read_wf calls recGblGetLinkValue which performs the following steps:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
If the INP link type is CONSTANT recGblGetLinkValue does nothing.
|
||||
|
||||
=item *
|
||||
|
||||
If the INP link type is DB_LINK, then dbGetLink is called to obtain a new input
|
||||
value. If dbGetLink returns an error, a LINK_ALARM with a severity of
|
||||
INVALID_ALARM is raised.
|
||||
|
||||
=item *
|
||||
|
||||
If the INP link type is CA_LINK, then dbCaGetLink is called to obtain a new
|
||||
input value. If dbCaGetLink returns an error, a LINK_ALARM with a severity of
|
||||
INVALID_ALARM is raised.
|
||||
|
||||
=item *
|
||||
|
||||
NORD is set to the number of values returned and read_wf returns.
|
||||
|
||||
=back
|
||||
If the INP link type is constant, then NORD is set to zero.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -19,26 +19,9 @@ use EPICS::macLib;
|
||||
use EPICS::Readfile;
|
||||
|
||||
BEGIN {
|
||||
$::XHTML = eval "require Pod::Simple::XHTML; 1";
|
||||
$::ENTITIES = eval "require HTML::Entities; 1";
|
||||
$::XHTML = eval "require EPICS::PodXHtml; 1";
|
||||
if (!$::XHTML) {
|
||||
require Pod::Simple::HTML;
|
||||
}
|
||||
if (!$::ENTITIES) {
|
||||
my %entities = (
|
||||
q{>} => 'gt',
|
||||
q{<} => 'lt',
|
||||
q{'} => '#39',
|
||||
q{"} => 'quot',
|
||||
q{&} => 'amp',
|
||||
);
|
||||
|
||||
sub encode_entities {
|
||||
my $str = shift;
|
||||
my $ents = join '', keys %entities;
|
||||
$str =~ s/([ $ents ])/'&' . ($entities{$1} || sprintf '#x%X', ord $1) . ';'/xge;
|
||||
return $str;
|
||||
}
|
||||
require EPICS::PodHtml;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +114,7 @@ my $contentType =
|
||||
'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >';
|
||||
|
||||
if ($::XHTML) {
|
||||
$podHtml = Pod::Simple::XHTML->new();
|
||||
$podHtml = EPICS::PodXHtml->new();
|
||||
$podHtml->html_doctype(<< '__END_DOCTYPE');
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
|
||||
@@ -153,7 +136,7 @@ __END_DOCTYPE
|
||||
}
|
||||
} else { # Fall back to HTML
|
||||
$Pod::Simple::HTML::Content_decl = $contentType;
|
||||
$podHtml = Pod::Simple::HTML->new();
|
||||
$podHtml = EPICS::PodHtml->new();
|
||||
$podHtml->html_css('style.css');
|
||||
|
||||
$idify = sub {
|
||||
@@ -191,7 +174,7 @@ my $pod = join "\n", '=for html <div class="pod">', '',
|
||||
} $dbd->pod,
|
||||
'=for html </div>', '';
|
||||
|
||||
$podHtml->force_title(encode_entities($title));
|
||||
$podHtml->force_title($podHtml->encode_entities($title));
|
||||
$podHtml->perldoc_url_prefix('');
|
||||
$podHtml->perldoc_url_postfix('.html');
|
||||
$podHtml->output_fh($out);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "postfix.h"
|
||||
#include "postfixPvt.h"
|
||||
|
||||
|
||||
static double calcRandom(void);
|
||||
static int cond_search(const char **ppinst, int match);
|
||||
|
||||
@@ -48,7 +49,6 @@ epicsShareFunc long
|
||||
double *ptop; /* stack pointer */
|
||||
double top; /* value from top of stack */
|
||||
epicsInt32 itop; /* integer from top of stack */
|
||||
epicsUInt32 utop; /* unsigned integer from top of stack */
|
||||
int op;
|
||||
int nargs;
|
||||
|
||||
@@ -287,45 +287,60 @@ epicsShareFunc long
|
||||
*ptop = ! *ptop;
|
||||
break;
|
||||
|
||||
/* For bitwise operations on values with bit 31 set, double values
|
||||
* must first be cast to unsigned to correctly set that bit; the
|
||||
* double value must be negative in that case. The result must be
|
||||
* cast to a signed integer before converting to the double result.
|
||||
/* Be VERY careful converting double to int in case bit 31 is set!
|
||||
* Out-of-range errors give very different results on different sytems.
|
||||
* Convert negative doubles to signed and positive doubles to unsigned
|
||||
* first to avoid overflows if bit 32 is set.
|
||||
* The result is always signed, values with bit 31 set are negative
|
||||
* to avoid problems when writing the value to signed integer fields
|
||||
* like longout.VAL or ao.RVAL. However unsigned fields may give
|
||||
* problems on some architectures. (Fewer than giving problems with
|
||||
* signed integer. Maybe the conversion functions should handle
|
||||
* overflows better.)
|
||||
*/
|
||||
#define d2i(x) ((x)<0?(epicsInt32)(x):(epicsInt32)(epicsUInt32)(x))
|
||||
#define d2ui(x) ((x)<0?(epicsUInt32)(epicsInt32)(x):(epicsUInt32)(x))
|
||||
|
||||
case BIT_OR:
|
||||
utop = *ptop--;
|
||||
*ptop = (epicsInt32) ((epicsUInt32) *ptop | utop);
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) | d2i(top));
|
||||
break;
|
||||
|
||||
case BIT_AND:
|
||||
utop = *ptop--;
|
||||
*ptop = (epicsInt32) ((epicsUInt32) *ptop & utop);
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) & d2i(top));
|
||||
break;
|
||||
|
||||
case BIT_EXCL_OR:
|
||||
utop = *ptop--;
|
||||
*ptop = (epicsInt32) ((epicsUInt32) *ptop ^ utop);
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) ^ d2i(top));
|
||||
break;
|
||||
|
||||
case BIT_NOT:
|
||||
utop = *ptop;
|
||||
*ptop = (epicsInt32) ~utop;
|
||||
*ptop = (double)~d2i(*ptop);
|
||||
break;
|
||||
|
||||
/* The shift operators use signed integers, so a right-shift will
|
||||
* extend the sign bit into the left-hand end of the value. The
|
||||
* double-casting through unsigned here is important, see above.
|
||||
/* In C the shift operators decide on an arithmetic or logical shift
|
||||
* based on whether the integer is signed or unsigned.
|
||||
* With signed integers, a right-shift is arithmetic and will
|
||||
* extend the sign bit into the left-hand end of the value. When used
|
||||
* with unsigned values a logical shift is performed. The
|
||||
* double-casting through signed/unsigned here is important, see above.
|
||||
*/
|
||||
|
||||
case RIGHT_SHIFT:
|
||||
utop = *ptop--;
|
||||
*ptop = ((epicsInt32) (epicsUInt32) *ptop) >> (utop & 31);
|
||||
case RIGHT_SHIFT_ARITH:
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) >> (d2i(top) & 31));
|
||||
break;
|
||||
|
||||
case LEFT_SHIFT:
|
||||
utop = *ptop--;
|
||||
*ptop = ((epicsInt32) (epicsUInt32) *ptop) << (utop & 31);
|
||||
case LEFT_SHIFT_ARITH:
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2i(*ptop) << (d2i(top) & 31));
|
||||
break;
|
||||
|
||||
case RIGHT_SHIFT_LOGIC:
|
||||
top = *ptop--;
|
||||
*ptop = (double)(d2ui(*ptop) >> (d2ui(top) & 31u));
|
||||
break;
|
||||
|
||||
case NOT_EQ:
|
||||
@@ -382,11 +397,11 @@ epicsShareFunc long
|
||||
*presult = *ptop;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
|
||||
# pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
|
||||
epicsShareFunc long
|
||||
calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
{
|
||||
|
||||
@@ -148,13 +148,14 @@ static const ELEMENT operators[] = {
|
||||
{":=", 0, 0, -1, STORE_OPERATOR, STORE_A},
|
||||
{";", 0, 0, 0, EXPR_TERMINATOR,NOT_GENERATED},
|
||||
{"<", 3, 3, -1, BINARY_OPERATOR,LESS_THAN},
|
||||
{"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT},
|
||||
{"<<", 2, 2, -1, BINARY_OPERATOR,LEFT_SHIFT_ARITH},
|
||||
{"<=", 3, 3, -1, BINARY_OPERATOR,LESS_OR_EQ},
|
||||
{"=", 3, 3, -1, BINARY_OPERATOR,EQUAL},
|
||||
{"==", 3, 3, -1, BINARY_OPERATOR,EQUAL},
|
||||
{">", 3, 3, -1, BINARY_OPERATOR,GR_THAN},
|
||||
{">=", 3, 3, -1, BINARY_OPERATOR,GR_OR_EQ},
|
||||
{">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT},
|
||||
{">>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_ARITH},
|
||||
{">>>", 2, 2, -1, BINARY_OPERATOR,RIGHT_SHIFT_LOGIC},
|
||||
{"?", 0, 0, -1, CONDITIONAL, COND_IF},
|
||||
{"AND", 2, 2, -1, BINARY_OPERATOR,BIT_AND},
|
||||
{"OR", 1, 1, -1, BINARY_OPERATOR,BIT_OR},
|
||||
@@ -579,8 +580,9 @@ epicsShareFunc void
|
||||
"BIT_AND",
|
||||
"BIT_EXCL_OR",
|
||||
"BIT_NOT",
|
||||
"RIGHT_SHIFT",
|
||||
"LEFT_SHIFT",
|
||||
"RIGHT_SHIFT_ARITH",
|
||||
"LEFT_SHIFT_ARITH",
|
||||
"RIGHT_SHIFT_LOGIC",
|
||||
/* Relationals */
|
||||
"NOT_EQ",
|
||||
"LESS_THAN",
|
||||
|
||||
@@ -84,8 +84,9 @@ typedef enum {
|
||||
BIT_AND,
|
||||
BIT_EXCL_OR,
|
||||
BIT_NOT,
|
||||
RIGHT_SHIFT,
|
||||
LEFT_SHIFT,
|
||||
RIGHT_SHIFT_ARITH,
|
||||
LEFT_SHIFT_ARITH,
|
||||
RIGHT_SHIFT_LOGIC,
|
||||
/* Relationals */
|
||||
NOT_EQ,
|
||||
LESS_THAN,
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* logClient.c,v 1.25.2.6 2004/10/07 13:37:34 mrk Exp */
|
||||
/*
|
||||
* Author: Jeffrey O. Hill
|
||||
* Date: 080791
|
||||
* Author: Jeffrey O. Hill
|
||||
* Date: 080791
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -80,7 +78,7 @@ static void logClientClose ( logClient *pClient )
|
||||
* mutex on
|
||||
*/
|
||||
epicsMutexMustLock (pClient->mutex);
|
||||
|
||||
|
||||
/*
|
||||
* close any preexisting connection to the log server
|
||||
*/
|
||||
@@ -140,9 +138,9 @@ static void logClientDestroy (logClientId id)
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
do {
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
epicsEventWaitWithTimeout (
|
||||
pClient->stateChangeNotify,
|
||||
LOG_SERVER_SHUTDOWN_TIMEOUT / 10.0 );
|
||||
epicsEventWaitWithTimeout (
|
||||
pClient->stateChangeNotify,
|
||||
LOG_SERVER_SHUTDOWN_TIMEOUT / 10.0 );
|
||||
epicsTimeGetCurrent ( & current );
|
||||
diff = epicsTimeDiffInSeconds ( & current, & begin );
|
||||
epicsMutexMustLock ( pClient->mutex );
|
||||
@@ -151,8 +149,8 @@ static void logClientDestroy (logClientId id)
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
|
||||
if ( ! pClient->shutdownConfirm ) {
|
||||
fprintf ( stderr, "log client shutdown: timed out stopping"
|
||||
" reconnect thread for \"%s\" after %.1f seconds - cleanup aborted\n",
|
||||
fprintf ( stderr, "log client shutdown: timed out stopping reconnect\n"
|
||||
" thread for '%s' after %.1f seconds - cleanup aborted\n",
|
||||
pClient->name, LOG_SERVER_SHUTDOWN_TIMEOUT );
|
||||
return;
|
||||
}
|
||||
@@ -174,7 +172,7 @@ static void sendMessageChunk(logClient * pClient, const char * message) {
|
||||
|
||||
strSize = strlen ( message );
|
||||
while ( strSize ) {
|
||||
unsigned msgBufBytesLeft =
|
||||
unsigned msgBufBytesLeft =
|
||||
sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex;
|
||||
|
||||
if ( msgBufBytesLeft < strSize && pClient->nextMsgIndex != 0u && pClient->connected)
|
||||
@@ -197,7 +195,7 @@ static void sendMessageChunk(logClient * pClient, const char * message) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* logClientSend ()
|
||||
*/
|
||||
void epicsShareAPI logClientSend ( logClientId id, const char * message )
|
||||
@@ -240,8 +238,7 @@ void epicsShareAPI logClientFlush ( logClientId id )
|
||||
nSent += status;
|
||||
}
|
||||
|
||||
if ( pClient->backlog > 0 && status >= 0 )
|
||||
{
|
||||
if ( pClient->backlog > 0 && status >= 0 ) {
|
||||
/* On Linux send 0 bytes can detect EPIPE */
|
||||
/* NOOP on Windows, fails on vxWorks */
|
||||
errno = 0;
|
||||
@@ -252,9 +249,9 @@ void epicsShareAPI logClientFlush ( logClientId id )
|
||||
if ( status < 0 ) {
|
||||
if ( ! pClient->shutdown ) {
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n",
|
||||
pClient->name, sockErrBuf );
|
||||
epicsSocketConvertErrnoToString(sockErrBuf, sizeof(sockErrBuf));
|
||||
fprintf(stderr, "log client: lost contact with log server at '%s'\n"
|
||||
" because \"%s\"\n", pClient->name, sockErrBuf);
|
||||
}
|
||||
pClient->backlog = 0;
|
||||
logClientClose ( pClient );
|
||||
@@ -285,19 +282,19 @@ static void logClientMakeSock (logClient *pClient)
|
||||
}
|
||||
|
||||
epicsMutexMustLock (pClient->mutex);
|
||||
|
||||
/*
|
||||
* allocate a socket
|
||||
|
||||
/*
|
||||
* allocate a socket
|
||||
*/
|
||||
pClient->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, 0 );
|
||||
if ( pClient->sock == INVALID_SOCKET ) {
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf ( stderr, "log client: no socket error %s\n",
|
||||
fprintf ( stderr, "log client: no socket error %s\n",
|
||||
sockErrBuf );
|
||||
}
|
||||
|
||||
|
||||
epicsMutexUnlock (pClient->mutex);
|
||||
|
||||
if (logClientDebug)
|
||||
@@ -312,16 +309,16 @@ static void logClientConnect (logClient *pClient)
|
||||
osiSockIoctl_t optval;
|
||||
int errnoCpy;
|
||||
int status;
|
||||
|
||||
|
||||
if ( pClient->sock == INVALID_SOCKET ) {
|
||||
logClientMakeSock ( pClient );
|
||||
if ( pClient->sock == INVALID_SOCKET ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while ( 1 ) {
|
||||
status = connect (pClient->sock,
|
||||
status = connect (pClient->sock,
|
||||
(struct sockaddr *)&pClient->addr, sizeof(pClient->addr));
|
||||
if ( status >= 0 ) {
|
||||
break;
|
||||
@@ -345,8 +342,9 @@ static void logClientConnect (logClient *pClient)
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr,
|
||||
"log client: failed to connect to \"%s\" because %d=\"%s\"\n",
|
||||
pClient->name, errnoCpy, sockErrBuf);
|
||||
"log client: failed to connect to server '%s'"
|
||||
" because '%s'\n",
|
||||
pClient->name, sockErrBuf);
|
||||
pClient->connFailStatus = errnoCpy;
|
||||
}
|
||||
logClientClose ( pClient );
|
||||
@@ -365,12 +363,14 @@ static void logClientConnect (logClient *pClient)
|
||||
* (after a long delay)
|
||||
*/
|
||||
optval = TRUE;
|
||||
status = setsockopt (pClient->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval));
|
||||
status = setsockopt (pClient->sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *)&optval, sizeof(optval));
|
||||
if (status<0) {
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr, "log client: unable to enable keepalive option because \"%s\"\n", sockErrBuf);
|
||||
fprintf (stderr, "log client: unable to enable SO_KEEPALIVE\n"
|
||||
" because '%s'\n", sockErrBuf);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -380,9 +380,9 @@ static void logClientConnect (logClient *pClient)
|
||||
status = shutdown (pClient->sock, SHUT_RD);
|
||||
if (status < 0) {
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr, "%s:%d shutdown(sock,SHUT_RD) error was \"%s\"\n",
|
||||
fprintf (stderr, "%s:%d shutdown(sock,SHUT_RD) error was '%s'\n",
|
||||
__FILE__, __LINE__, sockErrBuf);
|
||||
/* not fatal (although it shouldn't happen) */
|
||||
}
|
||||
@@ -395,25 +395,28 @@ static void logClientConnect (logClient *pClient)
|
||||
*/
|
||||
{
|
||||
struct linger lingerval;
|
||||
|
||||
|
||||
lingerval.l_onoff = TRUE;
|
||||
lingerval.l_linger = 60*5;
|
||||
status = setsockopt (pClient->sock, SOL_SOCKET, SO_LINGER, (char *) &lingerval, sizeof(lingerval));
|
||||
lingerval.l_linger = 60*5;
|
||||
status = setsockopt (pClient->sock, SOL_SOCKET, SO_LINGER,
|
||||
(char *) &lingerval, sizeof(lingerval));
|
||||
if (status<0) {
|
||||
char sockErrBuf[128];
|
||||
epicsSocketConvertErrnoToString (
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
fprintf (stderr, "log client: unable to set linger options because \"%s\"\n", sockErrBuf);
|
||||
fprintf(stderr, "log client: unable to set SO_LINGER\n"
|
||||
" because '%s'\n", sockErrBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pClient->connectCount++;
|
||||
|
||||
epicsMutexUnlock ( pClient->mutex );
|
||||
|
||||
|
||||
epicsEventSignal ( pClient->stateChangeNotify );
|
||||
|
||||
fprintf ( stderr, "log client: connected to log server at \"%s\"\n", pClient->name );
|
||||
fprintf(stderr, "log client: connected to log server at '%s'\n",
|
||||
pClient->name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -493,7 +496,7 @@ logClientId epicsShareAPI logClientCreate (
|
||||
}
|
||||
|
||||
pClient->restartThreadId = epicsThreadCreate (
|
||||
"logRestart", epicsThreadPriorityLow,
|
||||
"logRestart", epicsThreadPriorityLow,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
logClientRestart, pClient );
|
||||
if ( pClient->restartThreadId == NULL ) {
|
||||
@@ -501,7 +504,7 @@ logClientId epicsShareAPI logClientCreate (
|
||||
epicsEventDestroy ( pClient->stateChangeNotify );
|
||||
epicsEventDestroy ( pClient->shutdownNotify );
|
||||
free (pClient);
|
||||
fprintf(stderr, "log client: unable to start log client connection watch dog thread\n");
|
||||
fprintf(stderr, "log client: unable to start reconnection thread\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -516,10 +519,11 @@ void epicsShareAPI logClientShow (logClientId id, unsigned level)
|
||||
logClient *pClient = (logClient *) id;
|
||||
|
||||
if ( pClient->connected ) {
|
||||
printf ("log client: connected to log server at \"%s\"\n", pClient->name);
|
||||
printf ("log client: connected to log server at '%s'\n", pClient->name);
|
||||
}
|
||||
else {
|
||||
printf ("log client: disconnected from log server at \"%s\"\n", pClient->name);
|
||||
printf ("log client: disconnected from log server at '%s'\n",
|
||||
pClient->name);
|
||||
}
|
||||
|
||||
if (logClientPrefix) {
|
||||
|
||||
@@ -383,5 +383,11 @@ extern "C" {
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
// Ensure the main thread gets a unique ID
|
||||
epicsThreadId epicsThreadMainId = epicsThreadGetIdSelf();
|
||||
static epicsThreadId initMainThread(void) {
|
||||
epicsThreadId main = epicsThreadGetIdSelf();
|
||||
epicsThreadSetOkToBlock(1);
|
||||
return main;
|
||||
}
|
||||
|
||||
// Ensure the main thread gets a unique ID and allows blocking I/O
|
||||
epicsThreadId epicsThreadMainId = initMainThread();
|
||||
|
||||
@@ -48,8 +48,10 @@ void epicsAtomicLock ( EpicsAtomicLockKey * )
|
||||
status = pthread_mutex_lock ( & mutex );
|
||||
if ( status == 0 ) return;
|
||||
assert ( status == EINTR );
|
||||
static const useconds_t retryDelayUSec = 100000;
|
||||
usleep ( retryDelayUSec );
|
||||
struct timespec retryDelay = { 0, 100000000 };
|
||||
struct timespec remainingDelay;
|
||||
while (nanosleep(&retryDelay, &remainingDelay) == -1 && errno == EINTR)
|
||||
retryDelay = remainingDelay;
|
||||
countDown--;
|
||||
assert ( countDown );
|
||||
}
|
||||
|
||||
@@ -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 <stddef.h>
|
||||
@@ -101,7 +101,7 @@ void ClockTime_Init(int synchronize)
|
||||
|
||||
if (synchronize == CLOCKTIME_SYNC) {
|
||||
if (ClockTimePvt.synchronize == CLOCKTIME_NOSYNC) {
|
||||
|
||||
|
||||
#if defined(vxWorks) || defined(__rtems__)
|
||||
/* Start synchronizing */
|
||||
ClockTimePvt.synchronize = synchronize;
|
||||
@@ -229,7 +229,11 @@ int osdTimeGetCurrent(epicsTimeStamp *pDest)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CLOCK_REALTIME */
|
||||
/* Used in Report function below: */
|
||||
#define UNINIT_ERROR "initialized"
|
||||
#else
|
||||
#define UNINIT_ERROR "available"
|
||||
#endif /* CLOCK_REALTIME && !WIN32 */
|
||||
|
||||
/* Allow the following report routine to be compiled anyway
|
||||
* to avoid getting a build warning from ranlib.
|
||||
@@ -242,13 +246,7 @@ int ClockTime_Report(int level)
|
||||
char timebuf[32];
|
||||
|
||||
if (onceId == EPICS_THREAD_ONCE_INIT) {
|
||||
printf("OS Clock driver not %s.\n",
|
||||
#ifdef CLOCK_REALTIME
|
||||
"initialized"
|
||||
#else
|
||||
"available"
|
||||
#endif /* CLOCK_REALTIME */
|
||||
);
|
||||
puts("OS Clock driver not " UNINIT_ERROR);
|
||||
}
|
||||
else if (ClockTimePvt.synchronize == CLOCKTIME_SYNC) {
|
||||
int synchronized, syncFromPriority;
|
||||
|
||||
@@ -114,6 +114,11 @@ epicsThreadTest_SRCS += epicsThreadTest.cpp
|
||||
testHarness_SRCS += epicsThreadTest.cpp
|
||||
TESTS += epicsThreadTest
|
||||
|
||||
TESTPROD_HOST += epicsThreadClassTest
|
||||
epicsThreadClassTest_SRCS += epicsThreadClassTest.cpp
|
||||
testHarness_SRCS += epicsThreadClassTest.cpp
|
||||
TESTS += epicsThreadClassTest
|
||||
|
||||
TESTPROD_HOST += epicsThreadOnceTest
|
||||
epicsThreadOnceTest_SRCS += epicsThreadOnceTest.c
|
||||
testHarness_SRCS += epicsThreadOnceTest.c
|
||||
|
||||
@@ -104,7 +104,7 @@ void testUInt32Calc(const char *expr, epicsUInt32 expected) {
|
||||
testDiag("calcPerform: error evaluating '%s'", expr);
|
||||
}
|
||||
|
||||
uresult = (epicsUInt32) result;
|
||||
uresult = (result < 0.0 ? (epicsUInt32)(epicsInt32)result : (epicsUInt32)result);
|
||||
pass = (uresult == expected);
|
||||
if (!testOk(pass, "%s", expr)) {
|
||||
testDiag("Expected result is 0x%x (%u), actually got 0x%x (%u)",
|
||||
@@ -296,8 +296,8 @@ MAIN(epicsCalcTest)
|
||||
int repeat;
|
||||
const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0,
|
||||
g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0;
|
||||
|
||||
testPlan(613);
|
||||
|
||||
testPlan(630);
|
||||
|
||||
/* LITERAL_OPERAND elements */
|
||||
testExpr(0);
|
||||
@@ -320,7 +320,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(Inf);
|
||||
testCalc("Infinity", Inf);
|
||||
testExpr(NaN);
|
||||
|
||||
|
||||
/* OPERAND elements */
|
||||
testExpr(a);
|
||||
testExpr(b);
|
||||
@@ -337,7 +337,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(PI);
|
||||
testExpr(D2R);
|
||||
testExpr(R2D);
|
||||
|
||||
|
||||
for (repeat=0; repeat<100; repeat++) {
|
||||
double res = doCalc("rndm");
|
||||
if (res<0 || res >1) {
|
||||
@@ -346,13 +346,13 @@ MAIN(epicsCalcTest)
|
||||
}
|
||||
}
|
||||
testOk(repeat == 100, "rndm");
|
||||
|
||||
|
||||
/* UNARY_MINUS element */
|
||||
testExpr(-1);
|
||||
testExpr(-Inf);
|
||||
testExpr(- -1);
|
||||
testCalc("-0x80000000", 2147483648.0);
|
||||
|
||||
|
||||
/* UNARY_OPERATOR elements */
|
||||
testExpr((1));
|
||||
testExpr(!0);
|
||||
@@ -544,7 +544,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(tanh(0.5));
|
||||
testExpr(~5);
|
||||
testExpr(~~5);
|
||||
|
||||
|
||||
/* BINARY_OPERATOR elements */
|
||||
testExpr(0 != 1);
|
||||
testExpr(0 != 0);
|
||||
@@ -565,24 +565,24 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN != Inf);
|
||||
testExpr(NaN != -Inf);
|
||||
testExpr(NaN != NaN);
|
||||
|
||||
|
||||
testCalc("0 # 1", 0 != 1);
|
||||
testCalc("0 # 0", 0 != 0);
|
||||
testCalc("1 # 0", 1 != 0);
|
||||
testCalc("1 # 0 # 2", 1 != 0 != 2);
|
||||
|
||||
|
||||
testExpr(7 % 4);
|
||||
testExpr(-7 % 4);
|
||||
testExpr(63 % 16 % 6)
|
||||
testCalc("1 % 0", NaN);
|
||||
|
||||
|
||||
testExpr(7 & 4);
|
||||
|
||||
|
||||
testExpr(0 && 0);
|
||||
testExpr(0 && 1);
|
||||
testExpr(1 && 0);
|
||||
testExpr(1 && 1);
|
||||
|
||||
|
||||
testExpr(2 * 2);
|
||||
testExpr(0.0 * Inf);
|
||||
testExpr(0.0 * -Inf);
|
||||
@@ -599,32 +599,38 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN * Inf);
|
||||
testExpr(NaN * -Inf);
|
||||
testExpr(NaN * NaN);
|
||||
|
||||
|
||||
testCalc("2 ** 0.2", pow(2., 0.2));
|
||||
testCalc("2 ** -0.2", pow(2., -0.2));
|
||||
testCalc("-0.2 ** 2", pow(-0.2, 2.));
|
||||
testCalc("-0.2 ** -2", pow(-0.2, -2));
|
||||
testCalc("2 ** 2 ** 3", pow(pow(2., 2.), 3.));
|
||||
|
||||
|
||||
testExpr(0 + 1);
|
||||
testExpr(0.0 + Inf);
|
||||
testExpr(0.0 + -Inf);
|
||||
testExpr(0.0 + NaN);
|
||||
testExpr(Inf + 0.0);
|
||||
testExpr(Inf + Inf);
|
||||
// only test CALC as MSVC seems to incorrectly evaluate this expression at compile time.
|
||||
// see note in epicsMathTest
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testCalc("Inf + -Inf", NaN);
|
||||
#else
|
||||
testExpr(Inf + -Inf);
|
||||
#endif
|
||||
testExpr(Inf + NaN);
|
||||
testExpr(-Inf + 0.0);
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testCalc("-Inf + Inf", NaN);
|
||||
#else
|
||||
testExpr(-Inf + Inf);
|
||||
#endif
|
||||
testExpr(-Inf + -Inf);
|
||||
testExpr(-Inf + NaN);
|
||||
testExpr(NaN + 0.0);
|
||||
testExpr(NaN + Inf);
|
||||
testExpr(NaN + -Inf);
|
||||
testExpr(NaN + NaN);
|
||||
|
||||
|
||||
testExpr(0 - 1);
|
||||
testExpr(0 - 1 - 2);
|
||||
testExpr(0.0 - Inf);
|
||||
@@ -642,7 +648,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN - Inf);
|
||||
testExpr(NaN - -Inf);
|
||||
testExpr(NaN - NaN);
|
||||
|
||||
|
||||
testExpr(2.0 / 3.0);
|
||||
testExpr(1.0 / 2.0 / 3.0);
|
||||
testExpr(0.0 / Inf);
|
||||
@@ -660,7 +666,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN / Inf);
|
||||
testExpr(NaN / -Inf);
|
||||
testExpr(NaN / NaN);
|
||||
|
||||
|
||||
testExpr(0 < 1);
|
||||
testExpr(0 < 0);
|
||||
testExpr(1 < 0);
|
||||
@@ -680,10 +686,10 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN < Inf);
|
||||
testExpr(NaN < -Inf);
|
||||
testExpr(NaN < NaN);
|
||||
|
||||
|
||||
testExpr(1 << 2);
|
||||
testExpr(1 << 3 << 2)
|
||||
|
||||
testExpr(1 << 3 << 2);
|
||||
|
||||
testExpr(0 <= 1);
|
||||
testExpr(0 <= 0);
|
||||
testExpr(1 <= 0);
|
||||
@@ -703,12 +709,12 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN <= Inf);
|
||||
testExpr(NaN <= -Inf);
|
||||
testExpr(NaN <= NaN);
|
||||
|
||||
|
||||
testCalc("0 = 1", 0 == 1);
|
||||
testCalc("0 = 0", 0 == 0);
|
||||
testCalc("1 = 0", 1 == 0);
|
||||
testCalc("2 = 2 = 1", 2 == 2 == 1);
|
||||
|
||||
|
||||
testExpr(0 == 1);
|
||||
testExpr(0 == 0);
|
||||
testExpr(1 == 0);
|
||||
@@ -728,7 +734,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN == Inf);
|
||||
testExpr(NaN == -Inf);
|
||||
testExpr(NaN == NaN);
|
||||
|
||||
|
||||
testExpr(0 > 1);
|
||||
testExpr(0 > 0);
|
||||
testExpr(1 > 0);
|
||||
@@ -748,7 +754,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN > Inf);
|
||||
testExpr(NaN > -Inf);
|
||||
testExpr(NaN > NaN);
|
||||
|
||||
|
||||
testExpr(0 >= 1);
|
||||
testExpr(0 >= 0);
|
||||
testExpr(1 >= 0);
|
||||
@@ -768,29 +774,31 @@ MAIN(epicsCalcTest)
|
||||
testExpr(NaN >= Inf);
|
||||
testExpr(NaN >= -Inf);
|
||||
testExpr(NaN >= NaN);
|
||||
|
||||
|
||||
testExpr(8 >> 1);
|
||||
testCalc("8 >>> 1", 8u >> 1u);
|
||||
testExpr(64 >> 2 >> 1);
|
||||
|
||||
testCalc("64 >>> 2 >>> 1", 64u >> 2u >> 1u);
|
||||
|
||||
testExpr(7 AND 4);
|
||||
|
||||
|
||||
testExpr(1 OR 8);
|
||||
|
||||
|
||||
testExpr(3 XOR 9);
|
||||
|
||||
|
||||
testCalc("2 ^ 0.2", pow(2., 0.2));
|
||||
testCalc("2 ^ -0.2", pow(2., -0.2));
|
||||
testCalc("(-0.2) ^ 2", pow(-0.2, 2.));
|
||||
testCalc("(-0.2) ^ -2", pow(-0.2, -2.));
|
||||
testCalc("2 ^ 2 ^ 3", pow(pow(2., 2.), 3.));
|
||||
|
||||
|
||||
testExpr(1 | 8);
|
||||
|
||||
|
||||
testExpr(0 || 0);
|
||||
testExpr(0 || 1);
|
||||
testExpr(1 || 0);
|
||||
testExpr(1 || 1);
|
||||
|
||||
|
||||
/* CONDITIONAL elements */
|
||||
testExpr(0 ? 1 : 2);
|
||||
testExpr(1 ? 1 : 2);
|
||||
@@ -804,7 +812,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(0 ? 2 : 1 ? 3 : 4);
|
||||
testExpr(1 ? 2 : 0 ? 3 : 4);
|
||||
testExpr(1 ? 2 : 1 ? 3 : 4);
|
||||
|
||||
|
||||
/* STORE_OPERATOR and EXPR_TERM elements*/
|
||||
testCalc("a := 0; a", 0);
|
||||
testCalc("b := 0; b", 0);
|
||||
@@ -818,7 +826,7 @@ MAIN(epicsCalcTest)
|
||||
testCalc("j := 0; j", 0);
|
||||
testCalc("k := 0; k", 0);
|
||||
testCalc("l := 0; l", 0);
|
||||
|
||||
|
||||
testCalc("a; a := 0", a);
|
||||
testCalc("b; b := 0", b);
|
||||
testCalc("c; c := 0", c);
|
||||
@@ -831,7 +839,7 @@ MAIN(epicsCalcTest)
|
||||
testCalc("j; j := 0", j);
|
||||
testCalc("k; k := 0", k);
|
||||
testCalc("l; l := 0", l);
|
||||
|
||||
|
||||
// Check relative precedences.
|
||||
testExpr(0 ? 1 : 2 | 4); // 0 1
|
||||
testExpr(1 ? 1 : 2 | 4); // 0 1
|
||||
@@ -869,11 +877,14 @@ MAIN(epicsCalcTest)
|
||||
testExpr(3 << 2 & 10); // 2 2
|
||||
testCalc("18 & 6 << 2", (18 & 6) << 2); // 2 2
|
||||
testExpr(36 >> 2 & 10); // 2 2
|
||||
testCalc("36 >>> 2 & 10", 36u >> 2u & 10u); // 2 2
|
||||
testCalc("18 & 20 >> 2", (18 & 20) >> 2); // 2 2
|
||||
testCalc("18 & 20 >>> 2", (18u & 20u) >> 2);// 2 2
|
||||
testExpr(3 & 4 == 4); // 2 3
|
||||
testExpr(3 AND 4 == 4); // 2 3
|
||||
testCalc("1 << 2 != 4", 1 << (2 != 4)); // 2 3
|
||||
testCalc("16 >> 2 != 4", 16 >> (2 != 4)); // 2 3
|
||||
testCalc("16 >>> 2 != 4", 16u >> (2 != 4)); // 2 3
|
||||
testExpr(3 AND -2); // 2 8
|
||||
testExpr(0 < 1 ? 2 : 3); // 3 0
|
||||
testExpr(1 <= 0 ? 2 : 3); // 3 0
|
||||
@@ -885,12 +896,12 @@ MAIN(epicsCalcTest)
|
||||
testExpr(-1 - 2); // 7 4
|
||||
testCalc("-2 ** 2", pow(-2., 2.)); // 7 6
|
||||
testCalc("-2 ^ 2", pow(-2., 2.)); // 7 6
|
||||
|
||||
|
||||
// Check parentheses
|
||||
testCalc("(1 | 2) ** 3", pow((double) (1 | 2), 3.));// 8 6
|
||||
testCalc("1+(1|2)**3", 1+pow((double) (1 | 2), 3.));// 8 6
|
||||
testExpr(1+(1?(1<2):(1>2))*2);
|
||||
|
||||
|
||||
testArgs("a", A_A, 0);
|
||||
testArgs("A", A_A, 0);
|
||||
testArgs("B", A_B, 0);
|
||||
@@ -920,7 +931,7 @@ MAIN(epicsCalcTest)
|
||||
testArgs("11.1;L:=0", 0, A_L);
|
||||
testArgs("12.1;A:=0;B:=A;C:=B;D:=C", 0, A_A|A_B|A_C|A_D);
|
||||
testArgs("13.1;B:=A;A:=B;C:=D;D:=C", A_A|A_D, A_A|A_B|A_C|A_D);
|
||||
|
||||
|
||||
// Malformed expressions
|
||||
testBadExpr("0x0.1", CALC_ERR_SYNTAX);
|
||||
testBadExpr("1*", CALC_ERR_INCOMPLETE);
|
||||
@@ -945,7 +956,11 @@ MAIN(epicsCalcTest)
|
||||
testUInt32Calc("~0xaaaaaaaa", 0x55555555u);
|
||||
testUInt32Calc("~~0xaaaaaaaa", 0xaaaaaaaau);
|
||||
testUInt32Calc("0xaaaaaaaa >> 8", 0xffaaaaaau);
|
||||
testUInt32Calc("0x55555555 >> 8", 0x00555555u);
|
||||
testUInt32Calc("0xaaaaaaaa >>> 8", 0x00aaaaaau);
|
||||
testUInt32Calc("0x55555555 >>> 8", 0x00555555u);
|
||||
testUInt32Calc("0xaaaaaaaa << 8", 0xaaaaaa00u);
|
||||
testUInt32Calc("0x55555555 << 8", 0x55555500u);
|
||||
// using integer literals assigned to variables
|
||||
testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a AND b", 0xaaaa0000u);
|
||||
testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a OR b", 0xffffaaaau);
|
||||
@@ -953,7 +968,11 @@ MAIN(epicsCalcTest)
|
||||
testUInt32Calc("a:=0xaaaaaaaa; ~a", 0x55555555u);
|
||||
testUInt32Calc("a:=0xaaaaaaaa; ~~a", 0xaaaaaaaau);
|
||||
testUInt32Calc("a:=0xaaaaaaaa; a >> 8", 0xffaaaaaau);
|
||||
testUInt32Calc("a:=0xaaaaaaaa; a >>> 8", 0x00aaaaaau);
|
||||
testUInt32Calc("a:=0xaaaaaaaa; a << 8", 0xaaaaaa00u);
|
||||
testUInt32Calc("a:=0x55555555; a >> 8", 0x00555555u);
|
||||
testUInt32Calc("a:=0x55555555; a >>> 8", 0x00555555u);
|
||||
testUInt32Calc("a:=0x55555555; a << 8", 0x55555500u);
|
||||
|
||||
// Test proper conversion of double values (+ 0.1 enforces double literal)
|
||||
// when used as inputs to the bitwise operations.
|
||||
@@ -973,9 +992,13 @@ MAIN(epicsCalcTest)
|
||||
testUInt32Calc("~ -1431655766.1", 0x55555555u);
|
||||
testUInt32Calc("~ 2863311530.1", 0x55555555u);
|
||||
testUInt32Calc("-1431655766.1 >> 0", 0xaaaaaaaau);
|
||||
testUInt32Calc("-1431655766.1 >>> 0", 0xaaaaaaaau);
|
||||
testUInt32Calc("2863311530.1 >> 0", 0xaaaaaaaau);
|
||||
testUInt32Calc("2863311530.1 >>> 0", 0xaaaaaaaau);
|
||||
testUInt32Calc("-1431655766.1 >> 0.1", 0xaaaaaaaau);
|
||||
testUInt32Calc("-1431655766.1 >>> 0.1", 0xaaaaaaaau);
|
||||
testUInt32Calc("2863311530.1 >> 0.1", 0xaaaaaaaau);
|
||||
testUInt32Calc("2863311530.1 >>> 0.1", 0xaaaaaaaau);
|
||||
testUInt32Calc("-1431655766.1 << 0", 0xaaaaaaaau);
|
||||
testUInt32Calc("2863311530.1 << 0", 0xaaaaaaaau);
|
||||
testUInt32Calc("-1431655766.1 << 0.1", 0xaaaaaaaau);
|
||||
@@ -983,4 +1006,3 @@ MAIN(epicsCalcTest)
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,38 +20,38 @@ MAIN(epicsMathTest)
|
||||
double huge = 1e300;
|
||||
double tiny = 1e-300;
|
||||
double c;
|
||||
|
||||
|
||||
testPlan(35);
|
||||
|
||||
|
||||
testOk1(!isnan(0.0));
|
||||
testOk1(!isinf(0.0));
|
||||
|
||||
|
||||
testOk1(!isnan(epicsINF));
|
||||
testOk1(isinf(epicsINF));
|
||||
testOk1(epicsINF == epicsINF);
|
||||
testOk1(epicsINF > 0.0);
|
||||
testOk1(epicsINF - epicsINF != 0.0);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
testTodoBegin("Known failure on windows (MSVC optimizer bug?)");
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testTodoBegin("Known failure on windows-x64 and win32-x86");
|
||||
#endif
|
||||
testOk1(epicsINF + -epicsINF != 0.0);
|
||||
testOk1(-epicsINF + epicsINF != 0.0);
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testTodoEnd();
|
||||
#endif
|
||||
|
||||
testOk1(isnan(epicsINF - epicsINF));
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
testTodoBegin("Known failure on windows (MSVC optimizer bug?)");
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testTodoBegin("Known failure on windows-x64 and win32-x86");
|
||||
#endif
|
||||
testOk1(isnan(epicsINF + -epicsINF));
|
||||
testOk1(isnan(-epicsINF + epicsINF));
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testTodoEnd();
|
||||
#endif
|
||||
|
||||
|
||||
testOk1(isnan(epicsNAN));
|
||||
testOk1(!isinf(epicsNAN));
|
||||
testOk1(epicsNAN != epicsNAN);
|
||||
@@ -62,34 +62,34 @@ MAIN(epicsMathTest)
|
||||
testOk1(!(epicsNAN > epicsNAN));
|
||||
testOk1(isnan(epicsNAN - epicsNAN));
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
testTodoBegin("Known failure on windows (MSVC optimizer bug?)");
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testTodoBegin("Known failure on windows-x64 and win32-x86");
|
||||
#endif
|
||||
testOk1(isnan(epicsNAN + -epicsNAN));
|
||||
testOk1(isnan(-epicsNAN + epicsNAN));
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
testTodoEnd();
|
||||
#endif
|
||||
|
||||
|
||||
c = huge / tiny;
|
||||
testOk(!isnan(c), "!isnan(1e300 / 1e-300)");
|
||||
testOk(isinf(c), "isinf(1e300 / 1e-300)");
|
||||
testOk(c > 0.0, "1e300 / 1e-300 > 0.0");
|
||||
|
||||
|
||||
c = (-huge) / tiny;
|
||||
testOk(!isnan(c), "!isnan(-1e300 / 1e-300)");
|
||||
testOk(isinf(c), "isinf(-1e300 / 1e-300)");
|
||||
testOk(c < 0.0, "-1e300 / 1e-300 < 0.0");
|
||||
|
||||
|
||||
c = huge / huge;
|
||||
testOk(!isnan(c), "!isnan(1e300 / 1e300)");
|
||||
testOk(!isinf(c), "!isinf(1e300 / 1e300)");
|
||||
testOk(c == 1.0, "1e300 / 1e300 == 1.0");
|
||||
|
||||
|
||||
c = tiny / tiny;
|
||||
testOk(!isnan(c), "!isnan(1e-300 / 1e-300)");
|
||||
testOk(!isinf(c), "!isinf(1e-300 / 1e-300)");
|
||||
testOk(c == 1.0, "1e300 / 1e-300 == 1.0");
|
||||
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
210
modules/libcom/test/epicsThreadClassTest.cpp
Normal file
210
modules/libcom/test/epicsThreadClassTest.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2020 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.
|
||||
\*************************************************************************/
|
||||
/* epicsThreadClassTest.cpp */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
/* Key to the char's that define the test case actions:
|
||||
*
|
||||
* Upper case letters are for parent thread actions
|
||||
* B - Parent calls thread->start() and waits for child to start
|
||||
* D - Parent deletes thread. This waits for child to return if it hasn't yet
|
||||
* E - Parent calls thread->exitWait(), this may wait for child to return
|
||||
* S - Parent sleeps for SLEEP_TIME seconds
|
||||
* T - Parent sends sync trigger to child (w)
|
||||
* W - Parent waits for sync trigger from child (t)
|
||||
* X - Parent calls thread->exitWait(0)
|
||||
*
|
||||
* Lower case letters are for child thread actions
|
||||
* d - Child deletes thread
|
||||
* e - Child calls thread->exitWait()
|
||||
* r - Child returns
|
||||
* s - Child sleeps for SLEEP_TIME seconds
|
||||
* t - Child sends sync trigger to parent (W)
|
||||
* w - Child waits for sync trigger from child (T)
|
||||
*
|
||||
* Note that it is possible to write test cases that can hang,
|
||||
* segfault, or that trigger errors from thread APIs.
|
||||
*/
|
||||
|
||||
// The test cases
|
||||
|
||||
const char * const cases[] = {
|
||||
// These cases don't start the thread:
|
||||
"D", // Parent deletes thread
|
||||
"ED", // Parent does exitWait(), deletes thread
|
||||
|
||||
// In these cases the parent deletes the thread
|
||||
"BrSD", // Child returns; parent deletes thread
|
||||
"BsDr", // Parent deletes thread; child returns
|
||||
"BrSED", // Child returns; parent does exitWait(), deletes thread
|
||||
"BsErD", // Parent does exitWait(); child returns; parent deletes thread
|
||||
"BsXDr", // Parent does exitWait(0); parent deletes thread; child returns
|
||||
"BwXTDsr", // Parent does exitWait(0); parent deletes thread; child returns
|
||||
// These are currently broken
|
||||
// "BetWSrD", // Child does exitWait(); sync; child returns; parent deletes thread
|
||||
// "BetWsDr", // Child does exitWait(); sync; parent deletes thread; child returns
|
||||
|
||||
// In these cases the child deletes the thread
|
||||
"BdrS", // Child deletes thread, returns
|
||||
"BedrS", // Child does exitWait(), deletes thread, returns
|
||||
"BwXTSdr", // Parent does exitWait(0); sync; child deletes thread, returns
|
||||
|
||||
NULL // Terminator
|
||||
};
|
||||
|
||||
// How long to sleep for while the other thread works
|
||||
#define SLEEP_TIME 1.0
|
||||
|
||||
class threadCase: public epicsThreadRunable {
|
||||
public:
|
||||
threadCase(const char * const tcase);
|
||||
virtual ~threadCase();
|
||||
virtual void run();
|
||||
epicsThread *pthread;
|
||||
epicsEvent startEvt;
|
||||
epicsEvent childEvt;
|
||||
epicsEvent parentEvt;
|
||||
private:
|
||||
const char * const name;
|
||||
};
|
||||
|
||||
threadCase::threadCase(const char * const tcase) :
|
||||
pthread(new epicsThread(*this, tcase,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall))),
|
||||
name(tcase)
|
||||
{
|
||||
testDiag("Constructing test case '%s'", name);
|
||||
}
|
||||
|
||||
threadCase::~threadCase()
|
||||
{
|
||||
testDiag("Destroying test case '%s'", name);
|
||||
}
|
||||
|
||||
void threadCase::run()
|
||||
{
|
||||
testDiag("Child running for '%s'", name);
|
||||
startEvt.signal();
|
||||
|
||||
for (const char * pdo = name;
|
||||
const char tdo = *pdo;
|
||||
pdo++)
|
||||
{
|
||||
switch (tdo)
|
||||
{
|
||||
case 'd':
|
||||
testDiag("'%c': Child deleting epicsThread", tdo);
|
||||
delete pthread;
|
||||
pthread = NULL;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
testDiag("'%c': Child calling exitWait()", tdo);
|
||||
assert(pthread);
|
||||
pthread->exitWait();
|
||||
break;
|
||||
|
||||
case 's':
|
||||
testDiag("'%c': Child sleeping", tdo);
|
||||
epicsThreadSleep(SLEEP_TIME);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
testDiag("'%c': Child sending trigger", tdo);
|
||||
parentEvt.signal();
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
testDiag("'%c': Child awaiting trigger", tdo);
|
||||
childEvt.wait();
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
testDiag("'%c': Child returning", tdo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
testFail("Test case '%s' is missing 'r'", name);
|
||||
}
|
||||
|
||||
MAIN(epicsThreadClassTest)
|
||||
{
|
||||
const int ntests = NELEMENTS(cases);
|
||||
testPlan(ntests - 1); // The last element is the NULL terminator
|
||||
|
||||
for (const char * const * pcase = cases;
|
||||
const char * const tcase = *pcase;
|
||||
pcase++)
|
||||
{
|
||||
testDiag("======= Test case '%s' =======", tcase);
|
||||
threadCase thrCase(tcase);
|
||||
|
||||
for (const char * pdo = tcase;
|
||||
const char tdo = *pdo;
|
||||
pdo++)
|
||||
{
|
||||
switch (tdo)
|
||||
{
|
||||
case 'B':
|
||||
testDiag("'%c': Parent starting child", tdo);
|
||||
assert(thrCase.pthread);
|
||||
thrCase.pthread->start();
|
||||
thrCase.startEvt.wait();
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
testDiag("'%c': Parent deleting epicsThread", tdo);
|
||||
assert(thrCase.pthread);
|
||||
delete thrCase.pthread;
|
||||
thrCase.pthread = NULL;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
testDiag("'%c': Parent calling exitWait()", tdo);
|
||||
assert(thrCase.pthread);
|
||||
thrCase.pthread->exitWait();
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
testDiag("'%c': Parent calling exitWait(0)", tdo);
|
||||
assert(thrCase.pthread);
|
||||
thrCase.pthread->exitWait(0);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
testDiag("'%c': Parent sleeping", tdo);
|
||||
epicsThreadSleep(SLEEP_TIME);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
testDiag("'%c': Parent sending trigger", tdo);
|
||||
thrCase.childEvt.signal();
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
testDiag("'%c': Parent awaiting trigger", tdo);
|
||||
thrCase.parentEvt.wait();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
testPass("Test case '%s' passed", tcase);
|
||||
}
|
||||
|
||||
return testDone();
|
||||
}
|
||||
62
src/tools/EPICS/PodHtml.pm
Normal file
62
src/tools/EPICS/PodHtml.pm
Normal file
@@ -0,0 +1,62 @@
|
||||
package EPICS::PodHtml;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Pod::Simple::HTML';
|
||||
|
||||
sub encode_entities {
|
||||
my ($self, $str) = @_;
|
||||
my %entities = (
|
||||
q{>} => 'gt',
|
||||
q{<} => 'lt',
|
||||
q{'} => '#39',
|
||||
q{"} => 'quot',
|
||||
q{&} => 'amp'
|
||||
);
|
||||
my $ents = join '', keys %entities;
|
||||
$str =~ s/([$ents])/'&' . $entities{$1} . ';'/ge;
|
||||
return $str;
|
||||
}
|
||||
|
||||
# Translate L<link text|filename/Section name>
|
||||
# into <a href="filename.html#Section-name">link text</a>
|
||||
|
||||
sub do_pod_link {
|
||||
# EPICS::PodHtml object and Pod::Simple::PullParserStartToken object
|
||||
my ($self, $link) = @_;
|
||||
|
||||
my $ret;
|
||||
|
||||
# Links to other EPICS POD files
|
||||
if ($link->tagname eq 'L' and $link->attr('type') eq 'pod') {
|
||||
my $to = $link->attr('to');
|
||||
my $section = $link->attr('section');
|
||||
$section = $self->section_escape($section)
|
||||
if defined $section and length($section .= ''); # (stringify)
|
||||
|
||||
$ret = (defined $to and length $to) ? "$to.html" : '';
|
||||
$ret .= "#$section" if defined $section and length $section;
|
||||
}
|
||||
else {
|
||||
# all other links are generated by the parent class
|
||||
$ret = $self->SUPER::do_pod_link($link);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# Generate the same section IDs as Pod::Simple::XHTML
|
||||
|
||||
sub section_name_tidy {
|
||||
my($self, $section) = @_;
|
||||
$section =~ s/^\s+//;
|
||||
$section =~ s/\s+$//;
|
||||
$section =~ tr/ /-/;
|
||||
$section =~ s/[[:cntrl:][:^ascii:]]//g; # drop crazy characters
|
||||
$section = $self->unicode_escape_url($section);
|
||||
$section = '_' unless length $section;
|
||||
return $section;
|
||||
}
|
||||
|
||||
1;
|
||||
40
src/tools/EPICS/PodXHtml.pm
Normal file
40
src/tools/EPICS/PodXHtml.pm
Normal file
@@ -0,0 +1,40 @@
|
||||
package EPICS::PodXHtml;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Pod::Simple::XHTML';
|
||||
|
||||
BEGIN {
|
||||
if ($Pod::Simple::XHTML::VERSION < '3.16') {
|
||||
# encode_entities() wasn't a method, add it
|
||||
our *encode_entities = sub {
|
||||
my ($self, $str) = @_;
|
||||
my %entities = (
|
||||
q{>} => 'gt',
|
||||
q{<} => 'lt',
|
||||
q{'} => '#39',
|
||||
q{"} => 'quot',
|
||||
q{&} => 'amp'
|
||||
);
|
||||
my $ents = join '', keys %entities;
|
||||
$str =~ s/([$ents])/'&' . $entities{$1} . ';'/ge;
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Translate L<link text|filename/Section name>
|
||||
# into <a href="filename.html#Section-name">link text</a>
|
||||
|
||||
sub resolve_pod_page_link {
|
||||
my ($self, $to, $section) = @_;
|
||||
|
||||
my $ret = defined $to ? "$to.html" : '';
|
||||
$ret .= '#' . $self->idify($self->encode_entities($section), 1)
|
||||
if defined $section;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -16,6 +16,8 @@ PERL_MODULES += EPICS/Path.pm
|
||||
PERL_MODULES += EPICS/Release.pm
|
||||
PERL_MODULES += EPICS/Readfile.pm
|
||||
PERL_MODULES += EPICS/Getopts.pm
|
||||
PERL_MODULES += EPICS/PodHtml.pm
|
||||
PERL_MODULES += EPICS/PodXHtml.pm
|
||||
|
||||
# This goes into lib/perl, not bin/<host>
|
||||
PERL_MODULES += EpicsHostArch.pl
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin qw($Bin);
|
||||
use lib "$Bin/../../lib/perl";
|
||||
|
||||
use Getopt::Std;
|
||||
$Getopt::Std::STANDARD_HELP_VERSION = 1;
|
||||
|
||||
use Pod::Simple::HTML;
|
||||
use EPICS::PodHtml;
|
||||
|
||||
use Pod::Usage;
|
||||
|
||||
@@ -86,7 +89,7 @@ my $root = '../' x scalar @inpath;
|
||||
open my $out, '>', $opt_o or
|
||||
die "Can't create $opt_o: $!\n";
|
||||
|
||||
my $podHtml = Pod::Simple::HTML->new();
|
||||
my $podHtml = EPICS::PodHtml->new();
|
||||
|
||||
$podHtml->html_css($root . 'style.css');
|
||||
$podHtml->perldoc_url_prefix('');
|
||||
|
||||
Reference in New Issue
Block a user