#!python

from pycpsw import *
import numpy as np
import time
from math import *
import matplotlib.pyplot as plt


# save files to 
#f_dir = '/afs/slac/g/lcls/package/cpsw/controlGUI/MAIN_TRUNK/config/cryo/data/dataTest001'

# setup CPSW heirarchy
#h = Hub.loadYamlFile( '/afs/slac/u/re/ulegat/ProjDocs/LLRF/firmware/targets/mr/AmcCarrierMrRtmEth/images/AmcCarrierMrRtmEth_project.yaml/000TopLevel.yaml', 'NetIODev' )

p = Path.loadYamlFile( '/afs/slac/g/lcls/package/cpsw/controlGUI/MAIN_TRUNK/AmcCarrierMrRtmEth_project.yaml/000TopLevel.yaml', 'NetIODev' )


# setup PATHs 
#p = Path.create( p )
p_mmio = p.findByName('mmio')
#p_mr = p_mmio.findByName( 'AmcCarrierMrRtmEth' )
#p_AmcCore = p_mr.findByName( 'AmcCarrierCore' )

# Load YAML config
#p_mmio.loadConfigFromYamlFile( '/afs/slac/g/lcls/package/cpsw/controlGUI/MAIN_TRUNK/config/cryo/defaults.yaml' )


# create stream interfaces
# strm0 = Stream.create( p.findByName('Stream0') )
# strm1 = Stream.create( p.findByName('Stream1') )
# strm2 = Stream.create( p.findByName('Stream2') )
# strm3 = Stream.create( p.findByName('Stream3') )
# strm4 = Stream.create( p.findByName('Stream4') )
# strm5 = Stream.create( p.findByName('Stream5') )
# strm6 = Stream.create( p.findByName('Stream6') )
# strm7 = Stream.create( p.findByName('Stream7') )

# Thresholds
KlyWiperRegA = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/KlyWiperRegA') )
KlyWiperRegB = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/KlyWiperRegB') )
KlyNVRegA = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/KlyNVRegA') )
KlyNVRegB = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/KlyNVRegB') )
ModWiperRegA = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/ModWiperRegA') )
ModWiperRegB = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/ModWiperRegB') )
ModNVRegA = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/ModNVRegA') )
ModNVRegB = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/ModNVRegB') )


AdcFrameDelay = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcFrameSetDelay') )
AdcSetDelay = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcSetDelay') )
AdcIDelayLoad = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcIDelayLoad') )	

DataTrigDelay = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmData/PulseDelay') )
DataTrigMask = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmData/OpCodeMask[0-7]') )

AccelTrigDelay = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmAccel/PulseDelay') )
AccelTrigWidth = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmAccel/PulseWidth') )
AccelTrigMask = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmAccel/OpCodeMask[0-7]') )

StandbyTrigDelay = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmStandby/PulseDelay') )
StandbyTrigWidth = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmStandby/PulseWidth') )
StandbyTrigMask = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/TrigRtmStandby/OpCodeMask[0-7]') )


SoftBufferClear = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SoftBufferClear') )
SoftBufferTrigger = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SoftBufferTrigger') )

BeamVIData = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/RtmAdcBuffer[0]/MemoryArray[0-511]') )
BeamPwrData = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/RtmAdcBuffer[1]/MemoryArray[0-511]') )

Mode = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/Mode') )

FaultClear = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FaultClear') )

FaultStatusBit = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FaultOut') )

ClkConfig = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierCore/AxiSy56040/OutputConfig[0-3]') )
ClkSel = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierCore/AmcCarrierTiming/TimingFrameRx/ClkSel') )

# CPLD
Status = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/Status') )

# 
CfgRegister = ScalVal.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/CfgRegister') )

AdcIn0 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcIn[0]') )
AdcIn1 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcIn[1]') )
AdcIn2 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcIn[2]') )
AdcIn3 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/AdcIn[3]') )

FirmwareVersion = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FirmwareVersion') )
SystemId0 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SystemId[0]') )
SystemId1 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SystemId[1]') )
SystemId2 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SystemId[2]') )
SystemId3 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SystemId[3]') )

FirmwareDate0 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FirmwareDate[0]') )
FirmwareDate1 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FirmwareDate[1]') )
FirmwareDate2 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FirmwareDate[2]') )
FirmwareDate3 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/FirmwareDate[3]') )

