Skip to content

Commit cb0c8c9

Browse files
committed
Changes like those to 2slit_soft.vdb, to allow soft motors to be run more effectively from spec.
1 parent 7c44cd3 commit cb0c8c9

File tree

1 file changed

+125
-16
lines changed

1 file changed

+125
-16
lines changed

opticsApp/Db/table_soft.vdb

Lines changed: 125 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,23 @@
44
#! DBDEND
55

66

7-
7+
record(transform, "$(P)$(Q):setMonitor") {
8+
field(INPA, "$(P)$(Q):x.SET CP")
9+
field(INPB, "$(P)$(Q):y.SET CP")
10+
field(INPC, "$(P)$(Q):z.SET CP")
11+
field(INPD, "$(P)$(Q):ax.SET CP")
12+
field(INPE, "$(P)$(Q):ay.SET CP")
13+
field(INPF, "$(P)$(Q):az.SET CP")
14+
field(CLCG, "a||b||c||d||e||f")
15+
field(OUTG, "$(P)$(T).SET CA")
16+
}
17+
18+
# We already have a mechanism for stopping the table when any soft motor's
19+
# STOP field is 1. Reimplement existing table:stop PV to drive that mechanism
820
record(bo, "$(P)$(Q):stop") {
921
field(DTYP, "Soft Channel")
10-
field(OUT, "$(P)$(Q):stop1.A PP MS")
22+
field(DOL, "1")
23+
field(OUT, "$(P)$(Q):x.STOP PP MS")
1124
}
1225

