Difference between revisions of "V4 Link Support Tutorial"

From EPICSWIKI
(added discussion about analog conversion and special support for output records)
Line 1: Line 1:
EPICS: IOC Link Support Tutorial Oct 26 2005
EPICS: IOC link and struct Support November 01 2005


----
----
= Overview =
= Overview =


The V4 link support is a replacement for V3  
The V4 link/struct support is a replacement for V3  
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK
# device DBD definition and device support
# device DBD definition and device support
# driver DBD definition and driver support
# driver DBD definition and driver support


The link support model is:
Each link and struct field in a record can have associated support.
* For each link, record support defines a list of interfaces it can use for communicating with link support
* record support communicates with support via interfaces
* Link support defines the set of interfaces it implements
* link or struct support implements interfaces
** link or struct support registers the interfaces it implements
** record support looks for interfaces it uses
*** it uses only the interfaces it finds
*** if no interfaces are found it reports an error


Link support has no knowledge of what record types are using it
Support has no knowledge of what record types are using it.
and record support has no knowledge about link support other than the
Struct support may have knowledge of the struct field
but not of the record type.
recordSupport has no knowledge about support other than the
interface it is using.
interface it is using.


EPICS base defines a standard set of interfaces for link support.
For the rest of this document recordSupport means record support and support,
The intention is that the set includes enough functionality such that
unless qualified, means link or struct support.
most link support can be implemented via just these interfaces.


The interfaces support all the functionality needed by Channel/Database access
EPICS base defines a standard set of interfaces for support,
and by the generic EPICS device support supplied by asynDriver.
which includes enough functionality such that
most support can be implemented via just these interfaces.
 
Most of the support supplied with base is link support. In particular
support for channel/database access links. It also briefly describes
support for interfacing with asynDriver.
 
The link interfaces support Channel/Database access
and the generic EPICS device support supplied by asynDriver.
Since asynDriver is intended as a framework for interfacing to most hardware,
Since asynDriver is intended as a framework for interfacing to most hardware,
this means that the interfaces supplied and used by base allows support
this means that the interfaces supplied and used by base allows support
Line 29: Line 42:
by base.
by base.


This document gives a brief overview of the V4 link support model.
This document gives a brief overview of the V4 link/struct support model.


----
----
<center>
<center>
=  Database Definitions For Links =
=  Database Definitions For links and structures =
  </center>
  </center>


Line 42: Line 55:


A record link has the syntax:
A record link has the syntax:
     link(linkDirection,interface(interfaceName,...))
     field(name,link)
A link itself has the syntax:
A record struct has the syntax
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))
    field(name,struct(structName))
A record instance link definition has the syntax:
Support for a struct or link has the syntax
    field = { choice(interfaceName) {structAssignmentList}}
     support(choiceName) // no SupportStruct
      or
    support(choiceName,supportStructName)
    field = { choice(interfaceName) dataStructName {structAssignmentList} }
A record instance struct has the the syntax
 
    field = StructName{structAssignmentList} // no support
where
    field = support(choiceName)
 
            StructName{structAssignmentList} // support has no SupportStruct
; <tt>linkDirection</tt>
    field = support(choiceName) SupportStruct{structAssignmentList}
: Must be one of <tt>none</tt>,<tt>in</tt>,<tt>out</tt>,<tt>process</tt>, or <tt>inout</tt>. Compatible checks are made to match the interface with a field.
            StructName{structAssignmentList}


; <tt>interface</tt>
; <tt>structName</tt>
: This is a list of the interfaces that the record support understands or that link support implements.
: The name of a <tt>struct</tt>
; <tt>choiceName</tt>
; <tt>choiceName</tt>
: UTF-8 string that describes the choice
: UTF-8 string that describes the choice. Each support must have a unique name.
 
; <tt>supportStructName</tt>
; <tt>interfaceName</tt>
: The name of a <tt>struct</tt> containing configuration information for the support. recordSupport normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.
: The name of an interface via which record support communicates with link support.
 
; <tt>dataStructName</tt>
: The name of a <tt>struct</tt> containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.
; <tt>choice</tt>
: Selects a link with <tt>choiceName</tt> = <tt>choice</tt>
 
