SFELPHOTON-1335:rework triggerSync

This commit is contained in:
2024-10-24 12:10:00 +02:00
parent 786d9c0037
commit cf4a9362f2
7 changed files with 418 additions and 149 deletions

124
Readme.md
View File

@@ -10,4 +10,128 @@ This repository contains PowerBrick documents and tool to generate trajectories
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=?)
-2: got start trigger triggerSync.c:trigsync_func(mode&1) else motion code generated in MXMotion.py:setup_sync(mode=?)
0: after MXMotion.py:setup_sync call triggerSync.c:trigsync_func(mode&1)
idx: index of position during run triggerSync.c:trigsync_func(mode&1)
-1: motion is finished MXMotion.py:setup_sync(mode=?)
Gather.Enable : mode of gathering data
1: prepared (calculate Gather.MaxLines) MotionBase.py:setup_gather()
2: finite motion code: during data gathering
0: disabled motion code: when gather finished
Gather.Samples : number af gathered data samples
MXMotion.py:setup_sync():
sync_mode : default=2
0 : no sync at all
1 : synchronize start
2 : synchronize start and adapt motion speed
sync_flag : default=0
bit 0=1 : simulated start trigger
bit 1=2 : simulated frame trigger
triggerSync.c mode:
bit0:1: sync mode
bit1:2: simulate start trigger
bit2:4: simulate frame trigger
bit3:8: verbose
Acquisition 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
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
```
testing shapepath.py in different modes (tunneling)
---------------------------------------------------
```
zamofing_t@ganymede:~$
>>> kill previous tunnels 127.0.0.1:100??
ps -f `lsof -i -n | grep '127.0.0.1:100.. (LISTEN)' | awk '{print $2}'`
kill `lsof -i -n | grep '127.0.0.1:100.. (LISTEN)' | awk '{print $2}'`
#lsof -i -n | grep '127.0.0.1:100.. (LISTEN)' | tee /tmp/0.log | awk '{print $2}' | tee /tmp/1.log && grep -n '' /tmp/*.log
>>> open cameras in chrome
ssh -L 10010:cristallina-cam-top:80 saresc-vcons-01 'uname -a'
google-chrome --app-url 127.0.0.1:10010
google-chrome --app-url http://cristallina-cam-north.psi.ch/camera/index.html#/video
>>> prepare debug environment
cmdt.py -p EXPMX -tpb # select SAR-CPPM-EXPMX1
>>> prepare shapepath and ssh tunneling
cd ~/Documents/prj/SwissFEL/apps/PBSwissMX/python/
subl shapepath.py
./shapepath.py -h
PPMAC=SAR-CPPM-EXPMX1
ssh -L 10001:localhost:22 root@$PPMAC 'uname -a'
ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a'
gather_server triggerSync are copied with sftp. This does not work with tunneling:
gather_server: ~/Documents/prj/SwissFEL/PBTools/build/lib/pbtools/misc/pp_comm.py:889
triggerSync: ~/Documents/prj/SwissFEL/apps/PBSwissMX/python/MXMotion.py:122
rsync -vai ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/
rsync -vai ~/Documents/prj/SwissFEL/apps/PBSwissMX/src/triggerSync/triggerSync root@$PPMAC:/tmp/
gather_server needs to be started explicitly in tunneling:
ssh root@$PPMAC
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server
triggerSync is started if required at each acquisition and exits when done.
mode:
0 unused
1 pvt motion
2 unused
3 pvt motion using inverse fft velocity
4 pvt motion short code using grid parameters
5 pvt motion short code using grid parameters. Instead of continous motion it moves and waits as give in the parameter time
sync:
0 real start and frame trigger with sync
1 direct start
2 simulated start and frame trigger no sync
3 simulated start and frame trigger with sync
4 simulated start real frame trigger no sync
5 simulated start real frame trigger with sync
# set start EVT to value 0 (=Force Hi)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 9
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s0 # works
# set start EVT to value 1 (=Force Lo)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 8
# reset EVT default value (Pulser 0)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s1 # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s2 # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s3 # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s4 # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s5 # works
Debugging were the coordinate program counter is:
&1 list pc,10
```

View File

@@ -45,16 +45,17 @@ class MotionBase:
self.meta.update(kwargs)
def setup_sync(self, crdId=1, prgId=2,verbose=False, timeOfs=0.,timeCor=0.):
'''setup the timing synchronization for the motion program
kwargs:
'''setup the timing synchronization code snipplets for the motion program
- sync_run: command to start the motion program
- sync_prg: code snipplet at top of the motion program used for synchronization if required
- sync_cmd: Deltatau command to excutable for synchronization if required
starts the triggerSync on the Deltatau if required
args in self.meta:
sync_mode : default=2
0 : no sync at all
1 : synchronize start
2 : synchronize start and adapt motion speed
this function generates the code blocks:
self.sync_wait and self.sync_run
sync_wait can be put in the program to force a timing sync
sync_run are the commands to run the whole program
sync_flag : default=0
bit 0=1 : simulated start trigger
@@ -63,7 +64,7 @@ class MotionBase:
1 : simulated start and real frame trigger
2 : real start and simulated frame trigger
3 : simulated start and frame trigger
fel_per : FEL-period: time FEL-pulse to FEL-pulse in ms (needed for sync code)
fel_per : FEL-period: time FEL-pulse to FEL-pulse in ms (needed for triggerSync executable)
'''
sync_mode=self.meta['sync_mode']
sync_flag=self.meta['sync_flag']
@@ -74,62 +75,68 @@ class MotionBase:
_log.info({0: 'real start trigger', 1: 'simulated start trigger'}[sync_flag&1])
_log.info({0: 'real frame trigger', 2: 'simulated frame trigger'}[sync_flag&2])
self.sync_run = '&{crdId}b{prgId}r'''.format(prgId=prgId, crdId=crdId)
self.sync_run = f'&{crdId}b{prgId}r'
if sync_mode==0:
try:
del self.sync_prg
del self.sync_cmd
except AttributeError:
pass
elif sync_mode in(1,2):
else: # sync_mode 1,2
#frequence jitter 50Hz Swissgrid:
#https://www.swissgrid.ch/de/home/operation/grid-data/current-data.html#
flag0='Coord[{crdId}].Q[10]'.format(crdId=crdId) if sync_flag&1 else 'Gate3[1].Chan[0].UserFlag'
flag1='Coord[{crdId}].Q[11]'.format(crdId=crdId) if sync_flag&2 else 'Gate3[1].Chan[1].UserFlag'
if sync_mode==1:
prg = f'\n{flag0}=0\n' if sync_flag&1 else ''
prg += f'''
Coord[{crdId}].Q[0]=-2 // motion program started and armed
# Gather.Enable=2 is done in the triggerSync executable
# triggerSync waits for Coord[1].Q[0]=-3 and then sets Coord[1].DesTimeBase to continue motion
# triggerSync set Coord[1].DesTimeBase to the servoPeriod to match last interval of frame triggers if sync_mode==1
# triggerSync modifies Coord[1].DesTimeBase if sync_mode==2
if sync_mode==1: # triggerSync:trigsync_func not called, therefore need to make own start synchronization
flag0=f'Coord[{crdId}].Q[10]' if sync_flag&1 else 'Gate3[1].Chan[0].UserFlag'
flag1=f'Coord[{crdId}].Q[11]' if sync_flag&2 else 'Gate3[1].Chan[1].UserFlag'
prg= f'''
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 //
'''
else:
else: #sync_mode==2: triggerSync:trigsync_func called
prg = f'''
//Gather.Enable=2 is done in the triggerSync program
Coord[1].TimeBaseSlew=1 //1E-4 is default
Coord[1].DesTimeBase=0
Coord[1].Q[0]=-3 //motion program started and waits. Arm(-2) is done in triggerSync program
Coord[{crdId}].TimeBaseSlew=1 //1E-4 is default
Coord[{crdId}].DesTimeBase=0
Coord[{crdId}].Q[0]=-3 //motion program waiting at start position
'''
self.sync_prg = prg
#download and start triggerSync code
comm=self.comm
if comm is None:
_log.info('simulated');return
mode=0 #mode to pass to triggerSync program
mode=0 #for triggerSync
# mode: (triggerSync executable)
# bit0:1: sync mode
# bit1:2: simulate start trigger
# bit2:4: simulate frame trigger
# bit3:8: verbose
if sync_mode==2:mode+=1 #synchronize
mode+=sync_flag*2 #simulated or real triggers
if verbose: mode+=8
if sync_mode==2 or mode&4:
sftp = comm.sftp
dst = '/tmp/triggerSync'
src = os.path.abspath(os.path.join(os.path.dirname(__file__), 'triggerSync'))
sftp.put(src, dst)
sftp.chmod(dst, 0o755)
cmd = 'LD_LIBRARY_PATH=/opt/ppmac/libppmac/ ' + dst
#cmd+=' %d %g %g %g'%(mode,pt2pt_time,timeOfs,timeCor)
cmd+=' %d %g %g'%(mode,fel_per+timeCor,timeOfs)
self.cmdSync = cmd
print ('starting '+cmd)
self.syncShell=comm.shell_channel(cmd)
#syncChan=sc=comm._client.exec_command(cmd) #this is less simple to communicate with
sftp = comm.sftp
dst = '/tmp/triggerSync'
src = os.path.abspath(os.path.join(os.path.dirname(__file__), 'triggerSync'))
sftp.put(src, dst)
sftp.chmod(dst, 0o755)
cmd = 'LD_LIBRARY_PATH=/opt/ppmac/libppmac/ ' + dst
#cmd+=' %d %g %g %g'%(mode,pt2pt_time,timeOfs,timeCor)
cmd+=' %d %g %g'%(mode,fel_per+timeCor,timeOfs)
self.sync_cmd = cmd
def homing(self):
if self.comm is None: return
@@ -143,21 +150,30 @@ Coord[1].Q[0]=-3 //motion program started and waits. Arm(-2) is done in triggerS
time.sleep(1)
if gpascii.get_variable('Motor[1].HomeComplete', int)==1:
break
print('homing done')
_log.info('homing done')
def run(self, crdId=1):
'runs the code sync_run which has been generated with setup_sync()'
try:
run=self.sync_run
except AttributeError:
raise 'Need to call setup sync before'
comm = self.comm
if comm is None: return
gpascii = comm.gpascii
try:
cmd=self.sync_run
cmd=self.sync_cmd
except AttributeError:
raise 'Need to call setup sync before'
gpascii.send_block(cmd)
pass
else:
if gpascii.get_variable('Gather.Enable', type_=int)==0:
raise 'Gather.Enable must be !=0'
_log.info('starting '+cmd)
self.sync_shell=comm.shell_channel(cmd)
#syncChan=sc=comm._client.exec_command(cmd) #this is less simple to communicate with
gpascii.send_block(run)
def wait_armed(self,crdId=1): #wait until motors are at first position
sm=self.meta['sync_mode']
@@ -168,7 +184,7 @@ Coord[1].Q[0]=-3 //motion program started and waits. Arm(-2) is done in triggerS
if comm is None: return
gpascii = comm.gpascii
while (True):
val = gpascii.get_variable('Coord[{crdId}].Q[0]'.format(crdId=crdId), type_=int)
val = gpascii.get_variable(f'Coord[{crdId}].Q[0]', type_=int)
if val==-2:
break
time.sleep(.1)
@@ -196,9 +212,9 @@ Coord[1].Q[0]=-3 //motion program started and waits. Arm(-2) is done in triggerS
if comm is None: return
gpascii = comm.gpascii
gpascii.send_block('Coord[1].Q[10]=1')
else:
import CaChannel
pvTrigger = CaChannel.CaChannel('SAR-CVME-TIFALL5-EVG0:SoftEvt-EvtCode-SP.VAL')
pvTrigger.searchw()
pvTrigger.putw(254)
#else:
# import CaChannel
# pvTrigger = CaChannel.CaChannel('SAR-CVME-TIFALL5-EVG0:SoftEvt-EvtCode-SP.VAL')
# pvTrigger.searchw()
# pvTrigger.putw(254) # ??? does this send a trigger or just set the event code ???

View File

@@ -17,19 +17,26 @@ verbose bits:
0x20 plot pvt trajectory (before motion)
0x40 print sync details
mode:
0 unused
1 pvt motion
2 unused
3 pvt motion using inverse fft velocity
4 pvt motion short code using grid parameters
5 pvt motion short code using grid parameters. Instead of continous motion it moves and waits as give in the parameter time
if mode&1:
self.plot_trajectory()
sync:
0 real start and frame trigger with sync
1 direct start
2 simulated start and frame trigger no sync
3 simulated start and frame trigger with sync
4 simulated start real frame trigger no sync
5 simulated start real frame trigger with sync
if mode&2:
self.plot_pos_error()
if mode&4:
self.plot_bode(xy=(3,1),mode=31,db=True) # FX
self.plot_bode(xy=(2,0),mode=31,db=True) # FY
if mode&8:
self.plot_trigger_jitter()
if motion not possible check the DesTimeBase:
Coord[1].DesTimeBase
> Coord[1].DesTimeBase=0 // this is blocked
Coord[1].DesTimeBase=Sys.ServoPeriod // to unblock
Gather motor order
@@ -71,7 +78,7 @@ if __name__=="__main__":
sys.path.insert(0, os.path.abspath(os.path.join(base,'../../../PBTools')))
else:
base=os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(base,'PBTools'))
sys.path.insert(0, os.path.abspath(os.path.join(base,'../../PBTools')))
sys.path.insert(0, os.path.join(base,'PBSwissMX/python'))
#_log.info(sys.path)
@@ -652,7 +659,7 @@ class ShapePath(MotionBase):
address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Gate3[1].Chan[1].UserFlag")
#address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Gate3[1].Chan[1].UserFlag","EncTable[20].PrevEnc")
#address=("Motor[1].ActPos", "Motor[2].ActPos", "Motor[1].DesPos", "Motor[2].DesPos", "Gate3[1].Chan[1].UserFlag","Coord[1].TimeBase","EncTable[20].DeltaPos")
gtMaxLn=gt.set_address(*address)
gtMaxLn=gt.set_address(*address) # sets also Gather.Enable=1
if acq_per is None:
if numPts is None:
numPts=self.mot_pts.shape[0]
@@ -1016,11 +1023,11 @@ f(P100>0)
self.rec=rec=gt.upload()
try:
syncShell=self.syncShell
sync_shell=self.sync_shell
except AttributeError: pass
else:
print(syncShell.sync())
del self.syncShell
print(sync_shell.sync())
del self.sync_shell
pts=self.mot_pts
@@ -1066,23 +1073,30 @@ if __name__=='__main__':
comm=gather=None
gp=GenPath()
#real start and frame trigger with sync
#sp = ShapePath(comm, gather, args.verbose)
# direct start
#sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=0)
sync=args.sync
mode=args.mode
#simulated start and frame trigger no sync
#sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=1,sync_flag=3)
#simulated start and frame trigger with sync
#sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=2,sync_flag=3)
#simulated start real frame trigger no sync
sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=1,sync_flag=1)
#simulated start real frame trigger with sync
#sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=2,sync_flag=1)
if sync==0:
#real start and frame trigger with sync
sp = ShapePath(comm, gather, args.verbose)
elif sync==1:
# direct start
sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=0)
elif sync==2:
#simulated start and frame trigger no sync
sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=1,sync_flag=3)
elif sync==3:
#simulated start and frame trigger with sync
sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=2,sync_flag=3)
elif sync==4:
#simulated start real frame trigger no sync
sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=1,sync_flag=1)
elif sync==5:
#simulated start real frame trigger with sync
sp = ShapePath(comm, gather, args.verbose,fel_per=10,sync_mode=2,sync_flag=1)
else:
raise(ValueError(f'unsupported sync:{sync}'))
fn='/tmp/shapepath'
#fn =unique_filename('ShapePathAnalyser/records/19_01_24/spiral')
@@ -1130,7 +1144,8 @@ if __name__=='__main__':
gp.grid(w=10,h=15,pitch=120,rnd=0,ofs=(-1000,-1200));gp.sort(grp_sz=15)
# for motion mode 4,5
grid={'pos':(-1000, -1200), 'pitch':(120, 120), 'count':(10, 15)}
#grid={'pos':(-1000, -1200), 'pitch':(120, 120), 'count':(10, 15)}
grid={'pos':(-1000, -1200), 'pitch':(120, 120), 'count':(20, 25)}
# mode:0 unused
# mode:1 pvt motion
@@ -1139,7 +1154,6 @@ if __name__=='__main__':
# mode:4 pvt motion short code using grid parameters
# mode:5 pvt motion short code using grid parameters. Instead of continous motion it moves and waits as give in the parameter time
#mode=3;scale=0
mode=5
if mode==5:
tmove=20 # time to move in ms
twait=130# time to move in ms
@@ -1160,6 +1174,8 @@ if __name__=='__main__':
sp.setup_motion(fnPrg=fn+'.prg',scale=1.,cnt=1,dwell=100,mode=4,grid=grid)
elif mode==5:
sp.setup_motion(fnPrg=fn+'.prg',scale=1.,cnt=1,dwell=100,mode=5,tmove=tmove, twait=twait, grid=grid)
else:
raise(ValueError(f'unsupported mode:{mode}'))
if sp.comm:
sp.setup_gather()
@@ -1169,7 +1185,7 @@ if __name__=='__main__':
_log.info('wait_armed')
sp.wait_armed() # wait until motors are at first position
_log.info('trigger')
sp.trigger(0.5) #send a start trigger (if needed) ater given time
sp.trigger(0.5) #send a start trigger (if needed) after given time
_log.info('progress..')
if not comm is None:
while True:
@@ -1185,13 +1201,15 @@ if __name__=='__main__':
def parse_args():
'main command line interpreter function'
(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>3 else sys.argv[0])+' '
exampleCmd=('-v15',
'--host=SAR-CPPM-EXPMX1 -v 0x5d',
'--host=localhost:10001:10002 -v 0x59'
exampleCmd=('-v0xff',
'--host=SAR-CPPM-EXPMX1 -v0x5d',
'--host=localhost:10001:10002 -v0x59',
'--host=SAR-CPPM-EXPMX1 -v0x5d -m5',
)
epilog=__doc__+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-m", "--mode", type=lambda x:int(x, 0), help="mode (see bitmasks) default=0x%(default)x", default=0xff)
parser.add_argument("-m", "--mode", type=lambda x:int(x, 0), help="mode default=0x%(default)x", default=4)
parser.add_argument("-s", "--sync", type=lambda x:int(x, 0), help="sync default=0x%(default)x", default=2)
parser.add_argument('-v', '--verbose', type=lambda x:int(x, 0), dest='verbose', help='verbosity bits (see below) default=0x%(default)x', default=0x00)
parser.add_argument('--host', help='hostname', default=None)

View File

@@ -1,32 +1,110 @@
Activate an user servoloop
--------------------------
triggerSync
===========
```
PBTools/pbtools/usr_servo_phase$ make
PBTools/pbtools/usr_servo_phase/usrServoSample$ make
scp userservo_util userphase_util usrServoSample/usralgo.ko root@MOTTEST-CPPM-CRM0573:/tmp
rmmod usralgo
insmod /tmp/usralgo.ko
cat /proc/kallsyms | grep MyUserAlgoFunctionName (e.g. cat /proc/kallsyms | grep usr_servo_ctrl_2)
a10385ca r __kstrtab_usr_servo_ctrl_2 [usralgo]
a1038570 r __ksymtab_usr_servo_ctrl_2 [usralgo]
a103812c T usr_servo_ctrl_2 [usralgo]
UserAlgo.ServoCtrlAddr[1] = $a103812c
Motor[1].Ctrl =UserAlgo.ServoCtrlAddr[1].a
.. but this can not be set directly in gpascii.
root@:/opt/ppmac#
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -d 1
rmmod usralgo
insmod /tmp/usralgo.ko
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -l 1 usr_servo_ctrl_2
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -e 1
gpascii:
Motor[1].Ctrl =UserAlgo.ServoCtrlAddr[1]
samples: root@:/opt/ppmac#
/tmp/triggerSync 40 11 trigger all 40 ms, simulated start, use real frame triggers, verbose
/tmp/triggerSync 40 14 trigger all 40 ms, simulated start and frame triggers, no sync, verbose
/tmp/triggerSync 40 15 trigger all 40 ms, simulated start and frame triggers, with sync, verbose
/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:
#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
#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:
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 \
SAR-EXPMX-EVR0:Pul0-Evt-Trig0-SP SAR-EXPMX-EVR0:Pul1-Evt-Trig0-SP
SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-RB "Pulser 0"
SAR-EXPMX-EVR0:FrontUnivOut5-Src-Pulse-RB "Pulser 1"
SAR-EXPMX-EVR0:Pul0-Polarity-Sel "Active Low"
SAR-EXPMX-EVR0:Pul0-Delay-RB 0.000 us
SAR-EXPMX-EVR0:Pul0-Width-RB 5000.000 us
SAR-EXPMX-EVR0:Pul1-Polarity-Sel "Active Low"
SAR-EXPMX-EVR0:Pul1-Delay-RB 750.000 us
SAR-EXPMX-EVR0:Pul1-Width-RB 5000.000 us
SAR-EXPMX-EVR0:Pul0-Evt-Trig0-SP 214
SAR-EXPMX-EVR0:Pul1-Evt-Trig0-SP 40
```
testing simulated start triggers
--------------------------------
```
Gather.Enable=1 // else triggerSync stops if value is 0
Coord[1].Q[0]=-3 // simulate motion ready
Coord[1].Q[10]=0 // turn off simulated start event
root@:/opt/ppmac#
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 14 10 0 # trigger all 10 ms, simulated start and frame triggers , no sync , verbose
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 15 10 0 # trigger all 10 ms, simulated start and frame triggers , with sync, verbose
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 11 10 0 # trigger all 10 ms, simulated start, real frame triggers , with sync, verbose
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 7 10 0 # trigger all 10 ms, simulated start and frame triggers , with sync, minimal verbose
....
Coord[1].Q[10]=1 # turn on simulated start event
.s.s.s.s.
Coord[1].Q[10]=0 # turn off simulated start event
....
Coord[1].Q[10]=1 # turn on simulated start event
.s.s.s.s.
Coord[1].Q[0]=0 # simulate ready at start position
.s.s.s.x.........
Gather.Enable=0 # end triggerSync
```
testing real start triggers
---------------------------
```
Gather.Enable=1 // else triggerSync stops if value is 0
Coord[1].Q[0]=0 // simulate motion not ready (!=-3)
caget SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-RB
->SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-RB "Pulser 0"
# set start EVT to value 0 (=Force Hi)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 9
root@:/opt/ppmac#
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 9 10 0 # trigger all 10 ms, real start and frame triggers, with sync, verbose
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 1 10 0 # trigger all 10 ms, real start and frame triggers, with sync, minimal verbose
Coord[1].Q[0]=-3 // simulate motion ready
Coord[1].Q[0] // changed to -2 to indicate 'wait for start EVT
# set start EVT to value 1 (=Force Lo)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 8
# reset EVT default value (Pulser 0)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0
Gather.Enable=0 # end triggerSync
```

Binary file not shown.

View File

@@ -91,7 +91,7 @@ void trigsync_func(void *arg)
srvPer=pshm->ServoPeriod;
rtStart=rt_timer_read();
printf("Wait for 'arm' event...\n");
printf("Wait for 'acquire start' event...\n");
if(mode&2)
{
while(!SIMFLAG0)
@@ -217,44 +217,41 @@ void trigsim_func(void *arg)
rt_task_sleep_until(rtSlice); //in ns
if(mode&4)
{
SIMFLAG1=1;
SIMFLAG1=1; //set frame event on
//while(rt_timer_read()-rtStart<1E6*40*i)
// rt_task_wait_period(NULL);
rt_task_sleep_until(rtSlice+5*1E6); //in ns
SIMFLAG1=0;
SIMFLAG1=0; //set frame event off
if(mode&8)
{putchar('.');fflush(stdout);}
{putchar('.');fflush(stdout);} //indicates frame event has been generated (toggle on/off)
}
//if(pshm->Coord[1].DesTimeBase==0)
if(SIMFLAG0==1)
if(SIMFLAG0==1) //if start event on
{
if(j)
if(pshm->Coord[1].Q[0]>=0) //îf moved bejond start position, the start event was consumed
{
SIMFLAG0=0;j=0;
SIMFLAG0=0; //set start event off
if(mode&8){
putchar('x');fflush(stdout); //indicates start event has been turned off
}
}
else if(mode&8){
putchar('s');fflush(stdout); //indicates start event is on
}
else if(mode&8)
{putchar('x');fflush(stdout);}
j++;
}
if(!pshm->Gather.Enable)
{
if((mode&4) && j<10)
{
putchar('o');
putchar('o'); //indicates Gather.Enable==0 and trigsim_func will end after further 10 simulated frame triggers
j++;
continue;
}
break;
}
//if(pshm->Coord[1].Q[10]==2)
// break;
}
printf("trigsim_func done\n");
}
void trigsync_run()
{
RT_TASK trigsync_task;
@@ -275,7 +272,7 @@ void trigsync_run()
rt_task_start(&trigsync_task, &trigsync_func, 0); //Since task starts in suspended mode, start task
}
if(mode&2)
if(mode&6)
{
rt_task_create(&trigsim_task, strSim, 0, 50, T_JOINABLE);
rt_task_start(&trigsim_task, &trigsim_func, 0);
@@ -288,7 +285,7 @@ void trigsync_run()
printf("trigsync_task done\n");
}
if(mode&2)
if(mode&6)
{
rt_task_join(&trigsim_task);
printf("trigsim_task done\n");
@@ -311,27 +308,31 @@ timeOfs: once added time offset in ms (default=0, float value)\n\
scl: scale factor (so far unused, default=1, float value)\n\
\n\
\n\
simulate start trigger:\n\
set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start\n\
\n\
simulate frame trigger\n\
is output to pshm->Coord[1].Q[11]\n\
mode examples:\n\
1: synchronize real frame and start triggers\n\
3: synchronize real frame and simulated start triggers\n\
6: simulated frame and start triggers (no sync)\n\
7: synchronize simulated frame and start triggers\n\
\n\
in simulate mode:\n\
set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start\n\
set pshm->Coord[1].Q[10]=2 to stop simulate trigger generation\n\
Coord[1].Q[11] is the simulated frame trigger\n\
Acquire start event:\n\
SIM: Coord[1].Q[10]\n\
EVR: Gate3[1].Chan[0].UserFlag == (gate3_1->Chan[0].Status&0x800)\n\
\n\
in synchronize mode\n\
Coord[1].Q[0]=-2 : trigsync_func start, Wait for 'arm' trigger\n\
Coord[1].Q[0]=-1 : got 'arm' trigger, wait frame trigger\n\
Coord[1].Q[0]= 0 : got frame trigger 0\n\
Coord[1].Q[0] is incremented at each trigger\n\
sync task ends when Gather.Enable==0\n\
Frame event:\n\
SIM: Coord[1].Q[11]\n\
EVR: Gate3[1].Chan[1].UserFlag == (gate3_1->Chan[0].Status&0x800)\n\
\n\
Coord[1].Q[0] : sync points indicator: (at whick point is the motion program) (mode=2)\n\
val: desc set in code\n\
-3: motion armed at start position motion code MXMotion.py:setup_sync\n\
-2: wait for 'aquire start' event triggerSync.c:trigsync_func(mode&1==sync mode) or motion code MXMotion.py:setup_sync\n\
-1: start gathering data triggerSync.c:trigsync_func(mode&1==sync mode) or motion code MXMotion.py:setup_sync\n\
0: got first frame trigger triggerSync.c:trigsync_func(mode&1==sync mode)\n\
idx: index of frame during run triggerSync.c:trigsync_func(mode&1==sync mode)\n\
\n\
\n\
exec ends the tasks ends\n\
tasks ends (trigsync_func and trigsim_func) when Gather.Enable==0\n\
";
printf("usage:\n%s mode pt2ptTime timeOfs(default=0) scl(default=1)\n",cmd);
puts(s);

32
src/usrServo/Readme.md Normal file
View File

@@ -0,0 +1,32 @@
Activate an user servoloop
--------------------------
```
PBTools/pbtools/usr_servo_phase$ make
PBTools/pbtools/usr_servo_phase/usrServoSample$ make
scp userservo_util userphase_util usrServoSample/usralgo.ko root@MOTTEST-CPPM-CRM0573:/tmp
rmmod usralgo
insmod /tmp/usralgo.ko
cat /proc/kallsyms | grep MyUserAlgoFunctionName (e.g. cat /proc/kallsyms | grep usr_servo_ctrl_2)
a10385ca r __kstrtab_usr_servo_ctrl_2 [usralgo]
a1038570 r __ksymtab_usr_servo_ctrl_2 [usralgo]
a103812c T usr_servo_ctrl_2 [usralgo]
UserAlgo.ServoCtrlAddr[1] = $a103812c
Motor[1].Ctrl =UserAlgo.ServoCtrlAddr[1].a
.. but this can not be set directly in gpascii.
root@:/opt/ppmac#
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -d 1
rmmod usralgo
insmod /tmp/usralgo.ko
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -l 1 usr_servo_ctrl_2
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/userservo_util -e 1
gpascii:
Motor[1].Ctrl =UserAlgo.ServoCtrlAddr[1]
```