Difference between revisions of "V4 Database Definition"

From EPICSWIKI
(Converted from Marty's HTML page)
 
(Remove comparison with V3. Extent syntax with introspection in mind)
Line 1: Line 1:
= EPICS: IOC Database Definition =
= EPICS: IOC Database Definition =


April 29 2005
May 11 2005
 
 
<center>
 
== Goals ==
 
</center>
 
The following is a brief summary of the goals for the V4 Database Definition.
 
* Data Types
** Support "minimal" set of types, i.e. the minimum set that provides the functionality needed for V4 databases.
** Extensible: struct and array are DBD types
** Character Strings
*** Arbitrary Length
*** UTF-8
** Multidimensional Variable Length Arrays
** All supported types configurable by Database Configuration Tools
For example arrays and structs can be initialized via a DCT
* record and struct fields
** Arrays of most supported types
** metadata for database access
*** Each field can have associated metadata
*** Extensible set of properties
** remove artifical limits. For example allow arrays of link and menus.
* Links
Allow alternative implementations for soft links
* Device Support
Record type independent. Use interface for communication between record and device support..
 
struct can be the way time synchronous gets/puts can be handled. A client can request a get, put, or monitor on a struct and guaranteed that entire set of data is performed with the record containing the struct locked, i.e. no record processing can occur during the get/put. If this is the way time synchronous data is handled, then all the issues of trying to lock sets of record are avoided.


----
----
Line 41: Line 10:
  </center>
  </center>


This chapter describes the Database Definition Syntax for V4 databases. It assumes that the reader is familiar with the EPICS Version 3 (V3) Database Definition Syntax as described in chapter 6 of the [http://www.aps.anl.gov/epics/base/R3-14/7-docs/AppDevGuide.pdf  3.14 Application Developer's Guide]. The new Database Definition Syntax is meant to be used both by iocCore and by Database Configuration Tools (especially VDCT).
This chapter describes the Database Definition Syntax for V4 databases.
The Database Definition Syntax is meant to be used both by iocCore and by Database Configuration Tools (especially VDCT).


This document only describes the V4 Database Definition. Support libraries need to be created to support the V4 database. These will need their own documentation divided into something like the following:
This document describes the V4 Database Definition and C++ class definitions
 
that describe a V4 database.
* EPICS: iocTypes
To complete the design an implementation needs to be described. this design
* EPICS: IOC Database Access
will include the automatic generation of support modules for each record type.
* EPICS: IOC Record Support
 
=== Database Definitions ===
 
The following definitions are discussed:
 
; <b>include</b> - same as V3 include
; <b>menu</b> - like the V3 menu
; <b>struct</b> - New for V4.
; <b>record</b> - like the V3 recordtype
; <b>link</b>
; <b>device</b> - these replace V3 device plus much more
; <b>registrar</b> - same as V3 registrar
; <b>variable</b> - same as V3 variable
; <b>record instances</b> - like the V3 record
 
This document will not discuss the definitions that are the same as for V4.


=== Database Field Types ===
=== Database Field Types ===
Line 69: Line 22:
The V4 database field types are:
The V4 database field types are:


; bool
; <tt>bool</tt>
: A value that is (0,1) meaning (false,true)
: A value that is (0,1) meaning (false,true)
; octet
; <tt>octet</tt>
: A 8 bit byte. Replaces DBF_CHAR and DBF_UCHAR.
: A 8 bit byte. Note that char is not a supported type.
; int16
; <tt>int16</tt>
: Same as V3 DBF_SHORT.
: 16 bit signed interger
; uint16
; <tt>uint16</tt>
: Same as V3 DBF_USHORT.
: 16 bit unsigned interger
; int32
; <tt>int32</tt>
: Same as V3 DBF_LONG.
: 32 bit signed interger
; uint32
; <tt>uint32</tt>
: Same as V3 DBF_ULONG.
: 32 bit unsigned interger
; int64
; <tt>int64</tt>
: New 64 bit integer.
: 64 bit signed interger
; uint64
; <tt>uint64</tt>
: New unsigned 64 bit integer.
: 64 bit unsigned interger
; float32
; <tt>float32</tt>
: Same as V3 DBF_FLOAT.
: IEEE float
; float64
; <tt>float64</tt>
: Same as V3 DBF_DOUBLE.
: IEEE double
; string
; <tt>string</tt>
: Replaces V3 DBF_STRING. Arbitrary length character string. It supports Unicode/UTF-8.
: Arbitrary length character string containing unicode/UTF-8 characters.
; menu
; <tt>menu</tt>
: Like V3 DBF_MENU but with string for choices.
: 16 bit integer that is index of a string array of choices
; enum
; <tt>enum</tt>
: Like V3 DBF_ENUM but with string for choices.
: 16 bit integer and a string array of choices
; struct
; <tt>struct</tt>
: New for V4.
: an ordered set of other database field types
; link
; <tt>link</tt>
; device
: a link to data outside the record
: link and device are new for V4. Extensible replacement for V3 DBF_XXXLINK and DTYP
; <tt>device</tt>
; array
: a link to associated device support
: Multidimensional arrays are now a field type
; <tt>array</tt>
; private
: Multidimensional arrays are a field type
: Like V3 DBF_NOACCESS but new syntax.
; <tt>private</tt>
 
: a valid <tt>C</tt> type that is private to database access and/or record support
----
<center>


== V3 features not in V4 ==
=== Database Statements ===


</center>
The following statements are discussed:


=== V3 field types that do not exist in V4 ===
; <tt>include</tt> - include statements from a file
; <tt>#comment</tt> - comment statements
; <tt>menu</tt> - define a set of choices
; <tt>struct</tt> - like a C structure
; <tt>record</tt> - defines a record type
; <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
; <tt>registrar</tt> - same as V3 registrar
; <tt>variable</tt> - same as V3 variable
; <tt>record instances</tt> - describes a record instance


The following V3 field types no longer exist:


; DBF_CHAR
----
: Replaced by octet but no arithmetic or conversions are supported.
; DBF_UCHAR
: Replaced by octet but no arithmetic or conversions are supported.
; DBF_DEVICE
: Replaced by device.
; DBF_INLINK
: Replaced by link and device
; DBF_OUTLINK
: Replaced by link and device
; DBF_FWDLINK
: Replaced by link and device


=== V3 Database Definitions not in V4 ===
; path
: No longer needed.
; addpath
: No longer needed.
; driver
: Drivers must develop another way to configure and report. asynDrivers already has replacements.
; breaktable
: A replacement will be created. What!!!!
=== V3 field attributes not in V4 ===
; pp
: Is this part of CA V4? It should be.
; base
: This was needed for 3.12 releases. It is no longer needed.
; size
: Not needed since string is arbitrary length string.
; extra
: New syntax replaces this.
; menu
: New syntax replaces this.
; interest
: Only used by dbpr. Find a better way!!!
; prompt and group
: Replaced by struct, arbitrary length field names, and nodct.
----
<center>
<center>


Line 163: Line 83:


  </center>
  </center>
=== Statements for Record Types ===


  <nowiki>include "filename"
 
  include "filename"
  #comment
  #comment
  menu(name) {
  menu(name) {
Line 172: Line 94:


  struct(name) {
  struct(name) {
     field(field_name,field_definition) {field_attributes}
     field(field_name,field_type) {field_attributes}
     ...
     ...
  }
  }


  record(name) extends iocRecord {
  record(name) extends iocRecord value field_name{
    include "filename"
# field_name is name of default value field.
     field(field_name,field_definition) {field_attributes}
# Not needed if value is the name of a first level field
     field(field_name,field_type) {field_attributes}
     ...
     ...
  }
  }
  #If field_definition is empty record instance determines type
  #If field_type is empty record instance determines type
  #    must be one of bool,...,string
  #    must be one of bool,...,string
  #field_definition is one of the following:
  #field_type is one of the following:
     bool
     bool
     octet
     octet
Line 202: Line 125:
           # }
           # }
     struct(structName,interfaceName)
     struct(structName,interfaceName)
          #interfaceName (optional) is the name of the associated interface
     link(direction)
     link(direction)
          #direction is null,in,out,fwd, or inout
     device(direction,interfaceName)
     device(direction,interfaceName)
           #direction is null,in,out,fwd, or inout
           #direction is null,in,out,fwd, or inout
           #interfaceName is the name of the record/device interface
           #interfaceName is the name of the associated interface


     # an array field_definition has one of the following forms
     # an array field_type 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 217: Line 142:
     private("valid C type") #must NOT include field name
     private("valid C type") #must NOT include field name


  #field_attributes is any combination of the following:
  #field attributes is assignment of fields from the following:
     asl(asl_level)
     struct(metadata) {
    default("default_value")
        field(name,string)
     nodct
        field(field,string) #field holding the metadata
     readonly
        field(dynamic,bool)
    special
     }
    link                          #This field is a link to another record
     struct(field_attribute) {
    metadata(name,field,dynamic) #multiple properties can be specified
        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)
=== Statements for Accessing data/code related to the record ===
  link(dir,choiceName,configStruct)
  interface(interfaceName,choiceName,dataStruct)
  device(dir,interfaceName,choiceName,configStruct)
  link(dir,choiceName,dataStruct)
  device(dir,interfaceName,choiceName,dataStruct)
     #dir is null,in,out,fwd, or inout
     #dir is null,in,out,fwd, or inout
     #interfaceName is name of interface record support understands
     #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
     #choiceName is name that is mapped to interface implementation
    #configStruct is struct containing configuration information


  registrar(function_name)
  registrar(function_name)
  variable(variable_name)
  variable(variable_name)


=== Statements for Creating Record Instances ===
  #The Following defines a Record Instance
  #The Following defines a Record Instance


  recordType "recordName" = {
  recordType "recordName" = {
    include "filename"
     info name = {"info_value"};
     info name = {"info_value"};
     fieldName = {fieldValue};
     fieldName = {fieldValue};
Line 247: Line 178:
     fieldName = [capacities] {fieldValue}; /*Only if dim or capacities unknown*/
     fieldName = [capacities] {fieldValue}; /*Only if dim or capacities unknown*/
     fieldName = type[capacities] {fieldValue};/*type and capacities unknown*/
     fieldName = type[capacities] {fieldValue};/*type and capacities unknown*/
     fieldName = choiceName {configStructValue};/*for struct/link/device fields*/
     fieldName = choiceName {dataStructValue};/*for struct/link/device fields*/
    varFields = [number] {
              {field_name,interfaceName,choiceName,{dataStructValue}},
                ...
          }
     ...
     ...
  }
  }


  # type is one of bool,...,string
  # type is one of bool,...,string
  # capacity is one of
  # capacitys is one of
  #  capacity    1dim array
  #  capacity    1dim array
  #  capacity,capacity,...  ndim array
  #  capacity,capacity,...  ndim array
  #   
  #   
  #fieldValue is scalar_value or struct_value or array_def or link_value
  #fieldValue is scalar_value or struct_value or array_def or link_value
#dataStructValue is struct_value
#
  #where
  #where
  #scalar_value is num_value or string_value
  #scalar_value is num_value or string_value
Line 283: Line 220:
  #    inp = constant {"stringValue");
  #    inp = constant {"stringValue");
  #    inp = dblink {pvname = "pvname",pp=1,ms=1};
  #    inp = dblink {pvname = "pvname",pp=1,ms=1};
  #    inp = SomeVMEdevice {card = 0,signal = 2,parm = "parm stuff"}</nowiki>
  #    inp = SomeVMEdevice {card = 0,signal = 2,parm = "parm stuff"}
#example of varFields
# varFields = [1] {average,computeAverage,value}
 
----
<center>
 
== include ==
 
</center>
 
include "filename"
 
where
 
; <tt>filename</tt>
: Must be a valid filename
<tt>Question></tt> Where is this allowed?
----
 
<center>
 
== #comment ==
 
</center>
 
# anything
 
Anything after <tt>#<tt> is a comment. This may appear on a line by itself or at the end of another statement.


----
----
Line 301: Line 266:
; <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>filename</tt>
: Must be a valid filename
; <tt>choice_value</tt>
; <tt>choice_value</tt>
: Can be any UTF-8 compatible string
: Can be any UTF-8 compatible string
Line 320: Line 283:
     choice(".1 second")
     choice(".1 second")
  }
  }


----
----
Line 333: Line 297:


  struct(name) {
  struct(name) {
     field(field_name,field_definition) {field_attributes}
     field(field_name,field_type) {field_attributes}
     ...
     ...
  }
  }
Line 343: Line 307:
; <tt>field_name</tt>
; <tt>field_name</tt>
: Must be a valid C identifier
: Must be a valid C identifier
; <tt>field_definition</tt>
; <tt>field_type</tt>
: See field_definition below.
: See field_type below.
; <tt>field_attributes</tt>
; <tt>field_attributes</tt>
: See field_attributes below.
: See field_attributes below.
Line 353: Line 317:


  include "dbCommon.dbd"
  include "dbCommon.dbd"
  record(name) extends iocRecord {
  record(name) extends iocRecord value field_name {
     field(field_name,field_definition) {field_attributes}
     field(field_name,field_type) {field_attributes}
     ...
     ...
  }
  }
Line 360: Line 324:
; <tt>name</tt>
; <tt>name</tt>
: The record type name. It must be a valid C identifier. No two record types can have the same name.
: The record type name. It must be a valid C identifier. No two record types can have the same name.
; <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.
; <tt>value field_name</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.
; <tt>field_name</tt>
; <tt>field_name</tt>
: Must be a valid C identifier
: Must be a valid C identifier
; <tt>field_definition</tt>
; <tt>field_type</tt>
: See field_definition below.
: See field_type below.
; <tt>field_attributes</tt>
; <tt>field_attributes</tt>
: See field_attributes below.
: See field_attributes below.


=== field_definition ===
=== field_type ===


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_name,field_type)


    field(field_name,field_definition)
The syntax for <tt>field_type</tt> depends of the field type.


The syntax for <tt>field_definition</tt> depends of the field type.
; Numeric, Octet,and String Types
: The following types have no arguments: <tt>bool, int16, uint16, int32, uint32,int64,uint54, float32, float64, octet,and string</tt>.
: Examples:
        field(description,string)
        field(value,float64)
; enum
: An <tt>enum</tt> field also has no argument but has an implicit definition:
:        struct() {
:            field(index,int16)
:            field(choice,array(string[])
:        }
; menu
: A <tt>menu</tt> has the definition:
:          menu(name)
: where <tt>name</tt> is the name of the menu.
: Example:
:        field(scan,menu(menuScan))
; struct
: A <tt>struct</tt> has the definition:
:        struct(structName,interfaceName)
: where <tt>structName</tt> is the name of the struct, which must have been previously defined. and<tt>interfaceName</tt> 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
: <tt><type></tt> is any one of bool,...,link. In addition a null is acceptable. In this case the type is determined by record instance definitions.
: <tt>capacity</tt> 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 <tt>C</tt> definition must be specified.
: Example:
:            field(asp,private("void *"))
: The <tt>C</tt> definition must <tt>not</tt> 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
: <tt>linkDirection</tt> is <tt> null, in, out, fwd, </tt>or <tt>inout</tt>. If <tt>null</tt> or <tt>inout</tt> the direction is determined by the <tt>link</tt> or <tt>device</tt> a record instance selects.
: Examples:
:            field(disableLink,link(in))
:            field(flnk,link(fwd))
:            field(inp,device(in,digitalIO))


* Numeric, Octet,and String Types
=== field_attributes ===
The following types have no arguments: <tt>bool, int16, uint16, int32, uint32,int64,uint54, float32, float64, octet,and string</tt>.
Example:
    field(description,string)
    field(value,float64)
* enum
An <tt>enum</tt> field also has no argument but has an implicit <tt>int32</tt> and <tt>array(string[])</tt>.
struct() {
    field(index,int16)
    field(choice,array(string[])
}
* menu
A <tt>menu</tt> has the definition:
menu(name)
where
*; <tt>name</tt>
*: The name of the menu.
Example:
      field(SCAN,menu(menuScan))
* struct
A <tt>struct</tt> has the definition:
struct(structName,interfaceName)
where
*; <tt>structName</tt>
*: The name of the struct, which must have been previously defined.
*; <tt>interfaceName</tt>
*: The 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
where
*; <tt><type></tt>
*: Any one of bool,...,link. In addition a null is acceptable. In this case the type is determined by record instance definitions.
*; <tt>capacity</tt>
*: 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 <tt>C</tt> definition must be specified.
Example:
    field(asp,private("void *"))
The <tt>C</tt> definition must <b>not</b> include a field name since the field name in the generated include file is taken from the database definition.
* link 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
*; <tt>linkDirection</tt>
*;
*: one of null, "in", "out", "fwd", or "inout". If null or inout, i.e. the
direction is determined by the <tt>link</tt> or <tt>device</tt> a record instance selects.
Examples:
    field(disableLink,link(in))
    field(flnk,link(fwd))
    field(inp,device(in,digitalIO))


=== field_attributes ===
Associated with field_attributes are the following "hidden" definitions:


field_attributes can be any combination of the following:
    struct(metadata) {
        field(name,string)
        field(field,string) #field holding the metadata
        field(dynamic,bool)
    }
    struct(field_attribute) {
        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)[]))
      }


    asl(asl_level)