A record instance link definition selects a link as follows:
* The linkDirections must be compatible
** Except for inout the record link and link directions must be the same
** If record link specifies inout the link can specify either in or out or inout
* The interfaceName specified by the record instance must be in the record link interface list and in the link interface list.
* The dataStructName specified in the record instance must match the dataStructName in the link definition.


Assume the following definitions:
Assume the following definitions:
     record(AiRecord) {
     record(AiRecord) {
         ...
         ...
         field(in,link(in,interface(LinkInt64,LinkFloat64)))
         field(in,link)
         ...
         ...
     }
     }
    ...
     struct(PvMonitorLink) {
     struct(PvMonitorLink) {
         field(pvname,string)
         field(pvname,string)
Line 94: Line 95:
     }
     }
     ...
     ...
     link(in,monitorLink,PvMonitorLink,interface(
     support(monitorLink,PvMonitorLink)
        LinkBoolean,
     support(inputLink,PvInputLink)
        LinkInt16,LinkInt32,LinkInt64,
        LinkFloat32,LinkFloat64,
        LinkString
    ))
     link(in,inputLink,PvInputLink,interface(
        LinkBoolean,
        LinkInt16,LinkInt32,LinkInt64,
        LinkFloat32,LinkFloat64,
        LinkString
    ))
    ...
     struct VME{
     struct VME{
         field(a16,int16)  
         field(a16,int16)  
Line 113: Line 103:
     }
     }
     ...
     ...
     link(in,someVmeADC,VME, interface(LinkInt32))
     support(someVmeADC,VME)


