#!/usr/bin/env python
import sys, time
from ROOT import *
from array import array
import Herakles
fpga=[ 1, 3, 1, 3, 1, 3, 0, 2, 0, 2, 0, 2, 4]  #4=all
tube=[ 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 3]  #3=all
radc=[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11]
I2=[0,1,2,3,4,5,0,1,2,3,4,5]
I1=[0,0,0,0,0,0,1,1,1,1,1,1]
pset = [587,476,566,529,495,461,506,315,423,74,442,485]     
##pset=[290,450,250,180,240,330,160,75,110,200,90,350]
## 'command: 0=3in1 sw, 1=3in1 DAC, 2=HG+, 3=HG-, 4=LG+, 5=LG-'
MB3in1Map = [[0,2,0],[1,3,1],[6,0xA,2,0xC],[7,0xB,3,0xC],[4,8,4,0xD],[5,9,5,0xD]]

rbadr=[0x10021,0x10031,0x10041,0x10051,0x10061,0x10071,0x10081,0x10091,0x100a1,0x100b1,0x100c1,0x100d1]
nchan=12
chan_id = [0x530000] * nchan
nsamp=24
x, y = array( 'd' ), array( 'd' )
bx, by = array( 'd' ), array( 'd' )
lastx=[0]*100
lasty=[0]*100
best=[0]*12

f=open("BarCode.txt","r")
code = f.readline()

md=0
stableP=1650
stableM=2530
pedestalDAC=40
BCID_discharge = 0x8a0 # 2208
BCID_charge = 0x10
#bc = BCID_discharge+62 #286 or 297
bc = BCID_discharge+30 #286 or 297
Gain_cis = 1 ## '1' HG, '0' LG



