# i2c_master_1.py
# 15.11.2025
# www.g-heinrichs.de


from sys import exit
from utime import sleep_ms, sleep_us
from machine import Pin

SDA = Pin(21, Pin.OUT, value = 1) # in get_ACK_signal(): Pin.IN
SCL = Pin(22, Pin.OUT, value = 1) # unverändert

# clock_time = 1000 # in us; Bit-Länge = 2 * clock_time
clock_time = 500 # funktioniert, gesamte Übertragungsdauer ca. 20 ms
# clock_time = 200 # funktioniert auch, aber Diagramm nicht mehr so schön
# clock_time = 100 # funktioniert auch, aber Diagramm nicht mehr so schön

address = 176 # 8-Bit_Adresse
# address_list = [1, 0, 1, 1, 0, 0, 0, 0] # 176, RW-Bit = 0 (WRITE: Master sendet Datenbyte an Slave)
# address = 112 # 8-Bit_Adresse von PCF8574

######################### Funktionen #########################

def num_to_byte_list(num):
    pot_2_list = [128, 64, 32, 16, 8, 4, 2, 1]
    byte_list = []
    for i in range(8):
        byte_list.append((num & pot_2_list[i])//pot_2_list[i])
    return byte_list

def start():
    SCL.value(1)
    SDA.value(1)
    sleep_us(clock_time)
    SDA.value(0)
    sleep_us(clock_time)
    SCL.value(0)
    sleep_us(clock_time)    
    
def send_bit(bit):
    SCL.value(0)
    SDA.value(bit)
    sleep_us(clock_time)
    SCL.value(1)
    sleep_us(clock_time)
    SCL.value(0)
    
def send_byte(byte_list):
    for bit in byte_list:
        send_bit(bit)
         
def get_ACK_signal():
    global SDA
    SDA = Pin(21, Pin.IN)
    SCL.value(0) #?
    sleep_us(clock_time)
    SCL.value(1)    
    ack_bit = SDA.value()
    sleep_us(clock_time)
    SCL.value(0)     
    SDA = Pin(21, Pin.OUT)
    SDA.value(1)
    return ack_bit

def stop():
    # Stop-Signal: erst SCL und dann SDA "loslassen"
    sleep_us(clock_time)
    SDA = Pin(21, Pin.IN)
    sleep_us(clock_time)
    SCL = Pin(22, Pin.IN)
        
######################### Hauptprogramm #########################

print('I2C-Master gestartet')
data = int(input('Data:'))

address_list = num_to_byte_list(address)
# print('address_list =', address_list)
data_list = num_to_byte_list(data)
# print('data_list =', data_list)

start()
send_byte(address_list)
# print('gesendet: data =', data_list, '; empfangen: ACK =', get_ACK_signal())

ACK_signal = get_ACK_signal()
if ACK_signal == 1: 
    print('address: NACK')
    stop() # testen!!!
    print('Stop-Signal gesendet')
    exit()  
else: # ACK
    # print('address: ACK')    
    send_byte(data_list)

ACK_signal = get_ACK_signal()

if ACK_signal == 0:
    print('Data_ACK erhalten')
else:
    print('Kein Data_ACK erhalten')    

# Stop-Signal: erst SCL und dann SDA "loslassen"
stop()
print('I2C-Master fertig')    
    