The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a "raw" value that the
The first example instance definition selects a monitor link.
record support will convert to engineering units.
     AiRecord aiMonitorExample = {
     AiRecord aiMonitorExample = {
         ...
         ...
         in = {monitorLink(LinkInt32)  
         in = {support(monitorLink)
                   PvMonitorLink {     
                   PvMonitorLink {     
                         pvname = "someRecord";
                         pvname = "someRecord";
Line 126: Line 115:
                   }
                   }
               }
               }
The next example selects a channel access input link. It selects interface
The next example selects a channel access input link.
LinkFloat64, which means the support will provide a value in engineering units.
It asks that the linked record be processed and that the link not complete
until the linked record completes processing.
     AiRecord aiInputExample = {
     AiRecord aiInputExample = {
         ...
         ...
         in = {inputLink(LinkFloat64)  
         in = {support(inputLink)
                   PvInputLink {     
                   PvInputLink {     
                         pvname = "someRecord";
                         pvname = "someRecord";
Line 144: Line 130:
     AiRecord aiMonitorExample = {
     AiRecord aiMonitorExample = {
         ...
         ...
         in = {someVmeADC(LinkInt32) VME {a16 = 0xc000; channel = 1} }
         in = {support(someVmeADC) VME {a16 = 0xc000; channel = 1} }


== Standard Definitions For Channel/Database Access ==
== Standard Definitions For Channel/Database Access ==


These are the database definitions defined in dbCommon are used by
menuStructBase.dbd defines definitions for Channel/Database Access Links.
the base supplied support for Channel/Database access.
The base supplied support registers each choiceName in the support definitions.
This support registers each choiceName in the link definitions.
The complete set of data structure and support definitions are defined
The complete set of data structure and link definitions are defined
in "V4 DB RecordCommon".
in "V4 DB RecordCommon".


Line 180: Line 165:
     }
     }


=== link definitions ===
=== support definitions ===


     link(inout,asynInt32,AsynLink,interface(LinkInt32))
     support(asynInt32,AsynLink)
     link(in,asynInt32Average,AsynLink,interface(LinkInt32))
     support(asynInt32Average,AsynLink)
     link(in,asynInt32Monitor,AsynLink,interface(LinkInt32))
     support(asynInt32Monitor,AsynLink)
     link(inout,asynFloat64,AsynLink,interface(LinkFloat64))
     support(asynFloat64,AsynLink)
     link(in,asynFloat64Average,AsynLink,interface(LinkFloat64))
     support(asynFloat64Average,AsynLink)
     link(in,asynFloat64Monitor,AsynLink,interface(LinkFloat64))
     support(asynFloat64Monitor,AsynLink)
     link(in,asynDigitalMonitor,AsynLink,interface(AsynDigital))
     support(asynDigitalMonitor,AsynLink)
     link(inout,asynDigital,AsynLink,interface(AsynDigital)))
     support(asynDigital,AsynLink)
     link(inout,asynInt32Array,AsynLink,interface(LinkArrayInt32)))
     support(asynInt32Array,AsynLink)
     link(inout,asynFloat64Array,AsynLink,interface(LinkArrayFloat64)))
     support(asynFloat64Array,AsynLink)
     link(inout,asynOctet,AsynLink,interface(AsynOctet)))
     support(asynOctet,AsynLink)


This is the set of definitions for the standard EPICS device support implemented
This is the set of definitions for the standard EPICS device support implemented
Line 283: Line 268:
* <tt>removeMonitor</tt> - Remove monitor
* <tt>removeMonitor</tt> - Remove monitor


Normally record support does not need to call any of the Link  
Normally recordSupport does not need to call any of the Link  
or MonitorLink methods since database access does this automatically.
or MonitorLink methods since database access does this automatically.
For example if a link field is modified via a channel access put,
For example if a link field is modified via a channel access put,
Line 454: Line 439:
= Example - VME ADC support =
= Example - VME ADC support =
  </center>
  </center>
Assume the VME and link definitions given in the examples at the beginning
Assume the VME and support definitions given in the examples at the beginning
of this document.
of this document.


Line 518: Line 503:


== Overview ==
== Overview ==
The link definitions: record link, link, record instance links,
The definitions: record link, support, record instance links,
and the link interfaces are designed to support channel/database links,
and the link interfaces are designed to support channel/database links,
links to hardware support, and links to other types of support.
links to hardware support, and links to other types of support.
Line 535: Line 520:
raw values and engineering units. Raw values are 32 bit integers. Device
raw values and engineering units. Raw values are 32 bit integers. Device
support is responsible for setting the slope and intercept fields of the record.
support is responsible for setting the slope and intercept fields of the record.
Record support takes care of the actual conversions.
recordSupport takes care of the actual conversions.
Device support can tell record support that it set the engineering units
Device support can tell recordSupport that it set the engineering units
rather than a raw value by a different return value.
rather than a raw value by a different return value.
<b>NOTE:</b>Perhaps in V4 aiRecord should be separated into two records,
e.g. a record that always uses float values and an ADC record which handles
raw values. Another possibility is special link support that provides
floating values to the record support and links to the actual hardware support.
For this discussion it is assummed that aiRecord and aoRecord are still
responsible for conversions since most of the discussion is
independent of how the record support is structured.


For V4 the following is done:
For V4 the following is done:
Line 553: Line 529:


     menu(menuConvert) {
     menu(menuConvert) {
         choice(menuConvertRaw, "Raw")
         choice(menuConvertRaw, "None")
         choice(menuConvertLinear, "Linear")
         choice(menuConvertLinear, "Linear")
         choice(menuConvertTable, "Table")
         choice(menuConvertTable, "Table")
Line 572: Line 548:
     field(units, string)
     field(units, string)


The link field for aiRecord is
    field(in,link(in,interface( LinkInt32, LinkFloat64)))


The link field for aoRecord is
If a record instance has convert set to None then recordSupport does the following.
    field(out,link(out,interface( LinkInt32, LinkFloat64)))
* if link support implements LinkFloat64 it just calls this to obtain an engineering units value
* otherwise it gets a value via interface LinkInt32 and converts the value from in int32 to a float64.
 
If a record instance has convert linear
* if link support implements LinkInt32 it uses LinkInt32 otherwise it uses LinkFloat64
* it uses slope and interccept to convert from raw to engineering units


When a record instance is defined the link specifies the interface to use.
If the interface is:
* <tt>LinkInt32</tt> - Then the link support supplies raw values
* <tt>LinkFloat64</tt> - Then the link support supplies engineering units


<tt>LinkInt32</tt> is defined as:
<tt>LinkInt32</tt> is defined as:
Line 587: Line 562:
         LinkResult get(Callback callback,Int32 data);
         LinkResult get(Callback callback,Int32 data);
         LinkResult put(Callback callback,Int32 data);
         LinkResult put(Callback callback,Int32 data);
         void getBounds(Int32 low, Int32 high);
         boolean getBounds(Int32 low, Int32 high);
     }
     }
Thus link support is responsible for returning the ADC bounds.
 
If convert is linear and getBounds returns true than recordSupport
uses the returned value to compute slope and intercept. In all
other cases recordSupport just uses whatever values they have.
 
For example support for a 16 bit unipolar ADC would set low=0, high=65535,
For example support for a 16 bit unipolar ADC would set low=0, high=65535,
and return true.
and return true.
If link support can not determine the bounds then getBounds returns false.
If link support can not determine the bounds then getBounds returns false.


If the link interface is LinkFloat64 then record support does no conversion.
Thus the following only applys if the interface is LinkInt32.
Record support handles conversions as follows:
* Raw - The value obtained from the link support is converted to a double.
* Linear
** If link support returned the bounds record support computes slope and intercept
** otherwise it uses the slope and intercept from instance definition
* Table - The interface implementation for convertTable is located and used.


<b>NOTE:</b>The interface implemented by breakpoint tables must be defined.
<b>NOTE:</b>The interface implemented by breakpoint tables must be defined.
Line 657: Line 627:
         void removeMonitor();
         void removeMonitor();
     }
     }
At initialization record support looks for this interface and if found
At initialization recordSupport looks for this interface and if found
it calls <tt>addMonitor</tt>. The link support calls the callback whenever
it calls <tt>addMonitor</tt>. The link support calls the callback whenever
it detects a change in the output that it did not cause. Record support
it detects a change in the output that it did not cause. recordSupport
causes itself to be processed without making a new call to the
causes itself to be processed without making a new call to the
link support.
link support.
---
<center>
=  Struct Support =
</center>
== support for RecordCommon ==
This implements the same interface a record support.
== support for LinearConvert ==
This implements the interface
    interface LinearConvertSupport {
          convert(int32 raw,Float64 value) // from raw to eng
          convert(float64 value,Int32 raw) // from eng to raw
    }
In addition it provides a factory
    interface LinearConvertFactory {
        LinearConvertSupport(string choiceName,
            DbfStruct linearConvert,DbfLink inlink)
    }
== support for simulation ==
This needs to be defined.
== support for breakpoint tables ==
This needs to be defined.

Revision as of 20:23, 1 November 2005

EPICS: IOC link and struct Support November 01 2005


Overview

The V4 link/struct support is a replacement for V3

  1. DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK
  2. device DBD definition and device support
  3. driver DBD definition and driver support

Each link and struct field in a record can have associated support.

  • record support communicates with support via interfaces
  • link or struct support implements interfaces
    • link or struct support registers the interfaces it implements
    • record support looks for interfaces it uses
      • it uses only the interfaces it finds
      • if no interfaces are found it reports an error

Support has no knowledge of what record types are using it. Struct support may have knowledge of the struct field but not of the record type. recordSupport has no knowledge about support other than the interface it is using.

For the rest of this document recordSupport means record support and support, unless qualified, means link or struct support.

EPICS base defines a standard set of interfaces for support, which includes enough functionality such that most support can be implemented via just these interfaces.

Most of the support supplied with base is link support. In particular support for channel/database access links. It also briefly describes support for interfacing with asynDriver.

The link interfaces support Channel/Database access and the generic EPICS device support supplied by asynDriver. Since asynDriver is intended as a framework for interfacing to most hardware, this means that the interfaces supplied and used by base allows support for most hardware. The support can communicate with the hardware however it wants but must implement some set of the interfaces defined by base.

This document gives a brief overview of the V4 link/struct support model.


Database Definitions For links and structures

This section first reviews the DBD syntax related to link definitions. It then gives a brief description of link related definitions in dbCommon.dbd

Syntax

A record link has the syntax:

    field(name,link)

A record struct has the syntax

    field(name,struct(structName))

Support for a struct or link has the syntax

    support(choiceName) // no SupportStruct
    support(choiceName,supportStructName)

A record instance struct has the the syntax

   field = StructName{structAssignmentList} // no support
   field = support(choiceName)
           StructName{structAssignmentList} // support has no SupportStruct
   field = support(choiceName) SupportStruct{structAssignmentList}
           StructName{structAssignmentList}
structName
The name of a struct
choiceName
UTF-8 string that describes the choice. Each support must have a unique name.
supportStructName
The name of a struct containing configuration information for the support. recordSupport normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.

Assume the following definitions:

    record(AiRecord) {
        ...
        field(in,link)
        ...
    }
    ...
    struct(PvMonitorLink) {
        field(pvname,string)
        field(process,boolean) // process this record when monitor occurs
        field(inheritSeverity,boolean)
    }
    struct(PvInputLink) {
        field(pvname,string)
        field(process,boolean)
        field(wait,boolean)
        field(timeout,float64)
        field(inheritSeverity,boolean)
    }
    ...
    support(monitorLink,PvMonitorLink)
    support(inputLink,PvInputLink)
    struct VME{
        field(a16,int16) 
        field(a32,int32)
        field(channel,int16)
    }
    ...
    support(someVmeADC,VME)

The first example instance definition selects a monitor link.

    AiRecord aiMonitorExample = {
        ...
        in = {support(monitorLink)
                  PvMonitorLink {    
                       pvname = "someRecord";
                        process = true;
                       inheritSeverity = false
                  }
              }

The next example selects a channel access input link.

    AiRecord aiInputExample = {
        ...
        in = {support(inputLink)
                  PvInputLink {    
                       pvname = "someRecord";
                       process = true;
                       wait = true;
                       timeout = 1.0;
                       inheritSeverity = false
                  }
              }

The last example selects support for a VME Analog to Digital device.

    AiRecord aiMonitorExample = {
        ...
        in = {support(someVmeADC) VME {a16 = 0xc000; channel = 1} }

Standard Definitions For Channel/Database Access

menuStructBase.dbd defines definitions for Channel/Database Access Links. The base supplied support registers each choiceName in the support definitions. The complete set of data structure and support definitions are defined in "V4 DB RecordCommon".

Link support is provided for

  • monitor
  • input
  • output
  • process

For monitor, input, and output the following data types are supported:

  • primitive types
  • string
  • arrays of primitive types and strings

asynDriver link support

These are definitions that are used by the standard EPICS device support for asynDriver. Since asynDriver is a generic way of interfacing arbitrary hardware support, this is a generic way of attaching links in records to hardware.

Data Definitions

    struct(AsynLink) {
        field(portName,string)
        field(addr,int32)
        field(timeout,float64)
        field(drvPvt,string)
    }

support definitions

    support(asynInt32,AsynLink)
    support(asynInt32Average,AsynLink)
    support(asynInt32Monitor,AsynLink)
    support(asynFloat64,AsynLink)
    support(asynFloat64Average,AsynLink)
    support(asynFloat64Monitor,AsynLink)
    support(asynDigitalMonitor,AsynLink)
    support(asynDigital,AsynLink)
    support(asynInt32Array,AsynLink)
    support(asynFloat64Array,AsynLink)
    support(asynOctet,AsynLink)

This is the set of definitions for the standard EPICS device support implemented by asynDriver. Although, at least for the first few V4 releases, asynDriver will not be part of base, they are shown here because the LinkInt32,... interface definitions are defined as part of base. Again it is expected that almost all hardware support be created by implementing a combination of these link interface definitions or the interfaces implemented by Channel/Database access link support. ---

Link Support

Overview

An arbitrary number of Link Support implementations can exist. An implementation can be either soft support or support that communicates with hardware.

Other link support can also be supplied. Whenever possible support should implement the standard interfaces supplied by EPICS base, since these are the interfaces that the record types supplied with base know how to use.

Soft support should try to implement the same interfaces implemented by the Channel/Database access support supplied with base. The support can, of course, define data structures for it's own use. Implementing these interfaces means that the support will work for the same set of record links as the Channel/Database access support.

Hardware support should, if possible, also implement the same interfaces implemented by the Channel/Database access support. Message based support may also have to implement the AsynOctet interface but this interface is only used by a few record types.

This section describes the interfaces implemented by all link support and then the standard interfaces used by the records supplied with base.

The syntax is similar to Java syntax since it is more concise than C++. It can easily be translated to C++ syntax. For example the definition:

    interface LinkInt16 {
        LinkResult get(Callback callback,Int16 data);
        LinkResult put(Callback callback,Int16 data);
        boolean getBounds(Int16 low, Int16 high);
    }

In C++ would be:

    class LinkInt16 {
    public:
        virtual LinkResult get(Callback &callback, int16_t &data) = 0;
        virtual LinkResult put(Callback &callback, int16_t data) = 0;
        virtual bool getBounds(int16_t &low, int16_t &high) = 0;
    };


Link and MonitorLink

All support must register interface Link and if it supports monitors interface MonitorLink. NOTE: arguments and return types ignored for now

    interface Link {
        void report(int16 level);
        void cancel();
        void destroy();
        void initialize();
        void connect();
        void disconnect();
    }
    interface MonitorLink {
        void addMonitor(Callback callback);
        void removeMonitor();
    }

Link is an interface that must be implemented by every link support. An instance of this is connected to each DbfLink field. The Link methods are:

  • report - report
  • cancel - Cancel any outstanding I/O
  • destroy - This is called if the field is being changed after initialization or if the record is being removed.
  • initialize - Called to initialize a link.
  • connect - Called to connect. Note that this is different than initilization.
  • disconnect - disconnect.

MonitorLink is an interface that is implemented by link support that supports monitors. An example is support for hardware interrupts. The MonitorLink methods are:

  • addMonitor - Add a monitor callback
  • removeMonitor - Remove monitor

Normally recordSupport does not need to call any of the Link or MonitorLink methods since database access does this automatically. For example if a link field is modified via a channel access put, database access will call destroy before modifying the link and initialize and connect after the link is modified.

Note that neither Link or MonitorLink is listed in the link database definition since they are generic.

Definitions that apply to Process,Monitor,Input,and Output support

These are the definitions used by the Channel/Database access support supplied with base. It is also used by the standard EPICS support from asyn.

    enum LinkResult {
        linkNoop,           // Nothing was done, e.g. link is null link
        linkDone,           // field was modified. No wait is necessary
        linkWait,           // waiting. can do additional procsssing
    }
    interface Callback {
        void done();
        void failure();
    }

Process Link Support

    interface LinkProcess {
        LinkResult process(Callback callback);
    }

Octet Support

    interface LinkOctet {
        LinkResult get(Callback callback, Octet data);
        LinkResult put(Callback callback, octet data);
    }
    interface LinkArrayOctet {
        LinkResult get(Callback callback, octet[] data);
        LinkResult put(Callback callback, octet[] data);
    }

GENERIC QUESTION The data is passed as primitive or arrays of primitive types. Should Dbf interfaces be used? Needs thought.


asynOctet Support

This still needs more work. It attempts to reproduce the functionality of V3 asynDriver.

    interface AsynOctet {
        LinkResult write(Callback callback,
          octet[] data, int32 numchars, Int32 nbytesTransfered);
        LinkResult writeRaw(Callback callback,
          octet[] data, int32 numchars, Int32 nbytesTransfered);
        LinkResult read(Callback callback,
          octet[] data, Int32 nbytesTransfered);
        LinkResult readRaw(Callback callback,
          octet[] data, Int32 nbytesTransfered);
        void flush();
        void setInputEos(octet[] eos);
        void getInputEos(octet[] eos);
        void setOutputEos(octet[] eos);
        void getOutputEos(octet[] eos);
    }

asynDigital Support

    enum interruptReason {
        interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth
    }
    struct asynDigitalInterrupt {
        octet[] mask;
        int32 addr;
        Callback callback
    }
    interface AsynDigital {
         LinkResult write(Callback callback,octet[] value, octet[] mask);
         LinkResult read(Callback callback,octet[] value, octet[] mask);
         void setInterrupt(octet[] mask, interruptReason reason);
         void clearInterrupt(octet[] mask);
         void getInterrupt(octet[] mask, interruptReason reason);
         void registerInterruptUser(interruptCallbackUInt32Digital callback,
             octet[] mask);
         void cancelInterruptUser();
    }

Boolean Support

    interface LinkBoolean {
        LinkResult get(Callback callback,Boolean data);
        LinkResult put(Callback callback,boolean data);
    }
    interface LinkArrayBoolean {
        LinkResult get(Callback callback,boolean[] data);
        LinkResult put(Callback callback,boolean[] data);
    }


The data source must be a boolean or a string that contains a valid boolean value.

Integer Support

Support is available. for int16, int32, and int64.

    interface LinkInt16 {
        LinkResult get(Callback callback,Int16 data);
        LinkResult put(Callback callback,Int16 data);
        boolean getBounds(Int16 low, Int16 high);
    }
    interface LinkArrayInt16 {
        LinkResult get(Callback callback,int16[] data);
        LinkResult put(Callback callback,int16[] data);
    }
    interface LinkInt32 {
        LinkResult get(Callback callback,Int32 data);
        LinkResult put(Callback callback,Int32 data);
        boolean getBounds(Int32 low, Int32 high);
    }
    interface LinkArrayInt32 {
        LinkResult get(Callback callback,int32[] data);
        LinkResult put(Callback callback,int32[] data);
    }
    interface LinkInt64 {
        LinkResult get(Callback callback,Int64 data);
        LinkResult put(Callback callback,Int64 data);
        boolean getBounds(Int64 low, Int64 high);
    }
    interface LinkArrayInt64 {
        LinkResult get(Callback callback,int64[] data);
        LinkResult put(Callback callback,int64[] data);
    }


Float Support

Support is available. for float32 and float64.

    interface LinkFloat32 {
        LinkResult get(Callback callback,Float32 data);
        LinkResult put(Callback callback,float32 data);
    }
    interface LinkArrayFloat32 {
        LinkResult get(Callback callback,float32[] data);
        LinkResult put(Callback callback,float32[] data);
    }
    interface LinkFloat64 {
        LinkResult get(Callback callback,Float64 data);
        LinkResult put(Callback callback,float64 data);
    }
    interface LinkArrayFloat64 {
        LinkResult get(Callback callback,float64[] data);
        LinkResult put(Callback callback,float64[] data);
    }

String Support

    interface LinkString {
        LinkResult get(Callback callback,string data);
        LinkResult put(Callback callback,string data);
    }
    interface LinkArrayString {
        LinkResult get(Callback callback,string[] data);
        LinkResult put(Callback callback,string[] data);
    }


The data source must be a string.


Example - VME ADC support

Assume the VME and support definitions given in the examples at the beginning of this document.

The following is presented with Java syntax. It assumes that there is VME support of the form

    public class vme {
        static public short getShort(long addr);
        ...
    }

The link support would be something like:

    class AdcSupport implements Link LinkInt32 {
    AdcSupport(VME fromFactory)
    {
        addr = fromFactory;
        connected = false;
        //  from the VME initialize vmeaddr and channel
        // details left to your imagination
    }
    // Link methods
    void report(int16_t level)
    {
        printf("AdcSupport a16 %x channel %d\n",a16,channel);
    }
    void cancel() {} // nothing to do
    void destroy() {} //nothing to do
    void initialize()
    {
        // make sure we can access a16
    }
    void connect() {connected = true}
    void disconnect() {connected = false}
    
    // LinkInt32 methods
    LinkResult get(Callback callback, Int data)
    {
        data = (Int)VME.getShort(vmeaddr);
        return linkDone;
    }
    LinkResult put(Callback callback, Int data)
    {
        throw CantWriteAdc;
    }
    void getBounds(Int low, Int high) 
    {
        // assume 16 bit unipolor adc
        low = 0; high = 0xffff;
    }
    private:
        VME addr;
        int vmeaddr;
        int channel;
        boolean connected;
    }

Discussion of link support interfaces

Overview

The definitions: record link, support, record instance links, and the link interfaces are designed to support channel/database links, links to hardware support, and links to other types of support.

The following are two important requirements:

  • analog I/O
    • link support can return raw value. Support must convert to engineering units.
    • link support can return engineering units
  • output records
    • Can link support provide initial value?
    • What if multiple sources can change linked output?

Lets consider each of these separately.

Analog I/O

In V3 the aiRecord and aoRecords are responsible for conversion between raw values and engineering units. Raw values are 32 bit integers. Device support is responsible for setting the slope and intercept fields of the record. recordSupport takes care of the actual conversions. Device support can tell recordSupport that it set the engineering units rather than a raw value by a different return value.

For V4 the following is done:

aiRecord and aoRecord both have the following fields:

    menu(menuConvert) {
        choice(menuConvertRaw, "None")
        choice(menuConvertLinear, "Linear")
        choice(menuConvertTable, "Table")
    }
    struct(LinearConvert) {
        field(eguf,float64)
        field(egul,float64)
        field(slope,float64)
        field(intercept,float64)
    }


    ...
    field(convert, menu(menuConvert))
    field(linearConvert, struct(LinearConvert))
    field(convertTable,string);
    field(units, string)


If a record instance has convert set to None then recordSupport does the following.

  • if link support implements LinkFloat64 it just calls this to obtain an engineering units value
  • otherwise it gets a value via interface LinkInt32 and converts the value from in int32 to a float64.

If a record instance has convert linear

  • if link support implements LinkInt32 it uses LinkInt32 otherwise it uses LinkFloat64
  • it uses slope and interccept to convert from raw to engineering units


LinkInt32 is defined as:

    interface LinkInt32 {
        LinkResult get(Callback callback,Int32 data);
        LinkResult put(Callback callback,Int32 data);
        boolean getBounds(Int32 low, Int32 high);
    }

If convert is linear and getBounds returns true than recordSupport uses the returned value to compute slope and intercept. In all other cases recordSupport just uses whatever values they have.

For example support for a 16 bit unipolar ADC would set low=0, high=65535, and return true. If link support can not determine the bounds then getBounds returns false.


NOTE:The interface implemented by breakpoint tables must be defined. It will support the same semantics as the V3 breakpoint tables.

Output Records

The following are two features that link support should implement whenever possible:

  1. When a record is initalized provide the current value of the output
  2. If something else modifies the actual output value in the record

The first feature is especially desirable when an IOC is rebooted. If a hardware output can survive a reboot this is a very desirable feature. If the output is to a field bus, a PLC, or to a record in another IOC it is often possible for the link support to determine the current value.

The second feature is something that was often asked for in V3 but only implemented for some special cases. This is especially desirable when the output is connected to a system that can have multiple sources of control. Examples are GPIB devices with front pannel controls, PLC systems that have manual controls or non-epics network access.

For V3 some of the hardware , but none of the soft, support implemented the first feature but by modifying actual fields in the record. V3 did not implement the second feature. Some special device support, not part of base, was implemented to support this feature.

For V4 these features are supported as follows:

record initialization

The link support implements an interface that has a put and a get method. For example:

    interface LinkInt32 {
        LinkResult get(Callback callback,Int32 data);
        LinkResult put(Callback callback,Int32 data);
        boolean getBounds(Int32 low, Int32 high);
    }

If the link support can support readbacks then it implements get and returns linkDone. If it does not support readbacks then it implements get by just returning linkNoop.

monitors for outputs

If output link support can detect when something besides the link support itself modifies the output then it implements interface MonitorLink

    interface MonitorLink {
        void addMonitor(Callback callback);
        void removeMonitor();
    }

At initialization recordSupport looks for this interface and if found it calls addMonitor. The link support calls the callback whenever it detects a change in the output that it did not cause. recordSupport causes itself to be processed without making a new call to the link support. ---

Struct Support

support for RecordCommon

This implements the same interface a record support.

support for LinearConvert

This implements the interface

    interface LinearConvertSupport {
         convert(int32 raw,Float64 value) // from raw to eng
         convert(float64 value,Int32 raw) // from eng to raw
    }

In addition it provides a factory

    interface LinearConvertFactory {
        LinearConvertSupport(string choiceName,
            DbfStruct linearConvert,DbfLink inlink)
    }

support for simulation

This needs to be defined.

support for breakpoint tables

This needs to be defined.