From cf4a9362f2e8209b0f77844bd6aae7c17f21d0cc Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Thu, 24 Oct 2024 12:10:00 +0200 Subject: [PATCH] SFELPHOTON-1335:rework triggerSync --- Readme.md | 124 +++++++++++++++++++++++++++++++ python/MXMotion.py | 114 ++++++++++++++++------------- python/shapepath.py | 94 ++++++++++++++---------- src/triggerSync/Readme.md | 134 +++++++++++++++++++++++++++------- src/triggerSync/triggerSync | Bin 66458 -> 66906 bytes src/triggerSync/triggerSync.c | 69 ++++++++--------- src/usrServo/Readme.md | 32 ++++++++ 7 files changed, 418 insertions(+), 149 deletions(-) create mode 100644 src/usrServo/Readme.md diff --git a/Readme.md b/Readme.md index 8e1e0f4..b04f1f3 100644 --- a/Readme.md +++ b/Readme.md @@ -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 + +``` + diff --git a/python/MXMotion.py b/python/MXMotion.py index 6c7cb39..99935d0 100644 --- a/python/MXMotion.py +++ b/python/MXMotion.py @@ -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 ??? diff --git a/python/shapepath.py b/python/shapepath.py index 4794005..9718cf7 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -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) diff --git a/src/triggerSync/Readme.md b/src/triggerSync/Readme.md index 7c8dcd7..73f9a5e 100644 --- a/src/triggerSync/Readme.md +++ b/src/triggerSync/Readme.md @@ -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 ``` diff --git a/src/triggerSync/triggerSync b/src/triggerSync/triggerSync index c04b8cfb10380e596e8dbef9e83233dbdee57da9..4c1e86130461b8073edfdca2efdb879d709406b7 100755 GIT binary patch literal 66906 zcmce<4SZD9wKl$Ia%M8;5JG^cQ4j_PGzi7;Ap&Y8BtT;Lh)GZsZ5WaXnUZ9}%mjkM zOB8HTv5mrQsTV74X^U4|X=^L(r8c(MMzJluwTepb#THw7wJloO(iYA8JZtZBW+vjj z@BRPo@2|fwv!1o~+H3E<_TFoMoHLu}FIwR9`;_;eUlrrKuSg9k!RHL6ese~6GgMfG zRH?dDML-A1D>8o&2PrxN_+sHN4>b7t5A;y;N1i8)^ooB|tV|N)@e0cw{UYR%3JNO%dKh|mXe}y1u!*KkKFpQD-JP&{8 z6TVy&+y+{+Cau-%F3)@$bL=Vacrh#p&vW7asrW zsg27%`R~yo@rOq*U;D~+8=gP^hb5~THa__4@1(~*_3^%6*L(%?Z{7c!M}GS7h*6XN zJbTxow|+6d;^sqL7Zgo;`A-{n-%(Wf_Wj@f%GFQ*&e)#);ni1IqpSz{FRVYFFS0J* zjwZBBKLowk7Zyji+H~M{hL6>D{ z|3jc@FFL`%+bHKG(5#P6W8Wu1)4yH&zJ&aaWXX4c&oRX1PeOa{H#B_5zXJRhLA&

kJa`3M~zNY=v%p&D5 ze+7LQ1AOq$%V&A=7?V0X+oMewl~iNn>h?rOV=5g@rW+eotd_psdOw^(H2dm zVky3B;bj%~gERXtVBHp2@VaB5Ps$?{|K~=ORQZbisRit8VEnbp%$J(xV zGNu;B()F#;WUP5{ti3j!RGq2Tb`grV$C8aS*h`XXi^Vz{yE@YGwhR_aH+II7@kDdH ziMkfT$mvFvoA3H)+!a!t@kG1o>|!RJwaL}>{A^g&CZCI{__4I5B^66oFI{ZD)mORS zmSw&&sfRPYM?eX_qi$2_=B7!LScx;)mfhX7GnMFww#CyM8rMmav}-n`S2r~^rbtbN za7$Yvn(pdojyJcEig$N)q?%ir<5WxEpvLN@aE<18M`Kqi)~s4u+E6AGES=&%O{h^7 zU6n|tRVtlKCtCDJ8?<$_HLq%G>`cZx(nOmRU1`Vv=VxWmbr~lvZ zsfw(L(CwoPzHx33>PXZVU(R_q~|@-S3YhTyVcXiK*TF z4*g;G`yp88et!WYi~IdWgaz*RV<@Wo{RBb<_xoG0%Kd&CVTSwtEJ6(Po%5&VelJj} z*!^CtREhh2v{Dzk-^VL;x%+*xQkS~lXJATozh8qX%l%%d)F}7+B7`~eedoA=QyWA6 zFYS0ng?fFexXK!P;pTq-mwLtwoVlV$sq)XN5U_`9=R+b6sDN#k{tSnbf!AbydK8=6+UH zUK=j5uKwM`x9;4mtUD(ub;UiB|M*!$l(lIhbdFWlk{)YZHh=DC2TmYg-!AB)ZM16( zbkauGJ~waXNg3kg({`7~yvd&xFYWKKOZ!dPM_(IOYW76WmIB&A8$L+S2jp=?>iBgv z8T=U=uN%_cyIGYWPc_RPa{%QE$@lp9y*-bpl0`q9dRLV-W@^u7*8Q00W~qUJjd^+9 zcSe=!L0w4wzd3MrQ*=eQDZ~5pYu)3ILwAAsev0|bLU)AD#X7$U{2s@5YnwgkP=gA7 zxIyK=$4^uKS+mBXu8=qEDwwrLsabt$+N|Ri(p~(v%M)GqjO-;J_%nm_ZOqbDVswQD z>G~pc2~X=9cGl?X5;{Hse)&GV*>;Y0ZGqfylcp5k@BaW>C@=X{S)*S!^4CEAHuJp} z-*5Pz)HmC+_YpOkeSme|1N|tsul!*wS*}x~du*jx_L_lr|GaVKsBXxFtCVj$dGIfb z{Mpx`Z$W0$_?m8%-+^s0%CbFJj$LRYqt`$8VKv#L4Gm61Ednxb>08Jd;m1=>RymH{>lH}*-{G&bs8+T{8gzxTnuclRi{RQyVtoVeL8?C(Vv*Fg>vvXJWo?WSW7yWSByeezdaQtq%3jBT-u-p-eX$;3)9B`qRm&DKD--!c(3Wh z+e~|p$3VMlrTSElw5xT|v&ODc_*ohHaVg7yynoDmu3cGC#>E0M0)&0PAs_216jECBvN8bthPSC(Z zzza~OB8&;>mlutDwbNd6>^?np__VZ)l{gO2JqYZyF#>-tF+$Y~V&OZ6t>%Nj5pYs*$c->dr>+_8_ee;a*-CgLL zzLn}@d)UvA$3)XNccX9afp18k0zMVC?tH%w`>Y2x`&9o}pE^h1-1EVG^Zd2cw^6;< ziGH(lqn+1{@+&j%sZE!`&#LHW=f{Ej@cA=i7v`SxW!z_d=k(Y2*SlMHr;z4zRVtY6 zN1=ZE)>B8vDvl?n-4w9;mB8r3sPjw1%pY}LK-=)0zK#S_+QV_ zAtLAc#z*??QDw+uIrX{y3ggB$j2qicz718@d2dr!md_kC{iq>h&v|!y`Q`Q<-7o(A z)I4_#Z$%rsaSQA`1RY^rrt`|-Pqmzv8dRWE=P_^+`ES^`9b?^^QQhEgLmO@1bp6Vr zO%rb}%8UW$&CePyWIQ(ZV?J`n;Np7*mBaP@o=iE4zdNWLQvVnOq#Uf*EZGPCE7_(0 zb(!btG8Zp4W$tmyj66#f4Fm9}K* zKZh@j_?l<0_UZq^7e);B{~X!>H(wax`u_*`!iaI_@`WmE#LZc4(v3FRn6caMwm~!2 zV%>K>qBgqi<@O=8TPM<_fj6_AHma&x)X~a}4jGGjFiunvd*;!Jr}3%!?8|x)8;oac zfHtd=IdV7FL0BkLuFu4aw)EkEXV&N z^y$rCe6zd%I#orVW_;cAA8KX)BdVac9lOyVH=e@Q%-^@z}R0#U6sJtLHtU0%q^x$mYIxiZ^Z;)xGhbF~%R9gmu>+FYFo9 zqwf50k0tAai_c$MewUhY^>L*(&8g|W>3GqcjTfmYn5VzAIdZsrbMtH6oA3TL*4Ng! zs|S>C^TTIk{=>R|hOEC~%NE$O1-5K~En8p<_8v;H_b?f@mvLSG%He^|SKb`xes#z| z&#RLLw!K<2(EI9|fnBfOH?Zf`#|HMjdU#;}t8We*cx}i)-)oZw`d_OVIP%(>fupb8 zH*oy5#|BQmc6i{_Yp56Mdf@QDfd}3kIQSrBADlFB=)szS{s-3#yzt_gVb}Ap>oD><47(1)uEVhFFzh-EyAH!Hwik8X3A^ruU3WqD zF4%P!?79nf-37buf?apPuDf8@7TC1~c5Q)OTVU4~*tG?AZGl~A|Nk|+xIaSM*ha2D z{cqSvy|go1@8G?o*%M0-_Sgew^`6$iz}3GSIE%Qwgg!+-+B$aN>=iu&1DK0X^B$S-S}%&+_S}hPJ5y`HpdCCil@uwOq~-> zZRltU6BB6aoN0jK?Okoy(+|smLpYs`uU;KX3V+(18Cm?6WVAh&!=FB9)|~LVSaKDP zA{?hPJ*_j{fJ22j;czF8E7IX~!uD zWVow?d-;>Yo(+RcaHPJ%vF>PlXIm_ViZgZAnoM-WZ;yp>TGAHQ6%p-d&aJYP6P~VX z_=BWPO}{_g%uF>mf1vtsX-7gDaH12wDmNpy4L>-slJ64q4Hf32VmR!&lT^+vm+HmP=o&z;b z{m_S9Zhaa@Dyd7$x@VP@O>~?E;w~SY&(sgd2l@Sv^2xHj?6$D37wvW__zMoLqVRw@ z;nHY2yuLNww8pq(JQYs2#?Tki@kB?sGnrTodnblV**UJAhAO68&Vi?-n&?jd-G4aH zqIWh)*9wO}1Wz!kqsex7F>=@at22>`OO~ESBgdrS#mg6qK~p+6%z?_T&PMiF7!&>w zx+;&^!Y%OU%c5Crd0AL0+0z$x`)ECqPHCFM9!)KcEnOW=Qoc*4UVE)K5=;z3;s2uz z>iZA&C-wxeLI8g4Rg3Ue#hRj+Ki*gQutDm=bRsjBgrmtME(@Ha>$CFQG`cru z56z}KYatnJ;qeouT**>Mc?CmH%*LdB=Aaq$mkCp*OQBOuhQ^eWTvr=I#Z8&n0xb=C zmdAL7!~QuFFeNVGfFR!%C)UL{jZ^r_)!7N5zcSv^0(^Q4sx;N4spfEPA~ipmTz>PM zQnDuVA2=2M%dJ4|55z0VaGr(F@+n*S;r(~rDgCv)e#8-e>kDbRPk*TI8U9?*zEOEs zuY-2(%^N#pb2z`)5?d>$JZc=Iei`B#KL<-5HO zhic`%Q3Vn%5i5Z%oTEjt?U=pt;N;d7;`EG%2}h;MlL z=E|YGG=~4kzXtqWNZt7X{975bfq(h~_#2DVFxZ;66Z}2C+zi6dzq?3{?8SAzqvZP= z9?5$+@I8OF5d-)SayUiQpZuP=FDNl03(mi5%x8`HTwy*t%;*0xpZDlbxd(uBzCRfH zjQ*7Ke8i%12WKendL;(l`*V@~0Qh|Pa28)#cC_dpM{$uzYf~59j!_ zhxZ9szifki{9RC_?A`p1PqsJft`?uz;Zp^Pfr0mcTli#|^YD49NQLMR|KtBqM~CKx zb+RQrY8>xSdP;B!1Mvi|Fis5fR>m~NYZ?E)A+8ytSvzu_0{?1199HHs@hSYr53w7N zKN>vWaUt|SZ|n3*J$^{3FOQJf1Dr44;`Lcfc?3?#H5D9G#D!xfB5)p^?ul}I1oBwD zTrR?w7P$t5FI)9hAbi{9UI)VWuew))@cmGyz7~Y9uVk(UfqGk0yzK)kZB5A)A&{47 z(%cLJaIFT+y&(Y0HK4BxK?9ZanM&gY)NsY5Nu~iU76hvv9j&MpvgB54#^j3H-# z3d@JawDP|M;@&(f9~X||t2;0~V4; zF)0H&rRcQ+@(~J1I{8NfTG9Kp`5PP8cHs&eY~tYhH_(Ze7LvX2pNc$7YoZd(nmL2a z2f!RpS9=FvI&tO4*XdJ1D?i@~0rlO10*ZAuZ&fX*UNm3rvV6GdVp$IEVntV{l;s=B zE#A29C==#6uZ;RWua?1EU2Q1;SXLjHhFbhJ*2i zoT4m_&I1>J$tccZ=uB|KlZ+B!tmU#EZ+Q+iRT0L|Zdk6pIVM6OqLXe`GGybtM~{5^Y`W)cGMuKjx2AI*sen z3@|eZ7`VLTk1TK+#mP`15WfN@B>j-g>{pjXjuxUu!Mp`>(ms{-pONVOC;cEq~DJ3s>N zS=gA8Vt*SnD&8t=#F9=~-_^N>BnK-ZZofr*A98m|kHCDze9v>yU4mYw{OC>7ry>8q zvsB`;pAz<1H7px^LBNq()2_Ubh3kcAAx;0P2P*s@*5CwWi*3OfOewT<`5=Y|pW}};p}Kfu7D@7d55+Ab zJxKY;PPMTcG$lG(;uuO*{wWCEN1<$n7H#Hj+71f+2}1iRq#>iJIe~FuZC5OX8?!3^ zFOYdr6lHMbv!^u9oUKCnKHN(TUgtqiwu!nZ`Zed>=!I zdo4?$MT^_w9cvo9I)P&B0qV1WDrmk6j+^hB3C%l;6CDtXLFOtggOsW`fn^8o2=fjq zI1F8o+LxUd;5j-gKVW4VJGfWc<2rR7GP#PGd;*!AIDdXc<4qNfx6H3wid%b{s9sXB zbaCyX`3>`x&p;mF7b9n>f_&dUBTBl?S)WL*;S?ruek_U189uS_&U(3piVMg2zK4<5 zUXHN1B#cY3(T=7Kjo3KD>IKZt>I5M%Z8lB&B2?ectShVQ8mpJwSiY#bQkzF$>9U5} zWewUkEkM%m%2zC1wxj{4Whm&ZGHUxev>ld$R5n)5Ur@emQG+RKW#jxMQDOx_+f| zQciQ675@esgq7UU*x8H`Bj5KMQ?rhtf6K(2x7J5-zqmQET90V?zTdIJF>Oh1p+e?1 zLzU$F&`a#K4z4>#sqVCEySv2%?9UqWJJ{}PP9z)S%>dbPrqdFvRGYh+((n!pocX@L zYCL4@KcmwYfMj+44J4|w&@p3rzVGkMp0g<{I4je$8ZQ=e)xB(K4Al94bTRuywshV6 z8oX__hX9YK!*5qQJux2%gBb3)}f^s}MIqJ)*cFKNclFrxH$hVvu~3e|(Ul!G8k3AP;=? z4*mg}tJ4^T;IH6f$`_!Ese$H8@97fg}Zj*A22GYl>7MG*`jnqUY=U`V0O+m#*^&z6InTni-fbssl-*&oqQQ zP!K{aT5wwQ{2h9RqW2B8sYjOzeOY&%oTA7`6vE?gL#Ht1&>6;ehAu`*F+<&pZ$lSL zzC-KjK(`Dk4E;G7Yl$UeIK*jel9(`r_;;{N%M63rSA`G(5B;pc+xd2}WehU5xK8D+{gN$KU4)w1RRpT?~GRS4mG;b$cEBe1sc zD*SyH8lJRX6^uwhIy>^!8g*W=50 zH_d$RELW5_@L?kr8V}ZNk-QG28@80jurFai@prnS^SdcJ0nyAcfJnOl+W{Ow79o&Q zp-Yi)ljzuj+&B~sd(c%Oqj!!AHaDpdmMg=akQCo^Q~VMsG7czSnEj9Vsh*ul?d%SHRH=~TdZ4V8@;&?>~1w4Af4P`ieLg*QqJgjhAyAr2A=71rtqsDc4dD524U z!n)YHcna>TLY*2aLS`80*2>TwDF)>~8A`Icu{BUwTe(z)Qnbk*8BMCX15b#lP#Vw| z@*=y7h%Ls%ib!0Ax_~|jG+fBtrp3_?oZ2K+XdU1~d68q|3d>X6&naj8Eu$lPCw7b? zyT?m{vWg8&T<>*jbdN#nTjMRra)UWhH2+2O@9eMb4CR z^^<=X)E6*4V8>{H0LO=sPi6s(qDCH)_0cd2gl+--Vun@^fqo+^fe$4cdDZ|Tcb)RP zW0iKI(4BC*Cx>P^S0&CdtJ~2QsyVb3JI*f`8p*p^RC-u_*D6!`k7>xFA6yywxTZpd zRG~uKTrXOx_dY`RXns-Qym&g}l~{yRZ81^QI2R|O`!rTkXdGy}rbnBqyq{Hx%_U^( z%MX1*GgoGcrt|+Kj2}Kat7OVIZEk<)0X#l7s&G;5ysp#+6?zbfrQ6h*6<>NO28A6O zwRF)dcs8U$J2l9l0R8QsG*wVo$EssiLn?bXnt!nABJg}wwDCe&)$tg%90)@Vavx(WN3h|AklXrIQG7pB(4v7z;- zCT}go30wjL$-iiNW#MAkmywEBp~v8rZ}=n4C}E}SvKahv_|yq(mU;Nnt~3TO!~Kfp zcEj$RR9_{Y7uo9b7&*zF(Cl8H+lThk`7ng}&_1TczD6?xk=?IzjX?ez;9LvN=k{kfIy=pO(&c}{hB;ma-_#lG`P{cOtU}+?S?tw_E|6C7lvc6# z_3u+wbF#BI;PRifO|`1fw>j?yB70x&w+qYLJ8=|Ge@JlP|BlXjA6eB)=XJFp7*?Tw zg_0$K$m2vSE9zn`W`H@Ur60fZIfKu`p}z`!SHt@~xE2o}tI*RLe$s;%$Fa+)Lf_N) zfebFquR?vAaZod)$MV=#g`UxjJ}@|}jy%iiF{37d;+I)!0rF*J4)wDHSpY}g3mXL( zHjo*Iu#17zZ(htX2*F@^ZS{g>ODZbo*H@_W-Vk3>GUiQ(Cq}s7g?jNVBfu>wVi;8b z-3aI(d66E!Gyh!6d*5A-c_q^bQvF7VW;VN48C_gRrAT`5x-y~^>mfcu&i zIpA`0GSbUd-)gLXhFOt=u8f<{Iaj2aQ7=W-GSJj10^Y*!T9ISt5^>uO5pdxtD{}l?GE`$0K|aLBMYFBQiF3)B zm5vV)bJ0dCa?+E@DMTWBZHB!XHS7;ortlK!AojSoTl@PrjPOZl7ywGV;&u<;nWwq!VZ z{p>^VK5QvQD{|hqi1ytMZZk$JaycgEbO0`z8TJl)5Chg0zP15D3CBfZ>~KxX zzXNKFYZ`}WjJ=h(>-KwF_^*Sl@v&_c67+(^-*Dw&8+C5E}32x^e6dtUbqa|8FebH9%nRScKFqcCVd} zp>6g@!&4fkURkC>c0TH6+(~SFPrY&~Ntih9rE!qG#Lkzsh@9N0;@Vbh6X|U7u@d2l z4$f{=@nV?_4WmahLS$4#JJVgs*kUdK?fg46r+}QgXlJ~+zB3kUu8+a${4K)s6_Hn) zSRYF+?J%jf3MX&4aA-h1wop4f)Ko=IU6hD657ytS^`qX5 z0Y)f04=he-!+De`@9NH}BQ8~t$wlO)S2bTb8#Z&H0{KzE)Fp76XRx8A{>{!u5E-zP zc+E7r31YwrbHr<~QEKNSj2r(nyhi=Q&PVu0wLG;0;(N@_XVhj+>nKxa=l`olcu)t# z|9LzAphogo$qQmPMUx${hLIW)ilZ%vEx@42wq>9O6!pr)*qF;_hz2BR)cw)U@6$-W zM)Jz+{AV;m-(;%a+xdv4n94RX+wA-wXap@n8Q&Q@|Byz80HKc=yPnmkc(Z9a*!4q= z4mCNvYUlq*BZW+j8lHM3q!8*cS2V5UvD40fUL*8>TK0g=l{;nV_dxO*?EDurGJ=|P zObk^&*5F8j)g4#?1N(`_q*EZvX;XpyRAX=g$>1qF|A}+p!&L=fA39c#l;)udNb?fOh_C8iW5> z#r266yv+%+nsrRG;6>u+)31W~F9jRLzRB~-saMXR8y|;PN1S@ZaAlBr9WuDAp#)$( z{tCcDJolu;GyuQWK%M~80i4iDECFT!ctZn0cBXNE#XsYpMvux{Yjf3)9yOkMU#a{( zc4#It-!h>-mRy%mcIYbflhz5<5>MEnSxT*qPgr26*`PK|s5I0ZQ1|FU%v2?IXfE_T zqWA@@M7e`6WMJ6w_{D!xB>+#=nvIVpu!;QbBjrAB6vM09=WZ4SqBUXI0%3UsbS znNST%VCc;r^jxOTWo8XVF3-=t06kIa!JPqrBu{1ws?u&4S|uzWx^Et9Zo-iXG@&8^ zmrGy>kj=?^Q7Fy{NLJs1szw@9RD)))kW;<3qMd%)tkm_#c(PjEoC6d?VlhraG9o1q z$wfv(rWzYJo|Z5~a)9wpb=0K6EY6Hdo$6J&$YjXOZJY!KAo)VIYu7xHeD zosabZvs~_QV=qJB>Qu*bC007soh`XgGoV$uP^(kjjok~JAQ&7g2$Lww0G)yTMs)gL%D%*TC@3G&Pnc%x9<1sYgg7oO+&m*!hOD zE6V~ivuBvQeNHE~KcrXZV?lB~wte?_7{?|9?gi*&02r%|>tD)?>;p_o&%t^eEDW}g z#j2v>r`W0nfcnV*PXfrQ7$bJTMKi`4&Ox8UAXSn;3)T~3@5qbvY19mO`H1U@9`ap^ zFJI4#^z+NOlX;ONJ_q45-nYjw<6>M1z9BDi6m^3Ej_%I`M(f}5BE5b*h{bJS4toaM z<#+00sa$N2-&xR>PTm-6%M#q@r#?{^*6Q}V>Y&X)2V89#sLxZD!TSA<4vJlkn9OM4 z5x*IA4SiJ9d7@BY7{|3z&4Ha6&Pg!}_b|LvVlqZZW^n3#T%rX^NipIEJ{ zW`efjOrFE1IJ~McaF6965OJ%~fZHs`OAcRVA$kSUbzq=f7Bq6)iozI!?QtG$mjQP15O4SPlc|_u(fkN5WUxp0!=+w-80O z#nyW+E3Q6SYdXbTc{vh!%SsYuGOW{CEFQbD`xw?4#%0(_rdLhT!|z!GWsshLgDvMK z`cD}mtIuF6&`1W@20&*I!3?}T;OKR5Xd0K;Xl(#|{u3fIkljNV?E|``+|Z^K2L7ik zID>vF;NWm285Q@SCm88Z2jCJD=Hx|o1)L?Z^pklV}ZTHQN)hXbnG!2XGeo1SYJJIP?DuH!Db z2k#nA^JM_ML2KBp5hgXrp5d?@dotNldtEF`Zr^Z@NA8$Vr`0_!>IQ-Phs%VbozVzB zsWGo64SZlYy6w91_GmW@s@FOX3Rane^$B);4t8j`qnFBAuT%PH`hIxbqPf0w5w)CvUaSw;-7jwAMR)%vlhqEA&Y+@@I<}s-`=mUgPB5FDg zD6TgaTaaG0`#`Fct3|a`vA&p zv_y7wUHA}ScXJVHjd1@6^u(rQ!c;>_H_8hJ_3F&vM}RX7%8f@1^TiQPLo(VFGsBEQ zj~Y~;d)vGy#1+*sSC~&$!<;V6h0ns54Ll#uif7Oho^S#$^!9{Ly29KPb2Yr>7AVoa zfbe?chh^8P42+8c8T_3QPDNJ|cQw;Xy4u?Ch%jFCo#CF&;kx6wQTdk0=q(Rb@CI&v0B_hO=#?_BDF3*S9xmefJoi-usv9SjgpGgL+V6awx9+?eM)exbCp?bcsW zFzxHIE!l$Tge0%%6sQTuSKtPg$o?%Yvn*>r-yrig3QYx#Z(xNw!w2NapsUETawGkN;8^UNN7=L z!T!zc2l=QX5U9u?WtcYR;Lu>MtmLQ`W0TxX5`fwa(4ZxnF<`jR@=VsUbLrx@G8@;6 zt#xSbmHr5}-8zhq0AUub4!UM8)aKN-wBHnO#sxXs;xGfTPKk+3RT?bq@IDmAA_`G^ zx9k^}&0?$KEbyAhgoSu0*(l#kMFQw9Wc9E*uvv^(-9SY*T}E17&hw<$P_E{W)kOs?b-2_J1z}p2zJLJMxiDPSsClBu7 zsgd6)?xb7aB;gQ*46stask0`Az{E1hZmgeMOok#V@o(U;a)CDF%#;0WVXd& z2>P(1pFbZrO4^OIfgg8a`W_Smp8X(p;VgL1)o)`Gwj5Ts;ohaWSg{Mpvk=Q*Scem< z<&L?FVc}ed-=)xZdTnb9Qhy%R9grr*s)Yz`I~Z_o;`6$z9mO@bnKPjI z%S7ncX#Hds$di(wD>;>iU)DY?n(vBwC}oFwva?ysk7`-05 z#iR9gG~T^dF%D{QcpqB_kcB@yz^(+R-aPkmrAyHn%K6ULAD<=+5SLOW@mdyknC)q6~xPS?p!tjvSp3P z@hI{oP1iPbh&1cg&;_KYXXql*Y*NE7CXJI@mo6baGeeIijWb1;AC_JRFEl+AYRWJ5 zN5)Gl+zVo+aV}Ix-ubrm6BK#6ZRQ#^%eH>TU|XsLPiouN&ynO+2TR0QH%svglo*Yw zG{SPcq!C}S$gm_Y6Y=qpTfYWb93HO%#4)J9xQREAxdUar;)&)JrzMuOUiAd?WT2ml z$HQ&w4W;H4OyDN6>>45IZy@*11Q@P&1g+na)+z8*qHX;SDP~W|nu7n60`Lz`=<;0) z&!q70A^eaOn#YjVA3@&jG(`3aN3?7BdMpV3U}kc`4U}{c3^~pAGW| zNZyO^VP2KafG3&OUqJswGQgv@w)HoV|G}ddWBlJU+7YVqc+N5qG-F4>E%aYm2I_v4 zZeCtbgSb#))0|+#(cxH2z%;~ZH6$__kpiZD6|o0C=OH3M#KChl>n&|X3Cc(d40#cy zX5$eE?9^k!4)Ydxe}X7Zr^Ae|HF6pVJmV7W8T43#M3^3&@fV=q_t+LjIG&W2I`w>& z-vZprlbSRzZUtE^org0Ob)~=04)~O+T;Wv4qZnfXe&{;QN?3N|O`5D+ zfw9={EWi1d42{#2Wy@~7@un=1;}BVX^Ub$pN#TG&SH0GXsZIh{#5QM-1eZ(EecMXC85_J=)JV2XJeBTB;5JECMfw4=XUQymJ%KaRm)FC@y zBf)wMP^xv7jTh^vg;z7EorZ_1?Z6177W{y2gqsy0&jY!s7`sqcwvUVv4;C4DVvilWSY9S%x)6vv^0Q*ei_TvHD>) zZ_CK-7UU8ZC?MBmmhhokJAnBCQU!9mi|#a!(VmHf0_aFoF`6nW*T?WPPIdqT1hI>O zG3`@!V7x}gXe93eJ1{{bypkn1AEt5g2%z~EJjSg=XqgBJ87A>k3{5V)+8^=pHbLbn z{Ig)w1RZt-Dk1p}J9FjhQ0GVmAjJY^fzHfk3)+E&aDy6lWG)uKuF`#|$kE%=E?t5% zE;(~>fv_VRj4oMfywoIzOVLj1HZI7%SJ_WTY_$W``2M0@y;!a#(Y^`88tCKxQNdiK3v4F z5sa)ZlBX-3BXwXU-f>@Q^ioX}isjafD87=Z4CL3TI2s39vauP3MhhQ5!B)3UFZlpA?uQ>A($e42ZDrd7pQNMW~(C%dUuBaLbaH=?ZE6+ZfXu?ZA(q?6%7= zquy3z2cB1|rjLDZx^%@CKz>B3_$Zllhk%(@5 z$cgl?DUIC_&?0VVTtTW4c|+rNQH_kLhQ{Tgt|(pcgienOLS3t}Xj}s7Vvy_daoeXx zLcnAN3mgQq6S&hQ(Z{y5WT(I=5#jPk$L{8OY^K0}`Y z-IB%c@q^CdZ}U4flK!MlkLy7-lHSm`8dM|c4ZVjn(;FH$g681~ku{!UVKu`eF+{R8 ztH^+;fu8hpZ>@6GQjSen*H8?1g)}CfYQTdAtjE>&jA)-92ZZqsHw+IT=%No2^b~5dyOZ(S+Zw<-)6=ko+iikRKC#h>y7LChDT}@du?jhBP{An$}AGF9D z8n=&XMBdQ2cvREO^oGWrqpm2!nm_CGN0?t0jq65TO<6Rq8`X$BR-m-+B=aNR(5IMR z7L6-LHO*OckA?gg5dBrB$3AD*sw^5inO#j;G`1;gME;DH-ve6Y4UKKb8j&~je$dTK zZ|DQekD&&Z$h5bQ`DM}l%rA?^)?Hkkqg3z`K}EUqFDLSAbX5R@p&}=F9#nv+Yb(UW<=6OCG4V zgG0b(K#Eb^|0|F5<1iIJNsKNVEP&m-9F8@*oDI4_2wM$$#tr(I1E=6ckOy&NzI1Wy z`wCUU$LF|jj8_Tq6?S&e51CRtGj%t1h}#E)_d}GoBii53`X@`?){lWOmDP6Ym%VKMPnIna@6D zH2e@S+c+2f(YGwFT@jw5GoU4XotJua33efTonz(EW)UbA0W3pl6YEX{@`% zF2tRG{W<~Lg^HX-rkg|Cjn#PZ2##4z-gdAA*s{yeq?2J7?7nH7XT<1SBMfOd*fn3p z&DEemLK0w4wu2W#*XuTFzLJ4_$PR{~uhG*tE?1u+Ej7kXVF$5}x#>gpJY3L*f+9OO z0rYR_gfTDEON|!nA@Vg7cF+LW2iNb-@DO<)-IaC_rQ--$fE0XKFNjv)VuEk~qpKNm zm>Og9wSyRZZ%SaL;5%MaY6mCdH|PH-iy!U?1gC&(l;N05{a_i$#l?#kdwWsAY0!@y z9xirS#(V7GbV0`QeU99rSw0eMU)Kt&XCMKvv+gOb z!{Fc&Y-eF37T00{b>LD~2HO|lFdWm@kb_ILAWj4iqF)=jFR1Nx zE7QRJ*)V5zgCAjXx@aA}1J|oX9eP7O=y!0DDd<#GR7Bfwju31>yZi!yw}>7yEp}MbYzC`b!BY&=##vacxRwFLxA0IId@BpVBDY~GTMw!!fkke^R5qWXvB+(h z$_6tu7P;aMhQu0IyN98%#`WC8KnHy4VwPu`l&=%z!_6q}@Y0I4Zf|0@^#JxK4q~?s z_j)M4G+E0N7?uB-*_3+MpPwfDTSv zB3p4Yct{t-T-rEI8h~5C!H+BTk^d}Sl9-2=w9<{Y(b3H5gm;S*Q)(yPIRy4S!qz7g z@{l%03B5@kyjQd2h=PHo@wxj1)=z@tvM}bMhD7Z;4jS8aR$P)WLt%2`;7>IsJNf20>fjNLWuBuB{!AnC9JOqkr1TXQIt3zQMmh2*weGW1 z&9PVTMa`1us5NVv%ld_8@j+@76c0fMU(yIq4~px$B%F1HU)C%cZyK|MuWJT;6byH+`<2!M zH?@lSJeKLbzt%836AyvMR+9q_Co~FQ^iXq17koo2hx>V~O1$Y9$B@C_Xcl}>SebVH zt!BU#g~8!d&T4}vH3J@r+DIhUl(*uh)lJDLS7X=#WPQLlvv?FT>+Cl*AD)`Um&ezG zZ)p}>HjBkvq4xKh2hYvo@uuBs7W@yI3m?wn*2PRn@kh;-S3`K_F2Jj>a2+ssN;Bcu zSxLRddRueh+H4bv(aMtyQ~snGaBMO#f9aYztzkH|JlT)n1OxGmmr!4Oi;k@bZ3H_e07T6*Nh`|IuC zS&X>eQ~tqsA;awBJ7&9L<6JiUX$`#7@X`!Gf zn+_qr2J#sYG?wF^=DnB)u%gdL(1+*$aaBZq9}oGi!17@n4Z))(_)Q8n;H`ifxiG^M z47dx)9%P_mZ_Rp}UbBXs8^HYt2)vf-B$n(AWqMWw+Q=w_D8h=VgV9q&rwvBW5M|_K z()K(Bnvs>Ew~?kjhVCWJ7{buIgy!ur7uf^E^hvWKU#ZR72L=X>bMp2-#WgBJY$JRC z!WoZ~jSj=36qXJ$|O1JC2@xe!#M6Syg1BoPI?@7 zL^X_4U|`dM!=QfdDY#18bp{L*)Z{XH4j@Im1AU6G47FYPZGd&Il7qSL?s9vXDB4{S zPr4?XY<7X+j=_8g2@0FE0eiq)YE;Ey4e^!zVdH|??Jj-ayu=>Da z?xxXA&iz!A6_OeF2;d5{2yBLpr}3ICf%JOSg}xJVYMb=3--QlB-yrB|Lb(b1*xGm) zhy#2Ki_8_!|9vRqnl1%bu+W^Jz91qcCj&1IqB?HHu)#Vf>Kk~gbhNpFDdTEP72Z2=RU!(F;_5oYG*zCstA8o`T z!SuzkpuzgZ4sH?}-~|yvdm#YeGg~fx1UTc?rJb~Iv)1^c3%XmM20sdXA@1JeU@_RE zMUPQ$E_57FLoRdzP-QN35)js%cx0DFzEf*^OM}t^8T6D!O{tCOX;)Mi$Dn77s4UzK zc2;AHQu++Xpgk{3{@eu4)`ZxiD!G%V z4~Fuw(%XTyU)`j;9%xW<^(Jo`3FvJ7v+Y-Dt>2e+y zj;XYKY;vs~h0#SoU1u)#q!E-VbHM{zP+nwZ(jF8@N4z374kM9Z47_vk7l2n(m?Gb( ztKq0%Sw%MZF~KuMHt=zQx$bx$>x9;hCu!ctI;mOudByyjQ0l38Kcj%A)CN0c1a+wm zcv?VH6oZ}7iKQkCbQVxUtts7dUAms5#N-@`jbPBNg1U`xGxw_DJVzxG3)=Yx*e(FJ z)Lo!gk{LUU&`!bTiya2qrL}wA*G;|~ctsO_iv)(;f-1PmitGX8j#K#vkJm0n)+x5pl-;<$v;I{TNLSHBORQ!T_xC?K< zKNGfq_f6r+3*SZdS)s#vzjs?HHXT}QzHEN%-pdfidM-;+&RJ!uo*yNK{Eqb1~T#dADg z$2kMGd1bpWbT{iKFM<~mVb;sVzJk{#CA#qZdM^A`7lt~dUU+q0*TD1g?9j(hSufia(RMMn$L9OyyCjOhmW9*?8eVVTW>c6SSQ^7C zVn`#^V}KGow9}Lg$SIDy)$1lJWw3&5ka#ewj2iVlc~^Rtu3+rO@nLaqaJ; z;9ghSAwxDhof6NG<_})A3N1TGF4QLXsN~+G3w4^NM`A&i1I(N_hZKa znpBS+`V_U|D3gje+x$%clJcu!m)N0QnuPx)*WvgcNm?Y7oqYQ)?o;5BHRao6Fg+bdrCq63&_`a z(t)ibkdK2rWZovTC{o2sB`^x@*AVuHz~HsUol>#kT;rO+j!jx-MVtiAR+IV;>Izz zicnQPR5^EzLCSF-Dgr|jJpxlz1*o5E%E3aFYm^Z8ioq@5b`;28XcDh%NjBq^?%Y?c z;3hK>miKH!0Z}JM=0{KV{Pa8!*dN zceEtwFc$And|>JfhZ!B5JqjE!xR4X$Eh1{VZvjzdTI~- z);J(58UBA#lLdI;A6_V&vEX;md@t%rNl|Gtw)fyc*h;^O^!BevL3ywi z!e;61pTe6>@jxdgnZ`>*4tj6WU zLUg&6@~&pcd4&k4T+Vx%BS#jfkvjRgLHhB4X6W;ZOWZJ$pjy{G#*m@E(T*7w@>Xr=CW3SNUR-m?skdTO@+u0Bi0>1lE?h; zls)&$Wr(sTBDDJuFNky8?fxc(B<_)C?bbgJ`ej3N$g8*Q%h@yR`gBL#QkmON*!Gu| z+B6i;8oXbIg@wGFoycooeT+OG{oBv% z4Eq~+u<=rP8>W6hU%zYJwx85b)#H*oq8@qA(t;!(;o>$>HrsTu)Z$oocH8tJp(XC-Y`5uJp)XLEV{pCdN~Kojwc7UgmD>EYS%yIC z4@k0Z#Rk1P0elGX&jOL2o*umNQ9IYOfKCX+7a95v+4c{CoCdPBN05Bm{t?0kD-hWO zL@U%UkFooK7X$y8mb}8YpF?RL3Pkn;(UNYgW5Ykl`5HOZxWdXtJgl*=d(tlB1>mSsED(9plXhQ?V`Dlc=Ue1>i)0&9D$xU;e1;|SY9R6*vbg+FUSq{~*5OH= zB!6K6dJ$V#f4~6kJO8JrY#U+4mW%bmU49(Rwh>co;XI;2({D}yoNl2jVdW?* zjskwrg}uwF_J11I4wt3(cI`I}zSG6wK!){}Vf~ZKGNFxaBeIcvK858)I!S_j?OmV7u)wyiYcS1#$fpOt__6B|!?K3L43$1*Y(el7+=*-GhDnd31tuE=Ks{@5;*-T?TI9wM2uk02M7kG$A!N&R z=?MDH=yeKi%uS%N(YT<3y1L}6RM%2y^3z)M~QdrQu@2!(xqqFZY9Xl>vG(t%MnszT-$BuBWSNz(YAT5K9r+LsgGZ7 z9H&_)W=cVezC1eyp@@sk5wggY%v!6=p;U!F^LRs)*D$Q4U8{_so!=ju)?L3#L6 zqgD7l7{GB2_j^Ad^zk|3dpa1z2>J2r4UL|KFwprZ>heqHwXaISpHdRHqk=mi_mlG% z&ugq-T2V8

fI5hQ{)WhUy#9a#?WolIjMG6&bmTy7}b|^OZjvTDoM({E7yZmxYz% z$KY!lFz_JXn7mvCc_x(Fwvs~fv+&4riOEdU)wSi7m32BdjTqaq^VE!`wGGuvm(=Sl zHB@1&ure9c&tFoh0vWol;zkuzHkSCSx>7p$mjSNGcGfF(4=&os+NK&WsOK8X=_bf= zN8{}LKsTUOu{y#QgGlQQ1Lt<2*gOn6%kYEDoRJ+2(?s$i*MS#sG|9;UhAgl)f`#!F zXB3H!4lF_0(==z3<`l>f{t)s%U)nNHU97FHM;pfU%YgjLZD%X=T#atXEj8zEq=oCs za{(Yfh8Dh2?36UJLj_Za%E#D?9g*|Rci zZ_;-j(7d_M4PCJ$C!YsdYV;Q5>ATT(c97(Ascxm+yJ!?RoxXgp*7TY+tL`S-&Zm{S zuM#S-TkP!8btN4aW&eyW6rNFNi(@ZEniGv-+Dv1$#!3EJ;{{k}!KdUQ8D}>z**>F; zRJ_Z1SaU`=3o3H(&uU!1gv))!tn-LQ&xe(4gFPV8z$IQqd`?#c*Y>Q4&+CfV>*sES z+CAQO_9?ZUqqc9G?L4Ye>q#9ymL<<)xF}vUw|Z5&A;xzOI{%_2F}bgA*Gp9wD&PrN zv@PEJJ`VlF*XgCjPoPXo)5G}M1vj-g$wH6BPoN-A-k@NdkOZJ4&0M28Yc?AM7A zC19nMei*I0Ui?_sMxag&C&$_H@GOTHXc{mlq&mtk}OQr{9ScxfYbqo)n zV;Vy?-_XW!Vgt&y<_~&g7>iJOd0|hkmUTJOBO5^a3Ty{EDBQSNZr=Ooe3Kr)S4SeS z-5vsQjf|4{c&NTd`|po$o{cB4#!hk@T}leX`1FSf3D2 zGxNg_O|CQoozalUa+K3a1Rl9nyUakllR@BnH9Ff2@xkUd~9NMLd|Lqci`N0Bl=9mTNynJF|KCEG{K2PaEPF=6%0w2YfDRV5!I zLOFf|%-_Wv0k)4oKb%g$0kLO@!{PG)z6=0cFJKbXJaPUVn14g2*%KLZ-vsL-SxYc% zl2x_RZ-E7`&dHM-WxdC0d{e1on3|lt_Dl)SC zgM38skD&1l>&a^`W2gDvG#_LxfQ8RNPhNW++t<%xeFLF5|55sF2)PvcM{vXstn@oz zje>RVN7(;;yeFS~_2sv)eKsEdt;OGk^klgD(kFfle)q6tUj%y!>>EG9#@Z$!-{X`O zdH-rQmiL}wzt3?J=2^dh?Y*VzVRy?x>ga5d(-hgA9vg)}BzD;E7?nLRN{xaUqIymc zY5OOcU9LVuruH7-GBR%|mtfsA;``%kw*(O0T>e=jldt9>NgzK!&-%V_^|^ec4#*ER zGWA6-ObhRo+W}oRf%2i&jvc^$gs4u2tEXnXU^Fk$!UclTw~U4PU{ZrW)>|D6|!k?Hts|#S)fn5OhnrBh~{4X7F`mYQKg97N!fL=jnpEYXR zwzpyAhf=tq)UygY3D8YH3cH`JfaEzaWbC3JKB5kQ|3Do&cN*(#9Mj12SYInY8xbwg z;8B9>GTXoj>GV&N!*(6u9TOG0xd+%M$Yy)DD<4+J3lFIKo=3XNc*i zPP(ee>I7M4M{CPFCp>Z1=S|m0z9HP!E;Hn??DJ%=>&K017Vsv4)^yJ}Ucuu0i4AbU z1n~41=_FqyKaJOF^`5R#!@fi|`c|(94F59u(p|RfPYtEtP^#G*bcZam?c#o zx$1|~&wMt>H3HJe$@tMi;wBtm0kJ%%A}V zxhSzI$YlrMEEByMg7=53 zulz_e2kAi*T|jrmaP?Kg#4D5JVmXA1u-6Q?W2|5EZ_)hghTqjQr1`gM{^VO)b^9jG z=7Sg193;DAuva^{Mi*fb?~!ozA#fppud`dulay=6>pUqoH+WB5V2XhL^wiFLI7?;L4JowXZPMT z-k9O7Rc5m+_&EUwhxNl6r(!JfJQ15fS%HaSLXwGjA&8h)?kx6V5VJQA6YeEqy18I1 zFHITI8SrI-{3dGiP(Qx*9IaGb>8n0z+2#Qk$YNN*ap|wUsz)w9a=S*35s`s{5B;2m zP7v}23O-z=;TH(w#T5ej-Gk^7jhrOHIdDD;o1DjUCk;7eA(QQR68-S6!#l&Wy`8*R zCI*~&DWH!0rD#+Sg{#ke<<(p7!sF~xJR7|}gY@b5RiYaa6}q*{UHz!y`Z+W>t8qx6ryo(~}h z`b1#6f{!X%*$cA-x(2Z2qg1mFZQG&Cvn0GR%Kcj4NeZ-dJiwlMOfL#YcjzpfA|(7S z%#dbLJLEP6`#QD25elqtY3>563nqUiTzypH8=q)nvLBGe%j)yjK9hnQD0H+x2=0S2 z8B=}r;8DYEZUOfpnQE)P@?mgWx^}d8bdT`OtmsbYJ&u%q>}U%837T{C7j)#8J_$)= zSI;P4L5}_+xGW2DIfszO76cm`aaGy85)fqeL)J&AL7Nb7^K1C`EVO=#Vz&j0mH;U?hwkoB<4L z;4Fa@-uq!jjcDFE^42}tFOD10QO$eqXRx z^kTk-ED1tyAI#T~E}q5R7KnQD4*G1-7K`EXy2=#?-yFXw==a6YJcS`;Pwkw%shMm z^gdt9M=^*%m*$!AF?NZc@#%M?k)oY@_^-VP`VS0UFfoFyB6^3?ZcddpB2T_lu%oMO z>v|P^KLV8AG?sI7Sl)24xROc_z|$OkWTdQBspoDjAI)^*Z75Z?p87CxXc$RVwm}qO zei6#tuIA1yZby4_%lb{*+gsP~P-Pnt;On01LAsfDlp$}P`*C?s2H(h2WztPjWlGcN z0y&3SSkC?jU3?jOI$75%A4?BqWFoAL-5H#EE6PW@u|0p;ZnU!FSavHoJUD0b$oXXdjQD6_5ZRouzplMh)8joh*E5#`))cPElT)?P(j6{?)ik_dMEV$6eCcu_8gCm(ZE=`5SEvP3Q1cqE&Yx;>5-?nDG;#ev@)3`?b|5*X zm)DeozUbM%2pzs6tRdWUJl3THl9J=0K*8#yB$1Rlujt5=v@DpaP`B~E^Agsln{--| zIxRc>wAAagTtA@G(xB5qV0)o7wZVUZ<&fhvWcW1b;5PT{{Z2SkQFw1z13u<9thg)Z^ZPZcB7)}m z{1fw-8x0wG3@u;8%Aw(f4H-Oyc0x}%9@q*CHFr@%29Kb^#WRzYt!&6(9~+ADo@EqN zHR$Dow(VP0`R%MITE$Ys=MrDJJZxzGGQ)pBfGR)03Ii}=hPlIs>J3Co2_eNcnpy+F zFe24H(wJl~t{mub9%Jq-e=Rwj>&PWLP+1{|83Qoyxte6(zr7FTzSJ_8pAjaud{NGw z9`h`8t1l^Zi3P7=XHpe9QlTnqE7a{3sj*zPdoKoFu}&2q&E(?P$M?~A&-ma_Z#cZ`@$6VC-kTnoh_8E~t-Uplhuds6hpqc+YGd_vCTxEy zRZ|~J#*#JtLxVk{XH{)OqM<8Un{23&NHX+4KomoRBjXb~SPg>3ajK2m9;j;WtV+fb zt6~kcvD#Q7sU{s~zH?_}K{OP(Ei&J^*{LW(dTv#r$or!2kG3s9vX-i7^giII4vy2d zzyUA3M71r5N8#wIL8Xf4K}x9ze;BG{ffI^EqfioNfYO_^#&Fw$Moe^JJ(ogdHXiIF z=gCJYUvA`~i}LdtM84t{hv59MP&eO#{9mvDidUB@wa||t8oeo67G=0w@P(v+6}K*f zaOF*K*Mx96ZPV%(-D1-9Zm}ZFq%)%T7%^kTZIbG+Qk5cBWW^SHp(L%hn^ZwL9yNfK zN2yV;s(0lXw8Xc=H~Nm7Bze_7rqogi=c&097z;?ExQp^k?cEZWm*>l1he@PT_XtLl z#g2Q$WRF}fDMQJxh&gM@wCaznjkGObjaXa6yuhm{Hp&9T6|2u9<6gKZ!ug?UJw8nJ z*%;H>3Pxo~qYU{>65m4+!wrdTDy{IEG8T11kih`TnXf8}sGhYLwHalEBQzzA^9zN} z+o(?%)S!_noKAcsoii=0W}v$-8&6Mgr)te|+3LVTlVxL*#@RDC5|72=Xmo5y@%%<6 zEiyhhk{TLE|MI`q4ZY|S-1>=$4IL7h(G>6D=fVEp)cyZyif8x3F59h19(8nVZEkVL zMn`jf*_u@~`v%hKU)nDsnapr^Dn6FukBaApGhXJ^uWYE%Atcp!+U*{SPozgiF=nhu z##W-AOW0hEkBno{2IKhug9i9AU~50c;Zi@QPcV3mrC3XF6UBmmY=AX`Z;)kii9Q`= zJvfTXkk7@96T+A((Cjq2d0e5crTOL!rV2E*BeyYwyP_tnMzk$^S&U1JvVr4@3QaVa zKMn*$CtJW_f9OPkGZ4CK^{)7m(DP5^9&TC}zi;pO;K2C6eS4eM3^d($Unt(UFVQsq zM@>)jZ_C4x_=}-is_s}a9Qyo$+#~U(ruN91y@@UTy9XjKH4O}YqrZRPlhghE`}zm> zelp&4XH#frRcP5}2={$BzNTqwWX*H!TlO~HxodaRlA444yLUAWEUEcH&Cf?_@q3V$ zyO-2FylWs5KRn*QtN;7=f&D8>YJRxl7w%Z`i@SFJ^8LG>9*Eqr>+rzSPjA^48Q2oq z91Au6R#QO)EfCp#nwhKact@L5!J8(_Mbckc8%jD$-f@H$RlS3^2 z7dYB>+_7%p0QGot855&0a#DPnYQ)c;*7Dl+r=9uDPqf~|0glCvDm=f>jqwT0xjGBO z#4dI6K`C^kwS3wMDg{)faXzgSp9fyh^>pYr!(S}$BF0cUmsa}IdrGFCW#2o_yJvp)h;j%eFX>Riety=6A_{Aa=J1OuoxU ztL*38mCSyMY4lL!rf9}G-MVELPnm$r{?dbZYm{D04|J~I;kLLf+gsNw{SvsDe>FeI zfK*yk8ZSDrQSwT-Sg+2&L5dlxQtVrv*6ud48lE#4|gG@G`RE zN{OCSB|EU{AWLEro2s2sLys)rzy!`Hjv4Bft zEqYB2OJ%aCNQ1cd>fW@JgYnZfE=qoZ;Z??QU2l}mOuE@<-wu4No2KiiTcFq5ep>0> ztn`wMf@`aGdef5I;XkgtnhW=Z?jf<#7E2v7Bj^e&dIL3FY~~ca8X6tV7>nTym`(R0 z=Q9webN+^2)!f>m*BMM(lH#e=)t`R;*6CBp#J#R&y^8M_AhRdfig^?&hx7lqxhQS`(1D!G7X_`HH$)Ua%DJdT@vB0w<%@z=p)(?i z9~C-}_l2g>vEf1$?^K~rkgx|B3R?=%1nw+UoTD&0b6lu-wG?L0u8&xD|8TCmM{!a} z{|?wI+&}SzqGI?8Upm&juB`^{*ecdPG9H7|>wt>&?jJ#5{R>YBK~NK=4F?Gq7$)<& z8Ngg+;EXKOL@Ji!mqcTIm@@)4+Dq@iSbD(igWpWr9l(1Z9;IUZmTeXh>YqnajC2&A zd#2{@;lUIxBs`c%P!D|FWAYCR2g7U}v0l2ZxZUVM`!PRg$jo>TCl)dH%|H(4oN|8@kV73@q?P2xp1%q?06aMdpK>{aVha0AYcxQy#?A{J`RA<7 zm-}`Vism?Y_OR*L0!APm7ylgex2#YAn~!VuBj)(tZzCAjE$m@+@R$9OIWAwqR2I{5 zC(boEXy1x}V z%y7D26`Jh^wDg_SS8V8m`~@v_1o%^iW*Q(beI9X6#DHesCi1)wfR;XtINJp2Y5szi z`%#7NlSr4751Mt3G^ePQ?q`H%zLB2cFL0I#=`)7D+0bVVjY%uP(FcgUv>&wN%ZBFk zA;L?WroLM>Ep3Rj_&DfxD&Zwvm^Max6q+kEv1pXGEpaTDLmp!Wpmznm5S z*Fj7EoA|#A`Zda%_^(u`Wv2|y`ol4S96COyjMM&La4G`!IP+oeRnVNjhrQ0bfwMl5 zCcXqT>yxGL!L=MlAD6{~bPMW>&{!!&eR6ieKFMz+5b1OtnMHpPwB$eJ7Xtrqg<3ob z1&zpTl$UeF*4HX+-_y{K_E<0}m0dX}A-@OmJB|FSpxIvQ4Sg0%66Zj-8u~owAe=xBJJWQL9fs>jjlWddaa>RpDNoy*BW{e=!Zd98G0$`8PE|!V>x8;+5o;9 zbS-EbeiLY>f3=Z+(5zgR8M+U62XJF=!5Cunk7X$h~1^L22_@_Z% z2ffh9zli)qxu`-^UbOdu-viG4vgw@xJp?L(PUw3I(6rGv z41HHY8~Z|!+5Q)J8T5S!_A)rXa3?S{Bz|0NnW6S;eJ>6b;z#~Bna3CBQZK%4Z2 z-v^rUQy=m#yutP_71FM5A8^~Bg^vSY1lp8e`1gTN2IwyWzXp1d(f`+=Ujc3H`4-|^2->Fq+X#Odw6*6) zkUs|6<==&;gmZ!%w?N-Q;H;lGid}@K zys^LdQP3-U!;~V%pQF?T_&O$ojC!(3=rI?Kk#Cb|5`Vksl^KkpbY$4~wII zRpvlPOnB6<#ZQ4Y{aNG_2)_dK9^g14zXd#ki!vksIndB=^E2`V$k&4&F!HZM|Kp%- zde9!1p95|3CvpM!lORobL@on=1vKr$cq;NU;5$K^`chH~d^PH`(O>c&-~+%-`IX!S zds;yo`%99*uLbD)KwkpALfc=m8S=E((il%vPJ>=%@E*`7L7Va^8G-z1&^rzOIBaLpna}`{PGv35m@T_{_-G^{%G!7k}rYb9;^(kUAwWpZC#6-jMe&*iF!!- z;p&1^Vx@B7Y?Ky_@Aah;D}z$W22zykN6d*;fiQ`{b%QU1Qj!=cp9G&)%XN^SpjMZ@ zNNy@S?#gt#FKMjNF-rV8C%g}AWFQBa8&-Ydy*7+Q z&<**9nnR>TD5tvi_J{%-4ZN<4RvR;n8=^QanyB3hI)I3 zTzDOi)0hdkaR@L3M%WMVw= zbk5DlPN`U`@Dl|SI$N9Fbje!cc(pW=hJ>T@8bgkN$&hZm|_=;PmhKOt2n#lF3z|bjFA` zrk^wQfyy@27pP5vP6}zZvFz(cZ>X!JUp&l4YZG3*lxtmUn5EfKSHD-_DM{h=DXf)y zS)b&6!s}|-;Rdi(stpXUWqWnd5&2lKZ$lErYRfK=3)+cvE+^|@zMO-b zP zWI%;qiI_PF7QKX$tn%(1VhZn5o<^xM)*IMGmp?H+lI`v59Yj{Nw77M+Z|N#zoO8X@ z*)|~&u%|$~=3;-HZPvDO*owlq6UY)5Z}q}gWu$kom$`vR=y8Xnc%_WQ%U#!FG}5mM zP7`^>Rksal)ii0*x8W1>-S2Pq^|+A zcbmRUmj{w0tIn?5KQY0^lpP(x%MZEz?%vw9Yg=~i#L~H&h}9|UuWfv>eKSozE&0tJ SL*B*kErjK|5!v*jZ~Jdbg;C!C literal 66458 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 diff --git a/src/triggerSync/triggerSync.c b/src/triggerSync/triggerSync.c index 7372bbb..a3a0519 100644 --- a/src/triggerSync/triggerSync.c +++ b/src/triggerSync/triggerSync.c @@ -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); diff --git a/src/usrServo/Readme.md b/src/usrServo/Readme.md new file mode 100644 index 0000000..7c8dcd7 --- /dev/null +++ b/src/usrServo/Readme.md @@ -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] + + +```