class IPbus:
    def __init__(self, ipaddress, verbose=False):
        self.ipbus = Herakles.Uhal(ipaddress, 50001)
        self.ipbus.SetVerbose(verbose)
        pass
    def SyncClear(self): self.ipbus.Write(0x6, 0x1)
    def SyncRest(self): self.ipbus.Write(0x6, 0x0)
    def SyncEnable(self): self.ipbus.Write(0x6, 0x2)
    def SyncLoop(self, num):
        self.ipbus.Write(0x6, (num << 2) + 0x2)
        time.sleep(0.00001)
        pass
    def SyncFlush(self, bcid, dba):
        time.sleep(0.00001)
        self.SyncWrite(bcid, dba, 0x80000000)
        time.sleep(0.00001)
    def SyncWrite(self, bcid, dba, val): self.ipbus.Write(0x00010000, [bcid << 16|dba, val])
    def AsyncWrite(self, md, dba, val):
        self.ipbus.Write(0x10002, [(md+1<<28)+dba, val])
      #  print "Async writing : In sROD address:",0x10002," - ",  hex((md+1<<28)+dba), "/", hex(val)
    def RODRead(self, chan, gain, num):
        addr = 0x100 + (chan*N_samples)
        if not gain: addr += N_samples*N_chan
        #print " Read from address:", hex(addr)
        return self.ipbus.Read(addr, num)
    def RODConfigWrite(self,add,val): self.ipbus.Write(add,val)
    def RODWrite(self, bcid, val): self.ipbus.Write(0x00010004, [bcid << 16, val])
    def ReadVal(self, add): return self.ipbus.Read(add,1)

    def CheckValue(self,fpga,card,setting,value):
        cmd = (1<<22)+(FPGA<<18)+(card<<16)+(setting<<12)+0x111
        #print 'Send command request: %s'  %hex(cmd)
        self.ipbus.Write(0x00010002, [0x1, cmd])
        time.sleep(0.0001)
        cmd = (1<<21)+(FPGA<<18)+(card<<16)+(setting<<12)+0x111
        #print "Send command request: %s"  %hex(cmd)
        self.ipbus.Write(0x00010002, [0x1, cmd])
        time.sleep(0.0001)
        self.ipbus.Write(0x00010002, [0x1, 0x80000000])
        time.sleep(0.0001)
        if(FPGA<2):
			readbackvalue = self.ipbus.Read(0x10021)
        else:
			readbackvalue = self.ipbus.Read(0x10081)
		#print "Value expected/received: 0x%x  / %s " %((value),hex(readbackvalue))
        #valuemask = value & 0xFFF
        readbackvaluemask = readbackvalue & 0xFFF
        if (value == readbackvaluemask):
			#	print "GOOD"
			#print "Value expected/received: 0x%x  / %s " %((value), hex(readbackvalue))
			return True
        else:
			print "ERROR : FPGA / card:", FPGA, "/", card
			print "Value expected/received: 0x%x  / %s " %((value), hex(readbackvalue))
			#time.sleep(100000)
			return False
    def ResetPLL(self,side):
	    RstPLL0 = 0x0
	    RstPLL1 = 0x0
	    clk0 = side #FPGA A0, CH6, CH8, CH10 | FPGA B0, CH7, CH9, CH11 
	    clk1 = side #FPGA A1, CH0, CH2, CH4  | FPGA B1, CH1, CH3, CH5
	    phase = ((RstPLL1<<16) + (RstPLL0<<15) + (0<<14) + (clk1<<13) + (clk0<<12) + (0))
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    phase = ((RstPLL1<<16) + (RstPLL0<<15) + (1<<14) + (clk1<<13) + (clk0<<12) + (0))
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    RstPLL0 = 0x1
	    RstPLL1 = 0x1
	    clk0 = side
	    clk1 = side
	    phase = ((RstPLL1<<16) + (RstPLL0<<15) + (0<<14) + (clk1<<13) + (clk0<<12) + (0))
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    phase = ((RstPLL1<<16) + (RstPLL0<<15) + (1<<14) + (clk1<<13) + (clk0<<12) + (0))
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    RstPLL0 = 0x0
	    RstPLL1 = 0x0
	    clk0 = side
	    clk1 = side
	    phase = ((RstPLL1<<16) + (RstPLL0<<15) + (0<<14) + (clk1<<13) + (clk0<<12) + (0))
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    phase = ((RstPLL1<<16) + (RstPLL0<<15) + (1<<14) + (clk1<<13) + (clk0<<12) + (0))
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
    def Phase(self, side, fpga, value):
		#clk0 = side A -> #FPGA A0, CH6, CH8, CH10 | FPGA B0, CH7, CH9, CH11 
	    #clk1 = side B -> #FPGA A1, CH0, CH2, CH4  | FPGA B1, CH1, CH3, CH5
	    phase = 0x0
	    phase = ((side<<14) + (0<<13) + (0<<12) + value)
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    phase = ((side<<14) + (fpga<<12) + value)
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    phase = 0x0
	    phase = ((side<<14) + (0<<13) + (0<<12) + value)
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)
	    phase = ((side<<14) + (fpga<<12) + value)
	    ipbus.AsyncWrite(0,0xF0,phase)
	    time.sleep(0.001)

print 'communicating with host'
#ipbus = IPbus('128.135.102.102')
ipbus = IPbus('192.168.0.1')
#ipbus = IPbus('localhost')
#ipbus = IPbus('130.242.128.16')
#ipbus = IPbus('137.138.216.149')
#ipbus = IPbus('137.138.216.151')
print 'communication successful'

################# DECLARE HISTOGRAMS ###################
hist = []
for i in range(nchan):
        hist.append(TProfile("histo%i"%i,"HG channel %i "%(i),4095,0,3600,0,66000))

chargeP=0x3ff
chargeM=0x1ff
print "chargeP=",hex(chargeP),"   chargeM=",hex(chargeM)
#set DACs
md=0
ipbus.AsyncWrite(md,0x1,0x000000)
time.sleep(0.1)

#Disable TTC
ipbus.RODConfigWrite(0x4, 0x0)

#Disable Deadtime 
ipbus.RODConfigWrite(0x5,0x0)
time.sleep(0.01)

TTC= ipbus.ReadVal(0x4)
Trigger= ipbus.ReadVal(0x5)

