subArray记录类型的一般用法是从waveform记录获取子数组。设置元素数目(NELM)或索引(INDX)字段使得这个记录再被运行依次,因此使用标准EPICS操作接口工具能够实现这样的应用程序,在这个应用程序中在一个waveform记录中一个子数组的长度和位置动态变化。
subArray记录的第一个元素(在被引用的waveform记录中INDX位置)可以以标量被显示,或者用与waveform记录相同的方式显示整个subarray(NELM长度)。如果被引用waveform记录在INDX后的元素少于NELM个元素,返回实际可以获取的元素数目,并且被读取元素数目字段(NORD)被设置来反映这个。这个记录类型不支持写新值到waveform记录。
记录专用字段在下面描述,按功能分组:
subArray记录有用于指定在什么情况下将运行这个记录的标准字段。这些字段在Scan Fields中列出。
subArray输入链接(INP)应该被配置成引用Waveform记录。它应该指定一个waveform记录的VAL字段。INP字段可以是通道访问链接和数据库链接。
这些参数确定了数组元素的数目(数组长度)和那些元素的数据类型。字段值的类型(FTVL)字段确定了这个数组的数据类型。
用户在MALM字段中指定了要被读入到这个subarray的数目最大数目。这通常应该等于Waveform数组中元素数目(在Waveform的NELM字段中找到)。MALM字段用于分配内存。subArray的元素数目字段是用户指定subArray将提取的实际元素数目的地方。它当然不应该大于MALM;如果它是,记录运行的process例程设置其等于MALM。
INDX字段确定了subArray记录的数组相对于Waveform数组的偏移。例如,如果INDX是2,则subArray将读取NELM元素从Waveform的数组的第三个元素开始读取NELM个元素。因而,它等于Waveform的数组的索引号。
实际的子数组是被VAL字段引用。
这些参数用于向操作者显示有意义的数据。它们以文本或图形显示这个subArray记录的值和其它参数。EGU是一个最长16个字符的字符串,描述这个subArray记录保存值的工程单位。通过get_units()记录支持例程获取它。
HOPR和LOPR字段为这个sub-array元素设置上下显示限制。get_graphic_double()和get_control_double()记录支持例程都获取这些字段。
PREC字段确定了用什么浮点精度显示VAL。当调用get_precision()记录支持例程时使用它。
有关记录名(NAME)和描述(DESC)字段的更多信息见Fields Common to All Record Type。
subArray记录有所有记录类型共有的警报参数。Alarm Fields列出了与所有记录类型共有警报相关联的字段。
这些字段不是由用户配置的。它们用于记录内部运行或者代表这个记录的当前状态。
NORD字段保存了实际被读入这个数组的元素数目。当NELM和INDX字段之和超过了在源数组中找到的已有元素数目时,它将少于NELM。
BPTR包含了一个指向这个记录的数组的指针。
1) init_record
long (*init_record)(struct dbCommon *precord, int pass)
使用MALM和FTVL,为数组分配空间。数组地址存储在BPTR。这个例程检查设备支持是否可用以及设备支持读取例程是否被定义。如果二者中有一个不存在,发出一条错误消息,并且终结运行的process。如果设备支持包含init_record(),它被调用。
2) process
long (*process)(struct dbCommon *precord)
3) cvt_dbaddr
long (*cvt_dbaddr)(struct dbAddr *paddr)
这被dbNameToAddr()调用。它使得dbAddr结构体指向保存这个结果的实际缓存。
4) get_array_info
long (*get_array_info)(struct dbAddr *paddr, long *no_elements, long *offset)
获取NORD。
5) put_array_info
long (*put_array_info)(struct dbAddr *paddr, long nNew)
设置NORD。
6) get_graphic_double
long (*get_graphic_double)(struct dbAddr *paddr, struct dbr_grDouble *p)
对于数组中元素,这个例程设置HOPR和LOPR。对于INDX字段,这个例程返回MALM-1和0。对于MALM,返回MALM和1。对于其它字段,它调用recGblGetGraphicDouble。
7) get_control_double
long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p)
对于数组元素,这个例程获取HOPR和LOPR。否则,调用recGblControlDouble()。
8) get_units
long (*get_units)(struct dbAddr *paddr, char *units)
获取EGU。
9) get_precision
long (*get_precision)(const struct dbAddr *paddr, long *precision)
记录运行实现以下算法:
1) 检查合适的设备支持模块是否存在。如果它不存在,则发出一条错误消息并且用PACT字段仍设置为TRUE终止正在运行的process。这确保了不再为这个记录调用processes。因而不会发生错误风暴。
2) 检查NELM和INDX。如果NELM大于MALM,它被设置成MALM。如果INDX大于或等于MALM,它被设置成MALM-1。
3) 调用设备支持的read_sa()例程。预计这个例程从缓存起始放置所需的子数组,并且设置NORD为被读取的子数组的元素数目。
4) 如果PACT已经被更改为TRUE,设备支持读取操作已经开始,但还未结束写新值。
5) 检查是否应该调用monitors。
6) 如果需要,扫描forward链接,设置PACT为FALSE,并且返回。
设备支持例程主要使用以下字段:
设备支持由以下例程组成:
1) long report(int level)
这个可选的例程被IOC命令dbior调用,并且被传递用户请求的报告等级。它应该打印一个有关设备支持的报告到stdout。level参数可以用于用更改等级输出更加详细的信息,或者选择用不同级别的不同信息类型。级别0应该输出一小段概述。
2) long init(int after)
这个可选的例程在IOC初始化时被调用两次。第一次调用用整数参数after设置为0在进行任何init_record()调用前发生。第二次调用用after设置为1在已经进行了所有init_record()调用后发生。
3) init_record
long init_record(subArrayRecord *prec)
这个例程被记录支持init_record()例程调用。
4) read_sa
long read_sa(subArrayRecord *prec)
从源waveform开始读取源waveform足够到BPTR,去包含请求的子数组。接着数组被复制到这个缓存的起始。NORD被设置成被采集的子数组的元素数目。
当前只提供设备支持模块Soft Channel。
Soft Channel
预计INP指向一个waveform记录或者类似的一个数组字段。
这个数据库实例文件有三个记录实例组成:
1) $(USER):arrayIn记录实例是waveform类型记录实例,它驱动$(USER):subArray记录实例运行并且为其提供数据源。
2) $(USER):subArray记录实例是subArray类型记录实例,它用其INDX和ELEM字段从其源waveform记录实例数组中提取子数组,放入本记录数组中,并且驱动$(USER):arrayOut记录实例运行并且为其提供数据源。
3) $(USER):arrayOut记录实例是waveform类型记录实例,它从$(USER):subArray记录实例的数组中获取数组,存入本记录的数组中。
- record(waveform, "$(USER):arrayIn")
- {
- field(SCAN, "Passive")
- field(DTYP, "Soft Channel")
- field(NELM, "10")
- field(FTVL, "LONG")
- field(FLNK, "$(USER):subArray")
- }
-
- record(subArray, "$(USER):subArray")
- {
- field(SCAN, "Passive")
- field(DTYP, "Soft Channel")
- field(FTVL,"LONG")
- field(MALM, "10")
- field(NELM, "5")
- field(INDX, "2")
- field(INP, "$(USER):arrayIn.VAL")
- field(FLNK, "$(USER):arrayOut")
- }
-
- record(waveform, "$(USER):arrayOut")
- {
- field(SCAN, "Passive")
- field(DTYP, "Soft Channel")
- field(FTVL, "LONG")
- field(NELM, "10")
- field(INP, "$(USER):subArray.VAL")
- }
将上述记录数据库文件加载到IOC中,用dbl观察一共加载的记录实例:
- epics> dbl
- blctrl:arrayIn
- blctrl:arrayOut
- blctrl:subArray
另开一个命令窗口,用通道访问命令对以上记录实例的数据传递进行测试:
- # IOC初始化时,三个记录各自初始的值
- [root@bjAli ~]# caget blctrl:arrayIn blctrl:subArray blctrl:arrayOut
- blctrl:arrayIn 10 3 0 0 0 0 0 0 0 0 0
- blctrl:subArray 10 327690 0 0 0 0 0 0 0 0 0
- blctrl:arrayOut 10 0 0 0 0 0 0 0 0 0 0
-
- # 向blctrl:arrayIn记录中写入一个长度为10的数组,数组元素从1~10
- # 观察blctrl:subArray和blctrl:arrayOut记录实例中数组元素以及这两个记录实例实际获取的元素数目
- # INDX=2,ELEM=5,subArray记录获取的数组元素是从blctrl:arrayIn数组中第三个元素开始,取5个元素
- [root@bjAli ~]# caput -a blctrl:arrayIn 10 1 2 3 4 5 6 7 8 9 10
- Old : blctrl:arrayIn 10 3 0 0 0 0 0 0 0 0 0
- New : blctrl:arrayIn 10 1 2 3 4 5 6 7 8 9 10
- [root@bjAli ~]# caget blctrl:arrayIn blctrl:subArray blctrl:arrayOut
- blctrl:arrayIn 10 1 2 3 4 5 6 7 8 9 10
- blctrl:subArray 10 3 4 5 6 7 0 0 0 0 0
- blctrl:arrayOut 10 3 4 5 6 7 0 0 0 0 0
- [root@bjAli ~]# caget blctrl:arrayIn.NORD blctrl:subArray.NORD blctrl:arrayOut.NORD
- blctrl:arrayIn.NORD 10
- blctrl:subArray.NORD 5
- blctrl:arrayOut.NORD 5
-
- # 更改subArray记录实例的取值索引起始值
- [root@bjAli ~]# caput blctrl:arrayIn.INDX 4
- Channel connect timed out: 'blctrl:arrayIn.INDX' not found.
- [root@bjAli ~]# caput blctrl:subArray.INDX 4
- Old : blctrl:subArray.INDX 2
- New : blctrl:subArray.INDX 4
- [root@bjAli ~]# caget blctrl:arrayIn blctrl:subArray blctrl:arrayOut
- blctrl:arrayIn 10 1 2 3 4 5 6 7 8 9 10
- blctrl:subArray 10 5 6 7 8 9 0 0 0 0 0
- blctrl:arrayOut 10 5 6 7 8 9 0 0 0 0 0
- [root@bjAli ~]# caget blctrl:arrayIn.NORD blctrl:subArray.NORD blctrl:arrayOut.NORD
- blctrl:arrayIn.NORD 10
- blctrl:subArray.NORD 5
- blctrl:arrayOut.NORD 5
-
- # 更改subArray记录实例的取值数目值
- [root@bjAli ~]# caget blctrl:subArray.NELM 2
- Channel connect timed out: some PV(s) not found.
- [root@bjAli ~]# caput blctrl:subArray.NELM 2
- Old : blctrl:subArray.NELM 5
- New : blctrl:subArray.NELM 2
- [root@bjAli ~]# caget blctrl:arrayIn blctrl:subArray blctrl:arrayOut
- blctrl:arrayIn 10 1 2 3 4 5 6 7 8 9 10
- blctrl:subArray 10 5 6 0 0 0 0 0 0 0 0
- blctrl:arrayOut 10 5 6 0 0 0 0 0 0 0 0
- [root@bjAli ~]# caget blctrl:arrayIn.NORD blctrl:subArray.NORD blctrl:arrayOut.NORD
- blctrl:arrayIn.NORD 10
- blctrl:subArray.NORD 2
- blctrl:arrayOut.NORD 2