#TP3X4 Housekeeping Data Logger
#v01 Aug 16, 2021
#v02: Oct 25, 2021  Added file write of ASIC values


import time
import string
import socket
import sys
import os

#VREF is the HK ADC full-scale voltage
VREF =2500
#Current monitor scale factor
ISCALE = 1000/357 #amps per volt

hk_interval = 1

#run this under Python 3.x
if (sys.version_info < (3,0)):
	print("Must run under python 3.x")
	quit()

logfilename = "TP3X4_hklog.csv"
#Send to hard-coded IP address
#TARGET_IP_ADD = "192.168.1.255"
#KU105 expects commands on this port and will respond with housekeeping data to this port
UDP_HK_PORT= 60003
UDP_CMD_PORT= 60000
BYTES_IN_HK_PKT = 168

def flush_rx_buf():
    dumpcount = 0    
    #How big is the UDP buffer?  This is just guesswork
    while (dumpcount<32):
        try:
            #print (dumpcount)
            dumpbytes = sock.recvfrom(2048)
            dumpcount +=1
        except:
            break    

def sendit(payload):
    sock.sendto(bytes(payload), (TARGET_IP_ADD, UDP_CMD_PORT))   #AST
    time.sleep(.001)



print ("Timepix3 4chip Housekeeping Logger")
inp = input("subnet address x: 192.168.x.255 (1)")
if inp == "": inp = "1"
TARGET_IP_ADD = "192.168." + inp + ".255"

try :
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1) #TEST

    print ("Socket Created")