A field definition can have associated field_attributes such as:
    default("default_value")
    field(value,float64) {
    nodct
        asl = 0,
    readonly
        meta = {
    special
          {"timeStamp",time,1}, #Note that time is defined in iocRecord
    link
          {"units",units,0}
    metadata(name,field,dynamic)
        }
    }
    ...
    field(units,string)
       
The field attributes have the following meaning


; asl
; <tt>asl</tt>
: access security level. Must be 0 or 1
: access security level. Must be 0 or 1
; default
; <tt>default</tt>
: Default value
: Default value for a record instance
; nodct
; <tt>dct</tt>
: Database Configuration Tool should not show
: Should Database Configuration Tool allow the field to be configured
; readonly
; <tt>mod</tt>
: This field can not be modified via channel access or database links
: Can this field be modified via channel access or database links?
; special
; <tt>special</tt>
: Take special action if field is modified.
: Take special action if field is modified.
; link
; <tt>meta</tt>
: The field is a link to another record. This attribute is normally only defined for a <tt>field</tt> in a <tt>struct</tt> that is referenced in a <tt>link</tt> or <tt>device</tt> definition For example <tt>struct(pvlink)</tt> specifies the <tt>link</tt> <tt>attribute</tt> for <tt>field</tt> <tt>pvname</tt>.
: Defines an array of metadata for the field. Each metadata has the following fields:
; metadata
* <tt>name</tt> - The name of the metadata.
: Defines a metadata for the field. Multiple metadata attributes can be defined for a field.
* <tt>field</tt> - The name of a field in the same record that contains the metadata
;; <tt>name</tt>
* <tt>dynamic</tt> - Is the field dynamic, i.e. can it change because of record processing
:: The name of the metadata.
;; <tt>field</tt>
:: The name of a field in the same record.
;; <tt>dynamic</tt>
:: must be <tt>static</tt> or <tt>dynamic</tt>. The default is <tt>static</tt>. <tt>dynamic</tt> means that the value may change because of record processing. <tt>static</tt> means that the value does not change because of record processing. <tt>time</tt> is an example of a dynamic field and <tt>displayLimit</tt> is an example of a static field.


