## @package SLOWCONTROl phase 1
#  Documentation for this module.
#
#  More details.
#Config for TOPO
## Documentation of imported Libarys
import subprocess as sp
from time import localtime, strftime, gmtime
import time
import os
import datetime
import sys
from datetime import datetime
from collections import deque
from contextlib import contextmanager
from time import sleep


##Describtive
tdkdesadd = ['1V8', '2V5', '3V3', 'VCCINT (0.85V)', 'MGTYAVCC (0.9V)', 'MGTYAVTT (1.2V)', 'VCCINT (0.85V)', 'MGTYAVCC (0.9V)', 'MGTYAVTT (1.2V)']
tdkdesreg = ['V_in', 'V_out', 'I_out', 'T[C]']

maxdespage = ['VCCAUX_U1', 'MGTVCCAUX_U1', 'VCCAUX_U2', 'MGTVCCAUX_U2', '1V8_SEQ_CPLD', '1V8_CPLD', 'U1_VCCAUX_ISENS', 'U1_MGTVCCAUX_ISENS', 'U2_VCCAUX_ISENS', 'U2_MGTVCCAUX_ISENS']

minipoddes = [['MiniPOD Tx2 U1','MiniPOD Rx6 U1','MiniPOD Rx7 U1','MiniPOD Rx8 U1','MiniPOD Rx9 U1','MiniPOD Rx10 U1'],
		   ['MiniPOD Tx1 U1','MiniPOD Rx1 U1','MiniPOD Rx2 U1','MiniPOD Rx3 U1','MiniPOD Rx4 U1','MiniPOD Rx5 U1'],
		   ['MiniPOD Tx2 U2','MiniPOD Rx6 U2','MiniPOD Rx7 U2','MiniPOD Rx8 U2','MiniPOD Rx9 U2','MiniPOD Rx10 U2'],
		   ['MiniPOD Tx1 U2','MiniPOD Rx1 U2','MiniPOD Rx2 U2','MiniPOD Rx3 U2','MiniPOD Rx4 U2','MiniPOD Rx5 U2'],]

minipodregdes = ['Ch0 Op[E-10 W]', 'Ch1 Op[E-10 W]', 'Ch2 Op[E-10 W]', 'Ch3 Op[E-10 W]', 'Ch4 Op[E-10 W]', 'Ch5 Op[E-10 W]', 'Ch6 Op[E-10 W]', 'Ch7 Op[E-10 W]', 'Ch8 Op[E-10 W]', 'Ch9 Op[E-10 W]', 'Ch10 Op[E-10 W]', 'Ch11 Op[E-10 W]', 'T[C]']

minipodLOS = [['0x10', 0], ['0x10', 1], ['0x10', 2], ['0x10', 3], ['0x10', 4], ['0x10', 5], ['0x10', 6], ['0x10', 7], ['0x09', 0], ['0x09', 1], ['0x09', 2], ['0x09', 3]]

#TDK-lambdas
## I2C-hardware-adresses of each TDK-lambda power supplies 
tdkdevadd = ['0x10', '0x11', '0x12', '0x14', '0x15', '0x16', '0x18', '0x19', '0x1a', '0x1c', '0x1d', '0x1e', '0x20', '0x21', '0x22'] #JFEX

## I2C-register-adresses of TDK-lambda power supplies 
tdkregadd = ['0x88', '0x8B', '0x8C', '0x8D']

## Division factor to convert hex from I2C register to readable SI-float for TDK-lambdas
tdkregdiv =  [1862.0/1000, 640.0/1000, 10.24/1000, 1.0]

## TDK-lambdas multiplication factor
#
#  Used to shift the SI-floats decimal point, so those later can be cased to ints to hex

## TDK-lambdas readout adresses
tdkwadd = [[0xa0003000,0xa0003004,0xa0003008,0xa000300c],[0xa0003010,0xa0003014,0xa0003018,0xa000301c],[0xa0003020,0xa0003024,0xa0003028,0xa000302c],[0xa0003030,0xa0003034,0xa0003038,0xa000303c],[0xa0003040,0xa0003044,0xa0003048,0xa000304c],[0xa0003050,0xa0003054,0xa0003058,0xa000305c],[0xa0003060,0xa0003064,0xa0003068,0xa000306c],[0xa0003070,0xa0003074,0xa0003078,0xa000307c],[0xa0003080,0xa0003084,0xa0003088,0xa000308c],[0xa0003090,0xa0003094,0xa0003098,0xa000309c],[0xa00030a0,0xa00030a4,0xa00030a8,0xa00030ac],[0xa00030b0,0xa00030b4,0xa00030b8,0xa00030bc],[0xa00030c0,0xa00030c4,0xa00030c8,0xa00030cc],[0xa00030d0,0xa00030d4,0xa00030d8,0xa00030dc],[0xa00030e0,0xa00030e4,0xa00030e8,0xa00030ec]]

