#K1979_27Apr22_1841.py

import gpiozero as gp
import tkinter as tk
from MCP3008 import MCP3008

ws = tk.Tk()
ws.title('Schaefer K1979')
ws.geometry('940x350')
ws.config(bg='white')

# LabelFrame Size
box_height = 260
box_width = 160

# values for function my_map
in_min = 205
in_max = 1023
out_min = 0
out_max = 1023

# Analog to Digital Converter
# Channel 0 Volts
# Channel 1 Amps
adc = MCP3008()
v_lsb = adc.read( channel = 0 )
v_disp = 0
a_lsb = adc.read( channel = 1 )
a_disp = 0

# hardware LEDs and Buttons
# using Broadcom (BCM) GPIOZERO numbers
hwLedAC = gp.LED(18)        # AC_STAT_OK   HDR 12
hwBtnAC = gp.Button(5)      # AC_STAT      HDR 29
hwLedONcmd = gp.LED(23)     # ON_CMD_LED   HDR 16
hwLedDCout = gp.LED(24)     # DC_STAT_OK   HDR 18
hwBtnDCout = gp.Button(6)   # DC_STAT      HDR 31
hwBtnov = gp.Button(13)     # OV_STAT      HDR 33
hwLedov = gp.LED(16)        # OV_FAULT     HDR 36
hwBtnoc = gp.Button(19)     # OC_STAT      HDR 35
hwLedoc = gp.LED(20)        # OC_FAULT     HDR 38
hwBtnot = gp.Button(26)     # OT_STAT      HDR 37
hwLedot = gp.LED(21)        # OT_FAULT     HDR 40

# gui LEDs and Buttons
# guiACLed      AC input available
# guiOnCMDLed   P/S ON Command 
# guiLedDCout   P/S DC Output OK
# guiLedov      P/S OverVoltage Fault
# guiLedoc      P/S OverCurrent Fault
# guiLedot      P/S OverTemperature Fault

# gui LED images
redLed = tk.PhotoImage(file='redLed.png')
grnLed = tk.PhotoImage(file='grnLed.png')

# AC Power Input Functions
def acOn():
    hwLedAC.on()
    guiACLed.config(image=grnLed)
    
def acOff():
    hwLedAC.off()
    guiACLed.config(image=redLed)
    
# ON / OFF Control Functions
def onCmd():
    hwLedONcmd.on()
    guiOnCMDLed.config(image=grnLed)
    
def offCmd():
    hwLedONcmd.off()
    guiOnCMDLed.config(image=redLed)

# DC Output Status Functions
def dcOutOK():
    hwLedDCout.on()
    guiLedDCout.config(image=grnLed)

def dcOutFault():
    hwLedDCout.off()
    guiLedDCout.config(image=redLed)
    
# FAULTS Functions
def ovOK():
    hwLedov.off()
    #print("OV is OK")
    guiLedov.config(image=grnLed)

def ovFAULT():
    hwLedov.on()
    #print("OV is FAULTED")
    guiLedov.config(image=redLed)
    
def ocOK():
    hwLedoc.off()
    #print("OC is OK")
    guiLedoc.config(image=grnLed)

def ocFAULT():
    hwLedoc.on()
    #print("OC is FAULTED")
    guiLedoc.config(image=redLed)
    
def otOK():
    hwLedot.off()
    #print("OT is OK")
    guiLedot.config(image=grnLed)

def otFAULT():
    hwLedot.on()
    #print("OT is FAULTED")
    guiLedot.config(image=redLed)
    
# my_map transforms 4-20 mA voltage transducer ADC lsb's
# from 205-1023 to 0-1023
def my_map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)    

# refresh_volts updates the DC Output Volts reading every second
def refresh_volts():
    global v_lsb
    global v_disp
    global in_min
    global in_max
    global out_min
    global out_max
    v_lsb = adc.read( channel = 0 )
    v_disp = my_map(v_lsb, in_min, in_max, out_min, out_max)
    v_disp = int(v_disp * 1.96)
    label_volts.after(1000, refresh_volts)
    label_volts.config(text=v_disp)
  
# refresh_amps updates the DC Output Amps reading every second  
def refresh_amps():
    global a_lsb
    a_lsb = adc.read( channel = 1 )
    a_disp = a_lsb * 0.0049
    a_disp = format(a_disp, '.2f')
    label_amps.after(1000, refresh_amps)
    label_amps.config(text=a_disp)
#    OUT.configure(text=volts)
#    OUT.configure(text=amps)