==== Example of metadata definitions ====
==== Example of metadata definitions ====
Line 488: Line 457:
  record(ao) extends iocRecord {
  record(ao) extends iocRecord {
     field(value,float64) {
     field(value,float64) {
        metadata("timeStamp",time,dynamic)
        metadata("displayLimit",displayLimit)
        metadata("controlLimit",controlLimit)
         ...
         ...
        meta = [3] {
            {"timeStamp",time,true},
            {"displayLimit",displayLimit,false},
            {"controlLimit",controlLimit,false}
        }
     }
     }
     field(displayLimit,struct(displayLimit))
     field(displayLimit,struct(displayLimit))
Line 501: Line 472:
<center>
<center>


== link and device ==
== interface link and device ==


  </center>
  </center>


<tt>interface</tt> describes choices for code that supports
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.


the syntax:
syntax:


  link(dir,choiceName,configStruct)
interface(interfaceName,choiceName,dataStruct)
  device(dir,interfaceName,choiceName,configStruct)
  link(dir,choiceName,dataStruct)
  device(dir,interfaceName,choiceName,dataStruct)


where
where


; <tt>interfaceName</tt>
: The name of an interface via which record support communicates with device support.
; <tt>choiceName</tt>
; <tt>choiceName</tt>
: UTF-8 string that describes the choice
: UTF-8 string that describes the choice
; <tt>dir</tt>
; <tt>dir</tt>
: 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?????
: 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>configStruct</tt>
; <tt>dataStruct</tt>
: The name of a <tt>struct</tt> for configuration information
: 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.
; <tt>interfaceName</tt>
: The name of an interface via which record support communicates with device support.


----
----
Line 538: Line 512:
     fieldName = [capacities] {fieldValue}; #Only if dim or capacities unknown
     fieldName = [capacities] {fieldValue}; #Only if dim or capacities unknown
     fieldName = type[capacities] {fieldValue}; #Only if type and capacities unknown
     fieldName = type[capacities] {fieldValue}; #Only if type and capacities unknown
     fieldName = choiceName {configStructValue}; #for link/device fields   
     fieldName = choiceName {dataStructValue}; #for link/device fields   
    varFields = [number] {
                  {field_name,interfaceName,choiceName,{dataStructValue}},
                  ...
    }
     ...
     ...
  }
  }
