import smbus
import time
import json

# Adressen der beiden MCP23017 Chips
AusgangRechts = 0x20  # Ausgang rechte Hälfte
AusgangLinks = 0x21  # Ausgang linke Hälfte
EingangRechts = 0x24  # Eingang rechte Hälfte
EingangLinks = 0x23  # Eingang linke Hälfte

# Register-Adressen für den MCP23017
IODIRA = 0x00  # Eingang / Ausgang A
IODIRB = 0x01  # Eingang / Ausgang B
GPIOA = 0x12   # GPIO A
GPIOB = 0x13   # GPIO B

# Initialisiere den I2C Bus
bus = smbus.SMBus(1)

RechtsA_ausgang = ["Z", "AA", "W", "AB", "AC", "AD", "AE", "AF"]
RechtsB_ausgang = ["Q", "U", "V", "T", "S", "R", "Y", "X"]

RechtsA_eingang = ["R", "T", "V", "X", "Z", "AB", "AD", "AE"]
RechtsB_eingang = ["Q", "S", "W", "U", "AA", "Y", "AC", "AF"]

LinksA_ausgang = ["C", "D", "E", "J", "F", "G", "H", "I"]
LinksB_ausgang = ["A", "B", "P", "O", "K", "L", "M", "N"]

LinksA_eingang = ["B", "D", "F", "H", "J", "K", "M", "I"]
LinksB_eingang = ["A", "C", "E", "G", "L", "N", "O", "P"]


array = []

def default():
    adressen = [AusgangRechts, AusgangLinks, EingangRechts, EingangLinks]

    # Schleife für alle Registeradressen (0x00 bis 0x15)
    for register in range(0x00, 0x16):
        for adresse in adressen:
            bus.write_byte_data(adresse, register, 0x00)

# Konfiguriere alle Pins auf Chip 1 als Ausgang (A und B)
def configure_chip1_as_output():
    bus.write_byte_data(AusgangRechts, IODIRA, 0x00)  # Setze alle Pins von A als Ausgang
    bus.write_byte_data(AusgangRechts, IODIRB, 0x00)  # Setze alle Pins von B als Ausgang
    
    bus.write_byte_data(AusgangLinks, IODIRA, 0x00)  # Setze alle Pins von A als Ausgang
    bus.write_byte_data(AusgangLinks, IODIRB, 0x00)  # Setze alle Pins von B als Ausgang

# Konfiguriere alle Pins auf Chip 2 als Eingang (A und B)
def configure_chip2_as_input():
    bus.write_byte_data(EingangRechts, IODIRA, 0xFF)  # Setze alle Pins von A als Eingang
    bus.write_byte_data(EingangRechts, IODIRB, 0xFF)  # Setze alle Pins von B als Eingang
    
    bus.write_byte_data(EingangLinks, IODIRA, 0xFF)  # Setze alle Pins von A als Eingang
    bus.write_byte_data(EingangLinks, IODIRB, 0xFF)  # Setze alle Pins von B als Eingang


# Hauptprogramm
def main():
    default()
    time.sleep(0.5)
    configure_chip1_as_output()
    configure_chip2_as_input()

    # Teste alle Pins auf Chip 1 (A0-A7, B0-B7)
    for pin in range(32):  # 0 bis 31
        #print(f"Setze Pin {pin} auf HIGH auf Chip 1")
        

        bus.write_byte_data(AusgangRechts, GPIOA, 0x00)
        bus.write_byte_data(AusgangRechts, GPIOB, 0x00)
        
        bus.write_byte_data(AusgangLinks, GPIOA, 0x00)
        bus.write_byte_data(AusgangLinks, GPIOB, 0x00)
        
        
        if pin < 16:
            # Setze den gewählten Pin auf HIGH
            if pin < 8:  # Pins A0-A7
                bus.write_byte_data(AusgangRechts, GPIOA, 1 << pin)
                aktuellAn = RechtsA_ausgang[pin]
            else:  # Pins B0-B7
                bus.write_byte_data(AusgangRechts, GPIOB, 1 << (pin - 8))
                aktuellAn = RechtsB_ausgang[pin - 8]
        else:
            # Setze den gewählten Pin auf HIGH
            if pin < 24:  # Pins A0-A7
                bus.write_byte_data(AusgangLinks, GPIOA, 1 << pin - 16)
                aktuellAn = LinksA_ausgang[pin - 16]
            else:  # Pins B0-B7
                bus.write_byte_data(AusgangLinks, GPIOB, 1 << (pin - 24))
                aktuellAn = LinksB_ausgang[pin - 24]
            
        #print("====================" + aktuellAn + "==========================")

        time.sleep(0.02)  # Kurze Pause, damit die Änderung sichtbar wird
        
        Wert_Rechts_A = bus.read_byte_data(EingangRechts, GPIOA)
        Wert_Links_A = bus.read_byte_data(EingangLinks, GPIOA)
        
        Wert_Rechts_B = bus.read_byte_data(EingangRechts, GPIOB)
        Wert_Links_B = bus.read_byte_data(EingangLinks, GPIOB)
        


        for j in range(8): # Lese 4*8=32 Pins
            bitmaske = 1 << j  # Erstelle eine Maske: 1, 2, 4, 8, 16, ...
            
            Bit_Rechts_A = bool(Wert_Rechts_A & bitmaske)  # Isoliere das entsprechende Bit
            Bit_Links_A = bool(Wert_Links_A & bitmaske)  # Isoliere das entsprechende Bit
            Bit_Rechts_B = bool(Wert_Rechts_B & bitmaske)  # Isoliere das entsprechende Bit
            Bit_Links_B = bool(Wert_Links_B & bitmaske)  # Isoliere das entsprechende Bit
            
            if Bit_Rechts_A == True:
                if aktuellAn != RechtsA_eingang[j]:
                    array.append([aktuellAn ,RechtsA_eingang[j]])
                #print("Gefunden: " + RechtsA_eingang[j])
                    
            if Bit_Links_A == True:
                if aktuellAn != LinksA_eingang[j]:
                    array.append([aktuellAn ,LinksA_eingang[j]])
                #print("Gefunden: " + LinksA_eingang[j])
                    
            if Bit_Rechts_B == True:
                if aktuellAn != RechtsB_eingang[j]:
                    array.append([aktuellAn ,RechtsB_eingang[j]])
                #print("Gefunden: " + RechtsB_eingang[j])
            
            if Bit_Links_B == True:
                if aktuellAn != LinksB_eingang[j]:
                    array.append([aktuellAn ,LinksB_eingang[j]])
                #print("Gefunden: " + LinksB_eingang[j])




    json_output = json.dumps(array)
    print(json_output)

if __name__ == "__main__":
    main()

