#!/usr/bin/env python
"""
configure and run White Rabbit Pulse Generator on uut
./load_wrpg_stl.py --stl=file uut
WRTD: White Rabbit Trigger Distribution
WRTT: White Rabbit Time Trigger.
WRPG: White Rabbit Pulse Generator
Ext-Trg -> WRTD -> WRTT -> WRPG
WRTD detects an external trigger input, snaps the TAI time, broadcasts a WRTD message for a short time in the future (50ms).
When the specified TAI time is reached, all ACQ2106 units issue pulse WRTT
We set up the WRPG to trigger on the WRTT
Full sequence:
1. Activate package 99-custom_wrpg
On the UUT ::
mv /mnt/packages.opt/99-custom_wrpg* /mnt/packages
sync;sync;reboot
2. A standard ACQ2106_WR box boots with WRTD running
We typically connect a 2Hz signal to the WRTD INPUT port.
Check it's running: 2Hz count on TRG.d0
3. Actually, a free-running trigger is NOT helpful, stop it
If you have active control of the WRTD INPUT, stop the signal
Else, it's easy to stop the WRTTD output by stopping the wrtd rx process ::
nc localhost 4280
^T
^X
Check that the 2Hz clock on TRG.d0 stops.
4. Configure a transient capture to trigger on TRG.d0
From cs-studio:
Capture|Transient [DEFAULT POST] [setMode] ARM
The ADC sits in ARM mode.
Or use an external client program. Ensure that
UUT:1:TRG=enable UUT:1:TRG:DX=d0 UUT:1:TRG:SENSE=rising
Set a waterfall display:
/usr/local/epics/scripts/set.AI.waterfall
5. Configure the GPG to use TRG.d0
ACQ400GPG.OPI | set GPG_TRG
Or use an external client program. Ensure that
UUT:0:GPG_TRG=enable UUT:0:GPG_TRG:DX=d0 UUT:0:GPG_TRG:SENSE=rising
6. Load the STL, using this program
./load_wrpg_stl.py --stl=STL/ramp_1step_64samp.stl uut
7. Enable the WRTD INPUT.
^X again on the 4280 session will allow the WRTT signal to restart.
Both the GPG and the ADC will trigger on the next WRTT, and at the end of the shot you should see the preprogrammed pulse train.
Limits:
1. Number of DO lines: 32 (Single DIO482 in Site 6)
2. Time resolution: 1usec (clocks on WR 1MHz)
3. Maximum number of states: 512
4. Maximum delay per state: 2^24 = 16s
5. Maximum theoretical delay: > 8192s with 1usec resolution.
In practise, we don't expect delays > 600s.
"""
import acq400_hapi
import argparse
import sys
[docs]def load_stl_file(uut, stl_file):
with open(stl_file, 'r') as fp:
uut.load_wrpg(fp.read(), uut.s0.trace)
[docs]class SendsWrtd:
[docs] def __init__(self, uut):
self.uut = uut
def __call__(self):
self.uut.s0.wrtd_tx_immediate='1'
[docs]class EnablesWrtt:
[docs] def __init__ (self, uut):
self.uut = uut
def __call__ (self):
self.uut.s0.SIG_SRC_TRG_0 = 'WRTT0'
[docs]def tee_shots(args, uut, shot):
uut.s1.shot = shot
uut.s0.SIG_SRC_TRG_0 = 'NONE' # gate external trigger OFF
uut.s0.GPG_TRG = 'external'
uut.s0.GPG_TRG_DX = 'd0'
uut.s0.GPG_TRG_SENSE = 'rising'
uut.s0.transient= 'POST=100000'
uut.s1.TRG = 'enable'
uut.s1.TRG_DX = 'd0'
uut.s1.TRG_SENSE = 'rising'
[docs]def run_wrpg(args):
uut = acq400_hapi.acq400.Acq400(args.uut[0])
if args.shots > 0:
shot = 0
tee_shots(args, uut, shot)
shot_controller = acq400_hapi.ShotController([uut])
while shot < args.shots:
load_stl_file(uut, args.stl)
rt = SendsWrtd(uut) if args.trg == 'WrtdImmediate' else EnablesWrtt(uut)
shot_controller.run_shot(remote_trigger=rt)
shot = shot + 1
else:
load_stl_file(uut, args.stl)
[docs]def get_parser():
parser = argparse.ArgumentParser(description="Load WR STL")
parser.add_argument('--stl', default='none', type=str, help='stl file')
parser.add_argument('--trg', default='"WrtdImmediate', help="shot trigger: WrtdImmediate or WRTT")
parser.add_argument('--shots', default=0, type=int, help='run a series of shots, with immediate trigger')
parser.add_argument('uut', nargs=1, help="uut")
return parser
# execution starts here
if __name__ == '__main__':
run_wrpg(get_parser().parse_args())