Line 549: Line 527:
: 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>
: Like V3 except new syntax
: provide info for field
; <tt>fieldName</tt>
; <tt>fieldName</tt>
: The field name.
: The field name.
Line 556: Line 534:
; <tt>capacities</tt>
; <tt>capacities</tt>
: 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:  
: 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,...
:        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.
: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.
; <tt>choiceName</tt>
; <tt>choiceName</tt>
: This is the syntax 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>field_value</tt>
; <tt>field_value</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..
=== <tt>field_value</tt> ===


The format for <tt>field_value</tt> depends of the field type.
The format for <tt>field_value</tt> depends of the field type.


* Single Item Field types  
; Single Item Field types  
The following just have a single value: int16, uint16, int32, uint32, uint32, float32, float64, octet, string, enum, menu
: The following just have a single value: <tt>int16, uint16, int32, uint32, uint32, float32, float64, octet, string, enum, menu</tt>
For example
: For example
    value = {"1.0"} #Field Definition is float64
:        value = {"1.0"} #Field Definition is float64
    scan = {"1 second"} #Field Definition is menu
:        scan = {"1 second"} #Field Definition is menu
    description = {"This is a description"} #Field Definition is string
:        description = {"This is a description"} #Field Definition is string
    junk = {"\x01\x02"} #Field Definition is array(octet[])
:        junk = {"\x01\x02"} #Field Definition is array(octet[])
* Structure fields  
; Structure fields  
The syntax follows the C99 syntax for initializing structures. Lets give some examples.
: 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:
: assume that the following definitions have been made in a dbd file:
struct(point) {
:        struct(point) {
    field(x,float64)
:            field(x,float64)
    field(y,float64)
:            field(y,float64)
    field(z,float64)
:            field(z,float64)
}
:        }
...
:        ...
struct (pointdes) {
:        struct (pointdes) {
    field(des,string)
:            field(des,string)
    field(point,struct(point))
:            field(point,struct(point))
}
:        }
...
:        ...
record(example) extends iocRecord {
:        record(example) extends iocRecord {
...
:        ...
    field(value,struct(pointdes))
:            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.
: 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}}
:        value = {"this is the value for val.des",{0.0,1.0,2.0}}
    or
:        or
    value = {des = "this is the value for val.des",
:        value = {des = "this is the value for val.des",
              {x = 0.0, y =1.0, z = 2.0}}
:                  {x = 0.0, y =1.0, z = 2.0}}
    or
:        or
    value = {"this is the value for val.des", {y =1.0, z = 2.0}}
:        value = {"this is the value for val.des", {y =1.0, z = 2.0}}
* Array fields  
; Array fields  
The syntax for array fields uses the C99 array initialization syntax. Some examples:
: The syntax for array fields uses the C99 array initialization syntax. Some examples:
    oneD = [3] {1.0,2.0,3.0}
:        oneD = [3] {1.0,2.0,3.0}
    #The following creates a 3x3 identity matrix
:        #The following creates a 3x3 identity matrix
    twoD = [3,3] { {1},{[1] = 1}, {[2] = 1}}
:        twoD = [3,3] { {1},{[1] = 1}, {[2] = 1}}
    #The following initializes an arbitrary type, arbitrary dim matrix