# AC Power Available
PWR = tk.LabelFrame(ws, bd=7, background='white', text="AC Power", font=('Times', 18), relief="ridge", width=box_width, height=box_height, padx=10, pady=10)
PWR.grid_propagate(False)
guiACLed =tk.Label(PWR, image=redLed)
guiACLed.grid(row=1, column=0, pady=10)
acTxt = tk.Label(PWR, text="AC Input\nOK", bg='white', font=('Times', 16))
acTxt.grid(row=0, column=0, padx=10, pady=10)
PWR.place(x=50, y=50)

# GPIO 5 status from K1979
hwBtnAC.when_pressed = acOn
hwBtnAC.when_released = acOff

# Control: P/S On/Off
CTRL = tk.LabelFrame(ws, bd=7, background='white', text="Control", font=('Times', 18), relief="ridge", width=box_width, height=box_height, padx=10, pady=10)
CTRL.grid_propagate(False)
CTRL.place(x=215, y=50)
onButton=tk.Button(CTRL, text="Turn ON", command=onCmd, font=('Times', 16), bg="red", fg="white")
onButton.grid(row=0, column=0, pady=10)
offButton=tk.Button(CTRL, text="Turn OFF", command=offCmd, font=('Times', 16), bg="green", fg="white")
offButton.grid(row=1, column=0, pady=10)

# Status
STAT = tk.LabelFrame(ws, bd=5, background='white', text="Status", font=('Times', 18), relief="ridge", width=box_width, height=box_height, padx=10, pady=10)
STAT.place(x=380, y=50)
STAT.grid_propagate(False)
guiOnCMDLed = tk.Label(STAT, image=redLed)
guiOnCMDLed.grid(row=1, column=0, pady=10)
tk.Label(STAT, text="ON\nCommand", bg='white', font=('Times', 16)).grid(row=1, column=1, padx=10, pady=10)
guiLedDCout =tk.Label(STAT, image=redLed)
guiLedDCout.grid(row=2, column=0, pady=10)
tk.Label(STAT, text="DC\nOutput", bg='white', font=('Times', 16)).grid(row=2, column=1, padx=10, pady=10)

# GPIO 6 status from K1979
hwBtnDCout.when_pressed = dcOutOK
hwBtnDCout.when_released = dcOutFault

# Faults
FLTS = tk.LabelFrame(ws, bd=5, background='white', text="Faults", font=('Times', 18), relief="ridge", width=box_width, height=box_height, padx=10, pady=10)
FLTS.place(x=545, y=50)
FLTS.grid_propagate(False)
guiLedov = tk.Label(FLTS, image=grnLed)
guiLedov.grid(row=0, column=0, pady=10)
tk.Label(FLTS, text="Over\nVoltage", bg='white', font=('Times', 16)).grid(row=0, column=1, padx=10, pady=10)

guiLedoc = tk.Label(FLTS, image=grnLed)
guiLedoc.grid(row=1, column=0, pady=10)
tk.Label(FLTS, text="Over\nCurrent", bg='white', font=('Times', 16)).grid(row=1, column=1, padx=10, pady=10)
guiLedot = tk.Label(FLTS, image=grnLed)
guiLedot.grid(row=2, column=0, pady=10)
tk.Label(FLTS, text="Over\nTemp", bg='white', font=('Times', 16)).grid(row=2, column=1, padx=10, pady=10)

# GPIO 13 status from K1979 OverVoltage
hwBtnov.when_pressed = ovOK
hwBtnov.when_released = ovFAULT

# GPIO 19 status from K1979 OverCurrent
hwBtnoc.when_pressed = ocOK
hwBtnoc.when_released = ocFAULT

# GPIO 26 status from K1979 OverTemp
hwBtnot.when_pressed = otOK
hwBtnot.when_released = otFAULT


# Volts and Amps Output
OUT = tk.LabelFrame(ws, bd=5, background='white', text="DC Output", font=('Times', 18), relief="ridge", width=box_width + 10, height=box_height, padx=10, pady=10)
OUT.place(x=710, y=50)
OUT.grid_propagate(False)

frameV = tk.LabelFrame(OUT, background='white', text="Volts", font=('Times', 16) )
frameV.grid(row=0, column=0) 
label_volts = tk.Label(frameV, background='white', text=v_disp, font=('Times', 25))#.grid(row=0, column=1, padx=10, pady=10)
label_volts.pack(padx=35, pady=20)

frameA = tk.LabelFrame(OUT, background='white', text="Amps", font=('Times', 16))
frameA.grid(row=1, column=0) 
label_amps = tk.Label(frameA, background='white', text=a_disp, font=('Times', 25))#.grid(row=1, column=1, padx=10, pady=10)
label_amps.pack(padx=35, pady=20)

# read ADC and update display every second
label_volts.after(1000, refresh_volts)
label_amps.after(1000, refresh_amps)

# run forever
ws.mainloop()