#Mipo
## I2C-Hardware-adresses of miniports
mipoadd = ['0x28', '0x31', '0x32', '0x33', '0x34', '0x35']
mipobus = [3, 4, 5, 6]

## Register adresses of Minipod, 12 for power per channel one for temperature
miporeg = ['0x56', '0x54', '0x52', '0x50', '0x4e', '0x4c', '0x4a', '0x48', '0x46', '0x44', '0x42', '0x40', '0x1c', '0x22', '0x20']

miporegdiv = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

mipowadd = [[[0xa0003134, 0xa0003138, 0xA000313C, 0xA0003140, 0xA0003144, 0xA0003148, 0xA000314C, 0xA0003150, 0xA0003154, 0xA0003158, 0xA000315C, 0xA0003160, 0xA0003164, 0xA0003168, 0xA000316C], [0xA0003170, 0xA0003174, 0xA0003178, 0xA000317C, 0xA0003180, 0xA0003184, 0xA0003188, 0xA000318C, 0xA0003190, 0xA0003194, 0xA0003198, 0xA000319C, 0xA00031A0, 0xA00031A4, 0xA00031A8], [0xA00031AC, 0xA00031B0, 0xA00031B4, 0xA00031B8, 0xA00031BC, 0xA00031C0, 0xA00031C4, 0xA00031C8, 0xA00031CC, 0xA00031D0, 0xA00031D4, 0xA00031D8, 0xA00031DC, 0xA00031E0, 0xA00031E4], [0xA00031E8, 0xA00031EC, 0xA00031F0, 0xA00031F4, 0xA00031F8, 0xA00031FC, 0xA0003200, 0xA0003204, 0xA0003208, 0xA000320C, 0xA0003210, 0xA0003214, 0xA0003218, 0xA000321C, 0xA0003220], [0xA0003224, 0xA0003228, 0xA000322C, 0xA0003230, 0xA0003234, 0xA0003238, 0xA000323C, 0xA0003240, 0xA0003244, 0xA0003248, 0xA000324C, 0xA0003250, 0xA0003254, 0xA0003258, 0xA000325C], [0xA0003260, 0xA0003264, 0xA0003268, 0xA000326C, 0xA0003270, 0xA0003274, 0xA0003278, 0xA000327C, 0xA0003280, 0xA0003284, 0xA0003288, 0xA000328C, 0xA0003290, 0xA0003294, 0xA0003298]],
           [[0xA000329C, 0xA00032A0, 0xA00032A4, 0xA00032A8, 0xA00032AC, 0xA00032B0, 0xA00032B4, 0xA00032B8, 0xA00032BC, 0xA00032C0, 0xA00032C4, 0xA00032C8, 0xA00032CC, 0xA00032D0, 0xA00032D4], [0xA00032D8, 0xA00032DC, 0xA00032E0, 0xA00032E4, 0xA00032E8, 0xA00032EC, 0xA00032F0, 0xA00032F4, 0xA00032F8, 0xA00032FC, 0xA0003300, 0xA0003304, 0xA0003308, 0xA000330C, 0xA0003310], [0xA0003314, 0xA0003318, 0xA000331C, 0xA0003320, 0xA0003324, 0xA0003328, 0xA000332C, 0xA0003330, 0xA0003334, 0xA0003338, 0xA000333C, 0xA0003340, 0xA0003344, 0xA0003348, 0xA000334C], [0xA0003350, 0xA0003354, 0xA0003358, 0xA000335C, 0xA0003360, 0xA0003364, 0xA0003368, 0xA000336C, 0xA0003370, 0xA0003374, 0xA0003378, 0xA000337C, 0xA0003380, 0xA0003384, 0xA0003388], [0xA000338C, 0xA0003390, 0xA0003394, 0xA0003398, 0xA000339C, 0xA00033A0, 0xA00033A4, 0xA00033A8, 0xA00033AC, 0xA00033B0, 0xA00033B4, 0xA00033B8, 0xA00033BC, 0xA00033C0, 0xA00033C4], [0xA00033C8, 0xA00033CC, 0xA00033D0, 0xA00033D4, 0xA00033D8, 0xA00033DC, 0xA00033E0, 0xA00033E4, 0xA00033E8, 0xA00033EC, 0xA00033F0, 0xA00033F4, 0xA00033F8, 0xA00033FC, 0xA0003400]],
           [[0xA0003404, 0xA0003408, 0xA000340C, 0xA0003410, 0xA0003414, 0xA0003418, 0xA000341C, 0xA0003420, 0xA0003424, 0xA0003428, 0xA000342C, 0xA0003430, 0xA0003434, 0xA0003438, 0xA000343C], [0xA0003440, 0xA0003444, 0xA0003448, 0xA000344C, 0xA0003450, 0xA0003454, 0xA0003458, 0xA000345C, 0xA0003460, 0xA0003464, 0xA0003468, 0xA000346C, 0xA0003470, 0xA0003474, 0xA0003478], [0xA000347C, 0xA0003480, 0xA0003484, 0xA0003488, 0xA000348C, 0xA0003490, 0xA0003494, 0xA0003498, 0xA000349C, 0xA00034A0, 0xA00034A4, 0xA00034A8, 0xA00034AC, 0xA00034B0, 0xA00034B4], [0xA00034B8, 0xA00034BC, 0xA00034C0, 0xA00034C4, 0xA00034C8, 0xA00034CC, 0xA00034D0, 0xA00034D4, 0xA00034D8, 0xA00034DC, 0xA00034E0, 0xA00034E4, 0xA00034E8, 0xA00034EC, 0xA00034F0], [0xA00034F4, 0xA00034F8, 0xA00034FC, 0xA0003500, 0xA0003504, 0xA0003508, 0xA000350C, 0xA0003510, 0xA0003514, 0xA0003518, 0xA000351C, 0xA0003520, 0xA0003524, 0xA0003528, 0xA000352C], [0xA0003530, 0xA0003534, 0xA0003538, 0xA000353C, 0xA0003540, 0xA0003544, 0xA0003548, 0xA000354C, 0xA0003550, 0xA0003554, 0xA0003558, 0xA000355C, 0xA0003560, 0xA0003564, 0xA0003568]],
           [[0xA000356C, 0xA0003570, 0xA0003574, 0xA0003578, 0xA000357C, 0xA0003580, 0xA0003584, 0xA0003588, 0xA000358C, 0xA0003590, 0xA0003594, 0xA0003598, 0xA000359C, 0xA00035A0, 0xA00035A4], [0xA00035A8, 0xA00035AC, 0xA00035B0, 0xA00035B4, 0xA00035B8, 0xA00035BC, 0xA00035C0, 0xA00035C4, 0xA00035C8, 0xA00035CC, 0xA00035D0, 0xA00035D4, 0xA00035D8, 0xA00035DC, 0xA00035E0], [0xA00035E4, 0xA00035E8, 0xA00035EC, 0xA00035F0, 0xA00035F4, 0xA00035F8, 0xA00035FC, 0xA0003600, 0xA0003604, 0xA0003608, 0xA000360C, 0xA0003610, 0xA0003614, 0xA0003618, 0xA000361C], [0xA0003620, 0xA0003624, 0xA0003628, 0xA000362C, 0xA0003630, 0xA0003634, 0xA0003638, 0xA000363C, 0xA0003640, 0xA0003644, 0xA0003648, 0xA000364C, 0xA0003650, 0xA0003654, 0xA0003658], [0xA000365C, 0xA0003660, 0xA0003664, 0xA0003668, 0xA000366C, 0xA0003670, 0xA0003674, 0xA0003678, 0xA000367C, 0xA0003680, 0xA0003684, 0xA0003688, 0xA000368C, 0xA0003690, 0xA0003694], [0xA0003698, 0xA000369C, 0xA00036A0, 0xA00036A4, 0xA00036A8, 0xA00036AC, 0xA00036B0, 0xA00036B4, 0xA00036B8, 0xA00036BC, 0xA00036C0, 0xA00036C4, 0xA00036C8, 0xA00036CC, 0xA00036D0]]]



