#RPi5GPIO.py contains the functions listed below
#By D@CC 
#Purpose: to deprecate RPi.GPIO for the RPi 5B
#Source: https://ephotocaption.com/a/213/213.html
#Created  on 2024AJan18
#Modified on 2024AJan19
#Status: compatible with vsn I on the RPi5B, CM4
# PB down turns LED on with both RPi.GPIO and RPi5GPIO
# GPIO.BCM,GPIO.IN,GPIO.OUT, GPIO.HIGH, GPIO.LOW
# GPIO.setmode, GPIO.setup, GPIO.input, GPIO.output
# unity #which is used to support GPIO.BCM, GPIO.IN,
#        GPIO.OUT, GPIO.HIGH and GPIO.LOW
def BCM(parm="GPIO.BCM"):
    return parm
def IN(parm="GPIO.IN"):
    return parm
def OUT(parm="GPIO.OUT"):
    return parm
def HIGH(parm="GPIO.HIGH"):
    return parm
def LOW(parm="GPIO.LOW"):
    return parm
def PUD_UP(parm="GPIO.PUD_UP"):
    return parm
def PUD_DOWN(parm="GPIO.PUD_DOWN"):
    return parm
def PUD_NONE(parm="GPIO.PUD_NONE"):
    return parm
def cleanup():
    print("RPi7GPIO cleanup() null")
    return
def unity(func):
    #by D@CC on 2024AJan18
    #Purpose: return "constants" such as GPIO.BCM, GPIO.HIGH etc
    #strReturn=func()
    try:
        strReturn=func()
    except:
        strReturn=True
    finally:
        pass
    #try end
    if strReturn=="GPIO.PUD_UP":
        return strReturn
    #if end
    if strReturn=="GPIO.HIGH": strReturn=func(parm=True)
    if strReturn=="GPIO.LOW" : strReturn=func(parm=False)
    return strReturn
#/unity.py

def setmode(Qmode):
    global gix_Qmode
    global gix_QinOut
    global gix_PINs
    global gix_datetime
    RPi5GPIO_vsn="4A21 by D@CC"
    gix_QinOut={}      #initialize an empty dict
    gix_PINs=[0]*41    #initialize an empty pin list
#      BEWARE OF PIN # 0,1,40 and 41
    mode=unity(Qmode)
    if mode=="GPIO.BCM":
        gix_Qmode=mode
        gix_datetime = "2024-01-19 01:25:40"
        #print("@5.45 set gix_datetime=",gix_datetime)
        print("using RPi5GPIO (gpiozero) vsn",RPi5GPIO_vsn)
        print(" Issue 01: ignoring Pull_Up/Downs.")
        print(" Issue 02: reads buttons as True/False not 0/1.")
    else:
        print("RPi5GPIO ERROR mode must be GPIO.BCM")
    #if end
    return
