from pc410 import PC410
import traceback,time,sys,os

class PC410Controller:
    def __init__(self,threader,cmdcallback,infocallback,statecallback,recordcallback):
        self.threader=threader
        self.cmdcallback=cmdcallback
        self.infocallback=infocallback
        self.statecallback=statecallback
        self.recordcallback=recordcallback

        now=time.time()
        self.tstart0=now
        
        self.port="/dev/ttyUSB0"
        self.baudrate=9600
        self.pc410=PC410(self.port,self.baudrate,verbose=0)

        self.cycleRunning=0
        self.cycleEnabled=1        
        self.quit=0

        self.runnning=0
        self.runStart=now
        self.runLastTime=now

    def disableCycle(self):
        self.cycleEnabled=0
        while self.cycleRunning: time.sleep(0.1)
        time.sleep(0.5)
    def enableCycle(self):
        self.cycleEnabled=1
        
    def cmdRun(self):
        self.disableCycle()
        self.pc410.write("OS",2)
        self.enableCycle()
        self.running=1
        now=time.time()
        self.runStart=now
        self.runLastTime=now
        
    def cmdStop(self):
        self.disableCycle()
        self.pc410.write("OS",0)
        self.enableCycle()
        self.running=0


    def writeProgram(self,program):
        self.disableCycle()
        i=1
        e1=0
        for i1 in range(0,len(program)):
            r1,l1,t1=program[i1]
            e1,f1=self.pc410.write("r%d"%i,r1)
            if e1!=0: break
            e1,f1=self.pc410.write("l%d"%i,l1)
            if e1!=0: break
            e1,f1=self.pc410.write("t%d"%i,t1)
            if e1!=0: break
            i+=1
        if e1==0 and i<8:
            e1,f1=self.pc410.write("r%d"%i,-0.01)
        self.enableCycle()
        return e1

        
    def readProgram(self):
        self.disableCycle()
        program=[]
        print("reading program")
        for i in range(1,9):
            e1,r1=self.pc410.read("r%d"%i)
            if e1!=0: return []
            e1,l1=self.pc410.read("l%d"%i)
            if e1!=0: return []
            e1,t1=self.pc410.read("t%d"%i)
            if e1!=0: return []
            program+=[(r1,l1,t1)]
            #print("reading program",r1,l1,t1)
            
        self.enableCycle()
        return program
            

    def cycle1(self):
        state={}
        for readparam in ["PV","OP","SP","SL","HA","LA","DA","XP","TI","TD","HB","LB","CH","CC","RG","HS","LS","BP","HO","SR","Lc","SW","XS","OS"]:
            e1,value=self.pc410.read(readparam)
            now=time.time()
            if self.running: self.runLastTime=now
            print(value)
            s=[]
            if readparam=="SW":
                value1=int(value[1:],16)
                bits=["Data format",
                      "Input fault",
                      "Barring key operation",
                      "---",
                      "---",
                      "Modifying parameters by keys",
                      "Deviation alarm status",
                      "Deviation alarm condition",
                      "Lower limit alarm status",
                      "Lower limit alarm condition",
                      "Upper limit alarm status",
                      "Upper limit alarm condition",
                      "Alarm output",
                      "---",
                      "---",
                      "Auto/manual"]
                s+=["%04x"%value1]
                if 0:
                    for i in range(0,len(bits)):
                        if (value1>>i)&1: s+=[bits[i]]
            elif readparam=="XS":
                value1=int(value[1:],16)
                s+=["%04x"%value1]
                if value1: s+=["Turn on self-tuning"]
            elif readparam=="OS":
                value1=int(value[1:],16)
                s+=["%d"%value1]
                value1&=255
                if value1==0:
                    s+=["program stopped"]
                    self.running=0                
                elif value1==2:
                    s+=["program running"]
                    self.running=1
                elif value1==3: s+=["program hold"]
                elif value1==6: s+=["unknown 6"]
                else: s+=["unknown state"]            
            elif readparam=="PV":
                if self.running:
                    dt=self.runLastTime-self.runStart
                    if self.recordcallback: self.recordcallback(dt,value)
                s+=[str(value)]
            else:
                s+=[str(value)]
            state[readparam]=" ".join(s)
        self.statecallback(state)
    
    def cycle(self,tstart0):
        t2=time.time()
        while not self.quit:
            if self.cycleEnabled:
                self.cycleRunning=1
                self.cycle1()
                time.sleep(0.5)
                self.cycleRunning=0

            # wait 10 x 0.1 s
            for i in range(0,10):
                if self.quit: break
                time.sleep(0.1)

                
                
        
    def run(self):
        self.cycleThread=self.threader("cycle",self)
        self.cycleThread.start()
   