print "Trigger=",hex(Trigger), "  TTC=",hex(TTC)

## Reset CRC Counters ##
ipbus.RODConfigWrite(0x20,0x0)
ipbus.RODConfigWrite(0x20,0x1)
ipbus.RODConfigWrite(0x20,0x0)

#####======================#####
##### set the offset DACS  ####
#####======================#####
#charge = [0,0,1660,2520,1660,2520]
#charge = [1620,2560,1620,2560]
charge = [1640,2540,1640,2540]
adc=0
while(adc<12):
  FPGA=fpga[adc]
  TUBE=tube[adc]

  CMD=4  ## Here commands are: 0=3in1 sw, 1=3in1 DAC, 2=HG+, 3=HG-, 4=LG+, 5=LG-'
  while(CMD<8):
	### SET OFFSET DAC ==============================================================
	xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)| (CMD<<12) | charge[CMD-4]
	#print " SET DAC xcmd=", hex(xcmd)
	ipbus.AsyncWrite(md,0x1,xcmd)
	time.sleep(0.01)
	ipbus.AsyncWrite(md,0x1,0x8000000)
	time.sleep(0.001)
        print " CMD=",CMD,"  charge=",charge[CMD-4]
	CMD=CMD+1
  ### LOAD  HG  #####
  CMD=0xc
  xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)|(CMD<<12)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.01)
  ipbus.AsyncWrite(md,0x1,0x80000000)
  time.sleep(0.01)

  ### LOAD  LG  #####
  CMD=0xd
  xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)|(CMD<<12)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.01)
  ipbus.AsyncWrite(md,0x1,0x80000000)
  time.sleep(0.01)
  adc=adc+1

print " offset dac set complete"
adc=0
while(adc<12):
  FPGA=fpga[adc]
  TUBE=tube[adc]
  #####===============================#####
  ##### SET 3in1 SWITCH CONFIGURATION #####
  #####===============================#####
  CMD=0  ## Here commands are: 0=3in1 sw, 1=3in1 DAC, 2=HG+, 3=HG-, 4=LG+, 5=LG-'
  TPH=0 #closed  0-pass thru DB pulse  2-open 1-closed
  TPL=1 #closed  0-pass thru DB pulse  2-open 1-closed
  ITG=1 #enable
  S1=0
  S2=0
  S3=0
  S4=0
  TRG=1
  data=(CMD<<12)|(TPH<<10)|(TPL<<8)|(ITG<<7)|(S4<<6)|(S3<<5)|(S2<<4)|(S1<<3)|(TRG<<2)
  xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)| MB3in1Map[CMD][0]<<12 | data
  #print " 3in1 set xcmd=", hex(xcmd)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.001)
  ipbus.AsyncWrite(md,0x1,0x8000000)
  time.sleep(0.001)


  #raw_input("wait...")


  ### SET 3in1 readback ==============================================================
  CMD=2
  xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)| (CMD<<12)
  #print " 3in1 Readback xcmd=", hex(xcmd)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.001)

  ### CLOCK IT BACK TO DB
  xcmd=(1<<21)|(FPGA<<18)|(TUBE<<16)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.001)

  ### READ DB Register
  base=(0x10020 + (adc<<4))
  readbackvalue = ipbus.ReadVal(base)
  expectedreadback=(FPGA<<18)|(TUBE<<16)| (CMD<<12) | data
  time.sleep(0.001)
  readbackvalue = readbackvalue & 0xfffffc
  if(expectedreadback!=readbackvalue):
	print " 3in1 readback error bk=",hex(readbackvalue),"  exbk=",hex(expectedreadback)
	#exit(0)
  else:
	print " 3in1 readback good bk=",hex(readbackvalue),"  exbk=",hex(expectedreadback)
  print " 3IN1 Switches are set "


  #####===============================#####
  ##### SET 3in1 DAC                  #####
  #####===============================#####
  CMD=1  ## Here commands are: 0=3in1 sw, 1=3in1 DAC, 2=HG+, 3=HG-, 4=LG+, 5=LG-'
  dac=3800
  xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)| MB3in1Map[CMD][0]<<12 | dac
  #print " 3in1 set xcmd=", hex(xcmd)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.001)
  ipbus.AsyncWrite(md,0x1,0x8000000)
  time.sleep(0.001)

  ### SET 3in1 DAC readback ==============================================================
  xcmd=(1<<22)|(FPGA<<18)|(TUBE<<16)|  MB3in1Map[CMD][1]<<12
  #print " 3in1 Readback xcmd=", hex(xcmd)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.001)

  ### CLOCK IT BACK TO DB
  xcmd=(1<<21)|(FPGA<<18)|(TUBE<<16)
  ipbus.AsyncWrite(md,0x1,xcmd)
  time.sleep(0.001)

  ### READ DB Register
  base=(0x10020 + (adc<<4) +  MB3in1Map[CMD][2])
  readbackvalue = ipbus.ReadVal(base)
  expectedreadback=(FPGA<<18)|(TUBE<<16)| MB3in1Map[CMD][1]<<12 | dac
  time.sleep(0.001)
  if(expectedreadback!=readbackvalue):
	print " 3in1 DAC readback error bk=",hex(readbackvalue),"  exbk=",hex(expectedreadback)
  else:
	print " 3in1 DAC readback good bk=",readbackvalue,"  exbk=",expectedreadback


  print "3in1 DAC is set"
  print " "
  adc=adc+1