1326
record(bo, "$(P)$(Q):update") {
@@ -35,7 +48,6 @@ record(calc, "$(P)$(Q):geomIsSRI") {
3548
field(INPA, "$(P)$(T).GEOM CP MS")
3649
}
3750

38-
3951
record(table, "$(P)$(T)") {
4052
field(DESC, "Optical Table")
4153
field(LX, "510")
@@ -92,6 +104,64 @@ record(table, "$(P)$(T)") {
92104
field(FLNK, "$(P)$(Q):ifValuesWritten")
93105
}
94106

107+
# We're going to monitor the STOP fields of the soft motors, so we know when
108+
# the user told a motor to stop. We're also going to write to all of those
109+
# STOP fields when we detect that the user wants the table to stop. We need
110+
# to distinguish our writes from the user's writes.
111+
record(bo, "$(P)$(Q):weSaidStop") {
112+
#field(TPRO, "1")
113+
field(ZNAM, "No")
114+
field(ONAM, "Yes")
115+
}
116+
record(transform, "$(P)$(Q):monitorStop") {
117+
#field(TPRO, "1")
118+
field(SDIS, "$(P)$(Q):weSaidStop")
119+
field(DISV, "1")
120+
# listen to our soft motors' .STOP fields
121+
field(INPA, "$(P)$(Q):x.STOP CP MS")
122+
field(INPB, "$(P)$(Q):y.STOP CP MS")
123+
field(INPC, "$(P)$(Q):z.STOP CP MS")
124+
field(INPD, "$(P)$(Q):ax.STOP CP MS")
125+
field(INPE, "$(P)$(Q):ay.STOP CP MS")
126+
field(INPF, "$(P)$(Q):az.STOP CP MS")
127+
# I==any soft motor was told to stop
128+
field(CLCI, "a||b||c||d||e||f")
129+
field(OUTI, "$(P)$(Q):weSaidStop PP MS")
130+
# don't write to the .STOP field that triggered us to process
131+
field(CMTJ, "bitmask for doStop")
132+
field(CLCJ, "!a+!b*2+!c*4+!d*8+!e*16+!f*32+64+128")
133+
field(OUTK, "$(P)$(Q):doStop.PROC PP")
134+
}
135+
record(seq, "$(P)$(Q):doStop") {
136+
#field(TPRO, "1")
137+
field(SDIS, "$(P)$(Q):weSaidStop")
138+
field(DISV, "0")
139+
field(SELL, "$(P)$(Q):monitorStop.J")
140+
field(SELM, "Mask")
141+
field(DOL1, "1")
142+
field(LNK1, "$(P)$(Q):x.STOP PP")
143+
field(DOL2, "1")
144+
field(LNK2, "$(P)$(Q):y.STOP PP")
145+
field(DOL3, "1")
146+
field(LNK3, "$(P)$(Q):z.STOP PP")
147+
field(DOL4, "1")
148+
field(LNK4, "$(P)$(Q):ax.STOP PP")
149+
field(DOL5, "1")
150+
field(LNK5, "$(P)$(Q):ay.STOP PP")
151+
field(DOL6, "1")
152+
field(LNK6, "$(P)$(Q):az.STOP PP")
153+
field(DOL7, "1")
154+
field(LNK7, "$(P)$(Q):stop1.A PP")
155+
# We need to wait for all the postings resulting from puts to stop_*
156+
# fields to be received by monitorStop's CP links before enabling
157+
# that record to respond to new postings of those fields. Writing
158+
# with a CA link should ensure that, but delaying by 0.1 s provides
159+
# additional protection.
160+
field(DOL8, "0")
161+
field(DLY8, ".1")
162+
field(LNK8, "$(P)$(Q):weSaidStop CA")
163+
}
164+
95165
record(transform, "$(P)$(Q):stop1") {
96166
field(DESC, "Table-stop distribution")
97167
field(CLCB, "a")
@@ -371,19 +441,6 @@ record(fanout, "$(P)$(Q)fpInit1") {
371441
field(LNK5, "$(P)$(Q)fpSelect.PROC PP")
372442
}
373443

374-
record(motor, "$(P)$(Q):x") {
375-
field(DTYP, "Soft Channel")
376-
field(OUT, "$(P)$(T).X PP")
377-
field(RDBL, "$(P)$(T).EX")
378-
field(MRES, ".00001")
379-
field(RRES, "1")
380-
field(URIP, "Yes")
381-
field(PREC, "$(PREC=3)")
382-
field(RTRY, "0")
383-
field(DINP, "$(P)$(Q):done.VAL")
384-
}
385-
386-
387444
record(sseq, "$(P)$(Q):writeMotors") {
388445
field(DO1, "1")
389446
field(LNK1, "$(P)$(Q):startMove.DO1 PP")
@@ -418,8 +475,27 @@ record(dfanout, "$(P)$(Q):isSoftFan") {
418475
field(OUTF, "$(P)$(Q):az.LOCK")
419476
}
420477

478+
record(motor, "$(P)$(Q):x") {
479+
# alias is for spec, to make it easier to manage configuration of soft motors
480+
alias("$(P)$(Q):m1")
481+
field(DTYP, "Soft Channel")
482+
# ignore the SET field, we're going to implement it in the database, rather
483+
# than in individual motor records
484+
field(IGSET, "1")
485+
field(OUT, "$(P)$(T).X PP")
486+
field(RDBL, "$(P)$(T).EX")
487+
field(MRES, ".00001")
488+
field(RRES, "1")
489+
field(URIP, "Yes")
490+
field(PREC, "$(PREC=3)")
491+
field(RTRY, "0")
492+
field(DINP, "$(P)$(Q):done.VAL")
493+
}
494+
421495
record(motor, "$(P)$(Q):y") {
496+
alias("$(P)$(Q):m2")
422497
field(DTYP, "Soft Channel")
498+
field(IGSET, "1")
423499
field(OUT, "$(P)$(T).Y PP")
424500
field(RDBL, "$(P)$(T).EY")
425501
field(MRES, ".00001")
@@ -432,7 +508,9 @@ record(motor, "$(P)$(Q):y") {
432508
}
433509

434510
record(motor, "$(P)$(Q):z") {
511+
alias("$(P)$(Q):m3")
435512
field(DTYP, "Soft Channel")
513+
field(IGSET, "1")
436514
field(OUT, "$(P)$(T).Z PP")
437515
field(RDBL, "$(P)$(T).EZ")
438516
field(MRES, ".00001")
@@ -445,7 +523,9 @@ record(motor, "$(P)$(Q):z") {
445523
}
446524

447525
record(motor, "$(P)$(Q):ax") {
526+
alias("$(P)$(Q):m4")
448527
field(DTYP, "Soft Channel")
528+
field(IGSET, "1")
449529
field(OUT, "$(P)$(T).AX PP")
450530
field(RDBL, "$(P)$(T).EAX")
451531
field(MRES, ".00001")
@@ -458,7 +538,9 @@ record(motor, "$(P)$(Q):ax") {
458538
}
459539

460540
record(motor, "$(P)$(Q):ay") {
541+
alias("$(P)$(Q):m5")
461542
field(DTYP, "Soft Channel")
543+
field(IGSET, "1")
462544
field(OUT, "$(P)$(T).AY PP")
463545
field(RDBL, "$(P)$(T).EAY")
464546
field(MRES, ".00001")
@@ -472,7 +554,9 @@ record(motor, "$(P)$(Q):ay") {
472554

473555

474556
record(motor, "$(P)$(Q):az") {
557+
alias("$(P)$(Q):m6")
475558
field(DTYP, "Soft Channel")
559+
field(IGSET, "1")
476560
field(OUT, "$(P)$(T).AZ PP")
477561
field(RDBL, "$(P)$(T).EAZ")
478562
field(MRES, ".00001")
@@ -612,6 +696,31 @@ record(calcout, "$(P)$(Q):done") {
612696
field(OOPT, "Transition To Non-zero")
613697
}
614698

699+
# Strategy: We need to find out when all motors have finished executing a move
700+
# that we started. To do this without a race condition, we set a gate PV to
701+
# "open", write to motors, and then have the last motor written to set the gate
702+
# PV to "closed" when it finishes. But we don't know which motor will be the
703+
# last motor written to, because the table record can work with fewer than six
704+
# motors, and we don't know which motors don't actually exist.
705+
# $(P)$(Q):lastMotor figures this out at init time.
706+
707+
# Evidently, $(P)$(Q):lastMotor's PINI==RUNNING field isn't getting
708+
# $(P)$(Q):closeGate.INPA initialized. This seems bulletproof.
709+
record(scalcout, "$(P)$(Q):initLastMotor") {
710+
#field(TPRO, "1")
711+
field(SCAN, "10 second")
712+
# Note that this must be a CA link so it can read a link field
713+
field(INAA, "$(P)$(Q):closeGate.INPA CA")
714+
field(CALC, "aa==''")
715+
field(OOPT, "When Zero")
716+
field(DOPT, "Use OCAL")
717+
field(OCAL, "'Passive'")
718+
field(OUT, "$(P)$(Q):initLastMotor.SCAN CA")
719+
field(FLNK, "$(P)$(Q):lastMotor")
720+
}
721+
722+
# Find the last motor that will be written to. (Ignore motors that
723+
# don't actually exist.) Write that motor's .DMOV PV
615724
record(scalcout, "$(P)$(Q):lastMotor") {
616725
field(CALC, "(f?ff:e?ee:d?dd:c?cc:b?bb:aa)[0,' ']+' CP'")
617726
field(INPA, "$(P)$(Q):dmov.INAV CA")

0 commit comments

Comments
 (0)