waveform记录类用于与waveform数字仪表做接口。这个记录在数组中存储其数据。此数组能够包含任意受支持的数据类型。
在下面描述记录特定的字段,按功能分组。
waveform记录有用于指定将在什么情况洗钱案运行这个记录的标准字段。这些字段在Scan Fields中被列出。
这些字段是由用户配置,指定记录如何以及从哪里读取其数据。如何配置INP字段决定了waveform从哪里获取其输入。它可以是一个硬件地址,通道访问链接或者数据库链接或者一个常数。仅在使用软设备支持的记录中,INP字段可以是通道访问链接,数据库链接或者一个常数。否则,INP字段必须是一个硬件地址。

DTYP字段必须包含合适的设备支持模块的名称。从输入链接获取的值被放入一个由VAL引用的数组。(如果INP链接是一个常数,可以通过dbPuts向这个数组中放置元素)。NELM指定这个数组将保存的元素数目,而FTVL制定了这些元素的数据类型。
FTVL字段一个类型menuFtype的菜单选项,其取值如下:

当RARM字段被设置为1时,RARM字段使得某些设备类型re-arm,但我们不再知道任何这样的设备。
这些参数用于向操作者显示有意义的数据。它们以文本或者图形显示这个waveform的值和其它参数。

EGU是一个最多16个字符的字符串,描述waveform测量的单位。由get_units记录支持例程获取它。
HOPR和LOPR字段设置由VAL字段引用的数组元素的上下显示限制。get_graphic_double和get_control_double记录支持例程获取这些字段。
PREC字段确定用哪种浮点精度显示这些数组值。当调用get_precision记录支持例程时使用它。
更多有关记录名(NAME)和描述(DESC)字段见Fields Common to All Record Types。
waveform记录有所有记录类型共有的警报参数。Alarm Fields列出了与所有记录类型共有的警报相关联的字段。
这些参数用于确定何时发送在VAL字段上的monitors。APST和MPST字段有一个带有选项Always和On Change的菜单。默认是Always,因而通常在这个记录每次运行时发送monitors。选择On Change,使得在记录每次运行时要计算一个VAL字段缓存的32位哈希值并且与线圈哈希值做比较;只在哈希不同时,才发送monitors,表明缓存已经变化。注意:有这样的小可能性,不同值缓存产生相同的哈希值,因此,对于关键系统,Always可能是更好的选择,即使它再次发送重复的数据。

这个菜单定义了APST和MPST字段的可能选项:

这些参数由运行时代码使用用于运行这个waveform记录。不能使用配置工具配置它们。在运行时仅VAL字段是可修改的。
VAL引用了这个数组,waveform记录在里面存储其数据。BPTR字段保存了这个数组的地址。
NORD字段表明被读取到这个数组中的元素数目。
BUSY字段允许异步设备支持在多次读取周期中按顺序采集数组元素,在结束一个读取操作前,这些多次读取周期可能很多次调用记录的process()。这样一个设备会在采集开始时(它也会设置NORD为0斌且给使用它跟踪多少元素已经被接收)设置BUSY和PACT为TRUE。在接收到最后一个元素后,read_wf()例程会清零BUSY,者告诉这个记录process()方法这个读取已经结束。注意:在使用此种设备支持类型时,执行VAL字段获取的CA客户端可以见到被部分填充的数组,因此,现在几乎不再使用BUSY字段。

以下字段用于在模仿模式中操作这个记录。
如果SIMM(通过SIML获取)是YES,这个记录被置入了SIMS严重性并且通过SIOL获取值。SSCN设置一个在仿真模式中要使用的不同的SCAN机制。SDLY设置一个延时(秒为单位),其用于异步仿真运行。
有关仿真模式和其字段的信息见Input Simulation Fields。