SubType0 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SubType[0]') )
SubType1 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SubType[1]') )
SubType2 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SubType[2]') )
SubType3 = ScalVal_RO.create( p_mmio.findByName('AmcCarrierMrRtmEth/AmcCarrierMrLlrfApp/RtmLlrfCore/SubType[3]') )

StatusBits1 = ['Normal Mode', 'Motor Time out', 'Detuning', 'Tuning', 'Lower Tuned', 'Upper Tuned', 'Motor Not Tuned',
              'Lower Detuned', 'Upper Detuned', 'Motor Not Detuned', 'Modulator Fault', 'Beam Under Current', 'Beam Over Current',
              'Beam Over Voltage', 'Forward Power Over', 'Reflected Power Over']

StatusBits0 = ['Standby Mode', 'Motor Not Timed out', 'Not Detuning', 'Not Tuning', 'Lower Not Tuned', 'Upper Not Tuned', 'Motor Tuned',
              'Lower Not Detuned', 'Upper not Detuned', 'Motor  Detuned', 'Modulator Ok', 'Beam Under Current OK', 'Beam Over Current Ok',
              'Beam Over Voltage Ok', 'Forward Power Over Ok', 'Reflected Power Over Ok']


def PotVolts2Counts(Threshold):

	RTop = 1
	RChip = 10
	RBottom = 1
	VSource = 3.3

	I = VSource/(RTop + RChip + RBottom)
	Counts = int((Threshold-I*RBottom)*255/I/RChip)
	return Counts
  
def ADCCounts2Volts(Counts):
	Volts = float(Counts)*2.5/65535
	return Volts

def DecodeStatus(Stat):
	for i in range(15,-1,-1):
#		print(i)
		if ((int(Stat) & int(pow(2,i))) > 0):
			print StatusBits1[(15-i)]
		else:
			print StatusBits0[(15-i)]
	return

def StatClear():
  FaultClear.setVal([1])
  FaultClear.setVal([0])

def SLEDStatus(Stat):
	SLEDBITs = (Stat >> 6) & 0x3F
	if (SLEDBITs == 0x31):
		print("SLED Tuned")
	elif (SLEDBITs == 0x0E):
		print('SLED Detuned')
	else:
		print('SLED Fault')
			
def FastADCCounts2Volts(Counts):
	Volts = (float(Counts) - 2048)/2048
	return Volts
	
def PulseWidth(Time):
	Counts = int(Time*119)
	return Counts

def ADCDataDelay(Taps):
	AdcSetDelay.setVal([(Taps)])
	AdcIDelayLoad.setVal([1])
	AdCIDelayLoad.setVal([0])
	
	
#KlyWiperRegAB.setVal( [0x55] )
#print("AB=0x%x" % (KlyWiperRegAB.getVal()))
#Mode.setVal( [0x1] )
#print("Mode=0x%x" % (Mode.getVal()))


print("FIrmware=0x%x" % (FirmwareVersion.getVal()))
  
#Mode.setVal( [0x1] )
#Mode.setVal( [0x0] )

#Registers
print("SystemId0=0x%4x" % (SystemId0.getVal()))
print("SystemId1=0x%4x" % (SystemId1.getVal()))
print("SystemId2=0x%4x" % (SystemId2.getVal()))
print("SystemId3=0x%4x" % (SystemId3.getVal()))
print("Status=0x%4x" % (Status.getVal()))


DateString =''

DateString = chr((FirmwareDate0.getVal()) >> 8)
DateString = DateString + chr((FirmwareDate0.getVal()) & 255)
DateString = DateString + chr((FirmwareDate1.getVal()) >> 8)
DateString = DateString + chr((FirmwareDate1.getVal()) & 255)
DateString = DateString + chr((FirmwareDate2.getVal()) >> 8)
DateString = DateString + chr((FirmwareDate2.getVal()) & 255)
DateString = DateString + chr((FirmwareDate3.getVal()) >> 8)
DateString = DateString + chr((FirmwareDate3.getVal()) & 255)



IdString =''