except socket.error as msg :
    print ('Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()    
sock.settimeout(10)

#Should not need to bind to the port, since we're not sending a reply.  But we do.
try:
#	sock.connect(("192.168.1.100",60003,"192.168.1.255",60002))
	sock.bind(("192.168.1.100", UDP_HK_PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()
     
print ('Socket bind complete')
print (' ')
print(sock)
print (' ')

try:
    fhand = open(logfilename, 'w')
except Exception as e:
    print (e)
    #continue

#Need to send out an HK command to get things started
#Why?
cmd_payload = bytearray(64)
for i in range(64): cmd_payload[i]=0
cmd_payload[0] = 0x20
cmd_payload[1] = hk_interval
#flush_rx_buf()
sendit(cmd_payload)


print("temp1\ttemp2\ttempF\tV33\tV25\tV18\tV0A\tV0D\tV1A\tV1D\tV2A\tV2D\tV3A\tV3D\tI0A\tI0D\tI1A\tI1D\tI2A\tI2D\tI3A\tI3D\t")
fhand.write("time,temp1,temp2,tempF,V33,V25,V18,V0A,V0D,V1A,V1D,V2A,V2D,V3A,V3D,I0A,I0D,I1A,I1D,I2A,I2D,I3A,I3D\n")
while (1):
    reply = sock.recvfrom(BYTES_IN_HK_PKT)
    print ("Bytes Received =" + str(len(reply[0])))
    now =time.ctime().split(" ")[3]
    fhand.write(now + ',')
    #print ("Bytes Received =" + str(len(reply[0])))
    bytesback = reply[0]
    #print(bytesback)
    #for n in range(BYTES_IN_HK_PKT):
    #    print (hex(int(bytesback[n])))
    val_array=[]
    #there are 36 values in all: 4 values read from each of 4 ASICs in bytes 4 to 35, and
    # 20 values starting at byte 36 read back from the ADCs, then 3 temperature values.  We'll display these
    for n in range(39):
        val_array.append(int(bytesback[2*n+4]) + 256*int(bytesback[2*n+5]))
        #print (hex(val_array[n]))
    #print(hex(val_array[20]),hex(val_array[21]))
    #drop the 3 LSBs
    temp1 = int(val_array[36]/8)
    if temp1 > 4095: temp1 = temp1 - 8192
    temp1 = temp1/16
    #drop the 3 LSBs
    temp2 = int(val_array[37]/8)
    if temp2 > 4095: temp2 = temp2 - 8192
    temp2 = temp2/16
    ##the temp from the FPGA XADC
    ftemp = val_array[38]
    ftemp = (((ftemp/65536)/0.00198421639) - 273.15)
    V18 = val_array[16]*VREF/4096
    V33 = val_array[17]*VREF/4096 * 2
    V25 = val_array[18]*VREF/4096 * 2
    #val_array[3] is unused
    I0A = val_array[20]*VREF/4096 * ISCALE
    I0D = val_array[21]*VREF/4096 * ISCALE
    I1A = val_array[22]*VREF/4096 * ISCALE
    I1D = val_array[23]*VREF/4096 * ISCALE
    I2A = val_array[24]*VREF/4096 * ISCALE
    I2D = val_array[25]*VREF/4096 * ISCALE
    I3A = val_array[26]*VREF/4096 * ISCALE
    I3D = val_array[27]*VREF/4096 * ISCALE
    V0A = val_array[28]*VREF/4096
    V0D = val_array[29]*VREF/4096
    V1A = val_array[30]*VREF/4096
    V1D = val_array[31]*VREF/4096
    V2A = val_array[32]*VREF/4096
    V2D = val_array[33]*VREF/4096
    V3A = val_array[34]*VREF/4096
    V3D = val_array[35]*VREF/4096
    
    #Write the ASIC analog values to file, but don't display- don't do this, not sure what these mean
    #for n in range(16):
    #    fhand.write('{:2.2f},'.format(val_array[n] * VREF/4096))

    #Print to screen and write to file
    print ('{:2.1f}\t'.format(temp1), end='')
    fhand.write('{:2.2f},'.format(temp1))
    print ('{:2.1f}\t'.format(temp2), end='')
    fhand.write('{:2.2f},'.format(temp2))
    print ('{:2.1f}\t'.format(ftemp), end='')
    fhand.write('{:2.2f},'.format(ftemp))
    print ('{:2.1f}\t'.format(V33),end='')
    fhand.write('{:2.2f},'.format(V33))
    print ('{:2.1f}\t'.format(V25),end='')
    fhand.write('{:2.2f},'.format(V25))
    print ('{:2.1f}\t'.format(V18),end='')
    fhand.write('{:2.2f},'.format(V18))
    
    print ('{:2.1f}\t'.format(V0A),end='')
    fhand.write('{:2.2f},'.format(V0A))
    print ('{:2.1f}\t'.format(V0D),end='')
    fhand.write('{:2.2f},'.format(V0D))
    print ('{:2.1f}\t'.format(V1A),end='')
    fhand.write('{:2.2f},'.format(V1A))
    print ('{:2.1f}\t'.format(V1D),end='')
    fhand.write('{:2.2f},'.format(V1D))
    print ('{:2.1f}\t'.format(V2A),end='')
    fhand.write('{:2.2f},'.format(V2A))
    print ('{:2.1f}\t'.format(V2D),end='')
    fhand.write('{:2.2f},'.format(V2D))
    print ('{:2.1f}\t'.format(V3A),end='')
    fhand.write('{:2.2f},'.format(V3A))
    print ('{:2.1f}\t'.format(V3D),end='')
    fhand.write('{:2.2f},'.format(V3D))
    
    print ('{:2.1f}\t'.format(I0A),end='')
    fhand.write('{:2.2f},'.format(I0A))
    print ('{:2.1f}\t'.format(I0D),end='')
    fhand.write('{:2.2f},'.format(I0D))
    print ('{:2.1f}\t'.format(I1A),end='')
    fhand.write('{:2.2f},'.format(I1A))
    print ('{:2.1f}\t'.format(I1D),end='')
    fhand.write('{:2.2f},'.format(I1D))
    print ('{:2.1f}\t'.format(I2A),end='')
    fhand.write('{:2.2f},'.format(I2A))
    print ('{:2.1f}\t'.format(I2D),end='')
    fhand.write('{:2.2f},'.format(I2D))
    print ('{:2.1f}\t'.format(I3A),end='')
    fhand.write('{:2.2f},'.format(I3A))
    print ('{:2.1f}\t'.format(I3D))
    fhand.write('{:2.2f},'.format(I3D))
    fhand.write('\n')
    
    


