# Caliper.py by Emily Mackevicius, Nov 6, 2012, based on Neil's step response code
# hello.load.45.py
#
# receive and display loading step response
# hello.step.45.py serial_port
#
# Neil Gershenfeld
# CBA MIT 10/29/10
#
# (c) Massachusetts Institute of Technology 2010
# Permission granted for experimental and personal use;
# license for commercial sale available from MIT
#

from Tkinter import *
import serial
import subprocess
import time
import math

WINDOW = 600 # window size
eps = 0.5 # filter time constant
filter1 = 0.0 # filtered value
filter2 = 0.0 # filtered value
filter3 = 0.0 # filtered value
x1 = 1
x2 = 1
x3 = 1
MIN = float(1024)
MAX = float(0)
minpress = 0
maxpress = 0

def idle(parent,canvas):
   global filter1, filter2, filter3, eps, maxpress, minpress
   #
   # idle routine
   #
   byte2 = 0
   byte3 = 0
   byte4 = 0
   ser.flush()
   #
   # find framing 
   #
   while 1:
      byte1 = byte2
      byte2 = byte3
      byte3 = byte4
      byte4 = ord(ser.read())
      if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)):
         break
   #
   # read and plot
   #
   up_low1 = ord(ser.read())
   up_high1 = ord(ser.read())
   down_low1 = ord(ser.read())
   down_high1 = ord(ser.read())
   up_low2 = ord(ser.read())
   up_high2 = ord(ser.read())
   down_low2 = ord(ser.read())
   down_high2 = ord(ser.read())
   up_low3 = ord(ser.read())
   up_high3 = ord(ser.read())
   down_low3 = ord(ser.read())
   down_high3 = ord(ser.read())
   up_value1 = 256*up_high1 + up_low1
   down_value1 = 256*down_high1 + down_low1
   up_value2 = 256*up_high2 + up_low2
   down_value2 = 256*down_high2 + down_low2
   up_value3 = 256*up_high3 + up_low3
   down_value3 = 256*down_high3 + down_low3
   value1 = (up_value1 + (1023 - down_value1))/2.0
   value2 = (up_value2 + (1023 - down_value2))/2.0
   value3 = (up_value3 + (1023 - down_value3))/2.0
   filter1 = (1-eps)*filter1 + eps*value1
   filter2 = (1-eps)*filter2 + eps*value2
   filter3 = (1-eps)*filter3 + eps*value3
   x1 = int(.2*WINDOW + (.9-.2)*WINDOW*filter1/1023.0)
   x2 = int(.2*WINDOW + (.9-.2)*WINDOW*filter2/1023.0)
   x3 = int(.2*WINDOW + (.9-.2)*WINDOW*filter3/1023.0)
   #F = ((1023.0-filter3)-(1023.0-MIN))/((1023.0-MAX)-(1023-MIN))
   tmin = 1023.0-MIN
   tmax = 1023.0-MAX
   tfil = 1023.0-filter3
   F = (tfil -tmin)/(tmax-tmin)
   #F = ((math.exp(-(tfil-tmin)/(tmax-tmin)))-(math.exp(-1)))/(1-math.exp(-1))
   X =  int(.2*WINDOW + (.9-.2)*WINDOW*F)
   if ((minpress==1)&(maxpress==1)):
      canvas.itemconfigure("text2", text ="calibrated (assuming linear)! value is min + (max-min)*%.1f"%(F))
      canvas.coords('rect11',.2*WINDOW,.3*WINDOW,X,.45*WINDOW)
      canvas.coords('rect12',X,.3*WINDOW,.9*WINDOW,.45*WINDOW)
      canvas.update()
   else:
      canvas.itemconfigure("text1", text =instructions)
      canvas.update()
   parent.after_idle(idle,parent,canvas)

