diff --git a/Readme.md b/Readme.md
index b04f1f3..c2b14f5 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,25 +1,23 @@
-Various motor documents
------------------------
-- /home/zamofing_t/Documents/doc-ext/SwissFEL/ESB-MX
+PBSwissMX
+=========
+This repository is used by the SwissMX application.
+A complete list of SwissMX repositories dependencies is shown in [grp-sf_cristallina/SwissMX.git](https://git.psi.ch/grp-sf_cristallina/SwissMX).
-Repository structure and dependency (update:23.09.24)
------------------------------------------------------
+PBSwissMX contains python application and executables to:
+ - generate trajectories and motion programs for SwissMX (`shapepath.py` and `helicalscan.py`[obsolete])
+ - motion synchronization executables (`triggerSync`) for Deltatau
+ - analyse recorded trajectories on SwissMX (`ShapePathAnalyser`)
+ - motor tuning tools (`MXTuning`)
+ - documentation about the tuning results (`MXfastStageDoc`)
+
+motion start/framesynchronization (update31.10.24)
+---------------------------------------------------
+
+**For more details about triggerSync read: [src/triggerSync/Readme.md](src/triggerSync/Readme.md)**
+
+#### Important used vaiables:
```
-This repository contains PowerBrick documents and tool to generate trajectories and motion programs for SwissMX
-
-for more info about SwissMX read:
-psigithub git@git.psi.ch:grp-sf_cristallina/SwissMX.git --> ~/Documents/prj/SwissFEL/apps/SwissMX/Readme.md
-
-For more details about triggerSync read:
- ~/Documents/prj/SwissFEL/apps/PBSwissMX/src/triggerSync/Readme.md
-```
-
-motion/frame synchronization
-----------------------------
-```
-s.a. ~/Documents/prj/SwissFEL/apps/PBSwissMX/src/triggerSync/Readme.md
-
Coord[1].Q[0] : sync points indicator: (at whick point is the motion program)
val: desc set in code
-3: waiting at start position motion code generated in MXMotion.py:setup_sync(mode=?)
@@ -50,18 +48,165 @@ triggerSync.c mode:
bit1:2: simulate start trigger
bit2:4: simulate frame trigger
bit3:8: verbose
+```
-Acquisition start event:
+### start/frame event system
+```
+Start event:
sim: Coord[1].Q[10]
- EVR: Gate3[1].Chan[0].UserFlag == (gate3_1->Chan[0].Status&0x800) == FrontUnivOut4 -> Pulser0 -> (active Low, 5000us delay 0us) Map: 214
+ EVR: Gate3[1].Chan[0].UserFlag == (gate3_1->Chan[0].Status&0x800) == FrontUnivOut4, EPICS MACRO: $(USR_FLAG_ID)=5
+ -> Pulser0 -> (active Low, 5000us delay 0us) Map: 214
+ -> event 214 is 'ESC multipurpose event. In this case used as: start motion'
Frame event:
sim: Coord[1].Q[11]
- EVR: Gate3[1].Chan[1].UserFlag == (gate3_1->Chan[1].Status&0x800) == FrontUnivOut5 -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40
+ EVR: Gate3[1].Chan[1].UserFlag == (gate3_1->Chan[1].Status&0x800) == FrontUnivOut5, EPICS MACRO: $(USR_FLAG_ID)=5
+ -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40
+ -> event 40 = 'ESA_detector 100 Hz' >>> should be 77='ESC detector'
+
+unused EVR input?:
+ EVR: Gate3[1].Chan[2].UserFlag == (gate3_1->Chan[2].Status&0x800) == FrontUnivOut6, EPICS MACRO: $(USR_FLAG_ID)=7
+
+!!! Deltatau flags are inverted: FrontUnivOut6(Force Low) -> Gate3[1].Chan[2].UserFlag==1
+```
+|event |simulated |real |
+|- |- |- |
+|start |Coord[.].Q[10] | Gate3[1].Chan[0].UserFlag |
+|frame |Coord[.].Q[11] | Gate3[1].Chan[1].UserFlag |
+
+**frequence jitter 50Hz Swissgrid:** https://www.swissgrid.ch/de/home/operation/grid-data/current-data.html
+
+### partial python class diagram of PBSwissMX
+
+```mermaid
+classDiagram
+MotionBase <|-- ShapePath
+MotionBase <|-- HelicalScan
+
+ class MotionBase {
+ @MXMotion.py
+ + setup_sync(self, crdId, prgId, verbose, timeOfs, timeCor)
+ + homing(self)
+ + run(self, crdId)
+ + wait_armed(self, crdId)
+ + progress(self)
+ + trigger(self, wait)
+ }
+
+ class ShapePath {
+ @shapepath.py
+ %%- __init__(self, args) None
+ + setup_gather(self,acq_per=None,numPts=None)
+ + setup_coord_trf(self,fx='X',fy='Y',cz='0')
+ + setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs)
+ + gather_upload(self,fnRec=None)
+ }
+
+ class HelicalScan {
+ @helicalscan.py [obsolete]
+ + setup_gather(self,acq_per=1)
+ + setup_coord_trf(self,fnCrdTrf='/tmp/coordTrf.cfg')
+ + setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs)
+ + gather_upload(self,fnRec=None)
+ }
+
+ class GenPath {
+ @shapepath.py
+ + swissmx(self, flipx, flipy, ofs, width)
+ + swissfel(self, flipx, flipy, ofs, width)
+ %%+ rand(self, n, scale, ofs)
+ + grid(self, w, h, pitch, rnd, ofs)
+ %%+ spiral(self, rStart, rInc, numSeg, numCir, phase, ofs)
+ %%+ closed_shifted(self, pitch, shift, mult)
+ %%+ sort(self, mode, grp_sz)
+ }
```
-testing shapepath.py in different modes (tunneling)
----------------------------------------------------
+### Simplified Python sequence
+
+Source for the instance "start/frame event system" can be:
+ - python code
+ - timing system (EVR)
+ - motion code
+ - triggerSync executable running on Deltatau
+
+```mermaid
+sequenceDiagram
+ participant es as start/frame
event system
+ participant py as Python
+ participant pb as PowerBrick
+
+ Note over py: .setup_sync()
prepare code snipplets
+ activate py
+ opt needs triggerSync
+ Note over es,pb: triggerSync is needed in case of:
simulated start/frame triggers
and/or adjust DesTimeBase
+ py -) pb: sftp / ssh
+ Note over pb: sftp triggerSync
run triggerSync
+ pb ->> es: run triggerSync
+ end
+
+ Note over py: .setup_coord_trf()
+ py -) pb: download code
+ Note over pb: setup coordinate transformation
+ Note over py: .setup_motion()
+ py -) pb: generate code
download code
+ Note over pb: setup motion program
+ Note over py: .setup_gather()
+ py -) pb: download code
set gather vars
+ Note over pb: set addresses to gather
Gather.Enable=1
+ Note over py: .homing()
+ py -)+ pb: download code
run homing PLC
+ Note over py: wait(Motor[1].HomeComplete)
+ deactivate py
+ Note over pb: runs homing PLC [if needed]
enable plc 1
+ pb ->>- py: Motor[1].HomeComplete
+ activate py
+ Note over py: .run()
+ py -)+ pb: run motion program
+ Note over pb: runs motion program 2 in coordSystem 1
&1br2
+ Note over pb: move to first point
DesTimeBase=0 (wait motion)
Q[0]=-3 (motion program waiting at start position)
+ pb ->>- es: Q[0]=-3
+ Note over es: Q[0]=-2 (event system armed)
[in motion code or
triggerSync exe]
+ Note over py: .wait_armed()
wait(Q[0]==-2) # wait until motors are at first position
+ deactivate py
+ es ->>+ py: Q[0]=-2
+ Note over es: wait for start trigger
+ Note over py: .trigger()
+ alt sim start trig
+ Note over py: Q[10]=1 [send a simulated start trigger
after given time]
+ py ->> es: Q[10]=1
+ else real start trig
+ es->> es: Gate3[1].Chan[0].UserFlag==1
+ end
+ Note over es: DesTimeBase=Sys.ServoPeriod
[in motion code or
triggerSync exe]
+ es->>+pb: continue motion
+ opt adjust time base
+ Note over es: in thread trigger_sync_func()
of triggerSync exe
+ es->>es: adjust DesTimeBase
+ end
+ Note over pb: pvt10abs
move to all points
+ loop 10 ms
+ Note over pb: move to next point
+ end
+ opt triggerSync running
+ pb ->> es: Gather.Enable=0
+ Note over es: exit triggerSync exe
+ end
+ Note over py: while .progress()
wait(Gather.Enable==0)
+ deactivate py
+ Note over pb: end motion program
+ pb ->>- py: Gather.Enable=0
+ activate py
+ Note over py: .gather_upload()
+ deactivate py
+```
+
+-------------------------------
+Work log
+========
+
+??10.24: testing shapepath.py in different modes (tunneling)
+-----------------------------------------------------------
```
zamofing_t@ganymede:~$
>>> kill previous tunnels 127.0.0.1:100??
@@ -132,6 +277,19 @@ caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0
Debugging were the coordinate program counter is:
&1 list pc,10
-
```
+??.10.24: mermaid tricks and links
+---------------------------------
+- https://mermaid.live/
+- https://app.zenuml.com/
+- https://www.mermaidchart.com/
+- https://help.whimsical.com/article/732-sequence-diagrams
+- https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-sequence-diagram/
+- https://www.geeksforgeeks.org/unified-modeling-language-uml-sequence-diagrams/
+
+```
+pip install pymermaider --user
+pymermaider ~/Documents/prj/SwissFEL/apps/PBSwissMX/python -o /tmp
+subl /tmp/python.md
+```
diff --git a/python/MXMotion.py b/python/MXMotion.py
index 99935d0..7e0425b 100644
--- a/python/MXMotion.py
+++ b/python/MXMotion.py
@@ -99,13 +99,13 @@ class MotionBase:
Coord[{crdId}].TimeBaseSlew=1 //1E-4 is default
Coord[{crdId}].DesTimeBase=0
Coord[{crdId}].Q[0]=-3 // motion program waiting at start position
-Coord[{crdId}].Q[0]=-2 // motion program started and armed
-while({flag0}==0){{}}
-Coord[{crdId}].Q[0]=-1
-Gather.Enable=2
-while({flag1}==0){{}}
-Coord[1].DesTimeBase=Sys.ServoPeriod
-Coord[{crdId}].Q[0]=0 //
+Coord[{crdId}].Q[0]=-2 // 'start/frame event system' armed (triggerSync not used in these modes)
+while({flag0}==0){{}} // wait start trigger
+Coord[{crdId}].Q[0]=-1 // start trigger received
+Gather.Enable=2 // start acquire date
+while({flag1}==0){{}} // wait first frame trigger
+Coord[1].DesTimeBase=Sys.ServoPeriod //run motion
+Coord[{crdId}].Q[0]=0 // indicates that motion moves to first measurement point
'''
else: #sync_mode==2: triggerSync:trigsync_func called
prg = f'''
diff --git a/src/triggerSync/Readme.md b/src/triggerSync/Readme.md
index 73f9a5e..fbb8fed 100644
--- a/src/triggerSync/Readme.md
+++ b/src/triggerSync/Readme.md
@@ -1,5 +1,8 @@
triggerSync
===========
+
+
+
```
samples: root@:/opt/ppmac#
/tmp/triggerSync 40 11 trigger all 40 ms, simulated start, use real frame triggers, verbose
@@ -8,37 +11,27 @@ samples: root@:/opt/ppmac#
/tmp/triggerSync 40 7 trigger all 40 ms, simulated start and frame triggers, with sync, minimal verbose
-For real triggers, deltatau is using flags from the EVR-card:
-
+//Simulated triggers uses Q variables
#define SIMFLAG0 (pshm->Coord[1].Q[10])
#define SIMFLAG1 (pshm->Coord[1].Q[11])
-
-//Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag
+//real triggers, uses inputsfrom the EVR-card
+// s.a. Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag
#define FLAG0 (gate3_1->Chan[0].Status&0x800)
#define FLAG1 (gate3_1->Chan[1].Status&0x800)
-
work of triggerSync program:
- wait for [SIM]FLAG0 (arm trigger)
- once armed, each [SIM]FLAG1 trigger is a frame trigger.
-SIMFLAG[0|1] are vairables Coord[1].Q[10] and Coord[1].Q[11]
-
the EVR flags are set in;
caqtdm -attach -macro SYS=SAR-EXPMX,DEVICE=EVR0,FF=PCIe G_EVR_main.ui
-FLAG0 == Gate3[1].Chan[0].UserFlag == FrontUnivOut4 -> Pulser0 -> (active Low, 5000us delay 0us) Map: 214
-FLAG1 == Gate3[1].Chan[1].UserFlag == FrontUnivOut5 -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40
-
-Pulser 0: event 214 is 'ESC multipurpose event. In this case used as: start motion'
-Pulser 1: maps event 40 = 'ESA_detector 100 Hz' >>> should be 77='ESC detector'
-
event 214 is set with the CTA. For tests one can set manually
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 9 # Force High(0) -> arm event, before start motion
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 8 # Force Low(1) -> trigger motion
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0 # set back to Pulser 0 -> reset for CTA usage
-This are values how they should be:
+Here values as they were set (??.10.24):
caget SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-RB SAR-EXPMX-EVR0:FrontUnivOut5-Src-Pulse-RB \
SAR-EXPMX-EVR0:Pul0-Polarity-Sel SAR-EXPMX-EVR0:Pul0-Delay-RB SAR-EXPMX-EVR0:Pul0-Width-RB \
SAR-EXPMX-EVR0:Pul1-Polarity-Sel SAR-EXPMX-EVR0:Pul1-Delay-RB SAR-EXPMX-EVR0:Pul1-Width-RB \
@@ -108,3 +101,4 @@ caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0
Gather.Enable=0 # end triggerSync
```
+
diff --git a/src/triggerSync/UnusedSeqDiag.md b/src/triggerSync/UnusedSeqDiag.md
new file mode 100644
index 0000000..77773dc
--- /dev/null
+++ b/src/triggerSync/UnusedSeqDiag.md
@@ -0,0 +1,231 @@
+
+Detailed Python sequence
+```mermaid
+sequenceDiagram
+ participant ts as TimingSystem
+ participant py as Python
+ participant pb as PowerBrick
+
+ activate py
+ Note over py: .setup_sync()
prepare code snipplets
+ py -)+ pb: sftp / ssh
+ Note over pb: sftp triggerSync
run triggerSync
+ pb --)- py: done
+ Note over py: .setup_coord_trf()
+ py -)+ pb: download code
+ Note over pb: setup coordinate transformation
+ pb --)- py: done
+ Note over py: .setup_motion()
+ py -)+ pb: generate code
download code
+ Note over pb: setup motion program
+ pb --)- py: done
+ Note over py: .setup_gather()
+ py -)+ pb: download code
+ Note over pb: set addresses to gather
Gather.Enable=1
+ pb --)- py: done
+ Note over py: .homing()
+ py -)+ pb: download code
+ Note over pb: runs homing PLC [if needed]
enable plc 1
+ pb --) py: done
+ Note over py: wait(Motor[1].HomeComplete)
+ deactivate py
+ pb ->>- py: HomeComplete
+ activate py
+ Note over py: .run()
+ py -)+ pb: .run()
+ Note over pb: runs motion program 2 in coordSystem 1
&1br2
+ pb --) py: done
+ Note over py: .wait_armed()
wait(Q[0]==-2) # wait until motors are at first position
+ deactivate py
+ Note over pb: move to first point
DesTimeBase=0 (wait motion)
Q[0]=-2 (motion armed)
+ pb ->>- py: Q[0]=-2 done
+ activate py
+ Note over py: .trigger() #send a start trigger (if needed) after given time
+ Note over pb: wait for the start trigger
+ alt simulated trigger
+ Note over py:Q[10]=1
+ py-)+pb: start trigger
+ Note over pb: DesTimeBase=Sys.ServoPeriod
+ else real trigger
+ ts-)pb: start trigger
triggerSync:DesTimeBase=Sys.ServoPeriod
+ end
+ Note over pb: pvt10abs
move to all points
+ Note over py: while .progress()
wait(Gather.Enable==0)
+ deactivate py
+ loop 10 ms
+ Note over pb: move to next point
+ end
+ Note over pb: Gather.Enable=0
+ pb ->>- py: Gather.Enable=0
+ activate py
+ Note over py: .gather_upload()
+ deactivate py
+```
+
+more detailed sequence trial 1
+```mermaid
+sequenceDiagram
+ participant py as Python
+ participant pb as PowerBrick
+
+ Note over py: .setup_sync()
+ create participant ts as TriggerSync
+ py -)+ ts: .setup_sync()
+ create participant tsync as triggersync_func()
+ ts -) tsync: start thread
+ create participant tsim as trig_sim_func()
+ ts -) tsim: ? if sync_mode&2 then start thread
+ deactivate ts
+
+ Note over py: .setup_coord_trf()
shapepath.py
+ py -)+ pb: download code
+ pb --)- py: done
+ Note over py: .setup_motion()
shapepath.py
+ py -)+ pb: generate code
download code
+ pb --)- py: done
+ Note over py: .setup_gather()
+ Note over py, pb: calls set_address(*address)
that sets also Gather.Enable=1.
+ py -)+ pb: download code
+ Note over pb: Gather.Enable=1
+ pb --)- py: done
+ Note over py: .homing()
+ py -)+ pb: download code
+ pb --) py: done
+ Note over pb: runs homing PLC if needed
enable plc 1
+ Note over py: wait(Motor[1].HomeComplete)
+ pb ->>- py: HomeComplete
+ Note over py: .run()
+ py -)+ pb: .run()
+ pb --)- py: done
+ Note over pb: runs motion program 2 in coordSystem 1
&1br2
move to first point
DesTimeBase=0 (wait motion)
+ Note over tsync: wait(Q[0]==-3)
+ pb -)+ tsync: Q[0]=-3
+ Note over py: MXMotion.py:.wait_armed()
wait(Q[0]==-2)
+ tsync -)+ py: Q[0]=-2
+ Note over py: MXMotion.py:.trigger()
if sync_mode&1 then Q[10]=1
+ deactivate py
+
+ tsync -)+ pb: DesTimeBase=ServoPerion
+ loop aaa
+ tsync ->> tsync:adjust DesTimeBase
while Gather.Enable!=0
+ end
+ activate tsim
+ loop bbb
+ tsim ->> tsim:simulate start and frame triggers
+ end
+ deactivate tsim
+
+ Note over pb: pvt10abs
move to all points
+ Note over pb: Gather.Enable=0
+ Note over py: while .progress()
wait(Gather.Enable==0)
+ pb -)+ py: Gather.Enable=0
+ pb -)- tsync: Gather.Enable=0
+
+ Note over py: shapepath.py:.gather_upload()
+ Note over ts: wait threds finished
+ activate ts
+
+ deactivate tsync
+ destroy tsync
+ tsync -x ts: thread finished
+ destroy tsim
+ tsim -x ts: thread finished
+ deactivate ts
+ deactivate py
+
+ box rgba(196,196,224,.3) TriggerSync executable
+ participant ts
+ participant tsim
+ participant tsync
+ end
+```
+more detailed sequence simulated trigger and speed adjustment
+```mermaid
+sequenceDiagram
+ participant py as Python
+ participant pb as PowerBrick
+ participant ts as TimingSystem
+
+ activate py
+ Note over py: .setup_sync()
prepare code snipplets
+ py -)+ pb: sftp / ssh
+ Note over pb: sftp triggerSync
run triggerSync
+ pb --)- py: done
+ Note over py: .setup_sync()
+ create participant tgss as TriggerSync
+ py -)+ tgss: .setup_sync()
+ create participant tsync as triggersync_func()
+ tgss ->> tsync: start thread
+ opt if sync_mode&2
+ create participant tsim as trig_sim_func()
+ tgss ->>- tsim: start thread
+ end
+# deactivate tgss
+
+
+
+ Note over py: .setup_coord_trf()
+ py -)+ pb: download code
+ Note over pb: setup coordinate transformation
+ pb --)- py: done
+ Note over py: .setup_motion()
+ py -)+ pb: generate code
download code
+ Note over pb: setup motion program
+ pb --)- py: done
+ Note over py: .setup_gather()
+ py -)+ pb: download code
+ Note over pb: set addresses to gather
Gather.Enable=1
+ pb --)- py: done
+ Note over py: .homing()
+ py -)+ pb: download code
+ Note over pb: runs homing PLC [if needed]
enable plc 1
+ pb --) py: done
+ Note over py: wait(Motor[1].HomeComplete)
+ deactivate py
+ pb -)- py: HomeComplete
+ activate py
+ Note over py: .run()
+ py -)+ pb: .run()
+ Note over pb: runs motion program 2 in coordSystem 1
&1br2
+ pb --) py: done
+ Note over py: .wait_armed()
wait(Q[0]==-2) # wait until motors are at first position
+ deactivate py
+ Note over pb: move to first point
DesTimeBase=0 (wait motion)
Q[0]=-3 (motion program waiting at start position)
+
+ pb -) tsync: Q[0]=-3 (motion program waiting at start position)
+
+ pb -)- py: Q[0]=-2 done
+ activate py
+ Note over py: .trigger() #send a start trigger (if needed) after given time
+ Note over pb: wait for the start trigger
+ Note over py:Q[10]=1
+ py-)+pb: start trigger
+ Note over pb: DesTimeBase=Sys.ServoPeriod
+ Note over pb: pvt10abs
move to all points
+ Note over py: while .progress()
wait(Gather.Enable==0)
+ deactivate py
+ loop 10 ms
+ Note over pb: move to next point
+ end
+ #activate tsync
+ #activate tsim
+ tgss->>tsync: Wait for tsync to Finish
+ tgss->>tsim: Wait for tsim to Finish
+
+ Note over pb: Gather.Enable=0
+ pb -) py: Gather.Enable=0
+ pb -) tsync: Gather.Enable=0
+ pb -)- tsim: Gather.Enable=0
+
+ destroy tsync
+ tsync-->>tgss: exit triggersync_func() thread
+ destroy tsim
+ tsim-->>tgss: exit triggersync_func() thread
+ destroy tgss
+ tsync-->tgss: Exit Main Thread
+
+ activate py
+ Note over py: .gather_upload()
+ deactivate py
+
+```