================================= hwLowcal - LowCAL Hardware Record ================================= :Author: Benjamin Franksen Introduction ============ The normal use of this record is to read or write data over the CAN bus, using a protocol called LowCAL. The record transports only raw integral values as defined by the LowCAL specification. If conversion to engineering units is desired, the 8 input (RDx) and 8 output (WRx) fields of the hwLowcal record can be targeted by the INP or OUT field of a standard record (ai, ao, bi, bo, etc.). In this way the hwLowcal record acts as a kind of server record, and the records of standard type as client records. The client records may use a special device support called 'HwClient' to enable asynchronous link processing and to obtain information about raw value data, such as minimum and maximum value or number of significant bits. For details see the document 'HwClient - Device Support for Clients of Hardware Records'. LowCAL Variables ================ The hwLowcal record represents one entity of the LowCAL protocol, a so called LowCAL variable. In general, LowCAL variables are arrays of up to 8 elements of one of the simple types signed or unsigned char (8 bits), short (16 bits) or long (32 bits). The array elements of the variable can be accessed for reading through the 8 fields RD1...RD8, or for writing through the fields RD1...RD8. Like any other variable, LowCAL variables have a unique location on the bus, that is, there is exactly one CAN node in which they 'exist'. This node is called the Server node; all other nodes are called Clients with respect to this variable. A LowCAL variable is defined by the following data which can be (statically) configured by setting the appropriate fields of the hwLowcal record: * **User type**: Either Client or Server. A Server variable 'exists' on the same CAN node (the IOC), whereas a Client variable 'exists' on some other node. * **Access type**: There are three choices: 'RO' (read-only), 'WO' (write-only) and 'RW' (read-write). As the names suggest, only RO and RW variables can be read and only WO and RW variables can be written. Note that 'read' and 'write' only refers to the direction of the data flow over the CAN bus if the variable has user type Client. A Server variable never initiates actual I/O - it only answers to Client requests. E.g. a write to a Server variable will only update the local copy; Server-WO variables are read by Clients and Server-RO variables are written to by Clients. * **Class**: This must be either 'Basic' or 'Multiplexed'. Basic variables use all 8 data bytes for 'real' data. Multiplexed variables use one of the 8 bytes as a sort of channel identifier, so that only 7 bytes may be 'real' data. * **Multiplexer**: An integral number between 0 and 127 (inclusive). If the variable's class is Multiplexed, then this is the identifier of the 'channel'. * **Base type**: This can be either 'NIL' (meaning zero data length) or any standard integral data type, i.e. one, two or four byte, signed or unsigned integers. They are named after the standard EPICS data types, i.e. 'CHAR', 'UCHAR, 'SHORT', 'USHORT', 'LONG', and 'ULONG'. * **Array size**: The number of elements of the data array. Scalar data is equivalent to an array with one element. * **Data size**: This is the size of the data area in bytes, including Multiplexer (if variable is Multiplexed). * **CAN Port**: A hardware (resp. driver) dependent value that identifies the CAN port. * **CAN object ids**: These are the COBs of at most two CAN objects that are used for incoming and outgoing messages. Not all variable types need two COBs: Variables of type Basic-RO and all WO types need only one. * **Inhibit time**: This can be used to slow down the sending of certain CAN messages, for example if receiving nodes are single tasked and can process new messages only after previous data has been digested. * **Timeout**: This value determines how long to wait for confirmation, if the variable's type is a confirmed one. Confirmed variables are those of type RW and RO. Timeouts make sense only if the variable is configured as Server, because otherwise read and write operations are purely local. For further details concerning the LowCAL protocol definition, please refer to the document 'MultiCAN - EPICS goes CAN with Multiple Protocol Support'. Field Summary ============= .. table:: Field Summary +-------+-----------+-----+---------+--------+--------+---------+----+ | Field | Type | DCT | Initial | Access | Modify | Monitor | PP | +=======+===========+=====+=========+========+========+=========+====+ | VAL | NOACCESS | No | 0 | No | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | ATYP | GBLCHOICE | Yes | RO | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | UTYP | GBLCHOICE | Yes | Client | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | CLAS | GBLCHOICE | Yes | Basic | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | BTYP | GBLCHOICE | Yes | NIL | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | NELM | UCHAR | Yes | 1 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | DLEN | UCHAR | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | MUX | UCHAR | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | PORT | UCHAR | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | NOBT | UCHAR | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | OBJI | USHORT | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | OBJO | USHORT | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | INHB | ULONG | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | TMO | ULONG | Yes | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | RD1..8| CHAR | No | 0 | Yes | Yes | Yes | Yes| +-------+-----------+-----+---------+--------+--------+---------+----+ | WR1..8| CHAR | No | 0 | Yes | Yes | Yes | Yes| +-------+-----------+-----+---------+--------+--------+---------+----+ | ORD | STRING | No | 0 | Yes | No | Yes | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | OWR | STRING | No | 0 | Yes | No | Yes | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | RMIN | LONG | No | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | RMAX | LONG | No | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | ASYN | UCHAR | No | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | BMPL | UCHAR | No | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | WNPM | UCHAR | Yes | 0 | Yes | Yes | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | WNPF | UCHAR | No | 0 | Yes | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | WNPL | INLINK | Yes | 0 | Yes | Yes | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | NLIS | NOACCESS | No | 0 | No | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ | IOSC | NOACCESS | No | 0 | No | No | No | No | +-------+-----------+-----+---------+--------+--------+---------+----+ Field Descriptions ================== .. table:: Field Descriptions +----------+---------------------------------+-----------------------------------------------------------------------+ | Field | Summary | Description | +==========+=================================+=======================================================================+ | VAL | Current Value | Dummy field, only present because every record needs a ``VAL`` field. | +----------+---------------------------------+-----------------------------------------------------------------------+ | ATYP | Access Type | 'RO' (readonly) or 'WO' (writeonly) or 'RW' (read-write) | +----------+---------------------------------+-----------------------------------------------------------------------+ | UTYP | User Type | 'Client' or 'Server' | +----------+---------------------------------+-----------------------------------------------------------------------+ | CLAS | Class | 'Basic' or 'Multiplexed' | +----------+---------------------------------+-----------------------------------------------------------------------+ | BTYP | Base Type | 'NIL', 'CHAR', 'UCHAR', 'SHORT', 'USHORT', 'LONG', 'ULONG' | +----------+---------------------------------+-----------------------------------------------------------------------+ | NELM | Number of Elements | Size of the data array in elements. | +----------+---------------------------------+-----------------------------------------------------------------------+ | DLEN | Data Length | Size of data in bytes. This includes the ''MUX'' byte, if | | | | appropriate. | +----------+---------------------------------+-----------------------------------------------------------------------+ | MUX | Multiplexor | A number between 0 and 127 for multiplexed data. | +----------+---------------------------------+-----------------------------------------------------------------------+ | PORT | CAN Port on card | Port number on the CAN bus interface device. | +----------+---------------------------------+-----------------------------------------------------------------------+ | NOBT | Number of significant Bits | Higher order bits are ignored. This value must be set correctly! | +----------+---------------------------------+-----------------------------------------------------------------------+ | OBJI | CAN id of Incoming Object | Every LowCAL variable needs at most two COBs for incoming and | +----------+---------------------------------+ outgoing messages. | | OBJO | CAN id of Outgoing Object | | +----------+---------------------------------+-----------------------------------------------------------------------+ | INHB | Inhibit time | CAN messages for this variable are sent only every ''INHB * 100'' | | | | microseconds. This feature is currently not supported by the driver. | +----------+---------------------------------+-----------------------------------------------------------------------+ | TMO | Timeout | After this number of milliseconds, the device support assumes a | | | | timeout. This is valid only for confirmed services, i.e. only for | | | | user type Client and access type RO and WR. | +----------+---------------------------------+-----------------------------------------------------------------------+ | RD1...8 | Read Input Values 1..8 | These are the fields from which data can be read. | +----------+---------------------------------+-----------------------------------------------------------------------+ | WR1...8 | Desired Output Values 1..8 | These are the fields to which data can be written. | +----------+---------------------------------+-----------------------------------------------------------------------+ | ORD | Old Read Values | The old ''RDx'' fields. | +----------+---------------------------------+-----------------------------------------------------------------------+ | OWR | Old Write Values | The old ''WRx'' fields. | +----------+---------------------------------+-----------------------------------------------------------------------+ | RMIN | Minimum Raw Value | These fields are used for communication with HwClient device support. | +----------+---------------------------------+ They are used to save device support specific information. ''RMIN'' | | RMAX | Maximum Raw Value | and ''RMAX'' are used to enable the device supports of analog records | +----------+---------------------------------+ to determine linear conversion parameters. They are calculated from | | ASYN | Is processing Asynchronous? | ''BTYP'' and ''NOBT''. ''ASYN'' and ''BMPL'' are for all record types | +----------+---------------------------------+ and enable client device supports to adapt their asynchronous and | | BMPL | Do we Bumpless Reboot? | warm reboot facilities. They are either 1 (yes) or 0 (no). | +----------+---------------------------------+-----------------------------------------------------------------------+ | WNPM | Write on Next Process Mask | For WO and RW variables. This fields contains an 8 bit mask. If bit | | | | x of the mask is set, then a write to the corresponding | | | | ''WR(x+1)'' field will cause the record to assemble and send the | | | | current data as soon as the record is processed the next time. | +----------+---------------------------------+-----------------------------------------------------------------------+ | WNPF | Write on Next Process Flags | Internals flags. | +----------+---------------------------------+-----------------------------------------------------------------------+ | WNPL | Write on Next Process mask | If not constant, then each time the record is processed, ''WNPL'' is | | | Location | read to determine a new ''WNPM'' value. If constant, this is done only| | | | at iocInit. | +----------+---------------------------------+-----------------------------------------------------------------------+ | NLIS | Notify List | These fields are for internal use only. | +----------+---------------------------------+ | | IOSC | I/O Scan private for clients | | +----------+---------------------------------+-----------------------------------------------------------------------+ Record Support Routines ========================= init_record ----------- ``long init_record(hwLowcalRecord *prec, int pass)`` This routine does all work in the first call to ``init_record``. It initializes the notify list (``NLIS``) and the ioscanpvt (``IOSC``) of the record. Afterwards, existence of a device support is checked and the ``init_record`` of the device support is called. process ------- ``long process(hwLowcalRecord *prec)`` This routine initiates and completes the actual I/O. 1. If ``PACT`` is set, then 2. Determine the kind of action. This depends on the access type (``ATYP``) and user type (``UTYP``) of the record, as well as the state of the ``WNPF`` field. .. table:: Process Actions +------+--------+---------------------------------------------------------------------------------------+ | ATYP | UTYP | Action | +======+========+=======================================================================================+ | RO | Client | Always read. | +------+--------+ | | WO | Server | | +------+--------+---------------------------------------------------------------------------------------+ | RO | Server | Always write. | +------+--------+ | | WO | Client | | +------+--------+---------------------------------------------------------------------------------------+ | RW | Server | If one of the ``WRx`` fields that have the corresponding bit in ``WNPM`` set has been | +------+--------+ written to, then write, else read. | | RW | Client | | +------+--------+---------------------------------------------------------------------------------------+ 3. If ``WNPL`` is not a constant link, get ``WNPM`` from ``WNPL``. 4. If ``BMPL`` is set, override action to `read' and reset ``BMPL``. 5. Clear action flag (read or write) in ``WNPF``. 6. Call device support read or write function depending on action. 7. If device support set ``PACT``, remember action (read or write) in ``WNPF`` for process completion and return. 8. If ``PACT`` is not set, then complete processing by calling device support's read or write function, depending on remembered action. 9. Set ``PACT``. 10. If status is ok, clear ``UDF``. 11. Get timestamp. 12. Reset alarms and post events for ``VAL`` and for the ``RDx`` and ``WRx`` fields. 13. Complete processing of the records in the notify list. 14. Process forward link. 15. Reset ``PACT`` and return status (i.e. result from device support call). special ------- ``long special(struct dbAddr *paddr, int after)`` After a write to one of the ``WRx`` fields, set write action bit in ``WNPF``. cvt_dbaddr ---------- ``long cvt_dbaddr(struct dbAddr *paddr)`` This routine is called whenever one of the ``RDx`` or ``RDx`` fields is accessed. It converts the addresses of the fields according to the size (in bytes) of the base type (``BTYP``) and the index in the array. For example, if the base type has two bytes (`SHORT' or `USHORT'), then ``WR2`` is relocated to ``WR3``, ``WR3`` to ``WR5``, and ``WR4`` to ``WR7``. Thus, the index `x' in ``WRx`` or ``RDx`` always refers to the array index, not the position in bytes. Warning: This may cause confusion if the a record instance is viewed with the ``dbpr`` command line tool, because ``dbpr`` does not relocate fields, i.e. does not call ``cvt_dbaddr``. The number of elements in the array must not exceed 8 bytes divided by the base type size. For example, if the base type is `LONG', the only ``RDx`` and ``WRx`` fields that may be accessed are ``RD1``, ``RD2``, ``WR1``, and ``WR2``. Access to other fields is an error and will cause processing to fail. Note that this routine not only relocates the field address, but also adapts the field size according to the base type. get_hw_info ----------- ``long get_hw_info(hwLowcalRecord *prec, HW_INFO *pinfo)`` This is a non-standard additional record support function. It is meant to be called by client records during the initialization phase to receive information for conversion, bumpless reboot and asynchronous processing, and to register themselves with the hwLowcalRecord for process callbacks. For details see the document 'HwClient - Device Support for Clients of Hardware Records'. Device Support ============== The only admissible device support (``DTYP``) is `lowcal`. In principle, this record wouldn't need device support, because it is by design limited to exactly one sort of device, whose access methods could be integrated into the record support directly. Nevertheless, in order to use this record together with standard record types that use the same CAN bus protocol, the actual device I/O was factored out into the (already existing) mCANSupport module.