nevnt=0
adc=0
while(adc<12):
  nevnt=0
  diffbst=4000
  #ipbus.ResetPLL(0)
  #ipbus.ResetPLL(1)

  #   ipbus.Phase(side,fpga,deskew)
  #   side = 0  #A=0  B=1
  #  xxxx Not Correct xxxx   fpga=3  # 0=no change   1=A0/B0  2=A1,B1   3=both
  if((adc==6) or (adc==8) or (adc==10)):
        # ADCs 6-8-10
        ipbus.ResetPLL(0)
        ipbus.ResetPLL(1)
        ipbus.Phase(0,2,pset[adc])
        ipbus.Phase(0,1,pset[adc])

  if((adc==0) or (adc==2) or (adc==4)):
        # ADCs 0-2-4
        ipbus.ResetPLL(0)
        ipbus.ResetPLL(1)
        ipbus.Phase(0,2,pset[adc])
        ipbus.Phase(0,1,pset[adc])
 
  if((adc==7) or (adc==9) or (adc==11)):
        # ADCs 7-9-11
        ipbus.ResetPLL(0)
        ipbus.ResetPLL(1)
        ipbus.Phase(1,1,pset[adc])
        ipbus.Phase(1,2,pset[adc])

  if((adc==1) or (adc==3) or (adc==5)):
        # ADCs 1-3-5
        ipbus.ResetPLL(0)
        ipbus.ResetPLL(1)
        ipbus.Phase(1,2,pset[adc])
        ipbus.Phase(1,1,pset[adc])
  time.sleep(0.01)

  #####========================================#####
  ##### Disable autiomatic CIS from DB	     #####
  #####========================================#####
  Enable_LED=0x10
  ipbus.AsyncWrite(0,0x14, Enable_LED)
  time.sleep(0.0001)
                                
  #####========================================#####
  ##### Clear synchro memory                   #####
  #####========================================#####
  ipbus.SyncClear()
  ipbus.SyncRest()
  kja=30
  bc = BCID_discharge+kja #286 or 297
  #print "kja=",kja
  #####================================#####
  ##### Configure the L1A in the sROD  #####
  #####================================#####

  ####==============================####	               	
  #### Enable Synchronous commands  ####               
  ####     DISABLE DCS COMMANDS     ####
  ####==============================####	               	
  DisableDCS=0x1
  ConfigDCS=(DisableDCS<<17)
  EnableSync=0x2
  ipbus.RODConfigWrite(0x6,ConfigDCS&EnableSync)
  # print "Configure DCS.     Address=0x6 =",hex(ConfigDCS), " Disable the DCS commands ..."

  #####=======================================================================#####
  ##### Enable autiomatic CIS from DB. This is new from 06-April-2016	    #####
  #####=======================================================================#####
  print " ++ Enable Automatic CIS from DB"
  time.sleep(0.001)

  ##### enable
  BCIDcharge=(BCID_charge << 2)
  BCIDdischarge=(BCID_discharge << 14)
  CIS_Enable=1
  CIS_Gain=(Gain_cis << 1)
  ipbus.AsyncWrite(0,0x121, BCIDdischarge + BCIDcharge + CIS_Gain + CIS_Enable)
  time.sleep(0.001)
  icnt=0

  #####=======================================================================#####
  #####                           send L1A                                    #####
  #####=======================================================================#####
  ipbus.SyncClear()
  ipbus.SyncRest()
  time.sleep(0.001)
  ipbus.RODWrite(bc & 0xFFF, 0x3)# 0x3 sends a internal L1A (bit0) and external (bit1)
  time.sleep(0.001)
  ipbus.SyncLoop(0)
  time.sleep(0.001)
  ipbus.SyncClear()
  ipbus.SyncRest()

  ##################################################
  ####  Now read the data from the sROD mem ########
  ################################################## 
  N_samples = 0xFF & ipbus.ReadVal(0x9F)
  N_chan = 0xFF & (ipbus.ReadVal(0x9F)>>8)
  rdx=adc
  print "adc=",adc," rdx=",rdx,"  md=",md,"   nchan=",nchan,"  nsamp=",nsamp
  hg = ipbus.RODRead(rdx+(md*nchan),1,nsamp)
  lg = ipbus.RODRead(rdx+(md*nchan),0,nsamp)
  maxm=0
  maxn=0
  for a in range(len(hg)):
    hg[a] = hg[a] & 0xFFF
    lg[a] = lg[a] & 0xFFF
    if(hg[a]>maxm and a<23):
      maxm=hg[a]
      maxn=a
  print " lsamples=",hg[0]," ",hg[1]," ",hg[2]," ",hg[3]," ",hg[4]," ",hg[5]," ",hg[6]," ",hg[7]
  print "          ",hg[8]," ",hg[9]," ",hg[10]," ",hg[11]," ",hg[12]," ",hg[13]," ",hg[14]," ",hg[15]
  print "          ",hg[16]," ",hg[17]," ",hg[18]," ",hg[19]," ",hg[20]," ",hg[21]," ",hg[22]," ",hg[23]
  i=0
  while(i<12):
     lasty[i]=hg[i+12]
     lastx[i]=i
     bx.append(lastx[i])
     by.append(lasty[i])
     i=i+1
  adc=adc+1

