Difference between revisions of "V4 Database Definition"
MartyKraimer (talk | contribs) (Remove comparison with V3. Extent syntax with introspection in mind) |
|||
(7 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
'''This page is currently undergoing surgery off-line by Andrew Johnson. <br>If you make any changes (such as spelling) they will be lost when I bring in the new version.''' | |||
May 11 2005 | May 11 2005 | ||
= <center>Overview</center> = | |||
<center> | |||
This document describes the Database Definition syntax for EPICS V4 databases. | |||
Files that follow this syntax can be used by the iocCore build system, and by Database Configuration Tools (especially VDCT). | |||
== Database Field Types == | |||
The database field types supported by EPICS V4 are: | |||
* <tt>bool</tt> - a value that is (0,1) meaning (false,true) | |||
* <tt>octet</tt> - an 8 bit byte. Note that char is not a supported type. | |||
* <tt>int16</tt> - 16 bit signed interger | |||
* <tt>uint16</tt> - 16 bit unsigned interger | |||
* <tt>int32</tt> - 32 bit signed interger | |||
* <tt>uint32</tt> - 32 bit unsigned interger | |||
* <tt>int64</tt> - 64 bit signed interger | |||
* <tt>uint64</tt> - 64 bit unsigned interger | |||
* <tt>float32</tt> - IEEE float | |||
* <tt>float64</tt> - IEEE double | |||
* <tt>string</tt> - arbitrary length string of unicode/UTF-8 characters. | |||
* <tt>menu</tt> - 16 bit integer index into a string array of choices | |||
* <tt>enum</tt> - 16 bit integer index into a string array of choices | |||
* <tt>struct</tt> - an ordered set of other database field types | |||
* <tt>link</tt> - a pointer to data outside the record | |||
* <tt>device</tt> - a link to associated device support | |||
* <tt>array</tt> - multidimensional arrays of most types are supported | |||
* <tt>private</tt> - any <tt>C</tt> type; content is private to the record and/or iocCore | |||
== Database Statements == | |||
The following statements are supported and discussed below: | |||
: | |||
* <tt>include</tt> - include contents of another file | |||
* <tt>#</tt> - comments | |||
* <tt>menu</tt> - defines a fixed set of choices | |||
* <tt>struct</tt> - like a C structure | |||
* <tt>record</tt> - defines a record type | |||
* <tt>field</tt> - defines a field in a struct or record type | |||
* <tt>view</tt> - defines a view of a record type | |||
* <tt>property</tt> - maps a property name in a view to a record field | |||
* <tt>interface</tt> - defines interface to code associated with a struct | |||
* <tt>link</tt> - defines a link to data outside the record | |||
* <tt>device</tt> - defines an interface to device/driver support | |||
The following statements are discussed: | The following statements or something like them will be supported, but these are not discussed here (yet): | ||
* <tt>registrar</tt> - like the V3 registrar() statement | |||
* <tt>variable</tt> - like the V3 variable() statement | |||
* <tt>command</tt> - iocsh command registration | |||
<center> | <center> | ||
= Summary of V4 Database Definition Syntax = | |||
</center> | |||
== Statements for Record Types == | |||
Line 89: | Line 65: | ||
#comment | #comment | ||
menu(name) { | menu(name) { | ||
choice(" | choice("choiceValue") | ||
... | ... | ||
} | } | ||
struct(name) { | struct(name) { | ||
field( | field(fieldName,fieldType) {fieldAttributes} | ||
... | ... | ||
} | } | ||
record(name) extends iocRecord | record(name) extends iocRecord { | ||
field(fieldName,fieldType) {fieldAttributes} | |||
field( | |||
... | ... | ||
} | } | ||
#If | #If fieldType is empty record instance determines type | ||
# must be one of bool,...,string | # must be one of bool,...,string | ||
# | #fieldType is one of the following: | ||
bool | bool | ||
octet | octet | ||
Line 132: | Line 106: | ||
#interfaceName is the name of the associated interface | #interfaceName is the name of the associated interface | ||
# an array | # an array fieldType has one of the following forms | ||
array(<type>[capacity]) #1dim array | array(<type>[capacity]) #1dim array | ||
array(<type>[capacity,capacity,...]) #ndim array | array(<type>[capacity,capacity,...]) #ndim array | ||
Line 148: | Line 122: | ||
field(dynamic,bool) | field(dynamic,bool) | ||
} | } | ||
struct( | struct(fieldAttribute) { | ||
field(asl,int16) {default = 1} | field(asl,int16) {default = 1} | ||
field(default,string) | field(default,string) | ||
Line 157: | Line 131: | ||
} | } | ||
== Statements for Accessing data/code related to the record == | |||
interface(interfaceName,choiceName,dataStruct) | interface(interfaceName,choiceName,dataStruct) | ||
link(dir,choiceName,dataStruct) | link(dir,choiceName,dataStruct) | ||
Line 166: | Line 141: | ||
#choiceName is name that is mapped to interface implementation | #choiceName is name that is mapped to interface implementation | ||
registrar( | registrar(functionName) | ||
variable( | variable(variableName) | ||
== Statements for Creating Record Instances == | |||
The Following defines a Record Instance: | |||
recordType "recordName" = { | recordType "recordName" = { | ||
info name = {" | info name = {"infoValue"}; | ||
fieldName = {fieldValue}; | fieldName = {fieldValue}; | ||
fieldName = type {fieldValue}; /*Only if type is not defined in record*/ | fieldName = type {fieldValue}; /*Only if type is not defined in record*/ | ||
Line 180: | Line 156: | ||
fieldName = choiceName {dataStructValue};/*for struct/link/device fields*/ | fieldName = choiceName {dataStructValue};/*for struct/link/device fields*/ | ||
varFields = [number] { | varFields = [number] { | ||
{ | {fieldName,interfaceName,choiceName,{dataStructValue}}, | ||
... | ... | ||
} | } | ||
Line 191: | Line 167: | ||
# capacity,capacity,... ndim array | # capacity,capacity,... ndim array | ||
# | # | ||
#fieldValue is | #fieldValue is scalarValue or structValue or arrayDef or linkValue | ||
#dataStructValue is | #dataStructValue is structValue | ||
# | # | ||
#where | #where | ||
# | #scalarValue is numValue or stringValue | ||
# where | # where | ||
# | # numValue is value | ||
# example: The following initializes a float64 field | # example: The following initializes a float64 field | ||
# outputRateOfChange = {1.0}; | # outputRateOfChange = {1.0}; | ||
# | # stringValue is "value" | ||
# example for menu field | # example for menu field | ||
# scan = {".1 second"}; | # scan = {".1 second"}; | ||
# example for string field | # example for string field | ||
# command = {"getValue\r\n"}; | # command = {"getValue\r\n"}; | ||
# | #structValue is fieldValue or name = fieldValue , ... | ||
# assume struct(point) {field(x,float64) field(y,float64) field(z,float64)} | # assume struct(point) {field(x,float64) field(y,float64) field(z,float64)} | ||
# example: xxx = { y = 1.0, 2.0}; | # example: xxx = { y = 1.0, 2.0}; | ||
# | #arrayDef is rowValue (1dim) or {rowValue}, {rowValue} ... (ndim) | ||
# | # rowValue is fieldValue or [index]=fieldValue , ... | ||
# 1dim example: The following perform the same initialization | # 1dim example: The following perform the same initialization | ||
# xxx = [4] {1.0,[2] = 3.0,4.0}; | # xxx = [4] {1.0,[2] = 3.0,4.0}; | ||
# xxx = [4] {1.0,0.0,3.0,4.0}; | # xxx = [4] {1.0,0.0,3.0,4.0}; | ||
# 2dim example: The following all create a 3x3 identity matrix | # 2dim example: The following all create a 3x3 identity matrix | ||
# xxx = [3,3]{{1, 0, 0} {0, 1, 0} {0, 0, 1}}; | # xxx = [3,3]{ {1, 0, 0} {0, 1, 0} {0, 0, 1}}; | ||
# xxx = [3,3]{{1}, {[1]=1}, {[2]=1}}; | # xxx = [3,3]{ {1}, {[1]=1}, {[2]=1}}; | ||
# xxx = [3,3]{[0]={1}, [1] = {0, 1}, {0, 0, 1}}; | # xxx = [3,3]{[0]={1}, [1] = {0, 1}, {0, 0, 1}}; | ||
#examples of link/device fields | #examples of link/device fields | ||
Line 225: | Line 201: | ||
---- | ---- | ||
<center> | <center> | ||
= General-purpose Statements = | |||
</center> | |||
== include == | == include == | ||
include "filename" | include "filename" | ||
Line 238: | Line 215: | ||
: Must be a valid filename | : Must be a valid filename | ||
<tt>Question></tt> Where is this allowed? | <tt>Question></tt> Where is this allowed? | ||
== #comment == | == #comment == | ||
# anything | # anything | ||
Anything after <tt>#<tt> is a comment. This may appear on a line by itself or at the end of another statement. | Anything on a line after a <tt>#</tt> character is a comment, and will be ignored. This may appear on a line by itself or at the end of another statement. | ||
<center> | <center> | ||
= menu definitions = | |||
</center> | |||
menu(name) { | menu(name) { | ||
choice(" | choice("choiceValue") | ||
... | ... | ||
} | } | ||
Line 266: | Line 236: | ||
; <tt>name</tt> | ; <tt>name</tt> | ||
: Must be a valid C identifier. Each menu must have a unique name. | : Must be a valid C identifier. Each menu must have a unique name. | ||
; <tt> | ; <tt>choiceValue</tt> | ||
: Can be any UTF-8 compatible string | : Can be any UTF-8 compatible string | ||
Line 284: | Line 254: | ||
} | } | ||
---- | |||
<center> | <center> | ||
= Structures, Record types and Fields = | |||
= | |||
</center> | </center> | ||
== struct == | |||
A | A structure is defined as follows: | ||
struct(name) { | struct(name) { | ||
field( | field(fieldName,fieldType) {fieldAttributes} | ||
... | ... | ||
} | } | ||
Line 305: | Line 273: | ||
; <tt>name</tt> | ; <tt>name</tt> | ||
: The structure name. It must be a valid C identifier. No two structures can have the same name. | : The structure name. It must be a valid C identifier. No two structures can have the same name. | ||
; <tt> | ; <tt>fieldName</tt> | ||
: Must be a valid C identifier | : Must be a valid C identifier | ||
; <tt> | ; <tt>fieldType</tt> | ||
: See | : See fieldType below. | ||
; <tt> | ; <tt>fieldAttributes</tt> | ||
: See | : See fieldAttributes below. | ||
== record == | |||
A record type is defined as follows: | A record type is defined as follows: | ||
include "dbCommon.dbd" | include "dbCommon.dbd" | ||
record(name) extends iocRecord value | record(name) extends iocRecord value fieldName { | ||
field( | field(fieldName,fieldType) {fieldAttributes} | ||
... | ... | ||
} | } | ||
Line 326: | Line 294: | ||
; <tt>extends iocRecord</tt> | ; <tt>extends iocRecord</tt> | ||
: This states that the record type extends the fields defined in iocRecord. iocRecord is described below. It's definition does not have an extends definition. | : This states that the record type extends the fields defined in iocRecord. iocRecord is described below. It's definition does not have an extends definition. | ||
; <tt>value | ; <tt>value fieldName</tt> | ||
: This specifies the name of the default value field, i.e. the default field for CA clients that do not specify a field name. If the record has a field name "value" then this clause does not have to be specified. | : This specifies the name of the default value field, i.e. the default field for CA clients that do not specify a field name. If the record has a field name "value" then this clause does not have to be specified. | ||
; <tt> | ; <tt>fieldName</tt> | ||
: Must be a valid C identifier | : Must be a valid C identifier | ||
; <tt> | ; <tt>fieldType</tt> | ||
: See | : See fieldType below. | ||
; <tt> | ; <tt>fieldAttributes</tt> | ||
: See | : See fieldAttributes below. | ||
== | == fieldType == | ||
Both <tt>struct</tt> and <tt>record</tt> define a field as: | Both <tt>struct</tt> and <tt>record</tt> define a field as: | ||
field( | field(fieldName,fieldType) | ||
The syntax for <tt> | The syntax for <tt>fieldType</tt> depends of the field type. | ||
; Numeric, Octet,and String Types | ; Numeric, Octet,and String Types | ||
Line 404: | Line 372: | ||
: field(inp,device(in,digitalIO)) | : field(inp,device(in,digitalIO)) | ||
== | == fieldAttributes == | ||
Associated with | Associated with fieldAttributes are the following "hidden" definitions: | ||
struct(metadata) { | struct(metadata) { | ||
Line 413: | Line 381: | ||
field(dynamic,bool) | field(dynamic,bool) | ||
} | } | ||
struct( | struct(fieldAttribute) { | ||
field(asl,int16) {default = 1} | field(asl,int16) {default = 1} | ||
field(default,string) | field(default,string) | ||
Line 422: | Line 390: | ||
} | } | ||
A field definition can have associated | A field definition can have associated fieldAttributes such as: | ||
field(value,float64) { | field(value,float64) { | ||
asl = 0, | asl = 0, | ||
Line 451: | Line 419: | ||
* <tt>dynamic</tt> - Is the field dynamic, i.e. can it change because of record processing | * <tt>dynamic</tt> - Is the field dynamic, i.e. can it change because of record processing | ||
=== Example of metadata definitions === | |||
An analog output record can have fields like | An analog output record can have fields like | ||
Line 470: | Line 438: | ||
---- | ---- | ||
<center> | <center> | ||
= Interfaces, Links and Devices = | |||
</center> | |||
<tt>interface</tt> describes choices for code that supports | <tt>interface</tt> describes choices for code that supports | ||
actions associated with record processing. | actions associated with record processing. | ||
<tt>link</tt> describes choices for link fields and <tt>device</tt> describes choices for device fields. | <tt>link</tt> describes choices for link fields, and <tt>device</tt> describes choices for device fields. | ||
syntax: | syntax: | ||
interface(interfaceName,choiceName, | interface(interfaceName,choiceName,dataStructName) | ||
link(dir,choiceName,dataStruct) | link(dir,choiceName,dataStruct) | ||
device(dir,interfaceName,choiceName, | device(dir,interfaceName,choiceName,dataStructName) | ||
where | where | ||
Line 494: | Line 461: | ||
; <tt>dir</tt> | ; <tt>dir</tt> | ||
: Must be one of <tt>null,in,out,fwd, </tt>or <tt>inout</tt>. Compatible checks are made to match the interface with a field. What are the rules????? | : Must be one of <tt>null,in,out,fwd, </tt>or <tt>inout</tt>. Compatible checks are made to match the interface with a field. What are the rules????? | ||
; <tt> | ; <tt>dataStructName</tt> | ||
: The name of a <tt>struct</tt> that the interface understands. This interface can contain data and configuration information. The <tt>struct</tt> must be defined before record instances can be created that assign values to it. | : The name of a <tt>struct</tt> that the interface understands. This interface can contain data and configuration information. The <tt>struct</tt> must be defined before record instances can be created that assign values to it. | ||
---- | ---- | ||
<center> | <center> | ||
= record instance = | |||
</center> | |||
A record instance has the following syntax | A record instance has the following syntax | ||
<recordType> " | <recordType> "recordName" = { | ||
info name = {" | info name = {"infoValue"}; | ||
fieldName = {fieldValue}; | fieldName = {fieldValue}; | ||
fieldName = type {fieldValue}; #Only if type is not defined in record | fieldName = type {fieldValue}; #Only if type is not defined in record | ||
Line 514: | Line 480: | ||
fieldName = choiceName {dataStructValue}; #for link/device fields | fieldName = choiceName {dataStructValue}; #for link/device fields | ||
varFields = [number] { | varFields = [number] { | ||
{ | {fieldName,interfaceName,choiceName,{dataStructValue}}, | ||
... | ... | ||
} | } | ||
Line 524: | Line 490: | ||
; <tt>recordType</tt> | ; <tt>recordType</tt> | ||
: The name of the record type | : The name of the record type | ||
; <tt> | ; <tt>recordName</tt> | ||
: The name of the record instance. What restrictions will we place on record instance name? Can this contain non-ascii characters? That is will UTF-8 instance names be supported? | : The name of the record instance. What restrictions will we place on record instance name? Can this contain non-ascii characters? That is will UTF-8 instance names be supported? | ||
; <tt>info name</tt> | ; <tt>info name</tt> | ||
Line 538: | Line 504: | ||
; <tt>choiceName</tt> | ; <tt>choiceName</tt> | ||
: This is for <tt>struct</tt>, <tt>link</tt>, and <tt>device</tt> fields. <tt>choiceName</tt> is a choice defined in a <tt>struct</tt>, <tt>link</tt>, or <tt>device</tt> definition. | : This is for <tt>struct</tt>, <tt>link</tt>, and <tt>device</tt> fields. <tt>choiceName</tt> is a choice defined in a <tt>struct</tt>, <tt>link</tt>, or <tt>device</tt> definition. | ||
; <tt> | ; <tt>fieldValue</tt> | ||
: The syntax depends on the field type. The details are described next.. | : The syntax depends on the field type. The details are described next.. | ||
== | == fieldValue == | ||
The format for <tt> | The format for <tt>fieldValue</tt> depends of the field type. | ||
; Single Item Field types | ; Single Item Field types | ||
Line 587: | Line 553: | ||
; link or device fields | ; link or device fields | ||
:The syntax is: | :The syntax is: | ||
: field = choiceName { | : field = choiceName {structValue} | ||
:For link choiceName is one of the choices from link definitions that have compatible directions. For device choiceName is one of the choices from link and device definitions that have compatible directions. | :For link choiceName is one of the choices from link definitions that have compatible directions. For device choiceName is one of the choices from link and device definitions that have compatible directions. structValue is like the value for struct fields where the structure is the dataStruct from the link or device definition which choiceName selected. | ||
:<tt>varFields</tt> contains user defined fields, i.e. extra fields for the record that are defined for record instances. Each has associated data and code. When a record is processed the associated code is invoked just before alarm and | :<tt>varFields</tt> contains user defined fields, i.e. extra fields for the record that are defined for record instances. Each has associated data and code. When a record is processed the associated code is invoked just before alarm and | ||
monitors are processed. | monitors are processed. | ||
: <tt>varFields</tt>is defined in <tt>iocRecord</tt> as follows: | : <tt>varFields</tt>is defined in <tt>iocRecord</tt> as follows: | ||
: struct(varFields) { | : struct(varFields) { | ||
: field( | : field(fieldName,string) | ||
: field(interfaceName,string) | : field(interfaceName,string) | ||
: } | : } | ||
Line 613: | Line 579: | ||
---- | ---- | ||
<center> | <center> | ||
= Process Variable Names = | |||
</center> | |||
A process variable name (PV) follows the C syntax for specifying fields and elements of arrays. A PV can select an elemenentary field, a structure, of an array. | |||
A process variable name (PV) | |||
For example if a pvname is: | For example if a pvname is: | ||
Line 670: | Line 635: | ||
---- | ---- | ||
<center> | <center> | ||
= Standard Properties = | |||
</center> | |||
The following is a list of standard metadata names. | The following is a list of standard metadata names. | ||
Line 709: | Line 673: | ||
---- | ---- | ||
<center> | <center> | ||
= dbCommon = | |||
</center> | |||
NOTE: dbCommon needs work. It should have more structure. | NOTE: dbCommon needs work. It should have more structure. | ||
Line 794: | Line 757: | ||
---- | ---- | ||
<center> | <center> | ||
= iocRecord = | |||
</center> | |||
<tt>iocRecord.dbd</tt>, which is part of every record, defines the following: | <tt>iocRecord.dbd</tt>, which is part of every record, defines the following: | ||
struct(varFields) { | struct(varFields) { | ||
field( | field(fieldName,string) | ||
field(interfaceName,string) | field(interfaceName,string) | ||
field(choiceName,string) | |||
field(dataStructName,string) | |||
} | } | ||
#The following are the fields that must be part of every recordtype | #The following are the fields that must be part of every recordtype | ||
Line 897: | Line 861: | ||
---- | ---- | ||
<center> | <center> | ||
= Example Record Types = | |||
</center> | |||
== aoRecord == | == aoRecord == | ||
aoRecord.dbd defines the following: | aoRecord.dbd defines the following: | ||
Line 945: | Line 910: | ||
field(rawValue,int32) { | field(rawValue,int32) { | ||
dct = false, | dct = false, | ||
meta{{"timeStamp",time}} | meta{ {"timeStamp",time}} | ||
} | } | ||
field(prevRawValue,int32) { | field(prevRawValue,int32) { | ||
dct = false, | dct = false, | ||
mod = false, | mod = false, | ||
meta{{"timeStamp",time}} | meta{ {"timeStamp",time}} | ||
} | } | ||
field(readBackValue,int32) { | field(readBackValue,int32) { | ||
dct = false, | dct = false, | ||
mod = false, | mod = false, | ||
meta{{"timeStamp",time}} | meta{ {"timeStamp",time}} | ||
} | } | ||
field(oldReadBackValue,int32) { | field(oldReadBackValue,int32) { | ||
dct = false, | dct = false, | ||
mod = false, | mod = false, | ||
meta{{"timeStamp",time}} | meta{ {"timeStamp",time}} | ||
} | } | ||
field(prevValue,float64) { | field(prevValue,float64) { | ||
Line 978: | Line 943: | ||
dct = false, | dct = false, | ||
mod = false, | mod = false, | ||
meta{{"timeStamp",time}} | meta{ {"timeStamp",time}} | ||
} | } | ||
field(simOutputLink,link(out)) | field(simOutputLink,link(out)) | ||
Line 993: | Line 958: | ||
---- | ---- | ||
== calcRecord == | == calcRecord == | ||
calcRecord.dbd defines the following: | calcRecord.dbd defines the following: | ||
Line 1,035: | Line 997: | ||
---- | ---- | ||
== mbbiRecord == | == mbbiRecord == | ||
mbbiRecord.dbd defines the following: | mbbiRecord.dbd defines the following: | ||
Line 1,084: | Line 1,043: | ||
---- | ---- | ||
== waveformRecord == | == waveformRecord == | ||
waveformRecord.dbd defines the following: | waveformRecord.dbd defines the following: | ||
Line 1,119: | Line 1,075: | ||
---- | ---- | ||
<center> | <center> | ||
= Record Instance Examples = | |||
</center> | |||
== Initializing link and device fields == | |||
In order to support the database and channel access links the following <tt>struct</tt> definitions are in <tt>dbCommon.dbd: constantlink, dblink, dbfwdlink, calink, cafwdlink, pvlink, and pvfwdlink.</tt> | In order to support the database and channel access links the following <tt>struct</tt> definitions are in <tt>dbCommon.dbd: constantlink, dblink, dbfwdlink, calink, cafwdlink, pvlink, and pvfwdlink.</tt> | ||
Line 1,156: | Line 1,111: | ||
in = SomeVMEdevice {0,2,"parm stuff"} | in = SomeVMEdevice {0,2,"parm stuff"} | ||
== Initializing choices associated with an enum field == | |||
The following is a record instance that defines an mbbiRecord with three states and initializes the state to state0 | The following is a record instance that defines an mbbiRecord with three states and initializes the state to state0 | ||
Line 1,176: | Line 1,131: | ||
} | } | ||
== Initializing an array of structures containing a link field == | |||
The calc record is defined as: | The calc record is defined as: | ||
Line 1,200: | Line 1,155: | ||
} | } | ||
== Initializing an array of arbitrary type == | |||
The waveform record is defined as: | The waveform record is defined as: | ||
Line 1,219: | Line 1,174: | ||
---- | ---- | ||
<center> | <center> | ||
= Unresolved Issues = | |||
</center> | |||
== attributes - dct == | |||
Should this be dct(interestLevel)? | Should this be dct(interestLevel)? | ||
== mbbi == | |||
Currently two fields define the states: | Currently two fields define the states: | ||
Line 1,243: | Line 1,197: | ||
CA clients dont normally care about the mask values | CA clients dont normally care about the mask values | ||
== dynamic metadata == | |||
Metadata can be dynamic meaning that the metadata might change as a result of record processing. Is this needed? The answer probably depends on how monitors are implemented. Can an efficient way be found to allow arbitrary metadata to be passed with a monitor or will it be necessary to limit the set of metadata, e.g. only timeStamp, status, and severity can be dynamic properties. | Metadata can be dynamic meaning that the metadata might change as a result of record processing. Is this needed? The answer probably depends on how monitors are implemented. Can an efficient way be found to allow arbitrary metadata to be passed with a monitor or will it be necessary to limit the set of metadata, e.g. only timeStamp, status, and severity can be dynamic properties. | ||
== union and extend == | |||
Benjamin suggested that the DBD syntax should include union and extend. A limited form of extend is used for record. Is more needed? | Benjamin suggested that the DBD syntax should include union and extend. A limited form of extend is used for record. Is more needed? | ||
== prompt and group == | |||
This version only describes nodct for fields that DCTs should not show. Is this sufficient? | This version only describes nodct for fields that DCTs should not show. Is this sufficient? | ||
== Scan Mechanism == | |||
Andrew gave a suggestion for a better way to define scan types and rates. Should this be considered. | Andrew gave a suggestion for a better way to define scan types and rates. Should this be considered. | ||
---- | ---- | ||
<center> | <center> | ||
= Implementation of special = | |||
</center> | |||
Unlike V3 attribute special does not have an argument. For fields in iocRecord, iocCore implements special action when the field is modified. | Unlike V3 attribute special does not have an argument. For fields in iocRecord, iocCore implements special action when the field is modified. | ||
Line 1,275: | Line 1,228: | ||
---- | ---- | ||
<center> | <center> | ||
= Implementation of link = | |||
</center> | |||
In V3 all links except INP,OUT were implemented by dbAccess. V4 provides an inplemention of link support that is similar to the V3 implementation but also allows other implementations. A link is defined as: | In V3 all links except INP,OUT were implemented by dbAccess. V4 provides an inplemention of link support that is similar to the V3 implementation but also allows other implementations. A link is defined as: | ||
link(dir,choiceName, | link(dir,choiceName,dataStructName) | ||
Record support communicates with the link support code via an interface something like the following: | Record support communicates with the link support code via an interface something like the following: | ||
Line 1,296: | Line 1,248: | ||
---- | ---- | ||
<center> | <center> | ||
= Implementation of device = | |||
</center> | |||
In V3 all links INP,OUT together with field DTYP were implemented by device support modules. For V4 a device is defined as: | In V3 all links INP,OUT together with field DTYP were implemented by device support modules. For V4 a device is defined as: | ||
device(dir,interfaceName,choiceName, | device(dir,interfaceName,choiceName,dataStructName) | ||
pinterface is the address of an implementation of interface iocDeviceConnect, which is something like the following: | pinterface is the address of an implementation of interface iocDeviceConnect, which is something like the following: | ||
Line 1,313: | Line 1,264: | ||
epicsStatus (*disconnect)(iocDbAddr *piocDbAddr); | epicsStatus (*disconnect)(iocDbAddr *piocDbAddr); | ||
}iocDeviceConnect; | }iocDeviceConnect; | ||
Latest revision as of 21:35, 17 May 2005
This page is currently undergoing surgery off-line by Andrew Johnson.
If you make any changes (such as spelling) they will be lost when I bring in the new version.
May 11 2005
Overview
This document describes the Database Definition syntax for EPICS V4 databases. Files that follow this syntax can be used by the iocCore build system, and by Database Configuration Tools (especially VDCT).
Database Field Types
The database field types supported by EPICS V4 are:
- bool - a value that is (0,1) meaning (false,true)
- octet - an 8 bit byte. Note that char is not a supported type.
- int16 - 16 bit signed interger
- uint16 - 16 bit unsigned interger
- int32 - 32 bit signed interger
- uint32 - 32 bit unsigned interger
- int64 - 64 bit signed interger
- uint64 - 64 bit unsigned interger
- float32 - IEEE float
- float64 - IEEE double
- string - arbitrary length string of unicode/UTF-8 characters.
- menu - 16 bit integer index into a string array of choices
- enum - 16 bit integer index into a string array of choices
- struct - an ordered set of other database field types
- link - a pointer to data outside the record
- device - a link to associated device support
- array - multidimensional arrays of most types are supported
- private - any C type; content is private to the record and/or iocCore
Database Statements
The following statements are supported and discussed below:
- include - include contents of another file
- # - comments
- menu - defines a fixed set of choices
- struct - like a C structure
- record - defines a record type
- field - defines a field in a struct or record type
- view - defines a view of a record type
- property - maps a property name in a view to a record field
- interface - defines interface to code associated with a struct
- link - defines a link to data outside the record
- device - defines an interface to device/driver support
The following statements or something like them will be supported, but these are not discussed here (yet):
- registrar - like the V3 registrar() statement
- variable - like the V3 variable() statement
- command - iocsh command registration
Summary of V4 Database Definition Syntax
Statements for Record Types
include "filename" #comment menu(name) { choice("choiceValue") ... }
struct(name) { field(fieldName,fieldType) {fieldAttributes} ... }
record(name) extends iocRecord { field(fieldName,fieldType) {fieldAttributes} ... } #If fieldType is empty record instance determines type # must be one of bool,...,string #fieldType is one of the following: bool octet int16 uint16 int32 uint32 int64 uint64 float32 float64 string menu(name) enum # has associated # struct() { # field(index,iocInt16) # field(choice,array(string[])) # } struct(structName,interfaceName) #interfaceName (optional) is the name of the associated interface link(direction) #direction is null,in,out,fwd, or inout device(direction,interfaceName) #direction is null,in,out,fwd, or inout #interfaceName is the name of the associated interface
# an array fieldType has one of the following forms array(<type>[capacity]) #1dim array array(<type>[capacity,capacity,...]) #ndim array array(<type>) #arbitary dimensional array #<type> is not specified or one of bool,...,link # If not specified record instance determines type #capacity is optional. If not specified record instance determines capacity
private("valid C type") #must NOT include field name
#field attributes is assignment of fields from the following: struct(metadata) { field(name,string) field(field,string) #field holding the metadata field(dynamic,bool) } struct(fieldAttribute) { field(asl,int16) {default = 1} field(default,string) field(dct,bool) {default = true} field(mod,bool) {default = true} field(special,bool) field(meta,array(struct(metadata)[])) }
interface(interfaceName,choiceName,dataStruct) link(dir,choiceName,dataStruct) device(dir,interfaceName,choiceName,dataStruct) #dir is null,in,out,fwd, or inout #interfaceName is name of interface record support understands #dataStruct is the name of a struct containg data and configuration info #choiceName is name that is mapped to interface implementation
registrar(functionName) variable(variableName)
Statements for Creating Record Instances
The Following defines a Record Instance:
recordType "recordName" = { info name = {"infoValue"}; fieldName = {fieldValue}; fieldName = type {fieldValue}; /*Only if type is not defined in record*/ fieldName = [capacities] {fieldValue}; /*Only if dim or capacities unknown*/ fieldName = type[capacities] {fieldValue};/*type and capacities unknown*/ fieldName = choiceName {dataStructValue};/*for struct/link/device fields*/ varFields = [number] { {fieldName,interfaceName,choiceName,{dataStructValue}}, ... } ... }
# type is one of bool,...,string # capacitys is one of # capacity 1dim array # capacity,capacity,... ndim array # #fieldValue is scalarValue or structValue or arrayDef or linkValue #dataStructValue is structValue # #where #scalarValue is numValue or stringValue # where # numValue is value # example: The following initializes a float64 field # outputRateOfChange = {1.0}; # stringValue is "value" # example for menu field # scan = {".1 second"}; # example for string field # command = {"getValue\r\n"}; #structValue is fieldValue or name = fieldValue , ... # assume struct(point) {field(x,float64) field(y,float64) field(z,float64)} # example: xxx = { y = 1.0, 2.0}; #arrayDef is rowValue (1dim) or {rowValue}, {rowValue} ... (ndim) # rowValue is fieldValue or [index]=fieldValue , ... # 1dim example: The following perform the same initialization # xxx = [4] {1.0,[2] = 3.0,4.0}; # xxx = [4] {1.0,0.0,3.0,4.0}; # 2dim example: The following all create a 3x3 identity matrix # xxx = [3,3]{ {1, 0, 0} {0, 1, 0} {0, 0, 1}}; # xxx = [3,3]{ {1}, {[1]=1}, {[2]=1}}; # xxx = [3,3]{[0]={1}, [1] = {0, 1}, {0, 0, 1}}; #examples of link/device fields # inp = constant {"stringValue"); # inp = dblink {pvname = "pvname",pp=1,ms=1}; # inp = SomeVMEdevice {card = 0,signal = 2,parm = "parm stuff"} #example of varFields # varFields = [1] {average,computeAverage,value}
General-purpose Statements
include
include "filename"
where
- filename
- Must be a valid filename
Question> Where is this allowed?
#comment
# anything
Anything on a line after a # character is a comment, and will be ignored. This may appear on a line by itself or at the end of another statement.
menu(name) { choice("choiceValue") ... }
where
- name
- Must be a valid C identifier. Each menu must have a unique name.
- choiceValue
- Can be any UTF-8 compatible string
Example:
menu(menuScan) { choice("Passive") choice("Event") choice("I/O Intr") choice("10 second") choice("5 second") choice("2 second") choice("1 second") choice(".5 second") choice(".2 second") choice(".1 second") }
Structures, Record types and Fields
struct
A structure is defined as follows:
struct(name) { field(fieldName,fieldType) {fieldAttributes} ... }
where
- name
- The structure name. It must be a valid C identifier. No two structures can have the same name.
- fieldName
- Must be a valid C identifier
- fieldType
- See fieldType below.
- fieldAttributes
- See fieldAttributes below.
record
A record type is defined as follows:
include "dbCommon.dbd" record(name) extends iocRecord value fieldName { field(fieldName,fieldType) {fieldAttributes} ... }
- name
- The record type name. It must be a valid C identifier. No two record types can have the same name.
- extends iocRecord
- This states that the record type extends the fields defined in iocRecord. iocRecord is described below. It's definition does not have an extends definition.
- value fieldName
- This specifies the name of the default value field, i.e. the default field for CA clients that do not specify a field name. If the record has a field name "value" then this clause does not have to be specified.
- fieldName
- Must be a valid C identifier
- fieldType
- See fieldType below.
- fieldAttributes
- See fieldAttributes below.
fieldType
Both struct and record define a field as:
field(fieldName,fieldType)
The syntax for fieldType depends of the field type.
- Numeric, Octet,and String Types
- The following types have no arguments: bool, int16, uint16, int32, uint32,int64,uint54, float32, float64, octet,and string.
- Examples:
field(description,string) field(value,float64)
- enum
- An enum field also has no argument but has an implicit definition:
- struct() {
- field(index,int16)
- field(choice,array(string[])
- }
- menu
- A menu has the definition:
- menu(name)
- where name is the name of the menu.
- Example:
- field(scan,menu(menuScan))
- struct
- A struct has the definition:
- struct(structName,interfaceName)
- where structName is the name of the struct, which must have been previously defined. andinterfaceName is the optional name of an interface that provides code for the struct.
- Example:
- struct(point) {
- field(x,float64)
- field(y,float64)
- field(z,float64)
- }
- ...
- record(haspoint) extends iocRecord {
- ...
- field(point,struct(point))
- }
- array
- An array has one of the following definitions:
- array(<type>[capacity]) #1dim array
- array(<type>[capacity,...]) #ndim array
- array(<type>) #arbitrary dimensional array
- <type> is any one of bool,...,link. In addition a null is acceptable. In this case the type is determined by record instance definitions.
- capacity is the capacity for each dimension or null. If not specified then record instance determines capacity..
- Examples:
- field(VAL1D,array(float64[])) #1d array with arbitrary capacity
- field(VAL2D,array(float64[,])) #2d array with arbitrary capacities
- field(anyTypeAnyD,array()) #arbitrary type,number of dimensions, and capacities
- private
- This is to allow "private" fields, i.e. fields not meant for use by database or channel access. The syntax is:
- private("valid C definition")
- where a valid C definition must be specified.
- Example:
- field(asp,private("void *"))
- The C definition must not include a field name since the field name in the generated include file is taken from the database definition.
- link and device
- This is for fields that can get or put data from/to a source outside the record. They replace the V3 DBF_XXXLINKs. A link field is similar to the non INP or OUT link fields from V3. A device field is similar to the INP or OUT together with the DTYP fields from V3. A link field obtains it's choices from link definitions. A device field obtains it's choices from device definitions. The main difference between link and device is that record support communicates with link support via a standard interface and with device support via specialized interfaces.
- The syntax is:
- link(linkDirection)
- device(linkDirection,deviceInterface)
- where
- linkDirection is null, in, out, fwd, or inout. If null or inout the direction is determined by the link or device a record instance selects.
- Examples:
- field(disableLink,link(in))
- field(flnk,link(fwd))
- field(inp,device(in,digitalIO))
fieldAttributes
Associated with fieldAttributes are the following "hidden" definitions:
struct(metadata) { field(name,string) field(field,string) #field holding the metadata field(dynamic,bool) } struct(fieldAttribute) { field(asl,int16) {default = 1} field(default,string) field(dct,bool) {default = true} field(mod,bool) {default = true} field(special,bool) field(meta,array(struct(metadata)[])) }
A field definition can have associated fieldAttributes such as:
field(value,float64) { asl = 0, meta = { {"timeStamp",time,1}, #Note that time is defined in iocRecord {"units",units,0} } } ... field(units,string)
The field attributes have the following meaning
- asl
- access security level. Must be 0 or 1
- default
- Default value for a record instance
- dct
- Should Database Configuration Tool allow the field to be configured
- mod
- Can this field be modified via channel access or database links?
- special
- Take special action if field is modified.
- meta
- Defines an array of metadata for the field. Each metadata has the following fields:
- name - The name of the metadata.
- field - The name of a field in the same record that contains the metadata
- dynamic - Is the field dynamic, i.e. can it change because of record processing
Example of metadata definitions
An analog output record can have fields like
record(ao) extends iocRecord { field(value,float64) { ... meta = [3] { {"timeStamp",time,true}, {"displayLimit",displayLimit,false}, {"controlLimit",controlLimit,false} } } field(displayLimit,struct(displayLimit)) field(controlLimit,struct(controlLimit)) ... }
Interfaces, Links and Devices
interface describes choices for code that supports actions associated with record processing. link describes choices for link fields, and device describes choices for device fields.
syntax:
interface(interfaceName,choiceName,dataStructName) link(dir,choiceName,dataStruct) device(dir,interfaceName,choiceName,dataStructName)
where
- interfaceName
- The name of an interface via which record support communicates with device support.
- choiceName
- UTF-8 string that describes the choice
- dir
- Must be one of null,in,out,fwd, or inout. Compatible checks are made to match the interface with a field. What are the rules?????
- dataStructName
- The name of a struct that the interface understands. This interface can contain data and configuration information. The struct must be defined before record instances can be created that assign values to it.
record instance
A record instance has the following syntax
<recordType> "recordName" = { info name = {"infoValue"}; fieldName = {fieldValue}; fieldName = type {fieldValue}; #Only if type is not defined in record fieldName = [capacities] {fieldValue}; #Only if dim or capacities unknown fieldName = type[capacities] {fieldValue}; #Only if type and capacities unknown fieldName = choiceName {dataStructValue}; #for link/device fields varFields = [number] { {fieldName,interfaceName,choiceName,{dataStructValue}}, ... } ... }
where
- recordType
- The name of the record type
- recordName
- The name of the record instance. What restrictions will we place on record instance name? Can this contain non-ascii characters? That is will UTF-8 instance names be supported?
- info name
- provide info for field
- fieldName
- The field name.
- type
- One of the types bool,...,string. This is only specified if the record definition did not specify a type.
- capacities
- The capacities for an array. This can only be specified if the record definition did not define the number of dimensions or the capacities. It has the format:
- capacity,...
- The number of dimensions must agree with what record defined. For example if the record defined that array as array(<type>[]) then only one capacity can be specified. If a record defined array(<type>) than the record instance determines the number of dimensions and the capacities.
- choiceName
- This is for struct, link, and device fields. choiceName is a choice defined in a struct, link, or device definition.
- fieldValue
- The syntax depends on the field type. The details are described next..
fieldValue
The format for fieldValue depends of the field type.
- Single Item Field types
- The following just have a single value: int16, uint16, int32, uint32, uint32, float32, float64, octet, string, enum, menu
- For example
- value = {"1.0"} #Field Definition is float64
- scan = {"1 second"} #Field Definition is menu
- description = {"This is a description"} #Field Definition is string
- junk = {"\x01\x02"} #Field Definition is array(octet[])
- Structure fields
- The syntax follows the C99 syntax for initializing structures. Lets give some examples.
- assume that the following definitions have been made in a dbd file:
- struct(point) {
- field(x,float64)
- field(y,float64)
- field(z,float64)
- }
- ...
- struct (pointdes) {
- field(des,string)
- field(point,struct(point))
- }
- ...
- record(example) extends iocRecord {
- ...
- field(value,struct(pointdes))
- ...
- }
- Then the following are some of the valid ways to initialize the val field of an instance of an example record. They all do the same initialization.
- value = {"this is the value for val.des",{0.0,1.0,2.0}}
- or
- value = {des = "this is the value for val.des",
- {x = 0.0, y =1.0, z = 2.0}}
- or
- value = {"this is the value for val.des", {y =1.0, z = 2.0}}
- Array fields
- The syntax for array fields uses the C99 array initialization syntax. Some examples:
- oneD = [3] {1.0,2.0,3.0}
- #The following creates a 3x3 identity matrix
- twoD = [3,3] { {1},{[1] = 1}, {[2] = 1}}
- #The following initializes an arbitrary type, arbitrary dim matrix
- anyDanyT = int16[3,3] { {1},{[1] = 1}, {[2] = 1}}
- link or device fields
- The syntax is:
- field = choiceName {structValue}
- For link choiceName is one of the choices from link definitions that have compatible directions. For device choiceName is one of the choices from link and device definitions that have compatible directions. structValue is like the value for struct fields where the structure is the dataStruct from the link or device definition which choiceName selected.
- varFields contains user defined fields, i.e. extra fields for the record that are defined for record instances. Each has associated data and code. When a record is processed the associated code is invoked just before alarm and
monitors are processed.
- varFieldsis defined in iocRecord as follows:
- struct(varFields) {
- field(fieldName,string)
- field(interfaceName,string)
- }
- ...
- record(iocRecord) {
- ...
- field(varFields,array(struct(varFields)[]))
- ...
- }
- As an example assume that the following has been defined:
- struct (computeAverageData) {
- field(source,string) #name of field that is to be averaged
- ...
- }
- interface(computeAverageIface,computeAverage,computeAverageData)
- Then a record instance could contain:
- varFields = [1] {average,computeAverage,value}
- This tells computeAverageIface to compute the average of the value field. The result will be stored in user defined field average.
Process Variable Names
A process variable name (PV) follows the C syntax for specifying fields and elements of arrays. A PV can select an elemenentary field, a structure, of an array.
For example if a pvname is:
recordname.f1.f2[ind].f3
Then:
- f1 is a field in recordname which is a structure
- f2 is a field of f1 that is an array of structures
- ind selects a structure from the array of structures
- f3 selects a field from the structure
Example: Assume that the following has been defined;
struct(s2) { ... field(f3,float64) ... } struct(s1) { ... field(f2,struct(s2) [] ) ... } record(sometype) extends iocRecord { ... field(f1,struct(s1)) ... } ... record(sometype,"xxx") { ... f1 = { f2 = [3] {[1] ={f3 = 2.0}}} ... }
Then:
xxx.f1.f2[1].f3
selects the float64 value 2.0
xxx.f1
selects the entire struct s1.
If a client accesses a struct it must know how to access the struct.
Standard Properties
The following is a list of standard metadata names.
- alarmStatus
- The metadata must be defined as:
- {"alarmStatus",alarmStatus,dynamic}
- alarmSeverity
- The metadata must be defined as:
- {alarmSeverity",alarmSeverity,dynamic}
- timeStamp
- The metadata must be defined as:
- {timeStamp",time,dynamic}
- displayLimit
- The metadata must be defined as:
- {displayLimit",<field>}
- where field must be defined as:
- field(<field>,struct(displayLimit)}
- controlLimit
- The metadata must be defined as:
- {controlLimit",<field>}
- where field must be defined as:
- field(<field>,struct(controlLimit))
- alarmLimit
- The metadata must be defined as:
- {alarmLimit",<field>}
- where field must be defined as:
- field(<field>,struct(alarmLimit))
- units
- The metadata must be defined as:
- {units",<field>}
- where field must be defined as:
- field(<field>,string)
dbCommon
NOTE: dbCommon needs work. It should have more structure.
dbCommon.dbd defines the following:
# menu definitions for dbRecordCommon fields menu(menuPriority) { choice("LOW") choice("MEDIUM") choice("HIGH") }
menu(menuScan) { choice("Passive") choice("Event") choice("I/O Intr") choice("10 second") choice("5 second") choice("2 second") choice("1 second") choice(".5 second") choice(".2 second") choice(".1 second") }
menu(menuAlarmSevr) { choice("NO_ALARM") choice("MINOR") choice("MAJOR") choice("INVALID") }
menu(menuConvert) { choice("NO CONVERSION") choice("SLOPE") choice("LINEAR") choice("Breakpoint Table") }
#definition for constant links struct constantlink { field(value,string) } #definitions for ca, da, pv links #dblink must reference a pv in the same ioc. struct(dblink) { field(pvname,string) { link} field(pp,bool) field(ms,bool) } struct(dbfwdlink) {field(pvname,string){link}} #calink forces a link to be a channel access link struct(calink) { field(pvname,string) { link} field(pp,bool) field(ms,bool) } struct(cafwdlink) {field(pvname,string){link}} #pvlink becomes (dblink,calink) if pvname is (local,remote) struct(pvlink) { field(pvname,string) { link} field(pp,bool) field(ms,bool) } struct(pvfwdlink) {field(pvname,string){link}} link(inout,"constant",constantlink) link(inout,"dblink",dblink) link(inout,"calink",calink) link(inout,"pvlink",pvlink) link(fwd,"dblink",dbfwdlink) link(fwd,"calink",cafwdlink) link(fwd,"pvlink",pvfwdlink)
#definitions for common properties struct(timeStamp) { field(secPastEpoch,uint64) field(nsec,uint32) }
iocRecord
iocRecord.dbd, which is part of every record, defines the following:
struct(varFields) { field(fieldName,string) field(interfaceName,string) field(choiceName,string) field(dataStructName,string) } #The following are the fields that must be part of every recordtype #THIS SHOULD BE RESTRUCTURED record(iocRecord) { field(varFields,array(struct(varFields)[])) field(description,string) field(accessSecurityGroup,string) { special } field(scan,menu(menuScan)) { special } field(pini,bool) field(phase,int16) field(eventNumber,int16) { special } field(timeStampEvent,int16) field(timeStampLink,link(in)) field(disableValue,int16) { default("1") } field(disableInput,int16) field(disableLink,link(in)) field(disablePutField,bool) field(process,bool) { special } field(alarmStatus,string) { readonly default("UDF") } field(alarmSeverity,menu(menuAlarmSevr)) { readonly default("INVALID") } field(newAlarmStatus,string) { nodct readonly } field(newAlarmSeverity,menu(menuAlarmSevr)) { nodct readonly } field(alarmAckSeverity,menu(menuAlarmSevr)) { nodct readonly } field(alarmAckTransient,bool) { readonly default("YES") } field(disableAlarmSeverity,menu(menuAlarmSevr)) field(lockCount,int16) { nodct readonly } field(pact,bool) { nodct readonly } field(putFieldProcess,bool) { nodct readonly } field(reprocess,bool) { nodct readonly } field(priority,menu(menuPriority)) { special } field(udf,bool) { default("1") } field(time,struct(timeStamp)) { nodct readonly } field(flnk,link(fwd)) field(monitorLock,private("epicsMutexId")) field(monitorList,private("ELLLIST")) field(asp,private("void *")) field(ppn,private("struct putNotify *") field(ppnr,private("struct putNotifyRecord *")) field(spvt,private("struct scan_element *")) field(rset,private("struct rset *")) field(rdes,private(struct dbRecordType *")) field(lset,private("struct lockRecord *")) }
Example Record Types
aoRecord
aoRecord.dbd defines the following:
include "dbCommon.dbd" record(ao) extends iocRecord { field(value,float64) { asl = 0, meta = { {"timeStamp",time,dynamic}, {"alarmSeverity",alarmSeverity,dynamic}, {"alarmStatus",alarmStatus,dynamic}, {"displayLimit",displayLimit}, {"controlLimit",controlLimit}, {"alarmLimit",alarmLimit}, {"units",units} } } field(outValue,float64) { mod = false, meta = { {"timeStamp",time,dynamic}, {"displayLimit",displayLimit}, {"units",units} } } field(out,device(out,analogOut)) field(outputRateOfChange,float64) field(desiredOutputLink,link(in)) field(closedLoop,bool) field(outputIncremental,bool) field(convert,menu(menuConvert)) { special } field(linearConvert,struct(linearConvert)) { special } field(units,string) field(displayLimit,struct(displayLimit)) field(controlLimit,struct(controlLimit)) field(alarmLimit,struct(alarmLimit)) field(alarmDeadband,float64) field(rawValue,int32) { dct = false, meta{ {"timeStamp",time}} } field(prevRawValue,int32) { dct = false, mod = false, meta{ {"timeStamp",time}} } field(readBackValue,int32) { dct = false, mod = false, meta{ {"timeStamp",time}} } field(oldReadBackValue,int32) { dct = false, mod = false, meta{ {"timeStamp",time}} } field(prevValue,float64) { dct = false, mod = false, } field(lastValueAlarmed,float64) { dct = false, mod = false, } field(pbrk,private("void *")) field(init,bool) { dct = false, mod = false, } field(lbrk,int16) { dct = false, mod = false, meta{ {"timeStamp",time}} } field(simOutputLink,link(out)) field(simModeLink,link(in)) field(simMode,bool) field(simSevr,menu(menuAlarmSevr)) field(invalidAction,menu(menuIvoa)) field(invalidValue,float64) field(outValueModified,bool) { dct = false, mod = false, } }
calcRecord
calcRecord.dbd defines the following:
include "dbCommon.dbd" struct(calcInpLink) { field(link,link(in)) field(value,float64) field(prevValue,float64) } record(calc) extends iocRecord { field(value,float64) { asl = 0, meta = { {"timeStamp",time,dynamic}, {"alarmSeverity",alarmSeverity,dynamic}, {"alarmStatus",alarmStatus,dynamic}, {"displayLimit",displayLimit}, {"alarmLimit",alarmLimit}, {"units",units} } } field(calc,string) { special = true } field(inp,array(struct(calcInpLink)[])) field(units,string) field(displayLimit,struct(displayLimit)) field(alarmLimit,struct(alarmLimit)) field(alarmDeadband,float64) field(lastValueAlarmed,float64) { dct = false, mod = false } field(rpcl,private("char *")) }
mbbiRecord
mbbiRecord.dbd defines the following:
include "dbCommon.dbd" record(mbbi) extends iocRecord { field(value,enum) { asl = 0, meta = { {"timeStamp",time,dynamic}, {"alarmSeverity",alarmSeverity,dynamic}, {"alarmStatus",alarmStatus,dynamic} } } field(mask,array(uint32[])) { special = true } field(nbits,int16) { mod = false } field(inp,device(in,digitalInput)) field(stateSeverity,array(menu(menuAlarmSevr)[])) field(unknownStateSeverity,menu(menuAlarmSevr)) field(changeStateSeverity,menu(menuAlarmSevr)) field(raw,uint32) { dct = false, mod = false } field(oldRaw,uint32) { dct = false, mod = false } field(hardwareMask,uint64 { mod = false } field(lastValueAlarmed,int16) { dct = false, mod = false } field(shift,uint16) { field(simInputLink,link(in)) field(simValue,uint64) field(simModeLink,link(in)) field(simMode,menu(menuYesNo)) field(simSevr,menu(menuAlarmSevr)) }
waveformRecord
waveformRecord.dbd defines the following:
include "dbCommon.dbd" record(waveform) extends iocRecord { field(value,array([])) { asl = 0, special = true, meta = { {"timeStamp",time,dynamic}, {"alarmSeverity",alarmSeverity,dynamic}, {"alarmStatus",alarmStatus,dynamic}, {"displayLimit",displayLimit}, {"units",units} } } field(reArm,bool) field(inp,device(in,waveformIO)) field(units,string) field(displayLimit,struct(displayLimit)) field(busy,bool) { dct = false, mod = false } field(simInputLink,link(in)) field(simModeLink,link(in)) field(simMode,menu(menuYesNo)) field(simSevr,menu(menuYesNo)) }
Record Instance Examples
Initializing link and device fields
In order to support the database and channel access links the following struct definitions are in dbCommon.dbd: constantlink, dblink, dbfwdlink, calink, cafwdlink, pvlink, and pvfwdlink.
Assume that the recordtype definition has:
field(in,link(in))
The dbCommon.dbd definitions are automatically available for this field.
The following creates a record instance with a dblink
in = dblink {"pvname","pp","ms"}
Assume that the recordtype definition has:
field(in,device(in,analogIO))
The dbCommon.dbd definitions are automatically available for this field. Lets assume that the following has also been defined:
struct(vmeLink) { field(card,uint16) field(signal,uint16) field(parm,string) } device(in,analogIO,SomeVMEdevice,vmeLink)
The following creates a record instance connected to a vme device
in = SomeVMEdevice {0,2,"parm stuff"}
Initializing choices associated with an enum field
The following is a record instance that defines an mbbiRecord with three states and initializes the state to state0
mbbiRecord "xxx" = { ... value {0, {[3] {"state0","state1","state2"}}; mask [3] {0x1,0x2,0x4}; ... }
or
mbbiRecord "xxx" = { ... value {index=0, choice={[3] {"state0","state1","state2"}}; mask [3] {0x1,0x2,0x4}; ... }
Initializing an array of structures containing a link field
The calc record is defined as:
struct(calcInpLink) { field(link,link(in)) field(value,float64) field(prevValue,float64) }
record(calc) { ... field(inp,struct(calcInpLink)[]) ... }
The following calc record instance creates 32 input links but only initializes the third link.
calcRecord "xxx" = { ... inp = [32] {[2] = {link = pvlink {"pvname", "npp", "nms"}}} ... }
Initializing an array of arbitrary type
The waveform record is defined as:
record(waveform) { ... field(value,array([])) ... }
The following waveform record instance creates a 1024 element array of doubles. It initializes the 4th element of the array to 1.0. All other elements will be initialized to 0.0.
calcRecord "xxx" = { ... value = float64[1024] {[3] = 1.0} ... }
Unresolved Issues
attributes - dct
Should this be dct(interestLevel)?
mbbi
Currently two fields define the states:
field(value,enum) field(mask,array(uint32[]))
Should there be a way to define these as one field?
- pro -
vdct can prompt for value and mask together
- con -
CA clients dont normally care about the mask values
dynamic metadata
Metadata can be dynamic meaning that the metadata might change as a result of record processing. Is this needed? The answer probably depends on how monitors are implemented. Can an efficient way be found to allow arbitrary metadata to be passed with a monitor or will it be necessary to limit the set of metadata, e.g. only timeStamp, status, and severity can be dynamic properties.
union and extend
Benjamin suggested that the DBD syntax should include union and extend. A limited form of extend is used for record. Is more needed?
prompt and group
This version only describes nodct for fields that DCTs should not show. Is this sufficient?
Scan Mechanism
Andrew gave a suggestion for a better way to define scan types and rates. Should this be considered.
Implementation of special
Unlike V3 attribute special does not have an argument. For fields in iocRecord, iocCore implements special action when the field is modified.
For record type specific fields, the record support must implement a special method. It has a prototype something like:
iocStatus (*special)(iocDbAddr *piocDbAddr)
iocDbAddr will provide information that allows record support to determine the record instance, the field, and the new value to be written to the field. Record support is responsible for writing the new value. It can decide not to write a value. Details TBD.
Implementation of link
In V3 all links except INP,OUT were implemented by dbAccess. V4 provides an inplemention of link support that is similar to the V3 implementation but also allows other implementations. A link is defined as:
link(dir,choiceName,dataStructName)
Record support communicates with the link support code via an interface something like the following:
typedef struct iocLinkSupport { epicsStatus (*connect)(iocDbAddr *piocDbAddr, const char *configName,void *pdataStruct); epicsStatus (*disconnect)(iocDbAddr *piocDbAddr); epicsStatus (*get)(iocDbAddr *piocDbAddr); epicsStatus (*put)(iocDbAddr *piocDbAddr); }iocLinkConnect;
Implementation of device
In V3 all links INP,OUT together with field DTYP were implemented by device support modules. For V4 a device is defined as:
device(dir,interfaceName,choiceName,dataStructName)
pinterface is the address of an implementation of interface iocDeviceConnect, which is something like the following:
typedef struct iocDeviceConnect { epicsStatus (*connect)(iocDbAddr *piocDbAddr, const char *configName,void *pdataStruct); epicsStatus (*disconnect)(iocDbAddr *piocDbAddr); }iocDeviceConnect;