IdString = chr((SystemId0.getVal()) >> 8)
IdString = IdString + chr((SystemId0.getVal()) & 255)
IdString = IdString + chr((SystemId1.getVal()) >> 8)
IdString = IdString + chr((SystemId1.getVal()) & 255)
IdString = IdString + chr((SystemId2.getVal()) >> 8)
IdString = IdString + chr((SystemId2.getVal()) & 255)
IdString = IdString + chr((SystemId3.getVal()) >> 8)
IdString = IdString + chr((SystemId3.getVal()) & 255)

SubTypeString =''

SubTypeString = chr((SubType0.getVal()) >> 8)
SubTypeString = SubTypeString + chr((SubType0.getVal()) & 255)
SubTypeString = SubTypeString + chr((SubType1.getVal()) >> 8)
SubTypeString = SubTypeString + chr((SubType1.getVal()) & 255)
SubTypeString = SubTypeString + chr((SubType2.getVal()) >> 8)
SubTypeString = SubTypeString + chr((SubType2.getVal()) & 255)
SubTypeString = SubTypeString + chr((SubType3.getVal()) >> 8)
SubTypeString = SubTypeString + chr((SubType3.getVal()) & 255)

print
print ("FirmwareVersion = 0x%4x" % (FirmwareVersion.getVal()))
print ("   Compile Date = " + DateString)
print ("      ID String = " + IdString)
print ("       Sub Type = " + SubTypeString)

#print ("Timing Setup")
#ClockConfig = [0,1,0,0]
#lkConfig.setVal(ClockConfig)
#ClockConfig = ClkConfig.getVal()
#print ClockConfig

#print "Clock Select"
#ClkSel.setVal([0])
#print ClkSel.getVal()

#DataTrigMask.setVal([0x00000000, 0x00000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000])
#DataTrigDelay.setVal([50])

#AccelTrigWidth.setVal([PulseWidth(5)])
#AccelTrigDelay.setVal([0])
#AccelTrigMask.setVal([0x00000000, 0x00000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000])

#StandbyTrigWidth.setVal([PulseWidth(5)])
#StandbyTrigDelay.setVal([2000])
#StandbyTrigMask.setVal([0x00000000, 0x00000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000])



print
print ("Test Threshold Pot and ADC")
Thres = 0x00


BCThres = 2.5
BVThres = 1.0
FWDThres = 1.5
REFLThres = 2.0


#while (True) :
KlyWiperRegA.setVal( [PotVolts2Counts(BCThres)] )
KlyWiperRegB.setVal( [PotVolts2Counts(BVThres)] )
ModWiperRegA.setVal( [PotVolts2Counts(FWDThres)] )
ModWiperRegB.setVal( [PotVolts2Counts(REFLThres)] )

# write CFG to scan
CfgRegister.setVal([0xFF1C])
time.sleep(0.1)

# Write CFG to no longer update
# clear msb, writing 0 does not work!
CfgRegister.setVal([0x7F1C])
time.sleep(0.1)
print
print

# Read adc's



BCThresADC = ADCCounts2Volts(AdcIn0.getVal())
BVThresADC = ADCCounts2Volts(AdcIn1.getVal())
FWDThresADC = ADCCounts2Volts(AdcIn2.getVal())
REFLThresADC = ADCCounts2Volts(AdcIn3.getVal())


BCThresErr = (BCThresADC - BCThres)/BCThres * 100
BVThresErr = (BVThresADC - BVThres)/BVThres * 100
FWDThresErr = (FWDThresADC - FWDThres)/FWDThres * 100
REFLThresErr = (REFLThresADC - REFLThres)/REFLThres * 100

print('   Beam Current Threshold {:06.4f}  {:6.2f}%'.format(BCThresADC, BCThresErr))
print('   Beam Voltage Thershold {:06.4f}  {:6.2f}%'.format(BVThresADC, BVThresErr))
print('  Forward Power Threshold {:06.4f}  {:6.2f}%'.format(FWDThresADC, FWDThresErr))
print('Reflected Power Threshold {:06.4f}  {:6.2f}%'.format(REFLThresADC, REFLThresErr))
print

time.sleep(1)
x=0
while (True):

  StatVal = Status.getVal()
  DecodeStatus(StatVal)
  print
  if (FaultStatusBit.getVal() == 1):
    print('Faulted')
  else:
    print('No Fault')

  SLEDStatus(StatVal)
  time.sleep(2)
  print
  print
  print x
  x=x+1
  if (x == 10):
	print ('Clear')
	StatClear()	
	x = 1