1) init_record
static long init_record(waveformRecord *prec, int pass)
使用NELM和FTVL,为数组分配空间。这个数组地址被存储在这个记录中。
如果SIML类型是CONSTANT链接,这个例程用SIML的值初始化SIMM,或者如果SIML类型是PV_LINK,创建一个通道访问链接。根据SIOL是CONSTANT或PV_LINK,对VAL进行类似地初始化。
这个例程接着检查设备支持是否可用以及设备支持读取例程是否被定义。如果二者中有一个不存在,发出一条错误消息并且终结正在运行地process。
如果设备支持包括init_record(),它被调用。
2) process
static long process(waveformRecord *prec)
2) cvt_dbaddr
static long cvt_dbaddr(DBADDR *paddr)
这被dbNameTtoAddr调用。它使得dbAddr结构体指向保存结果地实际缓存。
3) get_array_info
static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
从由VAL引用的数组获取值。
4) put_array_info
static long put_array_info(DBADDR *paddr, long nNew)
写值到由VAL引用的数组中。
5) get_units
static long get_units(DBADDR * paddr, char * units)
获取EGU
6) get_precision
static long get_precision(DBADDR *paddr, long *precision)
如果字段是VAL字段,获取PREC。否则,调用recGblGetPrec()。
7) get_graphic_double
static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble *pgd)
为一个字段设置上下显示限制。如果这个字段是VAL,这些限制被设置成HOPR和LOPR,否则如果这个字段有定义好的上下限制,将使用它们,否则将使用这个字段类型的上下最值。
设置以下值:
- upper_disp_limit = HOPR
- lower_disp_limit = LOPR
8) get_control_double
static long get_control_double(DBADDR *paddr, struct dbr_ctrlDouble *pcd)
为一个字段设置上控制和下控制限制。如果这个字段是VAL,这些字段被设置成HOPR和LOPR,否则如果这个字段有定义好的上下限制,将使用它们,否则将使用对应这个字段类型的上和下最值。
设置以下值:
- upper_ctrl_limit = HOPR
- lower_ctrl_limit = LOPR
例程process实现了以下算法:
1) 检查合适的设备支持模块是否存在。如果不存在,发出一条错误消息并且用PACT仍然设为TRUE终止正在运行的process。这确保了不再为这个记录调用processes。因而不会发生错误风暴。
2) 调用设备支持读取例程。
3) 如果PACT已经被更改为了TRUE,设备支持读取例程已经开始,但还没有结束写这个新值。在这种情况下,运行的process例程仅返回,保留PACT为TRUE。
4) 检查是否应该调用monitors:
5) 如果需要,扫描forward链接,设置PACT为FALSE,并返回。
每个waveform记录必须有一个相关联的设备支持例程集合。设备支持例程的首要作用是在调用read_wf时获得一个新值。设备支持例程主要使用以下字段:

设备支持由以下例程组成:
1) report
long report(int level)
这个可选的例程被IOC命令dbior调用并且被传递由用户请求的报告级别。它应该打印一个有关设备支持的状态的报告到标准输出。level参数可能被用于用更高级别输出更详细信息,或者选择不同等级的不同信息类型。级别0应该输出一小段概要。
2) init
long init(int after)
此可选例程在IOC初始化时被调用两次。第一次调用用整数参数after设为0,在进行任何init_record()调用之前发生。第二次调用用after设为0在已经进行了所有init_record()调用之后发生。
3) init_record
long init_record(dbCommon *precord)
这个例程是可选的。如果提供了,记录支持init_record()例程调用它。
4) get_ioinit_info
long get_ioint_info(int cmd, dbCommon *precord, IOSCANPVT *ppvt)
在这个记录每次被添加到一个I/O事件扫描列表或者从一个I/O事件扫描列表删除时,这个例程被ioEventScan系统调用。根据这个记录被添加到一个I/O事件列表或者被从一个I/O事件扫描列表删除,cmd有值(0,1)。必须为使用ioEvent scanner的任何设备类型提供它。
5) read_wf
long read_wf(waveformRecord *prec)
这个例程必须提供一个新输入值。它返回以下值:
提供了Soft Channel设备支持模块从其它记录读取值并且把它们存在VAL字段。如果INP是一个常数链接,则read_wf()什么也不做。在这种情况下,可以使用这个记录来保存一个固定的数据集合或者从别处被写的数组值。如果INP是一个有效链接,从那个链接读取新数组值。NORD被设置成它接收到的项。
如果INP链接类型是常数,在init_record()例程中从INP设置VAL并且也在同时设置NORD。
这个数据库实例文件由6个记录实例组成:
$(USER):longin, $(USER):string和$(USER):wflong2是三个被动记录,它们作为数据源,在其运行时,在其运行结束前,通过FLNK字段使得此字段指向的记录运行并且数据分别被$(USER):wflong1, $(USER):wfstring和$(USER):wflong2三个记录实例读取。
- record(longin, "$(USER):longin")
- {
- field(SCAN, "Passive")
- field(INP, "0")
- field(HOPR,"1000")
- field(LOPR,"0")
- field(DTYP, "Soft Channel")
- field(FLNK, "$(USER):wflong1")
- field(PINI, "YES")
- }
-
- record(stringin, "$(USER):string")
- {
- field(SCAN, "Passive")
- field(INP, "Hello World")
- field(DTYP,"Soft Channel")
- field(FLNK, "$(USER):wfstring")
- field(PINI, "YES")
- }
-
-
- record(waveform, "$(USER):wflong1")
- {
- field(NELM,"10")
- field(FTVL, "LONG")
- field(INP, "$(USER):longin")
- field(SCAN, "Passive")
- field(DTYP, "Soft Channel")
- }
-
- record(waveform, "$(USER):wflong2")
- {
- field(NELM, "10")
- field(FTVL, "LONG")
- field(SCAN, "Passive")
- field(DTYP, "Soft Channel")
- field(FLNK, "$(USER):wflong3")
- }
-
- record(waveform, "$(USER):wflong3")
- {
- field(NELM, "20")
- field(FTVL, "LONG")
- field(SCAN, "Passive")
- field(INP, "$(USER):wflong2")
- field(DTYP, "Soft Channel")
- }
-
- record(waveform, $(USER):wfstring)
- {
- field(NELM, "100")
- field(FTVL, "STRING")
- field(SCAN, "Passive")
- field(DTYP, "Soft Channel")
- field(INP, "$(USER):string")
- }
将上述数据库文件加载到IOC中,用dbl命令查看一共加载的记录实例:
- epics> dbl
- blctrl:wflong1
- blctrl:wflong2
- blctrl:wflong3
- blctrl:wfstring
- blctrl:longin
- blctrl:string
另开一个命令窗口,用通道访问命令进行测试:
刚初始化时,blctrl:wflong1 blctrl:wfstring和blctrl:wlong3的值:
- [root@bjAli ~]# caget blctrl:wflong1 blctrl:wfstring blctrl:wflong3
- blctrl:wflong1 10 50 0 0 0 0 0 0 0 0 0
- blctrl:wfstring 100
- blctrl:wflong3 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
对blctrl:longin写入数据,观察blctrl:wflong1的值:这个wavefrom记录中数组获取了一个元素值66
- [root@bjAli ~]# caput blctrl:longin 66
- Old : blctrl:longin 50
- New : blctrl:longin 66
- [root@bjAli ~]# caget blctrl:wflong1
- blctrl:wflong1 10 66 0 0 0 0 0 0 0 0 0
对blctrl:string写入一个字符串,观察blctrl:wfstring的值:这个waveform记录中数组获取了blctrl:string记录的值。
- [root@bjAli ~]# caput blctrl:string "Good Morning"
- Old : blctrl:string
- New : blctrl:string Good Morning
- [root@bjAli ~]# caget blctrl:wfstring
- blctrl:wfstring 100 Good Morning
对blctrl:wflong2写入一个数组,观察blctrl:wflong3的值:这个waveform记录的数组获取了写入了blctrl:wflong2记录的数组。
用法:caput -a waveform记录 写入数据的个数 写入的数组
- [root@bjAli ~]# caput -a blctrl:wflong2 10 1 2 3 4 5 6 7 8 9 10
- Old : blctrl:wflong2 10 3 0 0 0 0 0 0 0 0 0
- New : blctrl:wflong2 10 1 2 3 4 5 6 7 8 9 10
- [root@bjAli ~]# caget blctrl:wflong3
- blctrl:wflong3 20 1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 0