def checkup(parent, canvas):
   global filter1, filter2, filter3, FILTER, X, eps, minpress, maxpress, filter3
   byte2 = 0
   byte3 = 0
   byte4 = 0
   ser.flush()
   #
   # find framing 
   #
   while 1:
      byte1 = byte2
      byte2 = byte3
      byte3 = byte4
      byte4 = ord(ser.read())
      if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)):
         break
   #
   # read and plot
   #
   up_low1 = ord(ser.read())
   up_high1 = ord(ser.read())
   down_low1 = ord(ser.read())
   down_high1 = ord(ser.read())


   up_low2 = ord(ser.read())
   up_high2 = ord(ser.read())
   down_low2 = ord(ser.read())
   down_high2 = ord(ser.read())
   up_low3 = ord(ser.read())
   up_high3 = ord(ser.read())
   down_low3 = ord(ser.read())
   down_high3 = ord(ser.read())
   up_value1 = 256*up_high1 + up_low1
   down_value1 = 256*down_high1 + down_low1
   up_value2 = 256*up_high2 + up_low2
   down_value2 = 256*down_high2 + down_low2
   up_value3 = 256*up_high3 + up_low3
   down_value3 = 256*down_high3 + down_low3
   value1 = (up_value1 + (1023 - down_value1))/2.0
   value2 = (up_value2 + (1023 - down_value2))/2.0
   value3 = (up_value3 + (1023 - down_value3))/2.0
   filter1 = (1-eps)*filter1 + eps*value1
   filter2 = (1-eps)*filter2 + eps*value2
   filter3 = (1-eps)*filter3 + eps*value3
   x1 = int(.2*WINDOW + (.9-.2)*WINDOW*filter1/1023.0)
   x2 = int(.2*WINDOW + (.9-.2)*WINDOW*filter2/1023.0)
   x3 = int(.2*WINDOW + (.9-.2)*WINDOW*filter3/1023.0)
   FILTER = filter3
   print(FILTER)
#
#  check command line arguments
#
if (len(sys.argv) != 2):
   print "command line: hello.load.45.py serial_port"
   sys.exit()
port = sys.argv[1]
#
# open serial port
#
ser = serial.Serial(port,9600)
ser.setDTR()
#
# set up GUI
#
instructions =  "Press a to calibrate min, b to calibrate max"
def callow(root):
   global minpress, MIN, MAX, FILTER
   for i in range(10):
      checkup(root, canvas)
   MIN = FILTER
   print(MIN)
   minpress = 1
   canvas.itemconfigure("text1",text="recorded min")
   canvas.update()
   time.sleep(1)
   canvas.itemconfigure("text1", text =instructions)
def calhigh(root):
   global maxpress, MIN, MAX, FILTER
   for i in range(10):
      checkup(root, canvas)
   MAX = FILTER
   print(MAX)
   maxpress = 1
   canvas.itemconfigure("text1",text="recorded max")
   canvas.update()
   time.sleep(1)
   canvas.itemconfigure("text1", text =instructions)
root = Tk()
root.title('Caliper.py (q to exit)')
root.bind('q','exit')
global canvas
canvas = Canvas(root, width=WINDOW, height=.75*WINDOW, background='white')
root.bind('a',callow)
root.bind('b',calhigh)
#

canvas.create_text(.5*WINDOW,.1*WINDOW,text=instructions,font=("Helvetica", 16),tags="text1",fill="#0000b0")
canvas.create_text(.5*WINDOW,.5*WINDOW,text="Please calibrate",font=("Helvetica", 16),tags="text2",fill="#0000b0")
canvas.create_rectangle(.2*WINDOW,.3*WINDOW,.3*WINDOW,.45*WINDOW, tags='rect11', fill='#b00000')
canvas.create_rectangle(.3*WINDOW,.3*WINDOW,.9*WINDOW,.45*WINDOW, tags='rect12', fill='#0000b0')
"""
canvas.create_text(.1*WINDOW,.375*WINDOW,text="2",font=("Helvetica", 24),tags="text2",fill="#0000b0")
canvas.create_rectangle(.2*WINDOW,.3*WINDOW,.3*WINDOW,.45*WINDOW, tags='rect21', fill='#b00000')
canvas.create_rectangle(.3*WINDOW,.3*WINDOW,.9*WINDOW,.45*WINDOW, tags='rect22', fill='#0000b0')
#
canvas.create_text(.1*WINDOW,.625*WINDOW,text="3",font=("Helvetica", 24),tags="text3",fill="#0000b0")
canvas.create_rectangle(.2*WINDOW,.55*WINDOW,.3*WINDOW,.7*WINDOW, tags='rect31', fill='#b00000')
canvas.create_rectangle(.3*WINDOW,.55*WINDOW,.9*WINDOW,.7*WINDOW, tags='rect32', fill='#0000b0')"""
canvas.pack()
#
# start idle loop
#
root.after(100,idle,root,canvas)
root.mainloop()