#def end
def setup(QQPin,QQinOut,pull_up_down="GPIO.PUD_NONE"):
    #Purpose: Save LED or Button type for QPin
    from gpiozero import LED,Button
    global gix_QinOut   #matrix of directions
    global gix_PINs     #list of Pin object
    QPin=QQPin
    #print("@5.79, QPin:",QPin)
    QinOut=unity(QQinOut)
    #print("@5.81, QinOut:",QinOut)
    #Only do the following for GPIO.IN
    if QinOut== "GPIO.IN":
        #print("@5.84 processing PUD")
        isInOut = False
        #print("@5.86,pull_up_down:",pull_up_down)
        # if pull_up_down=="GPIO.PUD_UP")
        # must use Button(... , pull_up = True)
        # so set pullUpDown=unity(pull_up_down)
        pullUpDown="None"
        isUpDown=False
        pullUpDown=unity(pull_up_down)
        #print("@5.93 pullUpDown:",pullUpDown)
        if pullUpDown=="GPIO.PUD_UP" or \
            pullUpDown=="GPIO.PUD_DOWN": isUpDown=True
        if pullUpDown=="GPIO.PUD_NONE": isUpDown=False
        if isUpDown :
            #must save the PUD
            print("@5.99 pullUpDown:",pullUpDown)
            #a=input()
            pass
        else:
            #print("@5.103 no PUD")
            pass
        #if end
    #if end
            
            
            
    #print("@5.109,QPin:",QPin)
    #print("@5.110,QinOut:",unity(QinOut))
    IO="NA"
    inOrOut=unity(QQinOut)
    if inOrOut=="GPIO.IN"  : IO="Button"; isInOut=True
    if inOrOut=="GPIO.OUT" : IO="LED" ;   isInOut=True
    if QPin>0 and QPin<41 : isInOut=True
    #print("@5.116, isInOut:",isInOut)
    #print("@5.117, QPin:",QPin)




    
    
    if isInOut:                        #if QPin is valid
        #print("@5.125, unity(QinOut):",unity(QinOut))
        #print("@5.126")
    
    
        if not (inOrOut =="GPIO.IN"):   #if Pin is not IN ie is a LED
            #print("@5.130, IO:",IO)
            gix_QinOut[QPin]=IO
            gix_PINs[QPin]=LED(QPin) # create LED object
        else:
            #it must be a Button
            #print("@5.135, IO:",IO)
            gix_QinOut[QPin]=IO
            #print("@5.137 Must add Pud to Button creation")
            #print("@5.138 pullUpDown:",pullUpDown)
            pudText=""   #no pud is the default
            
            if pullUpDown=="GPIO.PUD_UP" :
                pudText=',pull_up = True,bounce_time= None'
                #print("@5.143 gpiozero text:",pudText)
            #if end
                
            if pullUpDown=="GPIO.PUD_DOWN" :
                pudText=',pull_up = False,bounce_time= None'            
                #print("@5.148 gpiozero text:",pudText)
            #if end
            #if pullUpDown=="GPIO.PUD_NONE": pass
            txtGZ_QPinSetUp=str(QPin)+pudText
            #print("@5.152, txtGZ_QPinSetUp:",txtGZ_QPinSetUp)
            pyExec="gix_PINs[QPin] =Button(QPin"+pudText+")"
            #print("@5.154, pyExec:",pyExec)
            gix_PINs[QPin] =Button(QPin)   # create Button object in gix_PINs wo pud
            #  should be python3 exec function
            code='print("test exec()")'
            #exec(code)
            
            #print("@6.160 code was:",code)
            #exec(pyExec)  # python3 exec(code)
            #print("RPi5GPIO has set up Button(QPin)")
        #if end
    #if end
    #print("@5.165 gix_QinOut",gix_QinOut)
    return
#def end
def output(QPin,TorF):
    from gpiozero import LED,Button
    global gix_QinOut
    global gix_PINs
    #print("@5.172 into output")
    #print("@5.173 QPin:",QPin)
    #print("@5.174 TorF:",TorF)
    if QPin>0 and QPin<41 :
        #process output
        dir= gix_QinOut[QPin]
        #print("@5.178 dir:",dir)
        isValidDir=False
        if dir=="LED":
            isValidDir=True
            if TorF :  #True
                #print("on")
                gix_PINs[QPin].on()
            else:
                #print("off")
                gix_PINs[QPin].off()
            #if end
        #if end
        if dir=="NA":
            isValidDir=True
            print("RPi5GPIO ERROR dir cannout be NA")
        #if end
        if not isValidDir:
            print("RPi5GPIO ERROR invalid Dir: is output Pin a Button?")  
        #if end        
    else:
        print("RPi5GPIO ERROR Bad Pin")
    #if end
#def end
        
        
def input(QQPin):
    from gpiozero import LED,Button
    #Purpose: read button, return True if Pressed
    #                                return False if Not Pressed
    global gix_QinOut
    global gix_PINs
    QPin=int(QQPin)
    #print("@5.210: QPin:",QPin)
    if QPin>0 and QPin<41 :
        #process input
        dir= gix_QinOut[QPin]
        if dir=="Button":
            # read Button and return True or False
            #print("@216: QPin:",QPin)
            if gix_PINs[QPin].is_pressed :  #is this Button Pressed
                #print("@5.218 RPi5GPIO button was pressed")
                return False
            else:
                #print("@5.221 RPi5GPIO button was NOT pressed")
                return True
            #if end
        else:
            print("RPi5GPIO ERROR Input cannot be LED")  
        #if end     
    else:
        print("RPi5GPIO ERROR Bad Pin")
    #if end
#def end