:        #The following initializes an arbitrary type, arbitrary dim matrix
    anyDanyT = int16[3,3] { {1},{[1] = 1}, {[2] = 1}}
:        anyDanyT = int16[3,3] { {1},{[1] = 1}, {[2] = 1}}
* link or device fields  
; link or device fields  
The syntax is:
:The syntax is:
    field = choiceName {struct_value}
:        field = choiceName {struct_value}
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. struct_value is like the value for struct fields where the structure is the configStruct from the link or device definition which choiceName selected.
: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. struct_value 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
monitors are processed.
: <tt>varFields</tt>is defined in <tt>iocRecord</tt> as follows:
:        struct(varFields) {
:            field(field_name,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.


----
----
Line 676: Line 678:
The following is a list of standard metadata names.
The following is a list of standard metadata names.


* alarmStatus  
; alarmStatus  
The metadata must be defined as:
: The metadata must be defined as:
metadata("alarmStatus",alarmStatus,dynamic)
:    {"alarmStatus",alarmStatus,dynamic}
* alarmSeverity  
; alarmSeverity  
The metadata must be defined as:
: The metadata must be defined as:
metadata("alarmSeverity",alarmSeverity,dynamic)
:    {alarmSeverity",alarmSeverity,dynamic}
* timeStamp  
; timeStamp  
The metadata must be defined as:
: The metadata must be defined as:
metadata("timeStamp",time,dynamic)
:    {timeStamp",time,dynamic}
* displayLimit  
; displayLimit  
The metadata must be defined as:
: The metadata must be defined as:
metadata("displayLimit",<field>)
:    {displayLimit",<field>}
where field must be defined as:  
: where field must be defined as:  
field(<field>,struct(displayLimit))
:    field(<field>,struct(displayLimit)}
* controlLimit  
; controlLimit  
The metadata must be defined as:
:The metadata must be defined as:
metadata("controlLimit",<field>)
:    {controlLimit",<field>}
where field must be defined as:  
: where field must be defined as:  
field(<field>,struct(controlLimit))
:    field(<field>,struct(controlLimit))
* alarmLimit  
; alarmLimit  
The metadata must be defined as:
: The metadata must be defined as:
metadata("alarmLimit",<field>)
:    {alarmLimit",<field>}
where field must be defined as:  
: where field must be defined as:  
field(<field>,struct(alarmLimit))
:    field(<field>,struct(alarmLimit))
* units  
; units  
The metadata must be defined as:
: The metadata must be defined as:
metadata("units",<field>)
:    {units",<field>}
where field must be defined as:  
: where field must be defined as:  
field(<field>,string)
:    field(<field>,string)


----
----
Line 717: Line 719:
<tt>dbCommon.dbd</tt> defines the following:
<tt>dbCommon.dbd</tt> defines the following:


  <nowiki># menu definitions for dbRecordCommon fields
  # menu definitions for dbRecordCommon fields
  menu(menuPriority) {
  menu(menuPriority) {
     choice("LOW")
     choice("LOW")
Line 789: Line 791:
     field(secPastEpoch,uint64)
     field(secPastEpoch,uint64)
     field(nsec,uint32)
     field(nsec,uint32)
  }</nowiki>
  }


----
----
Line 800: Line 802:
<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:


  <nowiki>include "dbCommon.dbd"
  struct(varFields) {
        field(field_name,string)
        field(interfaceName,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
  #THIS SHOULD BE RESTRUCTURED
  #THIS SHOULD BE RESTRUCTURED
  record(iocRecord) {
  record(iocRecord) {
    field(varFields,array(struct(varFields)[]))
     field(description,string)
     field(description,string)
     field(accessSecurityGroup,string) {
     field(accessSecurityGroup,string) {
Line 889: Line 895:
     field(lset,private("struct lockRecord *"))
     field(lset,private("struct lockRecord *"))
  }
  }
  </nowiki>
=== Comparison between V3 and V4 ===
The following discusses the differences between the fields defined in V3 dbCommon.dbd and V4 iocRecord.dbd. The NOACCESS (now private) fields are not discussed.
; NAME
: Does not exist.
; DESC => description
: Name change and now arbitrary length UTF-8 string
; ASG => accessSecurityGroup
: Name change and now arbitrary length UTF-8 string
; SCAN => scan
: Case change
; PINI => pini
: Case change and type is now bool
; PHAS => phase
: Case change
; EVNT => eventNumber
: Name change
; TSE => timeStampEvent
: Name change
; TSEL => timeStampLink
: Name change
; DTYP
: No longer exists. Replaced by device
; DISV => disableValue
: Name change
; DISA => disableInput
: Name change
; SDIS => disableLink
: Name change
; DISP => disablePutField
: Name change and now bool
; PROC => process
: Name change and now bool
; STAT => alarmStatus
: Name change
; SEVR => alarmSeverity
: Name change
; NSTA => newAlarmStatus
: Name change
; NSEV => newAlarmSeverity
: Name change
; ACKS => alarmAckSeverity
: Name change
; ACKT => alarmAckTransient
: Name change and now bool
; DISS => disableAlarmSeverity
: Name change
; LCNT => lockCount
: Name change and now int16
; PACT => pact
: Case change and now bool
; PUTF => putFieldProcess
: Name change and now bool
; RPRO => reprocess
: Name change and now bool
; PRIO => priority
: Name change
; TPRO => reprocess
: No longer exists. Replaced by new tracing facility.
; UDF => udf
: Case change and now bool
; TIME => time
: Case change and now struct
; FLNK => flnk
: Case change and now link


----
----
Line 970: Line 908:
  record(ao) extends iocRecord {
  record(ao) extends iocRecord {
     field(value,float64) {
     field(value,float64) {
         asl(0)
         asl = 0,
         metadata("timeStamp",time,dynamic)
         meta = {
        metadata("alarmSeverity",alarmSeverity,dynamic)
            {"timeStamp",time,dynamic},
        metadata("alarmStatus",alarmStatus,dynamic)
            {"alarmSeverity",alarmSeverity,dynamic},
        metadata("displayLimit",displayLimit)
            {"alarmStatus",alarmStatus,dynamic},
        metadata("controlLimit",controlLimit)
            {"displayLimit",displayLimit},
        metadata("alarmLimit",alarmLimit)
            {"controlLimit",controlLimit},
        metadata("units",units)
            {"alarmLimit",alarmLimit},
            {"units",units}
        }
     }
     }
     field(outValue,float64) {
     field(outValue,float64) {
         nodct
         mod = false,
         metadata("timeStamp",time,dynamic)
         meta = {
        metadata("displayLimit",displayLimit)
            {"timeStamp",time,dynamic},
        metadata("units",units)
            {"displayLimit",displayLimit},
            {"units",units}
        }
     }
     }
     field(out,device(out,analogOut))
     field(out,device(out,analogOut))
Line 1,002: Line 944:
     field(alarmDeadband,float64)
     field(alarmDeadband,float64)
     field(rawValue,int32) {
     field(rawValue,int32) {
         nodct
         dct = false,
         metadata("timeStamp",time)
         meta{{"timeStamp",time}}
     }
     }
     field(prevRawValue,int32) {
     field(prevRawValue,int32) {
         nodct
         dct = false,
         readonly
         mod = false,
         metadata("timeStamp",time)
         meta{{"timeStamp",time}}
     }
     }
     field(readBackValue,int32) {
     field(readBackValue,int32) {
         nodct
         dct = false,
         readonly
         mod = false,
         metadata("timeStamp",time)
         meta{{"timeStamp",time}}
     }
     }
     field(oldReadBackValue,int32) {
     field(oldReadBackValue,int32) {
         nodct
         dct = false,
         readonly
         mod = false,
         metadata("timeStamp",time)
         meta{{"timeStamp",time}}
     }
     }
     field(prevValue,float64) {
     field(prevValue,float64) {
         nodct
         dct = false,
         readonly
         mod = false,
     }
     }
     field(lastValueAlarmed,float64) {
     field(lastValueAlarmed,float64) {
         nodct
         dct = false,
         readonly
         mod = false,
     }
     }
     field(pbrk,private("void *"))
     field(pbrk,private("void *"))
     field(init,bool) {
     field(init,bool) {
         nodct
         dct = false,
         readonly
         mod = false,
     }
     }
     field(lbrk,int16) {
     field(lbrk,int16) {
         nodct
         dct = false,
         readonly
         mod = false,
         metadata("timeStamp",time)
         meta{{"timeStamp",time}}
     }
     }
     field(simOutputLink,link(out))
     field(simOutputLink,link(out))
Line 1,045: Line 987:
     field(invalidValue,float64)
     field(invalidValue,float64)
     field(outValueModified,bool) {
     field(outValueModified,bool) {
         nodct
         dct = false,
         readonly
         mod = false,
     }
     }
  }
  }
=== Comparison between V3 and V4 ===
The following discusses the differences between the fields defined in V3 and V4 aoRecord.dbd. The NOACCESS (now private) fields are not discussed.
; VAL => value
: Name change.
; OVAL => outValue
: Name change.
; OUT => out
: Case change and now device.
; OROC => outputRateOfChange
: Name change.
; DOL => desiredOutputLink
: Name change.
; OMSL => closedLoop
: Name change and now bool.
; OIF => outputIncremental
: Name change and now bool.
; PREC
: No longer supported
; LINR,EGUF,EGUL,ESLO,EOFF => linearConvert
: Handled via struct
; EGU => units
: Name change
; ROFF
: Obsolete
; HOPR,LOPR => displayLimit
: Now implemented via array
; DRVH,DRVL => controlLimit
: Now implemented via array
; AOFF,ASLO
: No longer supported.
; HIHI,LOLO,HIGH,LOW => alarmLimit
: Now implemented via struct
; HHSV,LLSV,HSV,LSV => alarmLimit
: Now implemented via struct
; HYST => alarmDeadband
: Name change
; ADEL,MDEL,ALST,MLST
: Replaced by new CA functionality. Is it???
; RVAL => rawValue
: Name change
; ORAW => prevRawValue
: Name change
; RBV => readBackValue
: Name change
; ORBV => oldReadBackValue
: Name change
; PVAL => prevValue
: Name change
; LALM => lastValueAlarmed
: Name change
; INIT => init
: Case change
; LBRK => lbrk
: Case change
; SIOL => simOutputLink
: Name change
; SIML => simModeLink
: Name change
; SIMM => simMode
: Name change
; SIMS => simSevr
: Name change
; IVOA => invalidAction
: Name change
; IVOV => invalidValue
: Name change
; OMOD => outValueModified
: Name change


----
----
Line 1,138: Line 1,009:
  record(calc) extends iocRecord {
  record(calc) extends iocRecord {
     field(value,float64) {
     field(value,float64) {
         asl(0)
         asl = 0,
         metadata("timeStamp",time,dynamic)
         meta = {
        metadata("alarmSeverity",alarmSeverity,dynamic)
            {"timeStamp",time,dynamic},
        metadata("alarmStatus",alarmStatus,dynamic)
            {"alarmSeverity",alarmSeverity,dynamic},
        metadata("displayLimit",displayLimit)
            {"alarmStatus",alarmStatus,dynamic},
        metadata("alarmLimit",alarmLimit)
            {"displayLimit",displayLimit},
        metadata("units",units)
            {"alarmLimit",alarmLimit},
            {"units",units}
        }
     }
     }
     field(calc,string) {
     field(calc,string) {
         special
         special = true
     }
     }
     field(inp,array(struct(calcInpLink)[]))
     field(inp,array(struct(calcInpLink)[]))
Line 1,155: Line 1,028:
     field(alarmDeadband,float64)
     field(alarmDeadband,float64)
     field(lastValueAlarmed,float64) {
     field(lastValueAlarmed,float64) {
         nodct
         dct = false,
         readonly
         mod = false
     }
     }
     field(rpcl,private("char *"))
     field(rpcl,private("char *"))
  }
  }
=== Comparison between V3 and V4 ===
The following discusses the differences between the fields defined in V3 and V4 calcRecord.dbd. The NOACCESS (now private) fields are not discussed.
; VAL => value
: Name change.
; CALC => calc
: Case change. What is new syntax?
; INPA,...INPL A,...L LA,...LL => inp
: Now implemented via array of structures. Record instances can create as many array elements as needed.
; EGU => units
: Name change.
; PREC
: No longer supported
; HOPR,LOPR => displayLimit
: Now implemented via struct
; HIHI,LOLO,HIGH,LOW => alarmLimit
: Now implemented via struct
; HHSV,LLSV,HSV,LSV => alarmLimit
: Now implemented via struct
; HYST => alarmDeadband
: Name change
; LALM => lastValueAlarmed
: Name change
; RPCL => rpcl
: Case change


----
----
Line 1,200: Line 1,046:
  record(mbbi) extends iocRecord {
  record(mbbi) extends iocRecord {
     field(value,enum) {
     field(value,enum) {
         asl(0)
         asl = 0,
         metadata("timeStamp",time,dynamic)
         meta = {
        metadata("alarmSeverity",alarmSeverity,dynamic)
            {"timeStamp",time,dynamic},
        metadata("alarmStatus",alarmStatus,dynamic)
            {"alarmSeverity",alarmSeverity,dynamic},
            {"alarmStatus",alarmStatus,dynamic}
        }
     }
     }
     field(mask,array(uint32[])) {
     field(mask,array(uint32[])) {
         special
         special = true
     }
     }
     field(nbits,int16) {
     field(nbits,int16) {
         readonly
         mod = false
     }
     }
     field(inp,device(in,digitalInput))
     field(inp,device(in,digitalInput))
Line 1,216: Line 1,064:
     field(changeStateSeverity,menu(menuAlarmSevr))
     field(changeStateSeverity,menu(menuAlarmSevr))
     field(raw,uint32) {
     field(raw,uint32) {
         nodct
         dct = false, mod = false
        readonly
     }
     }
     field(oldRaw,uint32) {
     field(oldRaw,uint32) {
         nodct
         dct = false, mod = false
        readonly
     }
     }
     field(hardwareMask,uint64 {
     field(hardwareMask,uint64 {
         readonly
         mod = false
     }
     }
     field(lastValueAlarmed,int16) {
     field(lastValueAlarmed,int16) {
         nodct
         dct = false, mod = false
        readonly
     }
     }
     field(shift,uint16) {
     field(shift,uint16) {
Line 1,237: Line 1,082:
     field(simSevr,menu(menuAlarmSevr))
     field(simSevr,menu(menuAlarmSevr))
  }
  }
=== Comparison between V3 and V4 ===
The following discusses the differences between the fields defined in V3 and V4 mbbiRecord.dbd. The NOACCESS (now private) fields are not discussed.
; VAL => value
: Name change. Now enum
; INP => inp
: Case change and now device.
; NOBT => nbits
: Name change.
; ZRVL,...,FFVL => mask
: Implemented via array. Record instances determine number of elements
; ONST,...,FFST => choice
: Implemented via array. Record instances determine number of elements
; ZRSV,...,FFSV => stateSeverity
: Implemented via array of menu(menuAlarmSevr). Record instances determine number of elements
; UNSV => unknownStateSeverity
: Name change and menu(menuAlarmSevr)
; COSV => changeStateSeverity
: Name change and menu(menuAlarmSevr).
; RVAL => raw
: Name change.
; ORAW => oldRaw
: Name change.
; MASK => hardwareMask
: Case change and now uint64
; MLST
: Handled by channel access???? Must discuss, i.e. to we want to post monitors every time record processes?
; SDEF
: Probably not needed.
; SHFT => shift
: Name change
; SIOL => simInputLink
: Name change
; SVAL => simValue
: Name change
; SIML => simModeLink
: Name change
; SIMM => simMode
: Name change
; SIMS => simSevr
: Name change


----
----
Line 1,293: Line 1,095:
  record(waveform) extends iocRecord {
  record(waveform) extends iocRecord {
     field(value,array([])) {
     field(value,array([])) {
         asl(0)
         asl = 0,
         special
         special = true,
         metadata("timeStamp",time,dynamic)
         meta = {
        metadata("alarmSeverity",alarmSeverity,dynamic)
            {"timeStamp",time,dynamic},
        metadata("alarmStatus",alarmStatus,dynamic)
            {"alarmSeverity",alarmSeverity,dynamic},
        metadata("displayLimit",displayLimit)
            {"alarmStatus",alarmStatus,dynamic},
        metadata("units",units)
            {"displayLimit",displayLimit},
            {"units",units}
        }
     }
     }
     field(reArm,bool)
     field(reArm,bool)
Line 1,306: Line 1,110:
     field(displayLimit,struct(displayLimit))
     field(displayLimit,struct(displayLimit))
     field(busy,bool) {
     field(busy,bool) {
         nodct
         dct = false, mod = false
        readonly
     }
     }
     field(simInputLink,link(in))
     field(simInputLink,link(in))
Line 1,314: Line 1,117:
     field(simSevr,menu(menuYesNo))
     field(simSevr,menu(menuYesNo))
  }
  }
=== Comparison between V3 and V4 ===
The following discusses the differences between the fields defined in V3 and V4 waveformRecord.dbd. The NOACCESS (now private) fields are not discussed.
; VAL => value
: Name change and is now a 1dim array field
; RARM => reArm
: Name change and is now an array field
; INP => inp
: Case change and now device.
; EGU => units
: Name change.
; HOPR,LOPR => displayLimit
: Now implemented via struct
; BUSY => busy
: Case change and now a bool
; SIOL => simInputLink
: Name change
; SIML => simModeLink
: Name change
; SIMM => simMode
: Name change
; SIMS => simSevr
: Name change
; PREC
: No longer supported
; NELM,FTVL,NORD,BPTR
: No longer needed because of new array support


----
----
Line 1,451: Line 1,225:
  </center>
  </center>


=== attributes - nodct ===
=== attributes - dct ===


Should this be dct(interestLevel)?
Should this be dct(interestLevel)?
Line 1,483: Line 1,257:
=== Scan Mechanism ===
=== Scan Mechanism ===


Andrew gave a suggestion for a better way to define scan types and rates. This should be considered.
Andrew gave a suggestion for a better way to define scan types and rates. Should this be considered.


----
----
Line 1,509: Line 1,283:
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,configStruct)
     link(dir,choiceName,dataStruct)


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,515: Line 1,289:
  typedef struct iocLinkSupport {
  typedef struct iocLinkSupport {
     epicsStatus (*connect)(iocDbAddr *piocDbAddr,
     epicsStatus (*connect)(iocDbAddr *piocDbAddr,
                             const char *configName,void *pconfigStruct);
                             const char *configName,void *pdataStruct);
     epicsStatus (*disconnect)(iocDbAddr *piocDbAddr);
     epicsStatus (*disconnect)(iocDbAddr *piocDbAddr);
     epicsStatus (*get)(iocDbAddr *piocDbAddr);
     epicsStatus (*get)(iocDbAddr *piocDbAddr);
Line 1,530: Line 1,304:
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,configStruct)
     device(dir,interfaceName,choiceName,dataStruct)


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,536: Line 1,310:
  typedef struct iocDeviceConnect {
  typedef struct iocDeviceConnect {
     epicsStatus (*connect)(iocDbAddr *piocDbAddr,
     epicsStatus (*connect)(iocDbAddr *piocDbAddr,
                             const char *configName,void *pconfigStruct);
                             const char *configName,void *pdataStruct);
     epicsStatus (*disconnect)(iocDbAddr *piocDbAddr);
     epicsStatus (*disconnect)(iocDbAddr *piocDbAddr);
  }iocDeviceConnect;
  }iocDeviceConnect;


----
----

Revision as of 14:06, 11 May 2005

EPICS: IOC Database Definition

May 11 2005


Overview

This chapter describes the Database Definition Syntax for V4 databases. The Database Definition Syntax is meant to be used both by iocCore and by Database Configuration Tools (especially VDCT).

This document describes the V4 Database Definition and C++ class definitions that describe a V4 database. To complete the design an implementation needs to be described. this design will include the automatic generation of support modules for each record type.

Database Field Types

The V4 database field types are:

bool
A value that is (0,1) meaning (false,true)
octet
A 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 character string containing unicode/UTF-8 characters.
menu
16 bit integer that is index of a string array of choices
enum
16 bit integer and a string array of choices
struct
an ordered set of other database field types
link
a link to data outside the record
device
a link to associated device support
array
Multidimensional arrays are a field type
private
a valid C type that is private to database access and/or record support

Database Statements

The following statements are discussed:

include - include statements from a file
#comment - comment statements
menu - define a set of choices
struct - like a C structure
record - defines a record type
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
registrar - same as V3 registrar
variable - same as V3 variable
record instances - describes a record instance



Summary of V4 Database Definition Syntax

Statements for Record Types

include "filename"
#comment
menu(name) {
    choice("choice_value")
    ...
}
struct(name) {
    field(field_name,field_type) {field_attributes}
    ...
}
record(name) extends iocRecord value field_name{
  1. field_name is name of default value field.
  2. Not needed if value is the name of a first level field
    field(field_name,field_type) {field_attributes}
    ...
}
#If field_type is empty record instance determines type
#     must be one of bool,...,string
#field_type 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 field_type 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(field_attribute) {
        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)[]))
     }

Statements for Accessing data/code related to the record

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(function_name)
variable(variable_name)

Statements for Creating Record Instances

#The Following defines a Record Instance
recordType "recordName" = {
    info name = {"info_value"};
    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] {
              {field_name,interfaceName,choiceName,{dataStructValue}},
               ...
          }
    ...
}
# type is one of bool,...,string
# capacitys is one of
#   capacity    1dim array
#   capacity,capacity,...  ndim array
#   
#fieldValue is scalar_value or struct_value or array_def or link_value
#dataStructValue is struct_value
#
#where
#scalar_value is num_value or string_value
#    where
#    num_value is value
#        example: The following initializes a float64 field
#                 outputRateOfChange = {1.0};
#    string_value is "value"
#        example for menu field
#                 scan = {".1 second"};
#        example for string field
#                 command = {"getValue\r\n"};
#struct_value is field_value or name = field_value , ... 
#    assume struct(point) {field(x,float64) field(y,float64) field(z,float64)}
#    example:  xxx = { y = 1.0, 2.0};
#array_def is row_value (1dim) or {row_value}, {row_value} ... (ndim)
#   row_value is  field_value or [index]=field_value , ...
#   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}

include

include "filename"

where

filename
Must be a valid filename

Question> Where is this allowed?


#comment

# anything

Anything after # is a comment. This may appear on a line by itself or at the end of another statement.


menu

menu(name) {
    choice("choice_value")
    ...
}

where

name
Must be a valid C identifier. Each menu must have a unique name.
choice_value
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")
}



struct and record

struct

A struct is defined as follows:

struct(name) {
    field(field_name,field_type) {field_attributes}
    ...
}

where

name
The structure name. It must be a valid C identifier. No two structures can have the same name.
field_name
Must be a valid C identifier
field_type
See field_type below.
field_attributes
See field_attributes below.

record

A record type is defined as follows:

include "dbCommon.dbd"
record(name) extends iocRecord  value field_name {
    field(field_name,field_type) {field_attributes}
    ...
}
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 field_name
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.
field_name
Must be a valid C identifier
field_type
See field_type below.
field_attributes
See field_attributes below.

field_type

Both struct and record define a field as:

    field(field_name,field_type)

The syntax for field_type 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))

field_attributes

Associated with field_attributes are the following "hidden" definitions:

    struct(metadata) {
        field(name,string)
        field(field,string) #field holding the metadata
        field(dynamic,bool)
    }
    struct(field_attribute) {
        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 field_attributes 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))
    ...
}

interface link and device

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,dataStruct)
link(dir,choiceName,dataStruct)
device(dir,interfaceName,choiceName,dataStruct)

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?????
dataStruct
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> "record_name" = {
    info name = {"info_value"};
    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] {
                 {field_name,interfaceName,choiceName,{dataStructValue}},
                 ...
    }
    ...
}

where

recordType
The name of the record type
record_name
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.
field_value
The syntax depends on the field type. The details are described next..

field_value

The format for field_value 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 {struct_value}
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. struct_value 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(field_name,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) follow 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(field_name,string)
       field(interfaceName,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 *"))
}

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,
        metaTemplate:"timeStamp",time
    }
    field(prevRawValue,int32) {
        dct = false,
        mod = false,
        metaTemplate:"timeStamp",time
    }
    field(readBackValue,int32) {
        dct = false,
        mod = false,
        metaTemplate:"timeStamp",time
    }
    field(oldReadBackValue,int32) {
        dct = false,
        mod = false,
        metaTemplate:"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,
        metaTemplate:"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,dataStruct)

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,dataStruct)

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;