#
# hello.step.45.py
#
# receive and display step response
# hello.step.45.py serial_port
#
# Neil Gershenfeld
# CBA MIT 7/19/09
#
# (c) Massachusetts Institute of Technology 2009
# Permission granted for experimental and personal use;
# license for commercial sale available from MIT
#

from Tkinter import *
import serial

WINDOW = 600
NSAMPLES = 254
MAX = 1040
saveflag = 0
index = 0
path = []
step = []
path_filt = []
step_filt = []
baseline = []

def idle(parent,canvas):
   global index, channel, baseline, path, path_filt, step, step_filt, saveflag
   #
   # idle routine
   #
   eps = float(sfilter.get())
   xoffset = float(sxoffset.get())
   xscale = float(sxscale.get())
   yoffset = float(syoffset.get())
   yscale = float(syscale.get())
   lo_dn = ord(ser.read())
   hi_dn = ord(ser.read())
   lo_up = ord(ser.read())
   hi_up = ord(ser.read())
   if ((lo_dn == 1) & (hi_dn == 2) & (lo_up == 3) & (hi_up == 4)):
      if (path_filt == []):
         path_filt = path
         step_filt = step
      else:
         for i in range(len(path_filt)):
            path_filt[i] = (1-eps)*path_filt[i] + eps*path[i]
         for i in range(len(step_filt)):
            step_filt[i] = (1-eps)*step_filt[i] + eps*step[i]
      canvas.delete("path")
      canvas.create_line(path_filt,tag="path",width=3,fill="#00b000")
      if (baseline != []):
         canvas.delete("baseline_path")
         canvas.create_line(baseline,tag="baseline_path",width=3,fill="#b00000")
      canvas.itemconfigure("y0",text="y[0]: %.2f"%step_filt[0])
      canvas.itemconfigure("y1",text="y[1]: %.2f"%step_filt[1])
      canvas.itemconfigure("y-1",text="y[-1]: %.2f"%step_filt[-1])
      canvas.coords('x0',0,.95*WINDOW,step_filt[0],WINDOW)
      if (saveflag == 1):
         file = open(soutfile.get(),"w")
         for i in range(len(step_filt)):
            file.write("%f\n"%(step_filt[i]))
         file.close()
         print 'saved to '+soutfile.get()
         saveflag = 0
      index = 0
      path = []
      step = []
   else:
      value_up = 256*hi_up + lo_up
      value_dn = 256*hi_dn + lo_dn
      value = (value_up + (1023-value_dn))/2.0
      index += 2
      step.insert(0,value)
      y = WINDOW-(yscale*(value/float(MAX)+yoffset))*WINDOW
      x = WINDOW-(xscale*(index/float(NSAMPLES)-xoffset))*WINDOW
      path.insert(0,y)
      path.insert(0,x)
   parent.after_idle(idle,parent,canvas)

def save_data(parent):
   global saveflag
   saveflag = 1

def store_baseline(parent):
   global path_filt, baseline
   baseline = []
   for i in range(len(path_filt)):
      baseline.append(path_filt[i])

#
# check command line arguments
#
if (len(sys.argv) != 2):
   print "command line: python hello.step.45.py serial_port"
   sys.exit()
port = sys.argv[1]
#
# open serial port
#
ser = serial.Serial(port,9600)
ser.setDTR()
ser.flush()
#
# find framing
#
print "finding framing ..."
byte2 = 0
byte3 = 0
byte4 = 0
while 1:
   byte1 = byte2
   byte2 = byte3
   byte3 = byte4
   byte4 = ord(ser.read())
   if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)):
      print "start plotting"
      break
#
# set up GUI
#
root = Tk()
root.title('hello.step.45.py')
root.bind('q','exit')
canvas = Canvas(root, width=WINDOW, height=WINDOW, background='white')
canvas.create_text(.2*WINDOW,.9*WINDOW,font=("Helvetica", 24),tags="y0",fill="#0000b0")
canvas.create_text(.5*WINDOW,.9*WINDOW,font=("Helvetica", 24),tags="y1",fill="#0000b0")
canvas.create_text(.8*WINDOW,.9*WINDOW,font=("Helvetica", 24),tags="y-1",fill="#0000b0")
canvas.create_rectangle(0,.95*WINDOW,0,WINDOW, tags='x0', fill='#b00000')
canvas.pack()
#
drawframe = Frame(root)
Label(drawframe, text=" filter:").pack(side="left")
sfilter = StringVar()
sfilter.set(0.9)
Entry(drawframe, width=4, textvariable=sfilter).pack(side="left")
Label(drawframe, text=" ").pack(side="left")
Label(drawframe, text=" x offset:").pack(side="left")
sxoffset = StringVar()
sxoffset.set(0)
Entry(drawframe, width=4, textvariable=sxoffset).pack(side="left")
Label(drawframe, text=" ").pack(side="left")
Label(drawframe, text=" x scale:").pack(side="left")
sxscale = StringVar()
sxscale.set(1)
Entry(drawframe, width=4, textvariable=sxscale).pack(side="left")
Label(drawframe, text=" ").pack(side="left")
Label(drawframe, text=" y offset:").pack(side="left")
syoffset = StringVar()
syoffset.set(0)
Entry(drawframe, width=4, textvariable=syoffset).pack(side="left")
Label(drawframe, text=" ").pack(side="left")
Label(drawframe, text=" y scale:").pack(side="left")
syscale = StringVar()
syscale.set(1)
Entry(drawframe, width=4, textvariable=syscale).pack(side="left")
Label(drawframe, text=" ").pack(side="left")
drawframe.pack()
#
ioframe = Frame(root)
basebtn = Button(ioframe, text="store baseline")
basebtn.bind('<Button-1>',store_baseline)
basebtn.pack(side="left")
Label(ioframe, text=" ").pack(side="left")
savebtn = Button(ioframe, text="save data")
savebtn.bind('<Button-1>',save_data)
savebtn.pack(side="left")
Label(ioframe, text=" output file:").pack(side="left")
soutfile = StringVar()
soutfile.set("out.dat")
Entry(ioframe, width=10, textvariable=soutfile).pack(side="left")
Label(ioframe, text=" ").pack(side="left")
quitbtn = Button(ioframe, text="quit")
quitbtn.bind('<Button-1>','exit')
quitbtn.pack(side="left")
ioframe.pack()
#
# start idle loop
#
root.after(100,idle,root,canvas)
root.mainloop()

