diff --git a/configure/RULES.Db b/configure/RULES.Db index d14666187..c0809577a 100644 --- a/configure/RULES.Db +++ b/configure/RULES.Db @@ -13,6 +13,8 @@ SUBST_SUFFIX ?= .substitutions ##################################################### vpath +vpath %.pm $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD)) +vpath %.pod $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD)) vpath %.dbd $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD)) vpath %.db $(USR_VPATH) $(SRC_DIRS) $(dir $(DB)) vpath %.vdb $(USR_VPATH) $(SRC_DIRS) $(dir $(DB)) @@ -231,9 +233,9 @@ menu%.h$(DEP): menu%.dbd @$(DBTOMENUH) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $< > $@ @echo "$(COMMONDEP_TARGET): ../Makefile" >> $@ -menu%.h$(DEP): ../menu%.dbd +%.dbd$(DEP): %.dbd.pod @$(RM) $@ - @$(DBTOMENUH) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $< > $@ + @$(DBEXPAND) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $< > $@ @echo "$(COMMONDEP_TARGET): ../Makefile" >> $@ %.dbd$(DEP): %Include.dbd @@ -361,14 +363,14 @@ $(COMMON_DIR)/menu%.h: ../menu%.dbd ##################################################### DBD files -$(COMMON_DIR)/bpt%.dbd: bpt%.data +$(COMMON_DIR)/bpt%.dbd: bpt%.data @$(RM) $(notdir $@) $(MAKEBPT) $< $(notdir $@) @$(MV) $(notdir $@) $@ -$(COMMON_DIR)/bpt%.dbd: ../bpt%.data +$(COMMON_DIR)/%.dbd: %.dbd.pod @$(RM) $(notdir $@) - $(MAKEBPT) $< $(notdir $@) + $(DBEXPAND) $(DBDFLAGS) -o $(notdir $@) $< @$(MV) $(notdir $@) $@ $(COMMON_DIR)/%.dbd: %Include.dbd @@ -422,6 +424,30 @@ $(foreach file, $(DBD_INSTALLS), $(eval $(call DBD_INSTALLS_template, $(file)))) .PRECIOUS: $(COMMON_DBDS) $(COMMON_DIR)/%Include.dbd +##################################################### HTML files + +$(COMMON_DIR)/%.html: %.dbd.pod $(TOOLS)/dbdToHtml.pl + @$(RM) $(notdir $@) + $(PERL) $(TOOLS)/dbdToHtml.pl $(DBDFLAGS) -o $(notdir $@) $< + @$(MV) $(notdir $@) $@ + +$(COMMON_DIR)/%.html: %.pod $(TOOLS)/podToHtml.pl + @$(RM) $(notdir $@) + $(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $< + @$(MV) $(notdir $@) $@ + +$(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl + @$(RM) $(notdir $@) + $(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $< + @$(MV) $(notdir $@) $@ + +$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl + @$(RM) $(notdir $@) + $(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $< + @$(MV) $(notdir $@) $@ + +.PRECIOUS: $(COMMON_DIR)/%.html %.html + ##################################################### DB files $(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 8c6cac578..41e4fa06d 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -68,6 +68,8 @@ else INSTALL_TEMPLATES_SUBDIR = $(INSTALL_TEMPLATES) endif +HTMLS_DIR ?= . + #--------------------------------------------------------------- # First target @@ -480,6 +482,10 @@ $(INSTALL_HTML)/$(HTMLS_DIR)/%: ../% $(ECHO) "Installing html $@" @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) +$(INSTALL_HTML)/$(HTMLS_DIR)/%: $(COMMON_DIR)/% + $(ECHO) "Installing generated html $@" + @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) + $(INSTALL_TEMPLATES_SUBDIR)/%: ../% $(ECHO) "Installing $@" @$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D) diff --git a/src/ca/client/perl/Makefile b/src/ca/client/perl/Makefile index b3fe549c7..1fb8627fc 100644 --- a/src/ca/client/perl/Makefile +++ b/src/ca/client/perl/Makefile @@ -61,10 +61,6 @@ ifdef T_A $(RM) $@ $@_new $(PERL) $(EXTUTILS)/xsubpp -typemap $(EXTUTILS)/typemap $< > $@_new && $(MV) $@_new $@ - %.html: ../%.pm - $(RM) $@ - podchecker $< && pod2html --infile=$< --outfile=$@ - $(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)/%: % $(ECHO) "Installing loadable shared library $@" @$(INSTALL_LIBRARY) -d -m $(LIB_PERMISSIONS) $< $(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH) diff --git a/src/ioc/bpt/Makefile b/src/ioc/bpt/Makefile index 7ed83ae9e..b8d73345f 100644 --- a/src/ioc/bpt/Makefile +++ b/src/ioc/bpt/Makefile @@ -25,3 +25,5 @@ PROD_HOST += makeBpt makeBpt_SRCS = makeBpt +HTMLS += menuConvert.html + diff --git a/src/ioc/bpt/menuConvert.dbd b/src/ioc/bpt/menuConvert.dbd.pod similarity index 66% rename from src/ioc/bpt/menuConvert.dbd rename to src/ioc/bpt/menuConvert.dbd.pod index 1e1e16c4c..e81d4e6f2 100644 --- a/src/ioc/bpt/menuConvert.dbd +++ b/src/ioc/bpt/menuConvert.dbd.pod @@ -1,12 +1,24 @@ #************************************************************************* -# Copyright (c) 2002 The University of Chicago, as Operator of Argonne +# Copyright (c) 2013 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 Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found +# EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Menu menuConvert + +This menu defines the standard analog conversions which are included with Base. +IOC applications may add choices or replace the later choices in this menu, +although the first three choices must not be renamed or moved to different +positions. The breakpoint table name must exactly match the choice string +listed here. + +=menu menuConvert + +=cut + menu(menuConvert) { choice(menuConvertNO_CONVERSION,"NO CONVERSION") choice(menuConvertSLOPE,"SLOPE") diff --git a/src/ioc/db/Makefile b/src/ioc/db/Makefile index 74b37ce60..5431c33c1 100644 --- a/src/ioc/db/Makefile +++ b/src/ioc/db/Makefile @@ -58,6 +58,7 @@ menuGlobal_DBD += menuSimm.dbd DBDINC += $(basename $(menuGlobal_DBD)) DBDINC += dbCommon +HTMLS += $(patsubst %.dbd.pod,%.html,$(notdir $(wildcard ../db/menu*.dbd.pod))) dbCore_SRCS += dbLock.c dbCore_SRCS += dbAccess.c diff --git a/src/ioc/db/RULES b/src/ioc/db/RULES index 36eee734a..b89e2711c 100644 --- a/src/ioc/db/RULES +++ b/src/ioc/db/RULES @@ -11,7 +11,7 @@ # This is a Makefile fragment, see src/ioc/Makefile. -dbCommon.h$(DEP): $(IOCDIR)/db/dbCommonRecord.dbd +dbCommon.h$(DEP): $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES @$(RM) $@ @$(DBTORECORDTYPEH) -D -I ../db -o $(COMMONDEP_TARGET) $< > $@ @echo "$(COMMONDEP_TARGET): ../Makefile" >> $@ diff --git a/src/ioc/db/menuAlarmSevr.dbd b/src/ioc/db/menuAlarmSevr.dbd.pod similarity index 58% rename from src/ioc/db/menuAlarmSevr.dbd rename to src/ioc/db/menuAlarmSevr.dbd.pod index ae6661a9e..1d86edba6 100644 --- a/src/ioc/db/menuAlarmSevr.dbd +++ b/src/ioc/db/menuAlarmSevr.dbd.pod @@ -1,12 +1,22 @@ #************************************************************************* -# Copyright (c) 2002 The University of Chicago, as Operator of Argonne +# Copyright (c) 2012 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 Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found +# EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Menu menuAlarmSevr + +This menu defines the four possible alarm severities that EPICS records can +exhibit. Note that it is not possible to add or remove severities just by +changing the choices defined here. + +=menu menuAlarmSevr + +=cut + menu(menuAlarmSevr) { choice(menuAlarmSevrNO_ALARM,"NO_ALARM") choice(menuAlarmSevrMINOR,"MINOR") diff --git a/src/ioc/db/menuSimm.dbd b/src/ioc/db/menuSimm.dbd.pod similarity index 57% rename from src/ioc/db/menuSimm.dbd rename to src/ioc/db/menuSimm.dbd.pod index 8021a9512..5df087ccc 100644 --- a/src/ioc/db/menuSimm.dbd +++ b/src/ioc/db/menuSimm.dbd.pod @@ -1,12 +1,21 @@ #************************************************************************* -# Copyright (c) 2002 The University of Chicago, as Operator of Argonne +# Copyright (c) 2013 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 Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found +# EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=head1 Menu menuSimm + +This menu is used for Simulation Mode (SIMM) fields of input record types that +can fetch either raw or engineering values through their SIOL link. + +=menu menuSimm + +=cut + menu(menuSimm) { choice(menuSimmNO,"NO") choice(menuSimmYES,"YES") diff --git a/src/std/filters/Makefile b/src/std/filters/Makefile index 7e33500d1..d4539898f 100644 --- a/src/std/filters/Makefile +++ b/src/std/filters/Makefile @@ -9,10 +9,12 @@ SRC_DIRS += $(STDDIR)/filters -DBD_INSTALLS += filters.dbd +DBD += filters.dbd dbRecStd_SRCS += ts.c dbRecStd_SRCS += dbnd.c dbRecStd_SRCS += arr.c dbRecStd_SRCS += sync.c +HTMLS += filters.html + diff --git a/src/std/filters/filters.dbd b/src/std/filters/filters.dbd deleted file mode 100644 index 7fb0c5133..000000000 --- a/src/std/filters/filters.dbd +++ /dev/null @@ -1,4 +0,0 @@ -registrar(tsInitialize) -registrar(dbndInitialize) -registrar(arrInitialize) -registrar(syncInitialize) diff --git a/src/std/filters/filters.dbd.pod b/src/std/filters/filters.dbd.pod new file mode 100644 index 000000000..4f6faefcd --- /dev/null +++ b/src/std/filters/filters.dbd.pod @@ -0,0 +1,244 @@ +=head1 Channel Filters + +Channel Filters can be applied to Channel Access channels by a client, using +a JSON Field Modifier to select the filter and any parameters. +The following filters are available in this release: + +=over + +=item * L + +=item * L + +=item * L + +=item * L + +=back + +=head2 Using Filters + +Channel filters can be added to any Channel Access channel name. +There can be more than one filter applied to the same channel, in which case the +order that they are specified will control the order in which they are applied +to the resulting data-stream. +The filter specification must appear after the field name, or if the default +(VAL) field is used after a dot C<.> appended to the record name. +With the exception of the array short-hand which is described below, all filters +must appear inside a pair of braces C< {} > after the dot expressed as a JSON +(L) object, which allows filter +parameters to be included as needed. + +Each filter is given as a name/value pair. The filter name (given in parentheses +in the titles below) is a string, and must be enclosed inside double-quotes C<"> +characters as per the JSON specification. +Parameters to that filter are provided as the value part of the name/value pair, +and will normally appear as a child JSON object consisting of name/value pairs +inside a nested pair of braces C< {} >. + +=head4 Example Filter + +Given a record called C the following would apply a filter C to +the VAL field of that record, giving the filter two numeric parameters named +C and C: + + test:channel.{"f":{"lo":0,"hi":10}} + +Note that due to the required presence of the double-quote characters in the +JSON strings in the name string, it will usually be necessary to enclose a +filtered name within single-quotes C<< ' ... ' >> when typing it as an +argument to a Unix shell command. + +=head2 Filter Reference + +=cut + +registrar(tsInitialize) + +=head3 TimeStamp Filter C<"ts"> + +This filter is used to set the timestamp of the value fetched through +the channel to the time the value was fetched (or an update was sent), +rather than the time the record last +processed which could have been days or even weeks ago for some records, or set +to the EPICS epoch if the record has never processed. + +=head4 Parameters + +None, use an empty pair of braces. + +=head4 Example + + Hal$ caget -a 'test:channel.{"ts":{}}' + test:channel.{"ts":{}} 2012-08-28 22:10:31.192547 0 UDF INVALID + Hal$ caget -a 'test:channel' + test:channel 0 UDF INVALID + +=cut + +registrar(dbndInitialize) + +=head3 Deadband Filter C<"dbnd"> + +This filter implements a channel-specific monitor deadband, which is applied +after any deadbands implemented by the record itself (it can only drop updates +that the unfiltered channel generates, never add additional updates). + +The deadband can be specified as an absolute value change, or as a relative +percentage. + +=head4 Parameters + +=over + +=item Mode+Deadband C<"abs">/C<"rel"> (shorthand) + +Mode and deadband can be specified in one definition (shorthand). +The desired mode is given as parameter name (C<"abs"> or C<"rel">), with the +numeric size of the deadband (absolute value or numeric percentage) as value. + +=item Deadband C<"d"> + +The size of the deadband to use. +Relative deadband values are given as a numeric percentage, but without any +trailing percent character. + +=item Mode C<"m"> (optional) + +A string (enclosed in double-quotes C<">), which should contain either +C or C. +The default mode is C if no mode parameter is included. + +=back + +=head4 Example + + Hal$ camonitor 'test:channel' + test:channel 2012-09-01 22:10:19.600595 1 LOLO MAJOR + test:channel 2012-09-01 22:10:20.600661 2 LOLO MAJOR + test:channel 2012-09-01 22:10:21.600819 3 LOW MINOR + test:channel 2012-09-01 22:10:22.600905 4 LOW MINOR + test:channel 2012-09-01 22:10:23.601023 5 + test:channel 2012-09-01 22:10:24.601136 6 HIGH MINOR + ^C + Hal$ camonitor 'test:channel.{"dbnd":{"abs":1.5}}' + test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:49.613341 1 LOLO MAJOR + test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:51.613615 3 LOW MINOR + test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:53.613804 5 + test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:55.614074 7 HIGH MINOR + test:channel.{"dbnd":{"d":1.5}} 2012-09-01 22:11:57.614305 9 HIHI MAJOR + ^C + +=cut + +registrar(arrInitialize) + +=head3 Array Filter C<"arr"> + +This filter is used to retrieve parts of an array (subarrays and strided +subarrays). + +=head4 Parameters + +Note: Negative index numbers address from the end of the array, with C<-1> being the last element. + +=over + +=item Square bracket notation C<[s:i:e]> (shorthand) + +The familiar C<[s:i:e]> notation with square brackets can be used (shorthand). + +=item Start index C<"s"> + +Index of the first original array element to retrieve. + +=item Increment C<"i"> + +Index increment between retrieved elements of the original array; must be +a positive number. + +=item End index C<"e"> + +Index of the last original array element to retrieve. + +=back + +Defaults (when parameters are omitted) are: +C (first element), C (fetch all elements), C +(last element) + +=head4 Example + + Hal$ caget test:channel 'test:channel.{"arr":{"s":2,"i":2,"e":8}}' test:channel.[3:5] test:channel.[3:2:-3] + test:channel 10 0 1 2 3 4 5 6 7 8 9 + test:channel.{"arr":{"s":2,"i":2,"e":8}} 4 2 4 6 8 + test:channel.[3:5] 3 3 4 5 + test:channel.[3:2:-3] 3 3 5 7 + +=cut + +registrar(syncInitialize) + +=head3 Synchronize Filter C<"sync"> + +This filter is used to dynamically enable or disable monitors according +to a condition and a state variable declared by the IOC. + +State variables have a boolean value and can be set by a binary output +record, an iocsh command or by other software running in the IOC calling +C. + +=head4 Parameters + +=over + +=item Mode+State + +Mode and state can be specified in one definition (shorthand). +The desired mode is given as parameter name (C<"before"> / C<"first"> / +C<"while"> / C<"last"> / C<"after"> / C<"unless">), with the state name +(enclosed in double quotes C<">) as value. + +=item Mode C<"m"> + +A single word from the list below, enclosed in double quotes C<">. +This controls how the state value should affect the monitor stream. + +=over + +=item C<"before"> E only the last value received before the state +changes from false to true is forwarded to the client. + +=item C<"first"> E only the first value received after the state +changes from true to false is forwarded to the client. + +=item C<"while"> E values are forwarded to the client as long as +the state is true. + +=item C<"last"> E only the last value received before the state +changes from true to false is forwarded to the client. + +=item C<"after"> E only the first value received after the state +changes from true to false is forwarded to the client. + +=item C<"unless"> E values are forwarded to the client as long +as the state is false. + +=back + +=item State C<"s"> + +The name of a state variable, enclosed in double quotes C<">. + +=back + +=head4 Example + +Assuming there is a system state called "blue", that is being controlled by +some other facility such as a timing system, updates could be restricted to +periods only when "blue" is true by using + + Hal$ camonitor 'test:channel' 'test:channel.{"while":"blue"}' + ... + +=cut diff --git a/src/std/filters/sync.c b/src/std/filters/sync.c index ec1bcd409..2646aefa6 100644 --- a/src/std/filters/sync.c +++ b/src/std/filters/sync.c @@ -21,11 +21,6 @@ #define STATE_NAME_LENGTH 20 -static const -chfPluginEnumType modeEnum[] = { {"before", 0}, {"first", 1}, - {"last", 2}, {"after", 3}, - {"while", 4}, {"unless", 5}, - {NULL,0} }; typedef enum syncMode { syncModeBefore=0, syncModeFirst=1, @@ -35,6 +30,17 @@ typedef enum syncMode { syncModeUnless=5 } syncMode; +static const +chfPluginEnumType modeEnum[] = { + {"before", syncModeBefore}, + {"first", syncModeFirst}, + {"last", syncModeLast}, + {"after", syncModeAfter}, + {"while", syncModeWhile}, + {"unless", syncModeUnless}, + {NULL, 0} +}; + typedef struct myStruct { syncMode mode; char state[STATE_NAME_LENGTH]; diff --git a/src/std/rec/Makefile b/src/std/rec/Makefile index c2d44ddb9..cf2eba9f2 100644 --- a/src/std/rec/Makefile +++ b/src/std/rec/Makefile @@ -51,3 +51,4 @@ stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords)) dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords)) +HTMLS += $(patsubst %.dbd.pod,%.html,$(notdir $(wildcard ../rec/*Record.dbd.pod))) diff --git a/src/std/rec/aSubRecord.dbd b/src/std/rec/aSubRecord.dbd.pod similarity index 91% rename from src/std/rec/aSubRecord.dbd rename to src/std/rec/aSubRecord.dbd.pod index 3297db59b..d188745f1 100644 --- a/src/std/rec/aSubRecord.dbd +++ b/src/std/rec/aSubRecord.dbd.pod @@ -1,3 +1,42 @@ +#************************************************************************* +# Copyright (c) 2012 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 Subroutine Record (aSub) + +... + +=head2 Record-specific Menus + +=head3 Menu aSubLFLG + +The LFLG field uses this menu to ... + +=menu aSubLFLG + +=head3 Menu aSubEFLG + +The EFLG field uses this menu to ... + +=menu aSubEFLG + +... + +=head2 Parameter Fields + +The record-specific fields are described below. + +=recordtype aSub + +... + +=cut + menu(aSubLFLG) { choice(aSubLFLG_IGNORE,"IGNORE") choice(aSubLFLG_READ,"READ") @@ -191,12 +230,24 @@ recordtype(aSub) { promptgroup(GUI_INPUTS) interest(1) } + +=head3 Input Fields + +... + +=fields A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U + +=cut + field(A,DBF_NOACCESS) { prompt("Input value A") asl(ASL0) special(SPC_DBADDR) interest(2) extra("void *a") + #=read Yes + #=write Yes + #=type Set by FTA } field(B,DBF_NOACCESS) { prompt("Input value B") @@ -204,6 +255,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *b") + #=read Yes + #=write Yes + #=type Set by FTB } field(C,DBF_NOACCESS) { prompt("Input value C") @@ -211,6 +265,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *c") + #=read Yes + #=write Yes + #=type Set by FTC } field(D,DBF_NOACCESS) { prompt("Input value D") @@ -218,6 +275,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *d") + #=read Yes + #=write Yes + #=type Set by FTD } field(E,DBF_NOACCESS) { prompt("Input value E") @@ -225,6 +285,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *e") + #=read Yes + #=write Yes + #=type Set by FTE } field(F,DBF_NOACCESS) { prompt("Input value F") @@ -232,6 +295,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *f") + #=read Yes + #=write Yes + #=type Set by FTF } field(G,DBF_NOACCESS) { prompt("Input value G") @@ -239,6 +305,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *g") + #=read Yes + #=write Yes + #=type Set by FTG } field(H,DBF_NOACCESS) { prompt("Input value H") @@ -246,6 +315,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *h") + #=read Yes + #=write Yes + #=type Set by FTH } field(I,DBF_NOACCESS) { prompt("Input value I") @@ -253,6 +325,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *i") + #=read Yes + #=write Yes + #=type Set by FTI } field(J,DBF_NOACCESS) { prompt("Input value J") @@ -260,6 +335,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *j") + #=read Yes + #=write Yes + #=type Set by FTJ } field(K,DBF_NOACCESS) { prompt("Input value K") @@ -267,6 +345,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *k") + #=read Yes + #=write Yes + #=type Set by FTK } field(L,DBF_NOACCESS) { prompt("Input value L") @@ -274,6 +355,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *l") + #=read Yes + #=write Yes + #=type Set by FTL } field(M,DBF_NOACCESS) { prompt("Input value M") @@ -281,6 +365,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *m") + #=read Yes + #=write Yes + #=type Set by FTM } field(N,DBF_NOACCESS) { prompt("Input value N") @@ -288,6 +375,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *n") + #=read Yes + #=write Yes + #=type Set by FTN } field(O,DBF_NOACCESS) { prompt("Input value O") @@ -295,6 +385,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *o") + #=read Yes + #=write Yes + #=type Set by FTO } field(P,DBF_NOACCESS) { prompt("Input value P") @@ -302,6 +395,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *p") + #=read Yes + #=write Yes + #=type Set by FTP } field(Q,DBF_NOACCESS) { prompt("Input value Q") @@ -309,6 +405,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *q") + #=read Yes + #=write Yes + #=type Set by FTQ } field(R,DBF_NOACCESS) { prompt("Input value R") @@ -316,6 +415,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *r") + #=read Yes + #=write Yes + #=type Set by FTR } field(S,DBF_NOACCESS) { prompt("Input value S") @@ -323,6 +425,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *s") + #=read Yes + #=write Yes + #=type Set by FTS } field(T,DBF_NOACCESS) { prompt("Input value T") @@ -330,6 +435,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *t") + #=read Yes + #=write Yes + #=type Set by FTT } field(U,DBF_NOACCESS) { prompt("Input value U") @@ -337,6 +445,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *u") + #=read Yes + #=write Yes + #=type Set by FTU } field(FTA,DBF_MENU) { prompt("Type of A") @@ -905,12 +1016,24 @@ recordtype(aSub) { promptgroup(GUI_OUTPUT) interest(1) } + +=head3 Value Fields + +... + +=fields VALA, VALB, VALC, VALD, VALE, VALF, VALG, VALH, VALI, VALJ, VALK, VALL, VALM, VALN, VALO, VALP, VALQ, VALR, VALS, VALT, VALU + +=cut + field(VALA,DBF_NOACCESS) { prompt("Output value A") asl(ASL0) special(SPC_DBADDR) interest(2) extra("void *vala") + #=read Yes + #=write Yes + #=type Set by FTVA } field(VALB,DBF_NOACCESS) { prompt("Output value B") @@ -918,6 +1041,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valb") + #=read Yes + #=write Yes + #=type Set by FTVB } field(VALC,DBF_NOACCESS) { prompt("Output value C") @@ -925,6 +1051,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valc") + #=read Yes + #=write Yes + #=type Set by FTVC } field(VALD,DBF_NOACCESS) { prompt("Output value D") @@ -932,6 +1061,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *vald") + #=read Yes + #=write Yes + #=type Set by FTVD } field(VALE,DBF_NOACCESS) { prompt("Output value E") @@ -939,6 +1071,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *vale") + #=read Yes + #=write Yes + #=type Set by FTVE } field(VALF,DBF_NOACCESS) { prompt("Output value F") @@ -946,6 +1081,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valf") + #=read Yes + #=write Yes + #=type Set by FTVF } field(VALG,DBF_NOACCESS) { prompt("Output value G") @@ -953,6 +1091,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valg") + #=read Yes + #=write Yes + #=type Set by FTVG } field(VALH,DBF_NOACCESS) { prompt("Output value H") @@ -960,6 +1101,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valh") + #=read Yes + #=write Yes + #=type Set by FTVH } field(VALI,DBF_NOACCESS) { prompt("Output value I") @@ -967,6 +1111,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *vali") + #=read Yes + #=write Yes + #=type Set by FTVI } field(VALJ,DBF_NOACCESS) { prompt("Output value J") @@ -974,6 +1121,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valj") + #=read Yes + #=write Yes + #=type Set by FTVJ } field(VALK,DBF_NOACCESS) { prompt("Output value K") @@ -981,6 +1131,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valk") + #=read Yes + #=write Yes + #=type Set by FTVK } field(VALL,DBF_NOACCESS) { prompt("Output value L") @@ -988,6 +1141,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *vall") + #=read Yes + #=write Yes + #=type Set by FTVL } field(VALM,DBF_NOACCESS) { prompt("Output value M") @@ -995,6 +1151,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valm") + #=read Yes + #=write Yes + #=type Set by FTVM } field(VALN,DBF_NOACCESS) { prompt("Output value N") @@ -1002,6 +1161,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valn") + #=read Yes + #=write Yes + #=type Set by FTVN } field(VALO,DBF_NOACCESS) { prompt("Output value O") @@ -1009,6 +1171,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valo") + #=read Yes + #=write Yes + #=type Set by FTVO } field(VALP,DBF_NOACCESS) { prompt("Output value P") @@ -1016,6 +1181,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valp") + #=read Yes + #=write Yes + #=type Set by FTVP } field(VALQ,DBF_NOACCESS) { prompt("Output value Q") @@ -1023,6 +1191,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valq") + #=read Yes + #=write Yes + #=type Set by FTVQ } field(VALR,DBF_NOACCESS) { prompt("Output value R") @@ -1030,6 +1201,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valr") + #=read Yes + #=write Yes + #=type Set by FTVR } field(VALS,DBF_NOACCESS) { prompt("Output value S") @@ -1037,6 +1211,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *vals") + #=read Yes + #=write Yes + #=type Set by FTVS } field(VALT,DBF_NOACCESS) { prompt("Output value T") @@ -1044,6 +1221,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valt") + #=read Yes + #=write Yes + #=type Set by FTVT } field(VALU,DBF_NOACCESS) { prompt("Output value U") @@ -1051,6 +1231,9 @@ recordtype(aSub) { special(SPC_DBADDR) interest(2) extra("void *valu") + #=read Yes + #=write Yes + #=type Set by FTVU } field(OVLA,DBF_NOACCESS) { prompt("Old Output A") diff --git a/src/std/rec/aaiRecord.dbd b/src/std/rec/aaiRecord.dbd index fb921cfc4..3b6c5fb2c 100644 --- a/src/std/rec/aaiRecord.dbd +++ b/src/std/rec/aaiRecord.dbd @@ -19,6 +19,9 @@ recordtype(aai) { special(SPC_DBADDR) pp(TRUE) extra("void * val") + #=type DOUBLE[] + #=read Yes + #=write Yes } field(PREC,DBF_SHORT) { prompt("Display Precision") diff --git a/src/std/rec/aaoRecord.dbd b/src/std/rec/aaoRecord.dbd index 025920a48..861a16613 100644 --- a/src/std/rec/aaoRecord.dbd +++ b/src/std/rec/aaoRecord.dbd @@ -19,6 +19,9 @@ recordtype(aao) { special(SPC_DBADDR) pp(TRUE) extra("void * val") + #=type DOUBLE[] + #=read Yes + #=write Yes } field(PREC,DBF_SHORT) { prompt("Display Precision") diff --git a/src/std/rec/aiRecord.dbd b/src/std/rec/aiRecord.dbd deleted file mode 100644 index 0573768fd..000000000 --- a/src/std/rec/aiRecord.dbd +++ /dev/null @@ -1,255 +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(ai) { - include "dbCommon.dbd" - field(VAL,DBF_DOUBLE) { - prompt("Current EGU Value") - promptgroup(GUI_INPUTS) - asl(ASL0) - pp(TRUE) - } - field(INP,DBF_INLINK) { - prompt("Input Specification") - promptgroup(GUI_INPUTS) - interest(1) - } - field(PREC,DBF_SHORT) { - prompt("Display Precision") - promptgroup(GUI_DISPLAY) - interest(1) - prop(YES) - } - field(LINR,DBF_MENU) { - prompt("Linearization") - promptgroup(GUI_CONVERT) - special(SPC_LINCONV) - pp(TRUE) - interest(1) - menu(menuConvert) - } - field(EGUF,DBF_DOUBLE) { - prompt("Engineer Units Full") - promptgroup(GUI_CONVERT) - special(SPC_LINCONV) - pp(TRUE) - interest(1) - } - field(EGUL,DBF_DOUBLE) { - prompt("Engineer Units Low") - promptgroup(GUI_CONVERT) - special(SPC_LINCONV) - pp(TRUE) - interest(1) - } - field(EGU,DBF_STRING) { - prompt("Engineering Units") - promptgroup(GUI_DISPLAY) - interest(1) - size(16) - prop(YES) - } - field(HOPR,DBF_DOUBLE) { - prompt("High Operating Range") - promptgroup(GUI_DISPLAY) - interest(1) - prop(YES) - } - field(LOPR,DBF_DOUBLE) { - prompt("Low Operating Range") - promptgroup(GUI_DISPLAY) - interest(1) - prop(YES) - } - field(AOFF,DBF_DOUBLE) { - prompt("Adjustment Offset") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(1) - } - field(ASLO,DBF_DOUBLE) { - prompt("Adjustment Slope") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(1) - initial("1") - } - field(SMOO,DBF_DOUBLE) { - prompt("Smoothing") - promptgroup(GUI_CONVERT) - interest(1) - } - field(HIHI,DBF_DOUBLE) { - prompt("Hihi Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(LOLO,DBF_DOUBLE) { - prompt("Lolo Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(HIGH,DBF_DOUBLE) { - prompt("High Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(LOW,DBF_DOUBLE) { - prompt("Low Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(HHSV,DBF_MENU) { - prompt("Hihi Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(LLSV,DBF_MENU) { - prompt("Lolo Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(HSV,DBF_MENU) { - prompt("High Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(LSV,DBF_MENU) { - prompt("Low Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(HYST,DBF_DOUBLE) { - prompt("Alarm Deadband") - promptgroup(GUI_ALARMS) - interest(1) - } - field(AFTC,DBF_DOUBLE) { - prompt("Alarm Filter Time Constant") - promptgroup(GUI_ALARMS) - interest(1) - } - field(ADEL,DBF_DOUBLE) { - prompt("Archive Deadband") - promptgroup(GUI_DISPLAY) - interest(1) - } - field(MDEL,DBF_DOUBLE) { - prompt("Monitor Deadband") - promptgroup(GUI_DISPLAY) - interest(1) - } - field(LALM,DBF_DOUBLE) { - prompt("Last Value Alarmed") - special(SPC_NOMOD) - interest(3) - } - field(AFVL,DBF_DOUBLE) { - prompt("Alarm Filter Value") - special(SPC_NOMOD) - interest(3) - } - field(ALST,DBF_DOUBLE) { - prompt("Last Value Archived") - special(SPC_NOMOD) - interest(3) - } - field(MLST,DBF_DOUBLE) { - prompt("Last Val Monitored") - special(SPC_NOMOD) - interest(3) - } - field(ESLO,DBF_DOUBLE) { - prompt("Raw to EGU Slope") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(2) - initial("1") - } - field(EOFF,DBF_DOUBLE) { - prompt("Raw to EGU Offset") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(2) - } - field(ROFF,DBF_LONG) { - prompt("Raw Offset, obsolete") - pp(TRUE) - interest(2) - } - field(PBRK,DBF_NOACCESS) { - prompt("Ptrto brkTable") - special(SPC_NOMOD) - interest(4) - extra("void * pbrk") - } - field(INIT,DBF_SHORT) { - prompt("Initialized?") - special(SPC_NOMOD) - interest(3) - } - field(LBRK,DBF_SHORT) { - prompt("LastBreak Point") - special(SPC_NOMOD) - interest(3) - } - field(RVAL,DBF_LONG) { - prompt("Current Raw Value") - pp(TRUE) - } - field(ORAW,DBF_LONG) { - prompt("Previous Raw Value") - special(SPC_NOMOD) - interest(3) - } - field(SIOL,DBF_INLINK) { - prompt("Sim Input Specifctn") - promptgroup(GUI_INPUTS) - interest(1) - } - field(SVAL,DBF_DOUBLE) { - prompt("Simulation Value") - } - field(SIML,DBF_INLINK) { - prompt("Sim Mode Location") - promptgroup(GUI_INPUTS) - interest(1) - } - field(SIMM,DBF_MENU) { - prompt("Simulation Mode") - interest(1) - menu(menuSimm) - } - field(SIMS,DBF_MENU) { - prompt("Sim mode Alarm Svrty") - promptgroup(GUI_INPUTS) - interest(2) - menu(menuAlarmSevr) - } -} diff --git a/src/std/rec/aiRecord.dbd.pod b/src/std/rec/aiRecord.dbd.pod new file mode 100644 index 000000000..e3f1cfdae --- /dev/null +++ b/src/std/rec/aiRecord.dbd.pod @@ -0,0 +1,631 @@ +#************************************************************************* +# Copyright (c) 2013 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. +#************************************************************************* + +=title Analog Input Record (ai) + +This record type is normally used to obtain an analog value from a hardware +input and convert it to engineering units. +The record supports linear and break-point conversion to engineering units, +smoothing, alarm limits, alarm filtering, and graphics and control limits. + +=head2 Parameter Fields + +The record-specific fields are described below, grouped by functionality. + +=recordtype ai + +=cut + +recordtype(ai) { + +=head3 Input Specification + +These fields control where the record will read data from when it is processed: + +=fields DTYP, INP + +The DTYP field selects which device support layer should be responsible for +providing input data to the record. +The ai device support layers provided by EPICS Base are documented in the +L section. +External support modules may provide additional device support for this record +type. +If not set explicitly, the DTYP value defaults to the first device support that +is loaded for the record type, which will usually be the C support +that comes with Base. + +The INP link field contains a database or channel access link or provides +hardware address information that the device support uses to determine where the +input data should come from. +The format for the INP field value depends on the device support layer that is +selected by the DTYP field. +See L
for a description of the various hardware +address formats supported. + +=head3 Units Conversion + +These fields control if and how the raw input value gets converted into +engineering units: + +=fields RVAL, ROFF, ASLO, AOFF, LINR, ESLO, EOFF, EGUL, EGUF + +These fields are not used if the device support layer reads its value in +engineering units and puts it directly into the VAL field. +This applies to Soft Channel and Async Soft Channel device support, and is also +fairly common for GPIB and similar high-level device interfaces. + +If the device support sets the RVAL field, the LINR field controls how this gets +converted into engineering units and placed in the VAL field as follows: + +=over + +=item 1. +RVAL is converted to a double and ROFF is added to it. + +=item 2. +If ASLO is non-zero the value is multiplied by ASLO. + +=item 3. +AOFF is added. + +=item 4. +If LINR is C the units conversion is finished after the above +steps. + +=item 5. +If LINR is C or C, the value from step 3 above is multiplied by +ESLO and EOFF is added to complete the units conversion process. + +=item 6. +Any other value for LINR selects a particular breakpoint table to be used on the +value from step 3 above. + +=back + +The distinction between the C and C settings for the LINR field +are in how the conversion parameters are calculated: + +=over + +=item * +With C conversion the user must set EGUL and EGUF to the lowest and +highest possible engineering units values respectively that can be converted by +the hardware. +The device support knows the range of the raw data and calculates ESLO and EOFF +from them. + +=item * +C conversion requires the user to calculate the appropriate scaling and +offset factors and put them directly in ESLO and EOFF. + +=back + +=head3 Smoothing Filter + +This filter is usually only used if the device support sets the RVAL field and +the Units Conversion process is used. +Device support that directly sets the VAL field may implement the filter if +desired. + +The filter is controlled with a single parameter field: + +=fields SMOO + +The SMOO field should be set to a number between 0 and 1. +If set to zero the filter is not used (no smoothing), while if set to one the +result is infinite smoothing (the VAL field will never change). +The calculation performed is: + +=over + +VAL = VAL * SMOO + (1 - SMOO) * New Data + +=back + +where C was the result from the Units Conversion above. +This implements a first-order infinite impulse response (IIR) digital filter +with z-plane pole at SMOO. +The equivalent continuous-time filter time constant E is given by + +=over + +E = ET / ln(SMOO) + +=back + +where T is the time between record processing. + +=head3 Undefined Check + +If after applying the smoothing filter the VAL field contains a NaN +(Not-a-Number) value, the UDF field is set to a non-zero value, indicating that +the record value is undefined, which will trigger a C with severity +C. + +=fields UDF + +=head3 Operator Display Parameters + +These parameters are used to present meaningful data to the operator. +They do not affect the functioning of the record at all. + +=over + +=item * +DESC is a string that is usually used to briefly describe the record. + +=item * +EGU is a string of up to 16 characters naming the engineering units that the VAL +field represents. + +=item * +The HOPR and LOPR fields set the upper and lower display limits for the VAL, +HIHI, HIGH, LOW, and LOLO fields. + +=item * +The PREC field determines the floating point precision (i.e. the number of +digits to show after the decimal point) with which to display VAL and the other +DOUBLE fields. + +=back + +=fields DESC, EGU, HOPR, LOPR, PREC + +=head3 Alarm Limits + +The user configures limit alarms by putting numerical values into the HIHI, +HIGH, LOW and LOLO fields, and by setting the associated alarm severity in the +corresponding HHSV, HSV, LSV and LLSV menu fields. + +The HYST field controls hysteresis to prevent alarm chattering from an input +signal that is close to one of the limits and suffers from significant readout +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). + +=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, AFTC, LALM + +=head3 Monitor Parameters + +These parameters are used to determine when to send monitors placed on the VAL +field. +The monitors are sent when the current value exceeds the last transmitted value +by the appropriate deadband. +If these fields are set to zero, a monitor will be triggered every time the +value changes; if set to -1, a monitor will be sent every time the record is +processed. + +The ADEL field sets the deadband for archive monitors (C events), while +the MDEL field controls value monitors (C events). + +The remaining fields are used by the record at run-time to implement the record +monitoring functionality. + +=fields ADEL, MDEL, ALST, MLST, ORAW + +=cut + + include "dbCommon.dbd" + field(VAL,DBF_DOUBLE) { + prompt("Current EGU Value") + promptgroup(GUI_INPUTS) + asl(ASL0) + pp(TRUE) + } + field(INP,DBF_INLINK) { + prompt("Input Specification") + promptgroup(GUI_INPUTS) + interest(1) + } + field(PREC,DBF_SHORT) { + prompt("Display Precision") + promptgroup(GUI_DISPLAY) + interest(1) + prop(YES) + } + field(LINR,DBF_MENU) { + prompt("Linearization") + promptgroup(GUI_CONVERT) + special(SPC_LINCONV) + pp(TRUE) + interest(1) + menu(menuConvert) + } + field(EGUF,DBF_DOUBLE) { + prompt("Engineer Units Full") + promptgroup(GUI_CONVERT) + special(SPC_LINCONV) + pp(TRUE) + interest(1) + } + field(EGUL,DBF_DOUBLE) { + prompt("Engineer Units Low") + promptgroup(GUI_CONVERT) + special(SPC_LINCONV) + pp(TRUE) + interest(1) + } + field(EGU,DBF_STRING) { + prompt("Engineering Units") + promptgroup(GUI_DISPLAY) + interest(1) + size(16) + prop(YES) + } + field(HOPR,DBF_DOUBLE) { + prompt("High Operating Range") + promptgroup(GUI_DISPLAY) + interest(1) + prop(YES) + } + field(LOPR,DBF_DOUBLE) { + prompt("Low Operating Range") + promptgroup(GUI_DISPLAY) + interest(1) + prop(YES) + } + field(AOFF,DBF_DOUBLE) { + prompt("Adjustment Offset") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(1) + } + field(ASLO,DBF_DOUBLE) { + prompt("Adjustment Slope") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(1) + initial("1") + } + field(SMOO,DBF_DOUBLE) { + prompt("Smoothing") + promptgroup(GUI_CONVERT) + interest(1) + } + field(HIHI,DBF_DOUBLE) { + prompt("Hihi Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(LOLO,DBF_DOUBLE) { + prompt("Lolo Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(HIGH,DBF_DOUBLE) { + prompt("High Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(LOW,DBF_DOUBLE) { + prompt("Low Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(HHSV,DBF_MENU) { + prompt("Hihi Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(LLSV,DBF_MENU) { + prompt("Lolo Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(HSV,DBF_MENU) { + prompt("High Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(LSV,DBF_MENU) { + prompt("Low Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(HYST,DBF_DOUBLE) { + prompt("Alarm Deadband") + promptgroup(GUI_ALARMS) + interest(1) + } + field(AFTC,DBF_DOUBLE) { + prompt("Alarm Filter Time Constant") + promptgroup(GUI_ALARMS) + interest(1) + } + field(ADEL,DBF_DOUBLE) { + prompt("Archive Deadband") + promptgroup(GUI_DISPLAY) + interest(1) + } + field(MDEL,DBF_DOUBLE) { + prompt("Monitor Deadband") + promptgroup(GUI_DISPLAY) + interest(1) + } + field(LALM,DBF_DOUBLE) { + prompt("Last Value Alarmed") + special(SPC_NOMOD) + interest(3) + } + field(AFVL,DBF_DOUBLE) { + prompt("Alarm Filter Value") + special(SPC_NOMOD) + interest(3) + } + field(ALST,DBF_DOUBLE) { + prompt("Last Value Archived") + special(SPC_NOMOD) + interest(3) + } + field(MLST,DBF_DOUBLE) { + prompt("Last Val Monitored") + special(SPC_NOMOD) + interest(3) + } + field(ESLO,DBF_DOUBLE) { + prompt("Raw to EGU Slope") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(2) + initial("1") + } + field(EOFF,DBF_DOUBLE) { + prompt("Raw to EGU Offset") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(2) + } + field(ROFF,DBF_LONG) { + prompt("Raw Offset, obsolete") + pp(TRUE) + interest(2) + } + field(PBRK,DBF_NOACCESS) { + prompt("Ptrto brkTable") + special(SPC_NOMOD) + interest(4) + extra("void * pbrk") + } + field(INIT,DBF_SHORT) { + prompt("Initialized?") + special(SPC_NOMOD) + interest(3) + } + field(LBRK,DBF_SHORT) { + prompt("LastBreak Point") + special(SPC_NOMOD) + interest(3) + } + field(RVAL,DBF_LONG) { + prompt("Current Raw Value") + pp(TRUE) + } + field(ORAW,DBF_LONG) { + prompt("Previous Raw Value") + special(SPC_NOMOD) + interest(3) + } + +=head3 Simulation Mode + +The record provides several fields to support simulation of absent hardware. +If the SIML field is set it is used to read a value into the SIMM field, which +controls whether simulation is used or not: + +=over + +=item * +SIMM must be zero (C) for the record to request a value from the device +support. + +=item * +If SIMM is C and the SIOL link field is set, a simlated value in +engineering units is read using the link into the SVAL field, from where it will +subsequently be copied into the VAL field. + +=item * +If SIMM is C the SIOL link is still read into SVAL, but is then truncated +and copied into the RVAL field. +The L process described above is then followed to transform +the simulated raw value into engineering units. + +=back + +The SIMS field can be set to give the record an alarm severity while it is in +simulation mode. + +=fields SIML, SIMM, SIOL, SVAL, SIMS + +=cut + + field(SIOL,DBF_INLINK) { + prompt("Sim. Input Specification") + promptgroup(GUI_INPUTS) + interest(1) + } + field(SVAL,DBF_DOUBLE) { + prompt("Simulation Value") + } + field(SIML,DBF_INLINK) { + prompt("Sim. Mode Location") + promptgroup(GUI_INPUTS) + interest(1) + } + field(SIMM,DBF_MENU) { + prompt("Simulation Mode") + interest(1) + menu(menuSimm) + } + field(SIMS,DBF_MENU) { + prompt("Simulation Mode Severity") + promptgroup(GUI_INPUTS) + interest(2) + menu(menuAlarmSevr) + } +} + +=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)(aiRecord *prec); + long (*get_ioint_info)(int cmd, aiRecord *prec, IOSCANPVT *piosl); + long (*read_ai)(aiRecord *prec); + long (*special_linconv)(aiRecord *prec, int after); + } aidset; + +The module must set C to at least 6, and provide a pointer to its +C routine; the other function pointers may be C if their +associated functionality is not required for this support layer. +Most device supports also provide an C routine to configure the +record instance and connect it to the hardware or driver support layer, and if +using the record's L features they set C +as well. + +The individual routines are described below. + +=head3 Device Support Routines + +=head4 long report(int level) + +This optional routine is called by the IOC command C 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 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 calls are made, with +the integer parameter C set to 0. +The second call happens after all of the C calls have been made, +with C set to 1. + +=head4 long init_record(aiRecord *prec) + +This optional routine is called by the record initialization code for each ai +record instance that has its DTYP field set to use this device support. +It is normally used to check that the INP address is the expected type and that +it points to a valid device; to allocate any record-specific buffer space and +other memory; and to connect any communication channels needed for the +C routine to work properly. + +If the record type's unit conversion features are used, the C +routine should calculate appropriate values for the ESLO and EOFF fields from +the EGUL and EGUF field values. +This calculation only has to be performed if the record's LINR field is set to +C, but it is not necessary to check that condition first. +This same calculation takes place in the C routine, so the +implementation can usually just call that routine to perform the task. + +=head4 long get_ioint_info(int cmd, aiRecord *prec, IOSCANPVT *piosl) + +This optional routine is called whenever the record's SCAN field is being +changed to or from the value C to find out which I/O Interrupt Scan +list the record should be added to or deleted from. +If this routine is not provided, it will not be possible to set the SCAN field +to the value C at all. + +The C parameter is zero when the record is being added to the scan list, +and one when it is being removed from the list. +The routine must determine which interrupt source the record should be connected +to, which it indicates by the scan list that it points the location at C<*piosl> +to before returning. +It can prevent the SCAN field from being changed at all by returning a non-zero +value to its caller. + +In most cases the device support will create the I/O Interrupt Scan lists that +it returns for itself, by calling C once for +each separate interrupt source. +That routine allocates memory and inializes the list, then passes back a pointer +to the new list in the location at C<*piosl>. + +When the device support receives notification that the interrupt has occurred, +it announces that to the IOC by calling C +which will arrange for the appropriate records to be processed in a suitable +thread. +The C routine is safe to call from an interrupt service routine +on embedded architectures (vxWorks and RTEMS). + +=head4 long read_ai(aiRecord *prec) + +This essential routine is called when the record wants a new value from the +addressed device. +It is responsible for performing (or at least initiating) a read operation, and +(eventually) returning its value to the record. + +... PACT and asynchronous processing ... + +... return value ... + +=head4 long special_linconv(aiRecord *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 routine returning a +status value of zero. +It is called by the record code whenever any of the the fields LINR, EGUL or +EGUF are modified and LINR has the value C. +The routine must calculate and set the fields EOFF and ESLO appropriately based +on the new values of EGUL and EGUF. + +These calculations can be expressed in terms of the minimum and maximum raw +values that the C routine can put in the RVAL field. +When RVAL is set to I the VAL field will be set to EGUF, and when RVAL +is set to I the VAL field will become EGUL. + +The fomulae to use are: + +=over + +EOFF = (I * EGUL E I * EGUF) / +(I E I) + +ESLO = (EGUF E EGUL) / (I E I) + +=back + +Note that the record support sets EOFF to EGUL before calling this routine, +which is a very common case (when I is zero). + +=head3 Extended Device Support + +... + +=cut diff --git a/src/std/rec/aoRecord.dbd b/src/std/rec/aoRecord.dbd deleted file mode 100644 index 2d0f36450..000000000 --- a/src/std/rec/aoRecord.dbd +++ /dev/null @@ -1,308 +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. -#************************************************************************* -menu(aoOIF) { - choice(aoOIF_Full,"Full") - choice(aoOIF_Incremental,"Incremental") -} -recordtype(ao) { - include "dbCommon.dbd" - field(VAL,DBF_DOUBLE) { - prompt("Desired Output") - promptgroup(GUI_OUTPUT) - asl(ASL0) - pp(TRUE) - } - field(OVAL,DBF_DOUBLE) { - prompt("Output Value") - } - field(OUT,DBF_OUTLINK) { - prompt("Output Specification") - promptgroup(GUI_OUTPUT) - interest(1) - } - field(OROC,DBF_DOUBLE) { - prompt("Output Rate of Chang") - promptgroup(GUI_OUTPUT) - interest(1) - } - field(DOL,DBF_INLINK) { - prompt("Desired Output Loc") - promptgroup(GUI_OUTPUT) - interest(1) - } - field(OMSL,DBF_MENU) { - prompt("Output Mode Select") - promptgroup(GUI_OUTPUT) - interest(1) - menu(menuOmsl) - } - field(OIF,DBF_MENU) { - prompt("Out Full/Incremental") - promptgroup(GUI_OUTPUT) - interest(1) - menu(aoOIF) - } - field(PREC,DBF_SHORT) { - prompt("Display Precision") - promptgroup(GUI_DISPLAY) - interest(1) - prop(YES) - } - field(LINR,DBF_MENU) { - prompt("Linearization") - promptgroup(GUI_CONVERT) - special(SPC_LINCONV) - pp(TRUE) - interest(1) - menu(menuConvert) - } - field(EGUF,DBF_DOUBLE) { - prompt("Eng Units Full") - promptgroup(GUI_CONVERT) - special(SPC_LINCONV) - pp(TRUE) - interest(1) - } - field(EGUL,DBF_DOUBLE) { - prompt("Eng Units Low") - promptgroup(GUI_CONVERT) - special(SPC_LINCONV) - pp(TRUE) - interest(1) - } - field(EGU,DBF_STRING) { - prompt("Engineering Units") - promptgroup(GUI_DISPLAY) - interest(1) - size(16) - prop(YES) - } - field(ROFF,DBF_LONG) { - prompt("Raw Offset, obsolete") - pp(TRUE) - interest(2) - } - field(EOFF,DBF_DOUBLE) { - prompt("EGU to Raw Offset") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(2) - } - field(ESLO,DBF_DOUBLE) { - prompt("EGU to Raw Slope") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(2) - initial("1") - } - field(DRVH,DBF_DOUBLE) { - prompt("Drive High Limit") - promptgroup(GUI_OUTPUT) - pp(TRUE) - interest(1) - prop(YES) - } - field(DRVL,DBF_DOUBLE) { - prompt("Drive Low Limit") - promptgroup(GUI_OUTPUT) - pp(TRUE) - interest(1) - prop(YES) - } - field(HOPR,DBF_DOUBLE) { - prompt("High Operating Range") - promptgroup(GUI_DISPLAY) - interest(1) - prop(YES) - } - field(LOPR,DBF_DOUBLE) { - prompt("Low Operating Range") - promptgroup(GUI_DISPLAY) - interest(1) - prop(YES) - } - field(AOFF,DBF_DOUBLE) { - prompt("Adjustment Offset") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(1) - } - field(ASLO,DBF_DOUBLE) { - prompt("Adjustment Slope") - promptgroup(GUI_CONVERT) - pp(TRUE) - interest(1) - } - field(HIHI,DBF_DOUBLE) { - prompt("Hihi Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(LOLO,DBF_DOUBLE) { - prompt("Lolo Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(HIGH,DBF_DOUBLE) { - prompt("High Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(LOW,DBF_DOUBLE) { - prompt("Low Alarm Limit") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - } - field(HHSV,DBF_MENU) { - prompt("Hihi Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(LLSV,DBF_MENU) { - prompt("Lolo Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(HSV,DBF_MENU) { - prompt("High Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(LSV,DBF_MENU) { - prompt("Low Severity") - promptgroup(GUI_ALARMS) - pp(TRUE) - interest(1) - prop(YES) - menu(menuAlarmSevr) - } - field(HYST,DBF_DOUBLE) { - prompt("Alarm Deadband") - promptgroup(GUI_ALARMS) - interest(1) - } - field(ADEL,DBF_DOUBLE) { - prompt("Archive Deadband") - promptgroup(GUI_DISPLAY) - interest(1) - } - field(MDEL,DBF_DOUBLE) { - prompt("Monitor Deadband") - promptgroup(GUI_DISPLAY) - interest(1) - } - field(RVAL,DBF_LONG) { - prompt("Current Raw Value") - pp(TRUE) - } - field(ORAW,DBF_LONG) { - prompt("Previous Raw Value") - special(SPC_NOMOD) - interest(3) - } - field(RBV,DBF_LONG) { - prompt("Readback Value") - special(SPC_NOMOD) - } - field(ORBV,DBF_LONG) { - prompt("Prev Readback Value") - special(SPC_NOMOD) - interest(3) - } - field(PVAL,DBF_DOUBLE) { - prompt("Previous value") - special(SPC_NOMOD) - interest(3) - } - field(LALM,DBF_DOUBLE) { - prompt("Last Value Alarmed") - special(SPC_NOMOD) - interest(3) - } - field(ALST,DBF_DOUBLE) { - prompt("Last Value Archived") - special(SPC_NOMOD) - interest(3) - } - field(MLST,DBF_DOUBLE) { - prompt("Last Val Monitored") - special(SPC_NOMOD) - interest(3) - } - field(PBRK,DBF_NOACCESS) { - prompt("Ptrto brkTable") - special(SPC_NOMOD) - interest(4) - extra("void * pbrk") - } - field(INIT,DBF_SHORT) { - prompt("Initialized?") - special(SPC_NOMOD) - interest(3) - } - field(LBRK,DBF_SHORT) { - prompt("LastBreak Point") - special(SPC_NOMOD) - interest(3) - } - field(SIOL,DBF_OUTLINK) { - prompt("Sim Output Specifctn") - promptgroup(GUI_INPUTS) - interest(1) - } - field(SIML,DBF_INLINK) { - prompt("Sim Mode Location") - promptgroup(GUI_INPUTS) - interest(1) - } - field(SIMM,DBF_MENU) { - prompt("Simulation Mode") - interest(1) - menu(menuYesNo) - } - field(SIMS,DBF_MENU) { - prompt("Sim mode Alarm Svrty") - promptgroup(GUI_INPUTS) - interest(2) - menu(menuAlarmSevr) - } - field(IVOA,DBF_MENU) { - prompt("INVALID output action") - promptgroup(GUI_OUTPUT) - interest(2) - menu(menuIvoa) - } - field(IVOV,DBF_DOUBLE) { - prompt("INVALID output value") - promptgroup(GUI_OUTPUT) - interest(2) - } - field(OMOD,DBF_UCHAR) { - prompt("Was OVAL modified?") - special(SPC_NOMOD) - } -} diff --git a/src/std/rec/aoRecord.dbd.pod b/src/std/rec/aoRecord.dbd.pod new file mode 100644 index 000000000..27e156ae1 --- /dev/null +++ b/src/std/rec/aoRecord.dbd.pod @@ -0,0 +1,917 @@ +#************************************************************************* +# Copyright (c) 2013 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. +#************************************************************************* + +=title Analog Output Record (ao) + +This record type is normally used to send an analog value to an output device, +converting it from engineering units into an integer value if necessary. +The record supports alarm and drive limits, rate-of-change limiting, output +value integration, linear and break-point conversion from engineering units, and +graphics and control limits. + +=head2 Record-specific Menus + +=head3 Menu aoOIF + +The OIF field which uses this menu controls whether the record acts as an +integrator (C) or not (C). + +=menu aoOIF + +=head2 Parameter Fields + +The record-specific fields are described below. + +=recordtype ao + +=cut + +menu(aoOIF) { + choice(aoOIF_Full,"Full") + choice(aoOIF_Incremental,"Incremental") +} + +recordtype(ao) { + +=head3 Output Value Determination + +These fields control how the record determines the value to be output when it +gets processed: + +=fields OMSL, DOL, OIF, PVAL, DRVH, DRVL, VAL, OROC, OVAL + +The following steps are performed in order during record processing. + +=head4 Fetch Value, Integrate + +The OMSL menu field is used to determine whether the DOL link and OIF menu +fields should be used during processing or not: + +=over + +=item * +If OMSL is C the DOL and OIF fields are not used. +The new output value is taken from the VAL field, which may have been set from +elsewhere. + +=item * +If OMSL is C the DOL link field is read to obtain a value; if OIF +is C and the DOL link was read successfully, the record's previous +output value PVAL is added to it. + +=back + +=head4 Drive Limits + +The output value is now clipped to the range DRVL to DRVH inclusive, provided +that DRVH > DRVL. +The result is copied into both the VAL and PVAL fields. + +=head4 Limit Rate of Change + +If the OROC field is not zero, the VAL field is now adjusted so it is no more +than OROC different to the previous output value given in OVAL. +OROC thus determines the maximum change in the output value that can occur each +time the record gets processed. +The result is copied into the OVAL field, which is used as the input to the +following Units Conversion processing stage. + +=head3 Units Conversion + +... + + +For analog output records that do not use the Soft Channel device support +routine, the specified conversions (if any) are performed on the OVAL field and +the resulting value in the RVAL field is sent to the address contained in the +output link after it is adjusted by the values in the AOFF and ASLO fields. + +=fields LINR, RVAL, ROFF, EGUF, EGUL, AOFF, ASLO, ESLO, EOFF + +=head4 Conversion Related Fields and the Conversion Process + +Except for analog outputs that use Soft Channel device support, the LINR field +determines if a conversion is performed and which conversion algorithm is used +to convert OVAL to RVAL. + +The LINR field can specify C or C for linear conversions, +C for no conversions at all, or the name of a breakpoint table +such as C 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. + +=over + +=item EGUF, EGUF + +The user must calculate these fields when configuring the database for records +that use C 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 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. +These values must be supplied by the user when LINR specifies C. +Used only when LINR is C or C. + +=item ROFF + +This field can be used to offset the raw value generated by the conversion +process, which is needed for some kinds of hardware. + +=back + +Conversion proceeds as follows: + +=over + +=item 1. If LINR==LINEAR or LINR==SLOPE, then X = (VAL - EOFF) / ESLO, +else if LINR==NO_CONVERSION, then X = VAL, +else X is obtained via breakpoint table. + +=item 2. X = (X - AOFF) / ASLO + +=item 3. RVAL = round(X) - ROFF + +=back + +To see how the Raw Soft Channel device support routine uses these +fields, see L below for more +information. + +=head3 Output Specification + +The analog output record sends its desired output to the address in the +OUT field. For analog outputs that write their values to devices, the +OUT field must specify the address of the I/O card. In addition, the +DTYP field must contain the name of the device support module. Be aware +that the address format differs according to the I/O bus used. See +Address Specification for information on the format of hardware +addresses. The user can see a list of the device support modules +currently supported at the user's local site by using the dbst utility +in R3.13. + +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. + +=fields DTYP, OUT + +=head3 Operator Display Parameters + +These parameters are used to present meaningful data to the operator. +They display the value and other parameters of the analog output either +textually or graphically. + +EGU is a string of up to 16 characters describing the units that the +analog output measures. It is retrieved by the get_units record support +routine. + +The HOPR and LOPR fields set the upper and lower display limits for the +VAL, OVAL, PVAL, HIHI, HIGH, LOW, and LOLO fields. Both the +get_graphic_double and get_control_double record support routines +retrieve these fields. If these values are defined, they must be in the +range: DRVL E= LOPR E= HOPR E= DRVH. + +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. + +=fields EGU, HOPR, LOPR, PREC, NAME, DESC + +=head3 Alarm Parameters + +The possible alarm conditions for analog outputs are the SCAN, READ, +INVALID and limit alarms. The SCAN, READ, and INVALID alarms are called +by the record or device support routines. + +The limit alarms are configured by the user in the HIHI, LOLO, HIGH, +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 +alarms that are common to all record types. + +=fields HIHI, HIGH, LOW, LOLO, HHSV, HSV, LSV, LLSV, HYST, IVOA, IVOV + +=head3 Monitor Parameters + +These parameters are used to specify deadbands for monitors on the VAL +field. The monitors are sent when the value field exceeds the last +monitored field by the specified deadband. If these fields have a value +of zero, everytime the value changes, a monitor will be triggered; if +they have a value of -1, everytime the record is processed, monitors +are triggered. ADEL is the deadband for archive monitors, and MDEL the +deadband for all other types of monitors. See Monitor Specification for +a complete explanation of monitors. + +=fields ADEL, MDEL + +=head3 Run-time and Simulation Mode Parameters + +These parameters are used by the run-time code for processing the +analog output. They are not configurable. They represent the current +state of the record. The record support routines use some of them for +more efficient processing. + +The ORAW field is used to decide if monitors should be triggered for +RVAL when monitors are triggered for VAL. The RBV field is the actual +read back value obtained from the hardware itself or from the +associated device driver. It is the responsibility of the device +support routine to give this field a value. + +ORBV is used to decide if monitors should be triggered for RBV at the +same time monitors are triggered for changes in VAL. + +The LALM, MLST, and ALST fields are used to implement the hysteresis +factors for monitor callbacks. + +The INIT field is used to initialize the LBRK field and for smoothing. + +The PBRK field contains a pointer to the current breakpoint table (if +any), and LBRK contains a pointer to the last breakpoint table used. + +The OMOD field indicates whether OVAL differs from VAL. It will be +different if VAL or OVAL have changed since the last time the record +was processed, or if VAL has been adjusted by OROC during the current +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. + +=fields SIOL, SIML, SIMM, SIMS + +=cut + + include "dbCommon.dbd" + field(VAL,DBF_DOUBLE) { + prompt("Desired Output") + promptgroup(GUI_OUTPUT) + asl(ASL0) + pp(TRUE) + } + field(OVAL,DBF_DOUBLE) { + prompt("Output Value") + } + field(OUT,DBF_OUTLINK) { + prompt("Output Specification") + promptgroup(GUI_OUTPUT) + interest(1) + } + field(OROC,DBF_DOUBLE) { + prompt("Output Rate of Change") + promptgroup(GUI_OUTPUT) + interest(1) + } + field(DOL,DBF_INLINK) { + prompt("Desired Output Loc") + promptgroup(GUI_OUTPUT) + interest(1) + } + field(OMSL,DBF_MENU) { + prompt("Output Mode Select") + promptgroup(GUI_OUTPUT) + interest(1) + menu(menuOmsl) + } + field(OIF,DBF_MENU) { + prompt("Out Full/Incremental") + promptgroup(GUI_OUTPUT) + interest(1) + menu(aoOIF) + } + field(PREC,DBF_SHORT) { + prompt("Display Precision") + promptgroup(GUI_DISPLAY) + interest(1) + prop(YES) + } + field(LINR,DBF_MENU) { + prompt("Linearization") + promptgroup(GUI_CONVERT) + special(SPC_LINCONV) + pp(TRUE) + interest(1) + menu(menuConvert) + } + field(EGUF,DBF_DOUBLE) { + prompt("Eng Units Full") + promptgroup(GUI_CONVERT) + special(SPC_LINCONV) + pp(TRUE) + interest(1) + } + field(EGUL,DBF_DOUBLE) { + prompt("Eng Units Low") + promptgroup(GUI_CONVERT) + special(SPC_LINCONV) + pp(TRUE) + interest(1) + } + field(EGU,DBF_STRING) { + prompt("Engineering Units") + promptgroup(GUI_DISPLAY) + interest(1) + size(16) + prop(YES) + } + field(ROFF,DBF_LONG) { + prompt("Raw Offset, obsolete") + pp(TRUE) + interest(2) + } + field(EOFF,DBF_DOUBLE) { + prompt("EGU to Raw Offset") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(2) + } + field(ESLO,DBF_DOUBLE) { + prompt("EGU to Raw Slope") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(2) + initial("1") + } + field(DRVH,DBF_DOUBLE) { + prompt("Drive High Limit") + promptgroup(GUI_OUTPUT) + pp(TRUE) + interest(1) + prop(YES) + } + field(DRVL,DBF_DOUBLE) { + prompt("Drive Low Limit") + promptgroup(GUI_OUTPUT) + pp(TRUE) + interest(1) + prop(YES) + } + field(HOPR,DBF_DOUBLE) { + prompt("High Operating Range") + promptgroup(GUI_DISPLAY) + interest(1) + prop(YES) + } + field(LOPR,DBF_DOUBLE) { + prompt("Low Operating Range") + promptgroup(GUI_DISPLAY) + interest(1) + prop(YES) + } + field(AOFF,DBF_DOUBLE) { + prompt("Adjustment Offset") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(1) + } + field(ASLO,DBF_DOUBLE) { + prompt("Adjustment Slope") + promptgroup(GUI_CONVERT) + pp(TRUE) + interest(1) + } + field(HIHI,DBF_DOUBLE) { + prompt("Hihi Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(LOLO,DBF_DOUBLE) { + prompt("Lolo Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(HIGH,DBF_DOUBLE) { + prompt("High Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(LOW,DBF_DOUBLE) { + prompt("Low Alarm Limit") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + } + field(HHSV,DBF_MENU) { + prompt("Hihi Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(LLSV,DBF_MENU) { + prompt("Lolo Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(HSV,DBF_MENU) { + prompt("High Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(LSV,DBF_MENU) { + prompt("Low Severity") + promptgroup(GUI_ALARMS) + pp(TRUE) + interest(1) + prop(YES) + menu(menuAlarmSevr) + } + field(HYST,DBF_DOUBLE) { + prompt("Alarm Deadband") + promptgroup(GUI_ALARMS) + interest(1) + } + field(ADEL,DBF_DOUBLE) { + prompt("Archive Deadband") + promptgroup(GUI_DISPLAY) + interest(1) + } + field(MDEL,DBF_DOUBLE) { + prompt("Monitor Deadband") + promptgroup(GUI_DISPLAY) + interest(1) + } + field(RVAL,DBF_LONG) { + prompt("Current Raw Value") + pp(TRUE) + } + field(ORAW,DBF_LONG) { + prompt("Previous Raw Value") + special(SPC_NOMOD) + interest(3) + } + field(RBV,DBF_LONG) { + prompt("Readback Value") + special(SPC_NOMOD) + } + field(ORBV,DBF_LONG) { + prompt("Prev Readback Value") + special(SPC_NOMOD) + interest(3) + } + field(PVAL,DBF_DOUBLE) { + prompt("Previous value") + special(SPC_NOMOD) + interest(3) + } + field(LALM,DBF_DOUBLE) { + prompt("Last Value Alarmed") + special(SPC_NOMOD) + interest(3) + } + field(ALST,DBF_DOUBLE) { + prompt("Last Value Archived") + special(SPC_NOMOD) + interest(3) + } + field(MLST,DBF_DOUBLE) { + prompt("Last Val Monitored") + special(SPC_NOMOD) + interest(3) + } + field(PBRK,DBF_NOACCESS) { + prompt("Ptrto brkTable") + special(SPC_NOMOD) + interest(4) + extra("void * pbrk") + } + field(INIT,DBF_SHORT) { + prompt("Initialized?") + special(SPC_NOMOD) + interest(3) + } + field(LBRK,DBF_SHORT) { + prompt("LastBreak Point") + special(SPC_NOMOD) + interest(3) + } + field(SIOL,DBF_OUTLINK) { + prompt("Sim Output Specifctn") + promptgroup(GUI_INPUTS) + interest(1) + } + field(SIML,DBF_INLINK) { + prompt("Sim Mode Location") + promptgroup(GUI_INPUTS) + interest(1) + } + field(SIMM,DBF_MENU) { + prompt("Simulation Mode") + interest(1) + menu(menuYesNo) + } + field(SIMS,DBF_MENU) { + prompt("Sim mode Alarm Svrty") + promptgroup(GUI_INPUTS) + interest(2) + menu(menuAlarmSevr) + } + field(IVOA,DBF_MENU) { + prompt("INVALID output action") + promptgroup(GUI_OUTPUT) + interest(2) + menu(menuIvoa) + } + field(IVOV,DBF_DOUBLE) { + prompt("INVALID output value") + promptgroup(GUI_OUTPUT) + interest(2) + } + field(OMOD,DBF_UCHAR) { + prompt("Was OVAL modified?") + special(SPC_NOMOD) + } +} + +=head2 Record Support + +=head3 Record Support Routines + +The following are the record support routines that would be of interest +to an application developer. Other routines are the get_units, +get_precision, get_graphic_double, and get_control_double routines. + +=over + +=item init_record + +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. + +This routine next checks to see that device support is available. If +DOL is a constant, then VAL is initialized with its value and UDF is +set to FALSE. + +The routine next checks to see if the device support write routine is +defined. If either device support or the device support write routine +does not exist, an error message is issued and processing is +terminated. + +For compatibility with old device supports that don't know EOFF, if +both EOFF and ESLO have their default value, EOFF is set to EGUL. + +If device support includes init_record, it is called. + +INIT is set TRUE. This causes PBRK, LBRK, and smoothing to be +re-initialized. If "backwards" linear conversion is requested, then VAL +is computed from RVAL using the algorithm: + + VAL = ((RVAL+ROFF) * ASLO + AOFF) * ESLO + EOFF + +and UDF is set to FALSE. + +For breakpoint conversion, a call is made to cvtEngToRawBpt and UDF is +then set to FALSE. PVAL is set to VAL. + +=item process + +See next section. + +=item special + +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 +called. + +INIT is set TRUE. This causes PBRK, LBRK, and smoothing to be +re-initialized. + +=item get_value + +Fills in the values of struct valueDes so that they refer to VAL. + +=item get_alarm_double + +Sets the following values: + + upper_alarm_limit = HIHI + upper_warning_limit = HIGH + lower_warning_limit = LOW + lower_alarm_limit = LOLO + +=back + +=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. Check PACT: If PACT is FALSE call fetch_values and convert +which perform the following steps: + +=over + +=item * fetch_values: + +=over + +=item * if DOL is DB_LINK and OMSL is CLOSED_LOOP then get value from +DOL + +=item * if OIF is INCREMENTAL then set value = value + VAL else value = +VAL + +=back + +=item * convert: + +=over + +=item * If Drive limits are defined force value to be within limits + +=item * Set VAL equal to value + +=item * Set UDF to FALSE. + +=item * If OVAL is undefined set it equal to value + +=item * If OROC is defined and not 0 make |value-OVAL| E=OROC + +=item * Set OVAL equal to value + +=item * Compute RVAL from OVAL. using linear or break point table +conversion. For linear conversions the algorithm is RVAL = +(OVAL-EOFF)/ESLO. + +=item * For break point table conversion a call is made to +cvtEngToRawBpt. + +=item * After that, for all conversion types AOFF, ASLO, and ROFF are +calculated in, using the formula RVAL = (RVAL -AOFF) / ASLO - ROFF. + +=back + +=back + +=item 3. Check alarms: This routine checks to see if the new VAL causes +the alarm status and severity to change. If so, NSEV, NSTA and y are +set. It also honors the alarm hysteresis factor (HYST). Thus the value +must change by at least HYST before the alarm status and severity is +reduced. + +=item 4. Check severity and write the new value. See Invalid Alarm +Output Action for details on how invalid alarms affect output records. + +=item 5. If PACT has been changed to TRUE, the device support write +output routine has started but has not completed writing the new value. +In this case, the processing routine merely returns, leaving PACT TRUE. + +=item 6. 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 ADEL and MDEL +conditions are met. + +=item * Monitors for RVAL and for RBV are checked whenever other +monitors are invoked. + +=item * NSEV and NSTA are reset to 0. + +=back + +=item 7. Scan forward link if necessary, set PACT and INIT FALSE, and +return. + +=back + +=head2 Device Support + +=head3 Fields Of Interest To Device Support + +Each analog output record must have an associated set of device support +routines. The primary responsibility of the device support routines is +to output a new value whenever write_ao is called. The device support +routines are primarily interested in the following fields: + +=over + +=item * +PACT E Process Active, used to indicate asynchronous completion + +=item * +DPVT E Device Private, reserved for device support to use + +=item * +OUT E Output Link, provides addressing information + +=item * +EGUF E Engineering Units Full + +=item * +EGUL E Engineering Units Low + +=item * +ESLO E Engineering Unit Slope + +=item * +EOFF E Engineering Unit Offset + +=item * +OVAL E Output Value, in Engineering units + +=item * +RVAL E Raw Output Value, after conversion + +=back + +=head3 Device Support routines + +Device support consists of the following routines: + +=over + +=item C + +This optional routine is called by the IOC command C 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 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. + +=item C + +This optional routine is called twice at IOC initialization time. +The first call happens before any of the C calls are made, with +the integer parameter C set to 0. +The second call happens after all of the C calls have been made, +with C set to 1. + +=item C + +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. +It is normally used to check that the OUT address has the expected type and +points to a valid device; to allocate any record-specific buffer space and +other memory; and to connect any communication channels needed for the +C routine to work properly. + +If the record type's unit conversion features are used, the C +routine should calculate appropriate values for the ESLO and EOFF fields from +the EGUL and EGUF field values. +This calculation only has to be performed if the record's LINR field is set to +C, but it is not necessary to check that condition first. +This same calculation takes place in the C routine, so the +implementation can usually just call that routine to perform the task. + +If the the last output value can be read back from the hardware, this routine +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 + +This optional routine is called whenever the record's SCAN field is being +changed to or from the value C to find out which I/O Interrupt Scan +list the record should be added to or deleted from. +If this routine is not provided, it will not be possible to set the SCAN field +to the value C at all. + +The C parameter is zero when the record is being added to the scan list, +and one when it is being removed from the list. +The routine must determine which interrupt source the record should be connected +to, which it indicates by the scan list that it points the location at C<*piosl> +to before returning. +It can prevent the SCAN field from being changed at all by returning a non-zero +value to its caller. + +In most cases the device support will create the I/O Interrupt Scan lists that +it returns for itself, by calling C once for +each separate interrupt source. +That API allocates memory and inializes the list, then passes back a pointer to +the new list in the location at C<*piosl>. +When the device support receives notification that the interrupt has occurred, +it announces that to the IOC by calling C +which will arrange for the appropriate records to be processed in a suitable +thread. +The C routine is safe to call from an interrupt service routine +on embedded architectures (vxWorks and RTEMS). + +=item C + +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 +either the engineering units value found in the record's OVAL field, or the raw +value from the record's RVAL field if the record type's unit conversion +facilities are used. A return value of zero indicates success, any other value +indicates that an error occurred. + +This routine must not block (busy-wait) if the device takes more than a few +microseconds to accept the new value. In that case the routine must use +asynchronous completion to tell the record when the write operation eventually +completes. It signals that this is an asynchronous operation by setting the +record's PACT field to TRUE before it returns, having arranged for the record's +C routine to be called later once the write operation is over. When +that happens the C 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 + +This optional routine should be provided if the record type's unit conversion +features are used by the device support's C routine utilizing the +RVAL field rather than OVAL or VAL. +It is called by the record code whenever any of the the fields LINR, EGUL or +EGUF are modified and LINR has the value C. +The routine must calculate and set the fields EOFF and ESLO appropriately based +on the new values of EGUL and EGUF. + +These calculations can be expressed in terms of the minimum and maximum raw +values that the C routine can accept in the RVAL field. +When VAL is EGUF the RVAL field will be set to I, and when VAL is +EGUL the RVAL field will become I. +The fomulae to use are: + +=over + +EOFF = (I * EGUL E I * EGUF) / +(I E I) + +ESLO = (EGUF E EGUL) / (I E I) + +=back + +Note that the record support sets EOFF to EGUL before calling this routine, +which is a very common case (I is zero). + +=back + +=head2 Device Support For Soft Records + +Two soft device support modules Soft Channel and Raw Soft Channel are +provided for output records not related to actual hardware devices. The +OUT link type must be either a CONSTANT, DB_LINK, or CA_LINK. + +=head3 Soft Channel + +This module writes the current value of OVAL. + +If the OUT link type is PV_LINK, then dbCaAddInlink is called by +init_record. init_record always returns a value of 2, which means that +no conversion will ever be attempted. + +write_ao calls recGblPutLinkValue to write the current value of VAL. +See Soft Output for details. + +=head3 Raw Soft Channel + +This module is like the previous except that it writes the current +value of RVAL. + +=cut diff --git a/src/std/rec/compressRecord.dbd b/src/std/rec/compressRecord.dbd.pod similarity index 87% rename from src/std/rec/compressRecord.dbd rename to src/std/rec/compressRecord.dbd.pod index 347b807e2..97b84a9a0 100644 --- a/src/std/rec/compressRecord.dbd +++ b/src/std/rec/compressRecord.dbd.pod @@ -3,10 +3,36 @@ # 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 +# EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=title Compress Record (compress) + +... + +=head2 Record-specific Menus + +=head3 Menu compressALG + +The ALG field which uses this menu controls the compression algorithm used. + +... + +=menu compressALG + +... + +=head2 Parameter Fields + +The record-specific fields are described below. + +=recordtype compress + +... + +=cut + menu(compressALG) { choice(compressALG_N_to_1_Low_Value,"N to 1 Low Value") choice(compressALG_N_to_1_High_Value,"N to 1 High Value") @@ -16,6 +42,11 @@ menu(compressALG) { choice(compressALG_N_to_1_Median,"N to 1 Median") } recordtype(compress) { + +=fields VAL + +=cut + include "dbCommon.dbd" field(VAL,DBF_NOACCESS) { prompt("Value") @@ -23,6 +54,9 @@ recordtype(compress) { special(SPC_DBADDR) pp(TRUE) extra("void * val") + #=type DOUBLE[] + #=read Yes + #=write Yes } field(INP,DBF_INLINK) { prompt("Input Specification") diff --git a/src/std/rec/histogramRecord.dbd b/src/std/rec/histogramRecord.dbd index 06a84b52a..08fc12d4f 100644 --- a/src/std/rec/histogramRecord.dbd +++ b/src/std/rec/histogramRecord.dbd @@ -20,6 +20,9 @@ recordtype(histogram) { asl(ASL0) special(SPC_DBADDR) extra("void * val") + #=type ULONG[] + #=read Yes + #=write Yes } field(NELM,DBF_USHORT) { prompt("Num of Array Elements") diff --git a/src/std/rec/mbboRecord.dbd b/src/std/rec/mbboRecord.dbd index 4f748a7fd..5920a0c76 100644 --- a/src/std/rec/mbboRecord.dbd +++ b/src/std/rec/mbboRecord.dbd @@ -15,6 +15,8 @@ recordtype(mbbo) { special(SPC_DBADDR) asl(ASL0) pp(TRUE) + #=read Yes + #=write Yes } field(DOL,DBF_INLINK) { prompt("Desired Output Loc") diff --git a/src/std/rec/subArrayRecord.dbd b/src/std/rec/subArrayRecord.dbd index 6442ede16..4a0bfe0c6 100644 --- a/src/std/rec/subArrayRecord.dbd +++ b/src/std/rec/subArrayRecord.dbd @@ -15,6 +15,9 @@ recordtype(subArray) { special(SPC_DBADDR) pp(TRUE) extra("void * val") + #=type Set by FTVL + #=read Yes + #=write Yes } field(PREC,DBF_SHORT) { prompt("Display Precision") diff --git a/src/std/rec/waveformRecord.dbd b/src/std/rec/waveformRecord.dbd.pod similarity index 84% rename from src/std/rec/waveformRecord.dbd rename to src/std/rec/waveformRecord.dbd.pod index 92d0fc156..d28302801 100644 --- a/src/std/rec/waveformRecord.dbd +++ b/src/std/rec/waveformRecord.dbd.pod @@ -6,11 +6,43 @@ # EPICS BASE is distributed subject to a Software License Agreement found # in file LICENSE that is included with this distribution. #************************************************************************* + +=title Waveform Record (waveform) + +... + +=head2 Record-specific Menus + +=head3 Menu waveformPOST + +The MPST and APST fields use this menu to determine when to post new value +and archive monitors respectively. + +=menu waveformPOST + +... + +=head2 Parameter Fields + +The record-specific fields are described below. + +=recordtype waveform + +... + +=cut + menu(waveformPOST) { - choice(waveformPOST_Always,"Always") - choice(waveformPOST_OnChange,"On Change") + choice(waveformPOST_Always,"Always") + choice(waveformPOST_OnChange,"On Change") } + recordtype(waveform) { + +=fields VAL, FTVL, MPST, APST + +=cut + include "dbCommon.dbd" field(VAL,DBF_NOACCESS) { prompt("Value") @@ -18,6 +50,9 @@ recordtype(waveform) { special(SPC_DBADDR) pp(TRUE) extra("void * val") + #=type Set by FTVL + #=read Yes + #=write Yes } field(RARM,DBF_SHORT) { prompt("Rearm the waveform") diff --git a/src/std/softIoc/RULES b/src/std/softIoc/RULES index 667e9db78..72492016e 100644 --- a/src/std/softIoc/RULES +++ b/src/std/softIoc/RULES @@ -8,7 +8,9 @@ # This is a Makefile fragment, see src/ioc/Makefile. softIoc.dbd$(DEP): $(COMMON_DIR)/stdRecords.dbd +softIoc.dbd$(DEP): $(COMMON_DIR)/filters.dbd $(COMMON_DIR)/softIoc.dbd: $(COMMON_DIR)/stdRecords.dbd +$(COMMON_DIR)/softIoc.dbd: $(COMMON_DIR)/filters.dbd $(COMMON_DIR)/softIoc.dbd: $(STDDIR)/softIoc/Makefile softMain$(DEP): epicsInstallDir.h diff --git a/src/tools/DBD.pm b/src/tools/DBD.pm index 20b149b85..3189588c3 100644 --- a/src/tools/DBD.pm +++ b/src/tools/DBD.pm @@ -21,7 +21,9 @@ sub new { 'DBD::Menu' => {}, 'DBD::Recordtype' => {}, 'DBD::Registrar' => {}, - 'DBD::Variable' => {} + 'DBD::Variable' => {}, + 'COMMENTS' => [], + 'POD' => [] }; bless $this, $class; return $this; @@ -43,6 +45,24 @@ sub add { } } +sub add_comment { + my $this = shift; + push @{$this->{COMMENTS}}, @_; +} + +sub comments { + return @{shift->{COMMENTS}}; +} + +sub add_pod { + my $this = shift; + push @{$this->{POD}}, @_; +} + +sub pod { + return @{shift->{POD}}; +} + sub breaktables { return shift->{'DBD::Breaktable'}; } diff --git a/src/tools/DBD/Base.pm b/src/tools/DBD/Base.pm index 92b23a388..b0388d725 100644 --- a/src/tools/DBD/Base.pm +++ b/src/tools/DBD/Base.pm @@ -104,7 +104,7 @@ sub escapeCstring { } -# Base class routines for the DBD component objects +# Base methods for the DBD component objects sub new { my $class = shift; @@ -128,6 +128,17 @@ sub what { return shift->{WHAT}; } +sub add_comment { + my $this = shift; + confess "add_comment() not supported by $this->{WHAT} ($this)\n", + "Context: ", join(' in ', @context), "\n"; +} + +sub add_pod { + my $this = shift; + warnContext "Warning: Pod text inside $this->{WHAT} will be ignored"; +} + sub equals { my ($a, $b) = @_; return $a->{NAME} eq $b->{NAME} diff --git a/src/tools/DBD/Breaktable.pm b/src/tools/DBD/Breaktable.pm index 8d2479834..eb7bea6c9 100644 --- a/src/tools/DBD/Breaktable.pm +++ b/src/tools/DBD/Breaktable.pm @@ -8,6 +8,7 @@ sub init { my ($this, $name) = @_; $this->SUPER::init($name, "breakpoint table"); $this->{POINT_LIST} = []; + $this->{COMMENTS} = []; return $this; } @@ -31,6 +32,15 @@ sub point { return $this->{POINT_LIST}[$idx]; } +sub add_comment { + my $this = shift; + push @{$this->{COMMENTS}}, @_; +} + +sub comments { + return @{shift->{COMMENTS}}; +} + sub equals { my ($a, $b) = @_; return $a->SUPER::equals($b) diff --git a/src/tools/DBD/Menu.pm b/src/tools/DBD/Menu.pm index a7ca26ab9..65bae1526 100644 --- a/src/tools/DBD/Menu.pm +++ b/src/tools/DBD/Menu.pm @@ -7,6 +7,7 @@ sub init { $this->SUPER::init($name, "menu"); $this->{CHOICE_LIST} = []; $this->{CHOICE_INDEX} = {}; + $this->{COMMENTS} = []; return $this; } @@ -39,6 +40,15 @@ sub legal_choice { return exists $this->{CHOICE_INDEX}->{$value}; } +sub add_comment { + my $this = shift; + push @{$this->{COMMENTS}}, @_; +} + +sub comments { + return @{shift->{COMMENTS}}; +} + sub equals { my ($a, $b) = @_; return $a->SUPER::equals($b) diff --git a/src/tools/DBD/Parser.pm b/src/tools/DBD/Parser.pm index b8cc82783..901420685 100644 --- a/src/tools/DBD/Parser.pm +++ b/src/tools/DBD/Parser.pm @@ -19,10 +19,9 @@ use DBD::Variable; our $debug=0; sub ParseDBD { - my $dbd = shift; - $_ = shift; + (my $dbd, $_) = @_; while (1) { - parseCommon(); + parseCommon($dbd); if (m/\G menu \s* \( \s* $RXstr \s* \) \s* \{/oxgc) { print "Menu: $1\n" if $debug; parse_menu($dbd, $1); @@ -59,12 +58,12 @@ sub ParseDBD { \s* $RXstr \s* , \s*$RXstr \s* \)/oxgc) { print "Device: $1, $2, $3, $4\n" if $debug; my $rtyp = $dbd->recordtype($1); - if (!defined $rtyp) { - $rtyp = DBD::Recordtype->new($1); - warn "Device using undefined record type '$1', place-holder created\n"; - $dbd->add($rtyp); + if (!defined $rtyp) { + $rtyp = DBD::Recordtype->new($1); + warn "Device using undefined record type '$1', place-holder created\n"; + $dbd->add($rtyp); } - $rtyp->add_device(DBD::Device->new($2, $3, $4)); + $rtyp->add_device(DBD::Device->new($2, $3, $4)); } else { last unless m/\G (.*) $/moxgc; dieContext("Syntax error in '$1'"); @@ -73,21 +72,27 @@ sub ParseDBD { } sub parseCommon { + my ($obj) = @_; while (1) { # Skip leading whitespace m/\G \s* /oxgc; - if (m/\G \# /oxgc) { - if (m/\G \#!BEGIN\{ ( [^}]* ) \}!\#\# \n/oxgc) { + # Extract POD + if (m/\G ( = [a-zA-Z] .* ) \n/oxgc) { + $obj->add_pod($1, &parsePod); + } + elsif (m/\G \# /oxgc) { + if (m/\G \# ! BEGIN \{ ( [^}]* ) \} ! \# \# \n/oxgc) { print "File-Begin: $1\n" if $debug; pushContext("file '$1'"); } - elsif (m/\G \#!END\{ ( [^}]* ) \}!\#\# \n?/oxgc) { + elsif (m/\G \# ! END \{ ( [^}]* ) \} ! \# \# \n?/oxgc) { print "File-End: $1\n" if $debug; popContext("file '$1'"); } else { m/\G (.*) \n/oxgc; + $obj->add_comment($1); print "Comment: $1\n" if $debug; } } else { @@ -96,12 +101,29 @@ sub parseCommon { } } +sub parsePod { + pushContext("Pod markup"); + my @pod; + while (1) { + if (m/\G ( =cut .* ) \n?/oxgc) { + popContext("Pod markup"); + return @pod; + } + elsif (m/\G ( .* ) $/oxgc) { + dieContext("Unexpected end of input file, Pod block not closed"); + } + elsif (m/\G ( .* ) \n/oxgc) { + push @pod, $1 + } + } +} + sub parse_menu { my ($dbd, $name) = @_; pushContext("menu($name)"); my $menu = DBD::Menu->new($name); while(1) { - parseCommon(); + parseCommon($menu); if (m/\G choice \s* \( \s* $RXstr \s* , \s* $RXstr \s* \)/oxgc) { print " Menu-Choice: $1, $2\n" if $debug; $menu->add_choice($1, $2); @@ -123,7 +145,7 @@ sub parse_breaktable { pushContext("breaktable($name)"); my $bt = DBD::Breaktable->new($name); while(1) { - parseCommon(); + parseCommon($bt); if (m/\G point\s* \(\s* $RXstr \s* , \s* $RXstr \s* \)/oxgc) { print " Breaktable-Point: $1, $2\n" if $debug; $bt->add_point($1, $2); @@ -149,7 +171,7 @@ sub parse_recordtype { pushContext("recordtype($name)"); my $rtyp = DBD::Recordtype->new($name); while(1) { - parseCommon(); + parseCommon($rtyp); if (m/\G field \s* \( \s* $RXstr \s* , \s* $RXstr \s* \) \s* \{/oxgc) { print " Recordtype-Field: $1, $2\n" if $debug; parse_field($rtyp, $1, $2); @@ -175,7 +197,7 @@ sub parse_field { my $fld = DBD::Recfield->new($name, $field_type); pushContext("field($name, $field_type)"); while(1) { - parseCommon(); + parseCommon($fld); if (m/\G (\w+) \s* \( \s* $RXstr \s* \)/oxgc) { print " Field-Attribute: $1, $2\n" if $debug; $fld->add_attribute($1, $2); diff --git a/src/tools/DBD/Recfield.pm b/src/tools/DBD/Recfield.pm index a370b2cc7..6dbf1696f 100644 --- a/src/tools/DBD/Recfield.pm +++ b/src/tools/DBD/Recfield.pm @@ -56,6 +56,7 @@ sub init { sort keys %field_types) unless exists $field_types{$type}; $this->{DBF_TYPE} = $type; $this->{ATTR_INDEX} = {}; + $this->{COMMENTS} = []; return $this; } @@ -109,6 +110,16 @@ sub check_valid { if (defined($default) and !$this->legal_value($default)); } +sub add_comment { + my $this = shift; + push @{$this->{COMMENTS}}, @_; +} + +sub comments { + return @{shift->{COMMENTS}}; +} + + # The C structure member name is usually the field name converted to # lower-case. However if that is a reserved word, use the original. sub C_name { diff --git a/src/tools/DBD/Recordtype.pm b/src/tools/DBD/Recordtype.pm index d0d76a5a0..8c8fabbae 100644 --- a/src/tools/DBD/Recordtype.pm +++ b/src/tools/DBD/Recordtype.pm @@ -12,6 +12,8 @@ sub init { $this->{DEVICE_LIST} = []; $this->{DEVICE_INDEX} = {}; $this->{CDEFS} = []; + $this->{COMMENTS} = []; + $this->{POD} = []; return $this; } @@ -69,6 +71,15 @@ sub device { return $this->{DEVICE_INDEX}->{$choice}; } +sub add_comment { + my ($this, $comment) = @_; + push @{$this->{COMMENTS}}, $comment; +} + +sub comments { + return @{shift->{COMMENTS}}; +} + sub add_cdef { my ($this, $cdef) = @_; push @{$this->{CDEFS}}, $cdef; @@ -82,6 +93,15 @@ sub toCdefs { return join("\n", shift->cdefs) . "\n\n"; } +sub add_pod { + my $this = shift; + push @{$this->{POD}}, @_; +} + +sub pod { + return @{shift->{POD}}; +} + sub equals { my ($new, $known) = @_; return 0 if ! $known->fields; diff --git a/src/tools/Makefile b/src/tools/Makefile index cd364519d..5d345e9fd 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -49,8 +49,11 @@ PERL_SCRIPTS += dbdToMenuH.pl PERL_SCRIPTS += dbdToRecordtypeH.pl PERL_SCRIPTS += dbdExpand.pl PERL_SCRIPTS += dbdToHtml.pl +PERL_SCRIPTS += podToHtml.pl PERL_SCRIPTS += registerRecordDeviceDriver.pl +HTMLS = style.css + # Build Package Config Files FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) diff --git a/src/tools/dbdToHtml.pl b/src/tools/dbdToHtml.pl index 936cbf48c..d64a38ea2 100644 --- a/src/tools/dbdToHtml.pl +++ b/src/tools/dbdToHtml.pl @@ -1,7 +1,6 @@ #!/usr/bin/perl - #************************************************************************* -# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne +# 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. @@ -9,6 +8,8 @@ # $Id$ +use strict; + use FindBin qw($Bin); use lib "$Bin/../../lib/perl"; @@ -17,20 +18,35 @@ use DBD::Parser; use EPICS::Getopts; use EPICS::macLib; use EPICS::Readfile; +use HTML::Entities; + +BEGIN { + $::XHTML = eval "require Pod::Simple::XHTML; 1"; + if (!$::XHTML) { + require Pod::Simple::HTML; + } +} my $tool = 'dbdToHtml'; -getopts('DI@o:') or - die "Usage: $tool [-D] [-I dir] [-o xRecord.html] xRecord.dbd\n"; -my @path = map { split /[:;]/ } @opt_I; +use vars qw($opt_D @opt_I $opt_o); +getopts('DI@o:') or + die "Usage: $tool [-D] [-I dir] [-o file.html] file.dbd.pod\n"; + my $dbd = DBD->new(); my $infile = shift @ARGV; -$infile =~ m/\.dbd$/ or - die "$tool: Input file '$infile' must have '.dbd' extension\n"; +$infile =~ m/\.dbd.pod$/ or + die "$tool: Input file '$infile' must have '.dbd.pod' extension\n"; &ParseDBD($dbd, &Readfile($infile, 0, \@opt_I)); +if (!$opt_o) { + ($opt_o = $infile) =~ s/\.dbd\.pod$/.html/; + $opt_o =~ s/^.*\///; + $opt_o =~ s/dbCommonRecord/dbCommon/; +} + if ($opt_D) { # Output dependencies only my %filecount; my @uniqfiles = grep { not $filecount{$_}++ } @inputfiles; @@ -39,214 +55,175 @@ if ($opt_D) { # Output dependencies only exit 0; } -my $out; -if ($opt_o) { - $out = $opt_o; -} else { - ($out = $infile) =~ s/\.dbd$/.html/; - $out =~ s/^.*\///; - $out =~ s/dbCommonRecord/dbCommon/; -} -open $out, '>', $opt_o or die "Can't create $opt_o: $!\n"; +(my $title = $opt_o) =~ s/\.html$//; -print $out "

$infile

\n"; +open my $out, '>', $opt_o or + die "Can't create $opt_o: $!\n"; -my $rtypes = $dbd->recordtypes; - -my ($rn, $rtyp) = each %{$rtypes}; -print $out "

Record Name $rn

\n"; - -my @fields = $rtyp->fields; - -#create a Hash to store the table of field information for each GUI type -%dbdTables = ( - "GUI_COMMON" => "", - "GUI_COMMON" => "", - "GUI_ALARMS" => "", - "GUI_BITS1" => "", - "GUI_BITS2" => "", - "GUI_CALC" => "", - "GUI_CLOCK" => "", - "GUI_COMPRESS" => "", - "GUI_CONVERT" => "", - "GUI_DISPLAY" => "", - "GUI_HIST" => "", - "GUI_INPUTS" => "", - "GUI_LINKS" => "", - "GUI_MBB" => "", - "GUI_MOTOR" => "", - "GUI_OUTPUT" => "", - "GUI_PID" => "", - "GUI_PULSE" => "", - "GUI_SELECT" => "", - "GUI_SEQ1" => "", - "GUI_SEQ2" => "", - "GUI_SEQ3" => "", - "GUI_SUB" => "", - "GUI_TIMER" => "", - "GUI_WAVE" => "", - "GUI_SCAN" => "", - "GUI_NONE" => "" -); - - -#Loop over all of the fields. Build a string that contains the table body -#for each of the GUI Types based on which fields go with which GUI type. -foreach $fVal (@fields) { - my $pg = $fVal->attribute('promptgroup'); - while ( ($typ1, $content) = each %dbdTables) { - if ( $pg eq $typ1 or ($pg eq "" and $typ1 eq "GUI_NONE")) { - buildTableRow($fVal, $dbdTables{$typ1} ); +# Parse the Pod text from the root DBD object +my $pod = join "\n", '=for html
', '', + map { + # Handle a 'recordtype' Pod directive + if (m/^ =recordtype \s+ (.*)/x) { + my $rn = $1; + my $rtyp = $dbd->recordtype($rn); + die "Unknown recordtype '$rn' in $infile POD directive\n" + unless $rtyp; + rtypeToPod($rtyp, $dbd); } - } -} - -#Write out each table -while ( ($typ2, $content) = each %dbdTables) { - printHtmlTable($typ2, $content); -} - - -#add a field to a table body. The specified field and table body are passed -#in as parameters -sub buildTableRow { - my ( $fld, $outStr) = @_; - $longDesc = " "; - %htmlCellFmt = ( - rowStart => "", - nextCell => "", - endRow => "", - nextRow => "" - ); - my %cellFmt = %htmlCellFmt; - my $rowStart = $cellFmt{rowStart}; - my $nextCell = $cellFmt{nextCell}; - my $endRow = $cellFmt{endRow}; - my $nextRow = $cellFmt{nextRow}; - $outStr = $outStr . $rowStart; - $outStr = $outStr . $fld->name; - $outStr = $outStr . $nextCell; - $outStr = $outStr . $fld->attribute('prompt'); - $outStr = $outStr . $nextCell; - my $recType = $fld->dbf_type; - $typStr = $recType; - if ($recType eq "DBF_STRING") { - $typStr = $recType . " [" . $fld->attribute('size') . "]"; - } - - $outStr = $outStr . $typStr; - $outStr = $outStr . $nextCell; - $outStr = $outStr . design($fld); - $outStr = $outStr . $nextCell; - my $initial = $fld->attribute('initial'); - if ( $initial eq '' ) {$initial = " ";} - $outStr = $outStr . $initial; - $outStr = $outStr . $nextCell; - $outStr = $outStr . readable($fld); - $outStr = $outStr . $nextCell; - $outStr = $outStr . writable($fld); - $outStr = $outStr . $nextCell; - $outStr = $outStr . processPassive($fld); - $outStr = $outStr . $endRow; - $outStr = $outStr . "\n"; - $outStr = $outStr . $nextRow; - $outStr = $outStr . $longDesc; - $outStr = $outStr . $endRow; - $outStr = $outStr . "\n"; - $_[1] = $outStr; -} - -#Check if the prompt group is defined so that this can be used by clients -sub design { - my $fld = $_[0]; - my $pg = $fld->attribute('promptgroup'); - if ( $pg eq '' ) { - my $result = 'No'; - } - else { - my $result = 'Yes'; - } -} - -#Check if this field is readable by clients -sub readable { - my $fld = $_[0]; - if ( $fld->attribute('special') eq "SPC_DBADDR") { - $return = "Probably"; - } - else{ - if ( $fld->dbf_type eq "DBF_NOACCESS" ) { - $return = "No"; + # Handle a 'menu' Pod directive + elsif (m/^ =menu \s+ (.*)/x) { + my $mn = $1; + my $menu = $dbd->menu($mn); + die "Unknown menu '$mn' in $infile POD directive\n" + unless $menu; + menuToPod($menu); + } + elsif (m/^ =title \s+ (.*)/x) { + $title = $1; + "=head1 $title"; } else { - $return = "Yes" + $_; } - } + } $dbd->pod, + '=for html
', ''; + +my $podHtml; + +if ($::XHTML) { + $podHtml = Pod::Simple::XHTML->new(); + $podHtml->html_doctype(<< '__END_DOCTYPE'); + + +__END_DOCTYPE +} else { # Fall back to HTML + $podHtml = Pod::Simple::HTML->new(); } -#Check if this field is writable by clients -sub writable { - my $fld = $_[0]; - my $spec = $fld->attribute('special'); - if ( $spec eq "SPC_NOMOD" ) { - $return = "No"; - } - else { - if ( $spec ne "SPC_DBADDR") { - if ( $fld->dbf_type eq "DBF_NOACCESS" ) { - $return = "No"; - } - else { - $return = "Yes"; - } +$podHtml->html_css('style.css'); +$podHtml->force_title(encode_entities($title)); +$podHtml->perldoc_url_prefix(''); +$podHtml->perldoc_url_postfix('.html'); +$podHtml->output_fh($out); +$podHtml->parse_string_document($pod); +close $out; + + +sub menuToPod { + my ($menu) = @_; + my $index = 0; + return '=begin html', '', '
', + '', + map({choiceTableRow($_, $index++)} $menu->choices), + '
IndexIdentifierChoice String
', '', '=end html'; +} + +sub choiceTableRow { + my ($ch, $index) = @_; + my ($id, $name) = @{$ch}; + return '', + "$index", + "$id", + "$name", + ''; +} + +sub rtypeToPod { + my ($rtyp, $dbd) = @_; + return map { + # Handle a 'fields' Pod directive + if (m/^ =fields \s+ (.*)/x) { + my @names = split /\s*,\s*/, $1; + # Look up the named fields + my @fields = map { + my $field = $rtyp->field($_); + die "Unknown field name '$_' in $infile POD\n" + unless $field; + $field; + } @names; + # Generate Pod for the table + '=begin html', '', '
', + '', + '', + '', + map({fieldTableRow($_, $dbd)} @fields), + '
FieldSummaryTypeDCTDefaultReadWriteCA PP
', '', '=end html'; + } + # Handle a 'menu' Pod directive + elsif (m/^ =menu \s+ (.*)/x) { + my $mn = $1; + my $menu = $dbd->menu($mn); + die "Unknown menu '$mn' in $infile POD directive\n" + unless $menu; + menuToPod($menu); } else { - $return = "Maybe"; + # Raw text line + $_; } + } $rtyp->pod; +} + +sub fieldTableRow { + my ($fld, $dbd) = @_; + my $html = ''; + $html .= $fld->name; + $html .= ''; + $html .= $fld->attribute('prompt'); + $html .= ''; + my $type = $fld->public_type; + $html .= $type; + $html .= ' [' . $fld->attribute('size') . ']' + if $type eq 'STRING'; + if ($type eq 'MENU') { + my $mn = $fld->attribute('menu'); + my $menu = $dbd->menu($mn); + my $url = $menu ? "#Menu_$mn" : "${mn}.html"; + $html .= " ($mn)"; } + $html .= ''; + $html .= $fld->attribute('promptgroup') ? 'Yes' : 'No'; + $html .= ''; + $html .= $fld->attribute('initial') || ' '; + $html .= ''; + $html .= $fld->readable; + $html .= ''; + $html .= $fld->writable; + $html .= ''; + $html .= $fld->attribute('pp') eq 'TRUE' ? 'Yes' : 'No'; + $html .= "\n"; + return $html; } - -#Check to see if the field is process passive on caput -sub processPassive { - my $fld = $_[0]; - $pp = $fld->attribute('pp'); - if ( $pp eq "YES" or $pp eq "TRUE" ) { - $result = "Yes"; - } - elsif ( $PP eq "NO" or $pp eq "FALSE" or $pp eq "" ) { - $result = "No"; - } +# Native type presented to dbAccess users +sub DBD::Recfield::public_type { + my $fld = shift; + m/^=type (.+)$/i && return $1 for $fld->comments; + my $type = $fld->dbf_type; + $type =~ s/^DBF_//; + return $type; } -#print the start row to define a table -sub printTableStart { - print $out " \n"; - print $out ""; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - +# Check if this field is readable +sub DBD::Recfield::readable { + my $fld = shift; + m/^=read (Yes|No)$/i && return $1 for $fld->comments; + return 'Probably' + if $fld->attribute('special') eq "SPC_DBADDR"; + return $fld->dbf_type eq 'DBF_NOACCESS' ? 'No' : 'Yes'; } -#print the tail end of the table -sub printTableEnd { - print $out "
$_[0]
FieldSummaryTypeDCTDefaultReadWritecaPut=PP
\n"; +# Check if this field is writable +sub DBD::Recfield::writable { + my $fld = shift; + m/^=write (Yes|No)$/i && return $1 for $fld->comments; + my $special = $fld->attribute('special'); + return 'No' + if $special eq "SPC_NOMOD"; + return 'Maybe' + if $special eq "SPC_DBADDR"; + return $fld->dbf_type eq "DBF_NOACCESS" ? 'No' : 'Yes'; } -# Print the table for a GUI type. The name of the GUI type and the Table body -# for this type are fed in as parameters -sub printHtmlTable { - my ($typ2, $content) = $_; - if ( (length $_[1]) gt 0) { - printTableStart($_[0]); - print $out "$_[1]\n"; - printTableEnd(); - } - -} diff --git a/src/tools/podToHtml.pl b/src/tools/podToHtml.pl new file mode 100644 index 000000000..2baf9e80f --- /dev/null +++ b/src/tools/podToHtml.pl @@ -0,0 +1,47 @@ +#!/usr/bin/env perl +#************************************************************************* +# Copyright (c) 2013 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. +#************************************************************************* + +# $Id$ + +use strict; +use warnings; + +use Getopt::Std; +use Pod::Simple::HTML; + +our ($opt_o); + +$Getopt::Std::OUTPUT_HELP_VERSION = 1; +&HELP_MESSAGE if !getopts('o:') || @ARGV != 1; + +my $infile = shift @ARGV; + +if (!$opt_o) { + ($opt_o = $infile) =~ s/\. \w+ $/.html/x; + $opt_o =~ s/^.*\///; +} + +open my $out, '>', $opt_o or + die "Can't create $opt_o: $!\n"; + +my $podHtml = Pod::Simple::HTML->new(); + +$podHtml->html_css('style.css'); +$podHtml->perldoc_url_prefix(''); +$podHtml->perldoc_url_postfix('.html'); +$podHtml->set_source($infile); +$podHtml->output_string(\my $html); +$podHtml->run; + +print $out $html; +close $out; + +sub HELP_MESSAGE { + print STDERR "Usage: podToHtml.pl [-o file.html] file.pod\n"; + exit 2; +} diff --git a/src/tools/style.css b/src/tools/style.css new file mode 100644 index 000000000..09647403b --- /dev/null +++ b/src/tools/style.css @@ -0,0 +1,442 @@ +BODY, .logo { background: white; } + +BODY { + color: black; + font-family: arial,sans-serif; + margin: 0; + padding: 1ex; +} + +TABLE { + border-collapse: collapse; + border-spacing: 0; + border-width: 0; + color: inherit; +} + +IMG { border: 0; } +FORM { margin: 0; } +input { margin: 2px; } + +.logo { + float: left; + width: 264px; + height: 77px; +} + +.front .logo { + float: none; + display:block; +} + +.front .searchbox { + margin: 2ex auto; + text-align: center; +} + +.front .menubar { + text-align: center; +} + +.menubar { + background: #006699; + margin: 1ex 0; + padding: 1px; +} + +.menubar A { + padding: 0.8ex; + font: bold 10pt Arial,Helvetica,sans-serif; +} + +.menubar A:link, .menubar A:visited { + color: white; + text-decoration: none; +} + +.menubar A:hover { + color: #ff6600; + text-decoration: underline; +} + +A:link, A:visited { + background: transparent; + color: #006699; +} + +A[href="#POD_ERRORS"] { + background: transparent; + color: #FF0000; +} + +TD { + margin: 0; + padding: 0; +} + +DIV { + border-width: 0; +} + +DT { + margin-top: 1em; +} + +.credits TD { + padding: 0.5ex 2ex; +} + +.huge { + font-size: 32pt; +} + +.s { + background: #dddddd; + color: inherit; +} + +.s TD, .r TD { + padding: 0.2ex 1ex; + vertical-align: baseline; +} + +TH { + background: #bbbbbb; + color: inherit; + padding: 0.4ex 1ex; + text-align: left; +} + +TH A:link, TH A:visited { + background: transparent; + color: black; +} + +.box { + border: 1px solid #006699; + margin: 1ex 0; + padding: 0; +} + +.distfiles TD { + padding: 0 2ex 0 0; + vertical-align: baseline; +} + +.manifest TD { + padding: 0 1ex; + vertical-align: top; +} + +.l1 { + font-weight: bold; +} + +.l2 { + font-weight: normal; +} + +.t1, .t2, .t3, .t4, .t5 { + background: #006699; + color: white; +} +.t4 { + padding: 0.2ex 0.4ex; +} +.t1, .t2, .t3 { + padding: 0.5ex 1ex; +} + +/* IE does not support .box>.t1 Grrr */ +.box .t1, .box .t2, .box .t3, .box .t5 { + margin: 0; +} + +.t1 { + font-size: 1.4em; + font-weight: bold; + text-align: center; +} + +.t2 { + font-size: 1.0em; + font-weight: bold; + text-align: left; +} + +.t3 { + font-size: 1.0em; + font-weight: normal; + text-align: left; +} + +.t5 { + font-size: 0.8em; + font-weight: normal; + text-align: center; +} + +/* width: 100%; border: 0.1px solid #FFFFFF; */ /* NN4 hack */ + +.datecell { + text-align: center; + width: 17em; +} + +.cell { + padding: 0.2ex 1ex; + text-align: left; +} + +.DBD_Menu.index { + padding: 0.2ex 2ex; + text-align: right; +} + +.DBD_Menu.choice { + font: 1.0em monospace; +} + +.label { + background: #aaaaaa; + color: black; + font-weight: bold; + padding: 0.2ex 1ex; + text-align: right; + white-space: nowrap; + vertical-align: baseline; +} + +.categories { + border-bottom: 3px double #006699; + margin-bottom: 1ex; + padding-bottom: 3ex; + padding-top: 2ex; +} + +.categories TABLE { + margin: auto; +} + +.categories TD { + padding: 0.5ex 1ex; + vertical-align: baseline; +} + +.path A { + background: transparent; + color: #006699; + font-weight: bold; +} + +.pages { + background: #dddddd; + color: #006699; + padding: 0.2ex 0.4ex; +} + +.path { + background: #dddddd; + border-bottom: 1px solid #006699; + color: #006699; + /* font-size: 1.4em;*/ + margin: 1ex 0; + padding: 0.5ex 1ex; +} + +.menubar TD { + background: #006699; + color: white; +} + +.menubar { + background: #006699; + color: white; + margin: 1ex 0; + padding: 1px; +} + +.menubar .links { + background: transparent; + color: white; + padding: 0.2ex; + text-align: left; +} + +.menubar .searchbar { + background: black; + color: black; + margin: 0px; + padding: 2px; + text-align: right; +} + +A.m:link, A.m:visited { + background: #006699; + color: white; + font: bold 10pt Arial,Helvetica,sans-serif; + text-decoration: none; +} + +A.o:link, A.o:visited { + background: #006699; + color: #ccffcc; + font: bold 10pt Arial,Helvetica,sans-serif; + text-decoration: none; +} + +A.o:hover { + background: transparent; + color: #ff6600; + text-decoration: underline; +} + +A.m:hover { + background: transparent; + color: #ff6600; + text-decoration: underline; +} + +table.dlsip { + background: #dddddd; + border: 0.4ex solid #dddddd; +} + +.pod, .manifest { margin-right: 0; } + +.pod PRE { + background: #eeeeee; + border: 1px solid #888888; + color: black; + padding: 1em; + white-space: pre; +} + +.pod H1 { + background: transparent; + color: #006699; + font-size: 1.4em; +} + +.pod H1 A { text-decoration: none; } +.pod H2 A { text-decoration: none; } +.pod H3 A { text-decoration: none; } +.pod H4 A { text-decoration: none; } + +.pod H2 { + background: transparent; + color: #006699; + font-size: 1.2em; +} + +.pod H3 { + background: transparent; + color: #006699; + font-size: 1em; + font-style: italic; +} + +.pod H4 { + background: transparent; + color: #006699; + font-size: 1em; + font-weight: normal; +} + +.pod IMG { + vertical-align: top; +} + +.pod .toc A { + text-decoration: none; +} + +.pod .toc LI { + line-height: 1.2em; + list-style-type: none; +} + +.faq DT { + font-size: 1.4em; + font-weight: bold; +} + +.chmenu { + background: black; + color: red; + font: bold 1.1em Arial,Helvetica,sans-serif; + margin: 1ex auto; + padding: 0.5ex; +} + +.chmenu TD { + padding: 0.2ex 1ex; +} + +.chmenu A:link, .chmenu A:visited { + background: transparent; + color: white; + text-decoration: none; +} + +.chmenu A:hover { + background: transparent; + color: #ff6600; + text-decoration: underline; +} + +.column { + padding: 0.5ex 1ex; + vertical-align: top; +} + +.datebar { + margin: auto; + width: 14em; +} + +.date { + background: transparent; + color: #008000; +} + +.footer { + margin-top: 1ex; + text-align: right; + color: #006699; + font-size: x-small; + border-top: 1px solid #006699; + line-height: 120%; +} + +.front .footer { + border-top: none; +} + +#permalink { + float: right +} + +#permalink A { + font-size: small; +} + +.sr { + font-size: inherit; + margin: 0; +} + +.cpanstats { + float: left; + text-align: left; + color: #bbb; + white-space: pre; +} + +form.tool { + margin: 1ex; +} + +.styleswitch { + text-align: right; +}