#!/usr/bin/python
import argparse
import subprocess
import os
import sys
import time
import glob
import shutil
import acq400_hapi
[docs]class Struct(object):
[docs]    def __init__(self, **kwds):
        self.__dict__.update(kwds)  
uut_port_map = {}
[docs]def map_uuts():
    ids = subprocess.check_output(["get-ident-all"]).split('\n')
    uut_port_map = {}
    maps = [ id.split(' ') for id in ids ]
    for map in maps:
        if len(map) == 4 and map[2].startswith('acq2106'):
            s = Struct(uut=map[2], lport=map[1], rport=map[3])
            uut_port_map[s.uut] = s
    return uut_port_map 
UUTS = []
[docs]def make_fifos(args):
    args.fifos = []
    for uut in args.uutnames:
        fn = "/tmp/{}.hts".format(uut)
        try:
            os.mkfifo(fn)
        except OSError as e:
            if e.errno != 17:
                sys.exit("ERROR OSError, {}", e)
        args.fifos.append(fn) 
scmd = ('python', '-u', './user_apps/acq400/sync_role.py')
[docs]def set_sync_roles(args):
    print("set_sync_roles")
    # --toprole=master,fptrg --fclk=10M --enable_trigger=1 $UUTS
    cmd = []
    cmd.extend(scmd)
    toprole = 'master'
    if args.etrg == 1:
        toprole += ',fptrg'
    cmd.append('--toprole={}'.format(toprole))
    cmd.append('--fclk={}'.format(args.fclk))
    for uut in args.uutnames:
        cmd.append(uut)
    print(cmd)
    subprocess.check_call(cmd) 
time0 = 0
[docs]def wait_for_state(args, state, timeout=0):
    global time0
    if time0 == 0:
        time0 = time.time()
    for uut in UUTS:
        olds = ""
        finished = False
        dots = 0
        pollcat = 0
        while not finished:
            st = uut.s0.CONTINUOUS_STATE.split(' ')[1]
            finished = st == state
            news = "polling {}:{} {} waiting for {}".format(uut.uut, st, 'DONE' if finished else '', state)
            if news != olds:
                sys.stdout.write("\n{:06.2f}: {}".format(time.time() - time0, news))
                olds = news
            else:
                sys.stdout.write('.')
                dots += 1
                if dots >= 20:
                    dots = 0
                    olds = ""
            if not finished:
                if timeout and (time.time() - time0) > timeout:
                    sys.exit("\ntimeout waiting for {}".format(news))
                time.sleep(1)
            pollcat += 1
    print("") 
[docs]def release_the_trigger(args):
    print("RELEASE the trigger REMOVEME when hardware fixed")
    cmd = []
    cmd.extend(scmd)
    cmd.append('--enable_trigger=1')
    cmd.append(args.uutnames[0])
    print(cmd)
    subprocess.check_call(cmd) 
[docs]def init_shot(args):
    global UUTS
    global uut_port_map
    if args.run_hts:
        uut_port_map = map_uuts()
        make_fifos(args)
    UUTS = [acq400_hapi.Acq400(u) for u in args.uutnames]
    for uut in UUTS:
        uut.s0.transient = "SOFT_TRIGGER=0"
    if acq400_hapi.intSI_cvt(args.fclk) > 40000000:
        print("fclk > 40M, setting 2x4 mode")
        for uut in UUTS:
            uut.s0.stack_480 = '2x4'
    set_sync_roles(args) 
def _store_shot(shot):
    print("store_shot {}".format(shot))
    src = os.getenv('HTSDATA')
    srcports = glob.glob('{}/*'.format(src))
    base = os.getenv('HTSARCHIVE', os.path.dirname(src))
    shotbase = "{}/SHOTS/{:08d}".format(base, shot)
    print("copy from {} to {}".format(src, shotbase))
    try:
        os.makedirs(shotbase)
#OSError: [Errno 17] File exists: '/mnt/datastream/SHOTS/00000144'
    except OSError as e:
        if e.errno == 17:
            sys.exit("WARNING: {}\nrefusing to overwrite duplicate shot, please backup by hand".format(e))
        else:
            sys.exit("ERROR OSError, {}", e)
    for sp in srcports:
        cmd = [ 'sudo', 'mv', sp, shotbase]
        subprocess.check_call(cmd)
    cmd = [ 'du', '-sh', shotbase]
    subprocess.check_call(cmd)
[docs]def store_shot(args):
    wait_for_state(args, 'IDLE')
    shot = [ u.s1.shot for u in UUTS]
    s0 = shot[0]
    for ii, s1 in enumerate(shot[1:]):
        if s0 != s1:
            print("WARNING: uut {} shot {} does not equal master {}".format(UUTS[ii].uut, s1, s0))
    _store_shot(int(shot[0])) 
[docs]def run_hts(args):
    cmd = ['mate-terminal']
    tabdef = '--window-with-profile=Default'
    for ii, uut in enumerate(args.uutnames):
        ports = uut_port_map[uut]
        cmd.append(tabdef)
        cmd.append('--title={}'.format(uut))
        cmd.append('--command=run-hts {} {} {} {}'.\
                   
format(uut, ports.lport, args.secs, ports.rport))
        tabdef = '--tab-with-profile=Default'
        cmd.append(tabdef)
        cmd.append('--title={}.hts'.format(uut))
        cmd.append('--command=cat {}'.format(args.fifos[ii]))
    print(cmd)
    subprocess.check_call(cmd) 
def _run_mgt_cmd(args, blocks):
    cmd = ['mate-terminal']
    tabdef = '--window-with-profile=Default'
    for ii, uut in enumerate(args.uutnames):
        spawned_cmd = "python -u ./user_apps/acq2106/mgtdramshot.py --captureblocks={} {}".format(blocks, uut)
        cmd.append(tabdef)
        cmd.append('--title={}'.format(uut))
        # spawned_cmd = 'powershell pwd'
        cmd.append('--command={}'.format(spawned_cmd))
        tabdef = '--tab-with-profile=Default'
    print(cmd)
    # subprocess.check_call(cmd)
    subprocess.Popen(cmd) # Popen runs asynchronously. 
[docs]def run_mgt_command(args):
    global UUTS
    BLOCKSZ = 0x400000
    nchan = int(UUTS[0].s0.NCHAN)
    mbps = nchan * acq400_hapi.intSI_cvt(args.fclk) * 2
    blocks = mbps * int(args.secs) / BLOCKSZ
    _run_mgt_cmd(args, blocks) 
# sudo mv /mnt/datastream/ACQ400DATA/* /mnt/datastream/SHOT_0134/
[docs]def run_shot(args):
    if args.run_hts:
        run_hts(args)
    else:
        run_mgt_command(args)
    wait_for_state(args, 'ARM', timeout=45)
    if args.etrg == 1:
        release_the_trigger(args)
    if args.store == 1:
        store_shot(args) 
[docs]def run_main(args):
    init_shot(args)
    run_shot(args) 
[docs]def get_parser():
    parser = argparse.ArgumentParser(description='Run HTS on mulitple UUTs')
    parser.add_argument('--secs', default=100, help='seconds to run')
    parser.add_argument('--etrg', type=int, default=0, help='1: enable external trg')
    parser.add_argument('--fclk', type=str, default='10M', help='sample clock before decimation')
    parser.add_argument('--store', type=int, default=0, help='1: store shot after capture')
    parser.add_argument('--run_hts', type=int, default=1, help='1: run the hts-helper, 0: do not run')
    parser.add_argument('uutnames', nargs='+', help='uut')
    return parser 
# execution starts here
if __name__ == '__main__':
    run_main(get_parser().parse_args())