You can give arguments to a protocol.
In the INP
or OUT
link, write:
field (OUT, "@protocolfile protocol(arg1,arg2,arg3) bus")
In the protocol, reference arguments as $1 $2 $3
or inside strings
as "\$1 \$2 \$3"
.
moveaxis {out "move\$1 %.6f";}
field (OUT, "@motor.proto moveaxis(X) motor1")
readpressure {out 0x02 0x00 $1; in 0x82 0x00 $1 "%2r";}
field (INP, "@vacuumgauge.proto readpressure(0x84) gauge3")
Use I/O Intr
processing.
The record receives any input and processes only when the input matches.
read {in "new value = %f";}
record (ai, "$(RECORD)") {
field (DTYP, "stream")
field (INP, "@$(DEVICETYPE).proto read $(BUS)")
field (SCAN, "I/O Intr")
}
Here is the value: 3.1415
Use as many in
commands as you get input lines.
read_value {in "Here is the value:"; in "%f";}
There is more than one solution to this problem. Different approaches have different requirements.
Use array records (e.g. waveform, aao).
array_out {separator=", "; out "an array: (%.2f)";}
The format %.2f
is repeated for each element of the array.
All elements are separated by ", "
.
Output will look like this:
an array: (3.14, 17.30, -12.34)
Use a calcout record and field references in the format.
write_ABC {out "A=%(A).2f B=%(B).6f C=%(C).0f";}
You must specify a valid expression in the CALC
field
even if you don't use it.
record (calcout, "$(RECORD)") {
field (INPA, "$(A_RECORD)")
field (INPB, "$(B_RECORD)")
field (INPC, "$(C_RECORD)")
field (CALC, "0")
field (DTYP, "stream")
field (OUT, "@$(DEVICETYPE).proto write_ABC $(BUS)")
}
Use record references in the format.
acquire {out 'ACQUIRE "%(\$1:directory.VAL)s/%s",%(\$1:time.VAL).3f;';}
You must specify the full record.FIELD
name,
even for VAL
fields.
To avoid record names in protocol files use
protocol arguments.
In the link, specify the record name or just the basename of the
other records (device name) in parentheses.
record (stringout, "$(DEVICE):getimage") {
field (DTYP, "stream")
field (OUT, "@$(DEVICETYPE).proto acquire($(DEVICE)) $(BUS)")
}
Again, there is more than one solution to this problem.
Use array records (e.g. waveform,
aai).
array_in {separator=","; in "array = (%f)";}
The format %f
is repeated for each element of the array.
A ","
is expected beween element.
Input may look like this:
array = (3.14, 17.30, -12.34)
Use I/O Intr
processing
and value skipping (%*
)
read_A {out "GET A,B"; in "A=%f, B=%*f";}
read_B {in "A=%*f, B=%f";}
record (ai, "$(DEVICE):A") {
field (DTYP, "stream")
field (INP, "@$(DEVICETYPE).proto read_A $(BUS)")
field (SCAN, "1 second")
}
record (ai, "$(DEVICE):B") {
field (DTYP, "stream")
field (INP, "@$(DEVICETYPE).proto read_B $(BUS)")
field (SCAN, "I/O Intr")
}
Record A actively requests values every second.
The reply contains values A and B.
Record A filters only value A from the input and ignores value B
by using the *
flag.
Nevertheless, a complete syntax check is performed: B must be a
valid floating point number.
Record B is I/O Intr
and gets (a copy of) any input, including
input that was directed to record A.
If it finds a matching string it ignores value A, reads value B and
then processes.
Any non-matching input is ignored by record B.
Use record references in the format. To avoid record names in protocol files, use protocol arguments.
read_AB {out "GET A,B"; in "A=%f, B=%(\$1.VAL)f";}
record (ai, "$(DEVICE):A") {
field (DTYP, "stream")
field (INP, "@$(DEVICETYPE).proto read_AB($(DEVICE):B) $(BUS)")
field (SCAN, "1 second")
}
record (ai, "$(DEVICE):B") {
}
Whenever record A reads input, it stores the first value in its own VAL field as usual and the second in the VAL field of record B. Because the VAL field of record B has the PP attribute, this automatically processes record B.
Use a @mismatch
exception handler and
record references in the format.
To avoid record names in protocol files, use
protocol arguments.
When asked "CURRENT?
", the device send something like
"CURRENT 3.24 A
" or a message like
"device switched off
".
read_current {out "CURRENT?"; in "CURRENT %f A"; @mismatch {in "%(\1.VAL)39c";}}
record (ai, "$(DEVICE):readcurrent") {
field (DTYP, "stream")
field (INP, "@$(DEVICETYPE).proto read_current($(DEVICE):message) $(BUS)")
}
record (stringin, "$(DEVICE):message") {
}
After processing the readcurrent record, you can see from SEVR/STAT if the read was successful or not. With some more records, you can clean the message record if SEVR is not INVALID.
record (calcout, "$(DEVICE):clean_1") {
field (INPA, "$(DEVICE):readcurrent.SEVR CP")
field (CALC, "A!=2")
field (OOPT, "When Non-zero")
field (OUT, "$(DEVICE):clean_2.PROC")
}
record (stringout, "$(DEVICE):clean_2") {
field (VAL, "OK")
field (OUT, "$(DEVICE):message PP")
}
Dirk Zimoch, 2007