c1 = TCanvas( 'c1', 'HG event at best phase ' + code, 400, 50, 1600, 1000 )
c1.Divide(6,2)
c1.SetFillColor( 33 )
c1.SetGrid()
i=0
i=0
gr=[];
while(i<12):
    c1.cd(i+1)
    gPad.SetTickx()
    gPad.SetTicky()
    gr.append( TGraph( 12, bx[(12*i):], by[(12*i):] ))
    k=0
    while(k<12):
       j=12*i+k
       print " i=",i,"  k=",k,"  bx=",bx[j],"  by=",by[j]
       k=k+1
    gr[i].SetLineColor( kBlack )
    gr[i].SetLineWidth( 1 )
    gr[i].SetMarkerColor( kRed )
    gr[i].SetMarkerStyle( 4 )
    gr[i].SetMarkerSize( 1 )
    gr[i].SetTitle( "HG ADC Channel %i"%i )
    gr[i].GetXaxis().SetTitle( 'Sample Number' )
    gr[i].GetXaxis().SetTitleSize(0.05)
    #gr[i].GetYaxis().SetTitle( 'ADC Counts' )
    gr[i].Draw( 'AP' )
    i=i+1
c1.Update()
c1.SaveAs(code[0:15] + "/evHG.png")
raw_input("wait...")