#Max33461
maxadd = '0x77'

maxpage = ['0x00', '0x01', '0x02', '0x03', '0x04', '0x05', '0x06', '0x07', '0x08', '0x09', '0x0a', '0x0b', '0x0c', '0x0d', '0x0e', '0x0f']

maxreg = '0x8b'
maxregdiv = 1

maxwadd = [0xa00030f0, 0xa00030f4, 0xa00030f8, 0xa00030fc, 0xa0003100, 0xa0003104, 0xa0003108,0xa000310c, 0xa0003110, 0xa0003114, 0xa0003118, 0xa000311c, 0xa0003120, 0xa0003124, 0xa0003128, 0xa000312c, 0xa0003130]

burstlen = 100
burstvar = [0]*burstlen

## Requests I2C Value using SHELL
#
# Due to SMBus beeing unavailable on petalinux for Zedboards this short methode uses the subprocess libary to use ic2get from shell. Returns readable SI-float.
#
# @param dadd The device address
# @param radd The register address
# @param rdiv The devider needed to convert raw hex output.
def get_i2cValue(bus, dadd, radd, rdiv, mode):
	try:	
		p = sp.Popen(['i2cget', '-y', str(bus), dadd, radd, mode], stdout=sp.PIPE)#add , '-w' in final for 2byte read
		p.wait()
		#To make sure process is finished
		output, err = p.communicate()
		out = hex(int(float(int(output.replace('\n', ''), 16))/rdiv))
		return out
	except ValueError:
		## Cathing Errors
		#
		# Prints Error Message and return 0, if value conversion fails.
		print("Could not i2cget on " + str(bus) + ' ' + dadd + ' ' + radd + '! \n Please check device adress.')
		return hex(0b10000000000000000000000000000000) ##0x80000000 as error code

