内容
1、介绍
数组计算输出或"aCalcout"记录源自sCalcout(字符串calcout)记录,sCalcout(字符串calcout)记录源自calcout记录。除了变量操作和表达式外,aCalcout记录还通过支持数组操作和表达式扩展了calcout记录。这个记录有12个用作表达式输入变量的数组字段(AA..LL),并且它调用一个清楚数组的扩展版本的EPICS计算引擎。随aCalcout记录一起提供的软设备支持根据它输出链接链接到的字段的元素数目,写数组或标量数据到记录的输出链接。
这是一个某些aCalcout记录字段的示例MEDM窗口
2、扫描参数
aCalcout记录有用于指定在什么情况下运行此记录的标准字段。这些字段和它们的用法见EPICS记录参考手册。
3、数组大小参数
aCalcout记录在它们被首次使用时分配NELM个元素。这是数组元素的最大数目,并且它应用于所有数组。必须在启动时,在使用任何数组前指定NELM。
实际使用的元素数目被指定为NUSE。NUSE的值将被强制在范围0到NELM(包含)之间。如果NUSE==0, 这个记录将其当成NELM。
当一个CA客户端连接到一个数组,取决于SIZE字段(其接受值"NELM"和"NUSE"。"NELM"是默认值,并且它是更安全的选项)的设置,acalcout记录可以告诉这个客户端数组大小是NELM或者NUSE。在某些情况下,"NELM"效率低于"NUSE"。如果SIZE设为"NUSE",当NUSE字段增大时,CA连接必须断开并且重新建立。
字段 | 概要 | 类型 | DCT | 初始 | 访问 | 修改 | Rec Proc Monitor |
NELM | 分配的数组元素数目 | DBF_ULONG | 是 | 1 | 是 | 否 | N/A |
NUSE | 实际使用的数组元素数目 | DBF_ULONG | 是 | 0 | 是 | 是 | 是 |
SIZE | 指定NELM或NUSE是向客户端声明的数组大小。 | MENU("NELM", "NUSE") | 是 | "NELM" | 是 | 是 | N/A |
4、输入链接
aCalcout记录有24个链接,它从这些链接获取在表达式中使用的值:12个用于标量字段(INPA->A, INPB->B, ..., INPL->L);和12个用于数组字段(INAA->AA, INBB->BB, ..., INLL->LL)。这些字段可以是数据库链接,通道访问链接或者(仅限标量字段)常数。这些链接字段不能是硬件地址。此外,aCalcout记录包含字段INVA, INBV, ...,INLV,这些表示对标量字段的链接的状态,而字段IAAV, IBBV, ..., ILLV,这些表明了数组字段的链接的状态。这些字段表明指定的PV是否被找到以及一个指向它的链接是否建立了。这些字段的解释见第7部分,显示参数。
如何指定数据库连接的信息见EPICS记录参考手册。
5、表达式
如Calcout记录,aCalc记录有一个CALC字段,你向其输入一个用于在其运行时用于此记录计算的表达式。产生的标量值将被放入VAL字段,而产生的数组值将被放置在AVAL字段。VAL可以被OOPT字段使用来确定是否写入输出连接或者提交一个输出事件(见第6部分,输出参数)。VAL和AVAL也可以被写入到输出连接。(如果你选择写一个输出值,取决于在输出链接另一端的字段的数据类型,这个记录将在VAL和AVAL之间选项。)
CALC表达式被转成操作码并且用postfix标注存储在RPCL字段。它是记录运行时实际被计算的后缀表达式。当在运行时,更改CALC字段,记录支持例程special()调用一个函数来检查它并且转换它成后缀。
记录也有第二个计算相关字段的集合,在第6部分输出参数中描述。
被数组计算记录(aCalc)支持的表达式可以包含标量和/或数组操作数,代数操作符和函数,三角函数,关系操作符,逻辑操作符,数组操作符和函数,括号和逗号和条件"?:"操作符。在接下来的部分中描述所有,但首先,我们需要讨论在出现标量,数组和混合操作符时操作符和函数如何作用。
除非另外声明,否则函数和操作符按以下作用:
1)单参数函数和操作符,在传给一个数组值的参数或操作数时,对每个数组元素单独操作,并且返回一个数组。
2)双参数函数和操作符,在传给数组值的操作数时,操作元素对并且返回一个数组(例如:aa+bb=aa[0]+bb[0], aa[1]+bb[1], ...)
3) 如果一个两参数函数或操作符的一个参数是一个数组,而另一个参数是一个标量,通过重复这个标量值,标量数组被转成一个数组。因而,表达式A*BB的值是数组a*bb[0], a*bb[1], a*bb[3],...
4) 当一个数组必须被隐式地转成一个标量(例如,杜宇操作符?: ^ ** >>和<<),使用地标量值是第一个数组元素的值。在以下表达式中,在方块号中的数组参数将被隐式地转成标量:
- [AA]?BB:CC
- AA^[BB]
- AA**[BB]
- AA>>[BB]
- AA<<[BB]
5.1 操作数
表达式可以使用从输入链接获取的值作为操作数。这些从输入链接获取的值被存储在A-L和AA-LL字段。要在表达式中使用的值只是通过字段名被引用。例如,从INPA链接获取的值被存储在字段A中,并且用'A'在表达式中被引用(或如'a', 大小写没有关系)。
数组操作数AA-LL的数组元素数目是由NELM字段在启动时设定。如果这个记录接收到一个数组值有更多或更少的元素,由aCalc记录使用的数组将被截短或者用0在末尾填充。
如果一个有效的输入链接与这个字段相关联,接着这个记录不允许它通过一个'put'操作被修改。
有特殊操作数与输入字段不相关联,而是由这个记录定义的(更准确地,由这个记录用于计算表达式的calc引擎定义)。除了RNDM,NRNDM和ARNDM外,其余都是常数。
PI | 3.141592654 |
D2R | 角度到弧度(PI/180) |
R2D | 弧度到角度(1/D2R) |
S2R | 角度秒到弧度(D2R/3600) |
R2S | 弧度到角度秒(1/S2R) |
NRNDM | 来自一个标注偏差为1的正态分布约为0的随机数 |
RNDM | 0和1之间的随机数 |
ARNDM | 0和1之间的随机数值的数组 |
IX | 数组(0,1,..., NUSE) |
VAL | VAL字段的先前值。(在OCAL表达式中,"VAL"是OVAL字段的先前值) |
AVAL | AVAL字段的先前值。(在OCAL表达式中,"AVAL"是OAV字段的先前值) |
5.2 代数函数/操作数
操作符 | 描述 | 示例 |
ABS | 绝对值(单参数函数) | ABS(A) |
DBL | 转换(数组)为double(单参数函数) | DBL(AA) |
FINITE | 如果所有参数都是有限的(变参数函数),返回True | DBL(AA) |
ISINF | 如果参数是无限的,返回True(单参数函数) | ISINF(A) |
ISNAN | 如果参数不是一个数值,返回True(单参数函数) | ISNAN(A) |
SQRT | 平方根(单参数函数) (SQR过时了) | SQRT(A) |
MIN | 最小(变参数函数) | MIN(A, B, ...) |
MAX | 最大(变参数函数) | MAX(A, B, ...) |
CEIL | 上取整(单参数函数) | CEIL(A) |
FLOOR | 下取整(单参数函数) | FLOOR(A) |
INT | 最近的整数(单参数函数) | INT(A) |
MINT | 最近的整数(单参数函数) | MINT(A) |
LOG | 10为底的对数(单参数函数) | LOG(A) |
LN | 自然对数(单参数函数) | LOGE(A) |
LOGE | ’LN‘的过时同义词 | LOGE(A) |
EXP | e指数函数(单元) | EXP(A) |
^ | 指数(二元)(与"**"相同) | A^B |
** | 指数(二元)(与"^"相同) | A**B |
+ | 加(二元) | A+B |
- | 减(二元) | A-B |
* | 乘(二元) | A*B |
/ | 除(二元) | A/B |
% | 模(二元) | A%B |
- | 负(二元) | -A |
NOT | 负(二元) | NOT A |
>& | 最大(二元) | A>?B |
<& | 最小(二元) | A<?B |
5.3 三角函数
5.4 关系操作符
5.5 逻辑操作符
5.6 位操作符
5.7 分隔符
支持开闭括号。支持嵌套的括号。方和花括号不可用于分隔符,因为它们被用作操作符。当用于分隔一个二元函数参数时,支持逗号。空格可以出现在表达式元素之间。元素之间需要空白,否则将被错误解析。解析器总是尝试匹配组成一个可识别操作符或变量的字符的最大串。例如,A AND B将被缩短位A ANDB,因为ANDB将被解析乘AND B。但A AND B不能简写位AAND B,因为AAND将被解析成AA ND。
5.8 If-Else表达式
C语言的if-else(“?:”)操作符被支持。格式是:
expression> ? <expression-true result> : <expression-false result>
5.9 数组特定的函数/操作符
对数组有用的大部分函数和操作符是对标量有用的函数和操作符的简单概括。这里不列出这些函数。在这部分,大部分函数或操作符只用于数组,并且其行为不是某些标量函数的简单逐元素演绎。
操作符 | 描述 | 示例 |
[ | 子数组 | AA[1,3]->aa(1), aa(2), aa(3) |
{ | 子数组准备 | AA{1,3}->0, aa(1), aa(2), aa(3), 0, .. |
>> | 数组右移。通过索引移动数组元素。如果索引不是整数,插值这个数组来移动分数部分。 | AA>>2 |
<< | 数组左移。通过索引移动数组元素。如果索引不是整数,插值这个数组来移动分数部分。 | AA<<2(与AA>>-2相同) |
AMIN | 数组的最小元素(但参数函数) | AMIN(AA)->标量 |
AMAX | 数组的最大元素(但参数函数) | AMAX('a','b','c')->'c' |
ARR | 转换参数为数组(但参数函数) | ARR(1)->1, 1, 1, ... |
AVR | 数组值的平均 | AVG(AA)=SUM(AA)/arraySize AVG(AA[4,9])=SUM(AA[4,9])/6 |
CAT | 连接数组子范围,或者一个数组子范围和一个double值。如果第二个参数是一个标量,在被添加到第一个参数前,它不被转成一个数组。注意:如果第一个参数不是一个子范围,CAT不做任何事情,因为一个满数组没有添加新值的空闲空间。 | CAT(AA[0,2], BB[0,2]) CAT(AA[0,2], B) |
CUM | 运行数组值的和。例如,如果AA=(1,2,3), CUM(AA)=(1,3,6)。 | CUM(AA) |
DERIV | 数组值的导数,相对于数组索引。等价于NDERIV(AA,2) | DERIV(AA) |
FWHM | 数组值的半高宽 | FWHM(AA) |
FITPOLY | (过时。使用FITQ)。按二项式a+b*x+c*x^2拟合数组 | FITPOLY(AA) |
FITMPOLY | (过时。使用FITMQ)。拟合带掩码的数组为二阶多项式。第一个参数是输入数据数组,第二个参数是掩码数组。如果如果掩码数组元素值为真(大于0),相应的数据数组元素将被用于计算最佳拟合多项式:a+b*x+c*x^2 | FITPOLY(AA, AA>0) |
FITQ | 拟合数组为二次方a+b*x+c*x^2,并且可选地返回拟合系数。如果第二,第三,第四个参数被指定为double变量的名称,拟合系数按a,b,c顺序被存储到那些acalcoutRecord字段。如果第二,第三和第四个参数中任何一个是一个数组变量,将忽略它。 | FITQ(AA) FITQ(AA, J, K, L) |
FITMQ | 拟合带掩码数组为一个二次,并且可选地返回拟合系数。第一个参数是输入数据数组,第二个参数是掩码数组。如果掩码数组元素值是真(大于0),相应的数据数组元素将被用于计算最佳拟合多项式a+b*x+c*x^2。如果第三,四和五个参数指定为double变量的名称,拟合系数将按a,b,c顺序被存储到那些acalcoutRecord字段。如果第三,四和五个参数中有任意一个是数组变量,将忽略它。 | FITMQ(AA) FITMQ(AA, J, K, L) |
IX | 数组(0,1,2,3,...,NUSE) | IX(AA) |
IXMAX | 数组最大元素(最正)的索引 | IXMAX(AA) |
IXMIN | 数组最小元素(最负)的索引 | IXMIN(AA) |
IXZ | 数组中第一次过零的(浮点)索引,由线性插值计算 | IXZ(AA) |
IXNZ | 数组的第一个非零元素的索引 | IXNZ(AA) |
NDERIV | 数组值的导数,对数组索引。用以下方式计算导数:在每个数组点, | NDERIV(AA, B) |
NSMOO | 平滑数组值,SMOO()多次使用 | NSMOO(AA,B) |
STD | 数组值的标准偏差 | STD(AA) |
SMOO | 平滑数组值,使用5点二项式公式 y'(i) = y(i-2)/16 + y(i-1)/4 + 3*y(i)/8 + y(i+1)/4 + y(i+2)/16 | SMOO(AA) |
SUM | 数组值的和 | SUM(AA) |
5.10 参数数组操作符
这些参数符以标量/数组的数组显示aCalcout记录的标量/数组字段。它们是指定字段A-L和AA-LL的备选方法。
操作符 | 描述 | 示例 |
@ | 标量数组元素。视数值字段A-L为一个数组,它们的元素被编号为0-11,并且返回其后跟数值的元素。因而,@0是说A的另一种方法。(单目操作) | @A |
@@ | 数组数组元素。视数组字段AA--LL为数组的数组,它们的元素被编号为0-11,并且返回其后跟数值的元素。因而, @@1是说BB的另一种方法。(单目操作) | @@A |
5.11 各种操作符
操作符 | 描述 | 示例 |
:= | 在左手指定的位置中存储右手的值。(二元) | A:=1.2 @7:=3 AA:=IX @@4:=sin(IX) |
UNTIL | 在其值为真前,执行表达式 迭代总数受限于ioc-shell变量sCalcLoopMax,其默认为1000 | until(1) until(a:=a+1;b:=b-1;b<1) |
5.12 示例
几何
A+B+10
结果是A+B+10
关系
(A+B) < (C+D)
如果(A+B) < (C+D),结果是1
如果(A+B) >= (C+D),结果是0
if-else
(A+B)<(C+D)?E:F+L+10
如果(A+B)<(C+D),结果是E
如果(A+B)>=(C+D), 结果是F+L+10
(A+B)<(C+D)?E
如果(A+B)<(C+D),结果是E。
如果(A+B)>=(C+D),结果不变。
逻辑
A&B
引起以下发生:
1)转换A为整数
2)转换B为整数
3)执行A和B的位与
4)转换结果为浮点
数组
注意:我将使用(1,2,3)来表示一个数组。注意:[1,2]不是一个数组,而是用参数1和2的子范围操作符。子范围操作符必须跟在一个数组后面,像这样:AA[2,5]。类似地,{1,2}不是一个数组,而是原地保留的操作符。
A+AA
此处A=1而AA=(1,2,3)
结果是(2,3,4)。
A+DBL(AA)
此处A=1而AA=(1,2,3)
结果是2。DBL返回第一个数组元素。
AA+BB
此处AA=(1,2,3)和BB=(7,8,9)
结果是(8,10,12)。逐元素求和。大部分操作符按这种方式作用。
AA[2,4]
此处AA=(1,2,3,4,5)
结果是(3,4,5)。(一个数组的首个元素被编号为"0")。
AA[-3,-1]
此处AA=(1,2,3,4)
结果是(2,3,4)。(一个数组的末尾元素编号为"-1"。)
AA{2,4}
此处AA=(1,2,3,4,5,6)
结果是(0,0,3,4,5,0)。(类似于[]操作符,但所选的子范围被原地保留)
参数数组
1)@0:结果是数值变量A的值。("@0是A的另一个名称")
2)@@0:结果是数组变量AA的值。
3)@(A+B):结果是由A和B之和指定编号的数值变量的值。
存储
"Store"操作符是不产生一个值的唯一数组计算操作符。因而,表达式a:=0是一个不完整并且因而非法的calc表达式,因为它让我们没有东西写入到这个记录的VAL字段。
1) A:=A-1;7:计算表达式A-1,再输入变量A中存储结果,设置VAL字段为7。
2) @0:=A-1;7:与上相同,因为@0只是A的另一个名称。
3) D:=0;@D=A-1;7:与以上相同,因为D==0。
4) AA:=IX;7:用数组(0,1,2,...)重写输入输入变量AA,并且设置VAL字段为7
5) AA:=IX;b:=0;1:多个存储表达式,由';'分隔,在最高层是合法的,但表达式总是以一个整体产生一个值。表达式产生值1。
6) A+(AA:="abc";b:=0;1):在括号中的索格存储表达式也是合法的,并且括号中子表达式再次必须产生一个值。在本例中括号中子表达式产生这个值1,它被加到1。
7)@0:=A-1;7:计算表达式A-1,在输入变量A中存储这个结果,并且设置VAL为7。
Loop("UNTIL")
UNTIL表达式在表达式返回一个非零值或者达到允许的迭代数目sCalcLoopMax前重复计算它的表达式。当循环结束或者取消时,返回表达式值。
1)UNTIL(1):计算表达式1,终止这个循环,并且被返回。这个do-nothing表达式等于(1)。
2)B:=10;UNTIL(B:=B-1;B<1):这个几乎什么也不做的表达式初始化B为10,重复地减少它,直到其值是0,并且返回这个值1(True)。
3)BB:=1;B:=1;AA:=BB;UNTIL(AA:=AA+(BB>>B);B:=B+1;B>10):初始化BB为(1,1,1,...)。循环在BB上积分,因而AA的第N个元素将是所有BB[0,N]元素的和。
这个表达式对把由一个多通道scaler积累的阶跃脉冲数组转成一个位置(在这些位置触发了多通道scaler的通道超前信号)数组有用。("CUM"函数进行此操纵)。
4)AA:=0;L:=0;UNTIL(AA:=CAT(AA[0,L],@L);L:=L+1;L>9);AA:=AA<<1:复制10个标量输入字段A-J到数组AA的前10个元素。(做这件事这非常低效。一个asub记录将高效多)。
5) L:=0;AA=IX;UNTIL(@L:=AA[L,L];L:=L+1;L>10):复制AA的前10个元素到标量输入变量A-J。(做这件事这非常低效。)
这是使用中更完整的aCalc的示例。假如我们想要分析来自一系列边缘扫描的结果来查找产生最锐边缘的条件。缺少任何硬件,我们也必须分析伪数据。我们使用三个aCalcout记录:
1)aCalc1:计算人工边缘扫描数据。
2)aCalc2:对此数据求导。
3)aCalc3:计算这个导数的FWHM
这是做这件事的字段值:
aCalc1.CALC = "tanh((ix-a)/b)+c*arndm"
aCalc1.A = <edge position>
aCalc1.B = <edge width control>
aCalc1.C = <amount of noise added to data>
aCalc1.OUT = "aCalc2.AA PP"
aCalc2.CALC = "nderiv(aa,20)"
aCalc2.OUT = "aCalc3.AA PP"
aCalc3.CALC = "fwhm(aa)"
6、输出参数
这些参数指定和控制aCalcout记录的输出功能。它们确定何时写输出,写它到哪里,以及输出将是什么。OUT链接指定这个结果将被写入哪个过程变量。OOPT字段确定了引起输出链接将被写入的条件。它是一个有6个选项的菜单字段:
Every Time | 记录每次运行时写输出 |
On Change | 每次VAL变化时,写输出,即:每次表达式结果变化 |
When Zero | 在记录运行时,如果VAL是0,写输出 |
When Non-zero | 在记录运行时,如果VAL不是0,写输出 |
Transition to Zero | 在记录运行时,只在VAL是0并且上个值非零时,才写输出。 |
Transition to Non-zero | 在记录运行时,只在VAL非零并且上个值是零时,才写输出 |
Never | 从不写输出 |
DOPT字段决定了在执行输出时数目数据被写入输出链接。这个字段时一个有两种选项的菜单字段:Use CALC或Use OCAL。如果指定Use CALC,则在记录写其输出时,它将写CALC字段中表达式的结果,即是,它将写VAL[AVAL]字段的置到一个标量[数组]目的地。如果指定Use OCAL,记录将写OCAL字段中表达式的结果,其结果包含在OVAL字段(数组结果在OAV字段)。OCAL字段完全类似于CALC字段,并且有相同功能:它能够包含一个在运行时被计算的表达式。因而,如果必要,记录可以使用CALC表达式的结果来决定是否应该写数据以及可以使用OCAL表达式的结果作为要写的数据。
OEVT字段指定一个非0整数以及在OOPT字段中被满足的条件,记录将提交一个相应的事件。如果ODLY字段是非零,记录在执行OUT链接或者提交输出事件前暂停指定的秒数。在这个等待十七种,记录是"活动的",并且在等待结束前将不再被运行。在延时阶段,字段DLYA等于1。延时项的分辨率是一个时钟tick,此处时钟频率在别处被定义(见EPICS应用程序开发指南种epicsThreadSleepQuantun())。
IVOA字段指定在aCalcout记录进入一个INVALID警报状态时要对OUT链接采取什么动作。选项是Continue normally, Don't drive outputs和Set output to IVOV。如果IOVA字段是Set Output to IOVO,在IVOV字段种输入的数据在此记录警报严重性是INVALID时被写入OUT链接。
aCalcout记录使用设备支持写入OUT链接。用.dbd格式选项此记录提供的软设备
field(DTYP,"Soft Channel")
在引起此记录执行其转发链接前,此设备支持使用记录的WAIT字段来决定是否等待由OUT链接启动的运行结束。执行这种等待结束的机制需要OUT链接有属性CA,即是,链接文本看起来像
xxx:record.field CA NMS
当前,记录记录没有尝试确保WAIT和OUT时被兼容设置的。如果WAIT==“Wait”,但这些链接看起来像:
xxx:record.field PP NMS
例如,接着这个记录在执行其转发链接前将不等待结束。
7、显示参数
这些参数是用于像操作者显示有意义数据。有些也用于显示运行时记录的状态。如一个交互MEDM显示窗口显示在这里显示aCalcout记录的状态。
EGU字段包含一个用户提供的最长16个字符的串并且描述正在被操作的字段。当调用get_units例程时,获取这个字符串。EGU字符串仅是用于操作原因,并且不是必须被使用。
HOPR和LOPR字段仅指向VAL,HIHI,HIGH,LOW和LOLO字段的限制。PREC控制VAL字段的精度。
INVA-INLV和IAAV-ILLV字段指明了在INPA-INPL和INAA-INLL字段种指定PV的链接的状态。这些字段有三种可能的值:
Ext PV NC | 在这个IOC上没有找到PV,并且通道访问链接还未被建立 |
Ext PV OK | 这个IOC上没有找到PV,并且通道访问链接已经被建立 |
Local PV | 在这个IOC上找到了这个PV |
Constant | 对应链接字段是一个常数 |
OUTV字段指示了OUT链接的状态。它有与INAV-INLV字段相同可能的值。
CLCV和OLCV字段各自指示了在CALC和OCAL字段种表达式的有效性。如果表达式无效,这个字段设为1。
DLYA字段在ODLY种指定的延时间隔内设为1。
有关记录名(NAME)和描述(DESC)字段的更多信息见EPICS记录参考手册。
8、警报参数
aCalcout记录的可能警报条件是SCAN,READ,计算和limit警报。SCAN和READ警报是被记录支持例程调用。计算警报在CALC表达式是一个无效表达式时被记录processing程序调用,对其产生一条错误消息。
HYST字段为每个limit定义一个警报死区。警报和这些字段的详细解释见EPICS记录参考手册。
9、monitor参数
这些参数用于确定何时发送用于这些值字段的monitors。当值字段超过了上次受到监视字段合适的死区时,发送这些monitors,ADEL用于存档monitors,而MDEL用于所有其它类型monitors。如果这些字段有一个0值,每次值变化时,触发monitors;如果它们有一个-1值时,每次记录被扫描时,触发monitors。
10、运行时参数
这些字段不是使用配置工具配置的并且在运行时都不可修改的。它们被用于运行这个记录。
LALM字段用于为警报限制实现回滞因子。
LA-LL字段用于决定何时为对应字段触发monitors。例如,如果LA不恩于A的值,触发对应A’的monitors。MLST和MLST字段以相同方式用于VAL字段。
11、记录支持例程
1) init_record
对于每个常数输入链接,如果用这个常数值初始化对应的值字段,或者如果输入链接是PV_LINK,创建一个通道访问链接。
调用例程postfix被调用来转换CALC和OCAL种内嵌表达式为反向polish标记。结果各自被存储在RPCL和ORPC。
2) process
见第十二部分。
3) special
在CALC或OCAL被修饰时被调用。spcial调用aCalcPostfix。
4)get_value
填充struct valueDes的值,使得它们指向VAL。
5)get_units
获取EGU
6)get_precision
获取PREC
7)get_graphic_double
设置一个字段的上显示和下显示限制。如果字段是VAL,HIHI,HIGH,LOW或LOLO,这些限制被设置为HOPR和LOPR,否则这个字段有已定义的上和下限制,将使用它们,否则将使用这个字段类型的上和下最值。
8)get_control_double
设置一个字段的上控制和下控制限制。如果这个字段是VAL,HIHI,HIGH,LOW或LOLO,这些限制被设置为HOPR和LOPR,否则字段有已定义的上和下限制,将使用它们,否则将使用这个字段类型的上和下最值。
9)get_alarm_double
设置以下值:
upper_alarm_limit = HIHI
upper_warning_limit = HIGH
lower_warning_limit = LOW
lower_alarm_limit = LOLO
12、记录运行
1) process
process()例程实现以下算法:
1、获取所有参数
2、调用程序aCalcPerform(),它从CALC种指定表达式的postfix版本计算VAL。如果aCalcPerform()返回成功。UDF设为FALSE。
3、检查警报。这个例程检查新的值是否引起警报状态和严重性变化。如果这样,NSEV,NSTA和LALM被设置。它也遵守警报回滞因子(HYST)。因而,在警报状态和严重性变化前,这个值必须至少变化HYST。
4、确定输出执行选项(OOPT)是否被满足。如果它被满足了,要么(如果ODLY=0)立即执行输出链接(和输出事件),或者在指定的间隔后调度一个回调。见以下execOutput()的解释。
5、检查是否应该调用monitors。
- 如果警报状态或严重性发生变化了,警报monitors被调用。
- 如果ADEL和MDEL条件被满足,存档和值变化monitors被调用。
- 当其它monitors被调用,A-L和AA-LL的monitors被调用。
- NSEV和NSTA被重置为0。
6、如果没有指定输出延时,如果需要需要扫描转发链接,设置PACT为FALSE,并且返回。
12.2 execOutput()
1、如果DOPT字段指定使用OCAL,为OCAL中表达式的后缀版本调用例程aCalcPerform。否则使用VAL。
2、如果警报严重性是INVALID,按照字段IVOA指定的选项。
3、如果警报严重性不是INVALID或IVOA指定"Continue Normally",调用设备支持写OVAL的值到由OUT链接指定的设备或PV,并且(如果非0)提交OEVT中的事件。
4、如果实现了一个输出延时,运行转发链接。