#! /usr/bin/env python

import sys, os, os.path
import time

import numpy as np

import dice.testbench.motor as dtm
import dice.testbench.utils.grid as dtug
import dice.testbench.multimeter.keithley6514 as multi

# --------- Parse command line arguments ------------------

def usage():
    print >>sys.stderr, \
        'usage: simple-beam-map z=<z>'
    print >>sys.stderr, \
        "                    [xmin=<xmin> xmax=<xmax> ymin=<ymin> ymax=<ymax>]"
    print >>sys.stderr, \
        "                    [dx=<dx> dy=<dy>]"
    

# print sys.argv

if len(sys.argv) < 1:
    usage()
    sys.exit(1)


phd = "NIST"
phd_port = "/dev/ttyS3"
keithley_range = '20e-12'
#keithley_range = '20e-11'
#keithley_range = '2e-6'
z = -1590. # mm
samples = 100
time_sleep = 3.0
ref_period = 20
# xmin =     0. # mm
# xmax =   300. # mm
# ymin =     0. # mm
# ymax =   300. # mm
# zmin = -1593. # mm
# zmax =     0. # mm

#sndice1 - led 23 ???
#xmin = 155. # mm
#xmax = 255. # mm
#ymin = 72.5 # mm
#ymax = 172.5 # mm
#sndice1 - led 23
#xmin = 105. # mm
#xmax = 205. # mm
#ymin = 122.5 # mm
#ymax = 222.5 # mm

#snide1 - led 07
#xmin = 90. # mm
#xmax = 190. # mm
#ymin = 70. # mm
#ymax = 170. # mm

#new_leds - led 28
#xmin = 100. # mm
#xmax = 300. # mm
#ymin = 0. # mm
#ymax = 200. # mm

xmin = 0. # mm
xmax = 305. # mm
ymin = 0. # mm
ymax = 305. # mm


dx = 20. # mm
dy = 20. # mm
#dx = 10. # mm
#dy = 10. # mm
#dx = 5. # mm
#dy = 5. # mm

for arg in sys.argv[1:]:
    if '=' not in arg:
        print >>sys.stderr, "error: invalid argument [%s]" % arg
        usage()
        sys.exit(2)
    eqparts = arg.split('=')
    if len(eqparts) != 2:
        print >>sys.stderr, "error: invalid argument format [%s]" % arg
        usage()
        sys.exit(3)
    
    param = eqparts[0].lower()
    if param not in ['led', 'z', 'current',
                     'xmin', 'xmax', 'ymin', 'ymax',
                     'dx', 'dy', 'time_sleep', 'keithley_range','ref_period','xref','yref'
                     ]:
        print >>sys.stderr, "error: invalid parameter [%s]" % arg
        usage()
        sys.exit(4)

    exec(arg)
    # print arg, param, eval(param)


xref = xmin + (xmax-xmin)/2
yref = ymin + (ymax-ymin)/2


# --------- Init testbench motors -------------------------

B = dtm.Bench()
B.open()
B.setup()

# ---------------------------------------------------------

# --------- Init multimeter Keithley 6514 -----------------

K = multi.Multimeter(port = phd_port)

K.open()
K.reset()
K.write("CURR:RANG %s" % keithley_range)
#K.write("CURR:RANG 2e-6")
#K.write("CURR:RANG 2e-10")
K.write("FUNC 'CURR:DC'")
K.write("SYST:ZCH OFF")
K.write("TRIG:COUN %d" % samples)
K.write(":SENS:CURR:NPLC 1") # 1 seems to be the default
K.write(":DISP:ENAB OFF")

# ---------------------------------------------------------

# xy_mm = 12800.0 # steps / mm
# z_mm  =  2560.0 # steps / mm

B.sensor_move_absolute('Z', z, unit = "mm")

filename = ("SIMPLE-BEAM-MAP-z=%06dmm-dxdy=%fmm%fmm-%s-%f.data" %
            (z, dx, dy, phd, time.time() ) )
f = open(filename, "w")
print >>f, "# time   x(mm)   y(mm)    I(A)"

# ipos = 0

xlast,ylast = None, None
for (x,y) in dtug.Grid(xmin, xmax, dx,
                       ymin, ymax, dy,
                       order = "faster",
                       reference = {'x':xref,'y':yref, 'period':ref_period} ):
    print "LED map: GOTO to ", x, y
    if x != xlast: B.sensor_move_absolute('X', x, unit = "mm")
    if y != ylast: B.sensor_move_absolute('Y', y, unit = "mm")
    xlast = x
    ylast = y

    # extra delay for capacity discharge ?
    time.sleep(time_sleep)

    T = time.time()
    K.write("READ?")
    data_str = K.read()
    print "Received [%s]" % data_str
    parts = data_str.split(',')
    if (len(parts) != 3*samples):
        print >>sys.stderr, "No data. stop."
        break

    flux = float(parts[0])
    print T, x, y, flux
    print >>f, T, x, y, flux
    f.flush()

    # ipos+=1

    # if (ipos==20):
    #     print "LED map: GOTO to ref position", xref, yref
    #     B.sensor_move_absolute('X', xref, unit = "mm")
    #     B.sensor_move_absolute('Y', yref, unit = "mm")
    #     xlast = xref
    #     ylast = yref
    #     time.sleep(10)
    #     T = time.time()
    #     K.write("READ?")
    #     data_str = K.read()
    #     print "Received [%s]" % data_str
    #     parts = data_str.split(',')
    #     if (len(parts) != 3):
    #         print >>sys.stderr, "No data. stop."
    #         break
    #     flux = float(parts[0])
    #     print T, xref, yref, flux
    #     print >>f, T, xref, yref, flux
    #     f.flush()
    #     ipos=0

f.close()

# ---------------------------------------------------------

K.close()
B.close()

# ---------------------------------------------------------