#readout for everything
def fullreadout():
	#tdks
	for i in range (len(tdkdevadd)):
		for j in range (len(tdkregadd)):
			var = get_i2cValue(mappedBusses[0], tdkdevadd[i], tdkregadd[j], tdkregdiv[j], 'w')
			os.system('devmem ' + str(tdkwadd[i][j]) + ' w ' + str(var))
 
	#max
	for j in range (len(maxpage)):
		os.system('i2cset -y ' + str(mappedBusses[0]) + ' ' + maxadd + ' 0x00 ' + maxpage[j])
		var = get_i2cValue(mappedBusses[0], maxadd, maxreg, maxregdiv, 'w' )
		os.system('devmem ' + str(maxwadd[j]) + ' w ' + str(var))
	os.system('i2cset -y ' + str(mappedBusses[0]) + ' ' + maxadd + ' 0x00 0x11')
        os.system('i2cset -y ' + str(mappedBusses[0]) + ' ' + maxadd + ' 0xf0 0x8000 w')
	var = get_i2cValue(mappedBusses[0], maxadd, '0x8d', maxregdiv, 'w' )
	os.system('devmem ' + str(maxwadd[-1]) + ' w ' + str(var))
 
	#minipod
	for k in range(1,5):
		for i in range (len(mipoadd)):	
			for j in range (len(miporeg)):
				if miporeg[j] == '0x1c':
					var = get_i2cValue(mappedBusses[k], mipoadd[i], miporeg[j], miporegdiv[j], 'b')
					os.system('devmem ' + str(mipowadd[k-1][i][j]) + ' w ' + str(var))
				else:
					var = get_i2cValue(mappedBusses[k], mipoadd[i], miporeg[j], miporegdiv[j], 'w')
					os.system('devmem ' + str(mipowadd[k-1][i][j]) + ' w ' + '0x' + (var[2:].zfill(4)[2:4]) + (var[2:].zfill(4)[0:2]))
	os.system('devmem ' + str(0xa00036d4) + ' w ' + str(hex(int(str(strftime("%s", time.localtime()))))))

##startup

##determine the correct i2c busses via i2cdetect
out = ''
try:
    p = sp.Popen(['i2cdetect','-l'], stdout=sp.PIPE)
    p.wait()
    out, err = p.communicate()
except ValueError:
    print('Faild to detect busses!!! Aborting!')
    sys.exit()

detBusses = out.split('\n')
mappedBusses = ['None']*5
print(mappedBusses)
for i in detBusses:
    if 'i2c-0-mux (chan_id 0)' in i:
        mappedBusses[0] = (i.split('\t')[0])[4:]
    if 'i2c-0-mux (chan_id 1)' in i:
        mappedBusses[1] = (i.split('\t')[0])[4:]
    if 'i2c-0-mux (chan_id 2)' in i:
        mappedBusses[2] = (i.split('\t')[0])[4:]
    if 'i2c-0-mux (chan_id 3)' in i:
        mappedBusses[3] = (i.split('\t')[0])[4:]
    if 'i2c-0-mux (chan_id 4)' in i:
        mappedBusses[4] = (i.split('\t')[0])[4:]
print(mappedBusses)

run = True
r = 1

while (run == True):
	fullreadout()
	print('Finished Cycle ' + str(r))
	r += 1
