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 c04b8cf..4c1e861 100755 Binary files a/src/triggerSync/triggerSync and b/src/triggerSync/triggerSync differ 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] + + +```