from machine import Pin, UART
import time

# ============================================================
# PIN-EMPFEHLUNGEN (Pico 2 W)
# ============================================================
# UART für DFPlayer-kompatibles MP3-Modul
UART_ID = 1
UART_TX_GPIO = 8   # Pico TX -> MP3 RX
UART_RX_GPIO = 9   # Pico RX <- MP3 TX

# Buttons (jeweils gegen GND, interner Pull-Up)
GPIO_CRY   = 2
GPIO_WHIM  = 3
GPIO_GIG   = 4
GPIO_STOP  = 5
GPIO_PEE   = 6

# Pumpen-Ausgang (später Treiber/ULN2003 etc.)
GPIO_PUMP_OUT = 7

# ============================================================
# DFPLAYER / MP3-MODUL SETUP (laut Datenblatt 9600 baud, 3.3V TTL)
# ============================================================
uart = UART(
    UART_ID,
    baudrate=9600,
    bits=8,
    parity=None,
    stop=1,
    tx=Pin(UART_TX_GPIO),
    rx=Pin(UART_RX_GPIO),
)

def dfplayer_cmd(cmd, param=0, feedback=False):
    """
    DFPlayer Serial Protocol:
    0x7E 0xFF 0x06 CMD FB PAR_H PAR_L CHK_H CHK_L 0xEF
    """
    start = 0x7E
    ver   = 0xFF
    ln    = 0x06
    fb    = 0x01 if feedback else 0x00
    ph    = (param >> 8) & 0xFF
    pl    = param & 0xFF

    checksum = -(ver + ln + cmd + fb + ph + pl) & 0xFFFF
    ch = (checksum >> 8) & 0xFF
    cl = checksum & 0xFF

    packet = bytes([start, ver, ln, cmd, fb, ph, pl, ch, cl, 0xEF])
    uart.write(packet)

def df_set_volume(vol):
    """Volume 0..30"""
    vol = max(0, min(30, vol))
    dfplayer_cmd(0x06, vol)

def df_play_mp3(track_no):
    """
    Play track from /mp3 folder:
    /mp3/0001.mp3 -> track_no=1
    /mp3/0002.mp3 -> track_no=2
    ...
    """
    dfplayer_cmd(0x12, track_no)

def df_stop():
    """Stop playback"""
    dfplayer_cmd(0x16, 0)

def df_pause():
    """Pause (optional)"""
    dfplayer_cmd(0x0E, 0)

def df_resume():
    """Resume (optional)"""
    dfplayer_cmd(0x0D, 0)

# Kurze Boot-Wartezeit, damit Modul initialisieren kann
time.sleep_ms(800)
df_set_volume(30)  # 0..30, ggf. anpassen

# ============================================================
# BUTTONS SETUP
# ============================================================
btn_cry  = Pin(GPIO_CRY,  Pin.IN, Pin.PULL_UP)
btn_whim = Pin(GPIO_WHIM, Pin.IN, Pin.PULL_UP)
btn_gig  = Pin(GPIO_GIG,  Pin.IN, Pin.PULL_UP)
btn_stop = Pin(GPIO_STOP, Pin.IN, Pin.PULL_UP)
btn_pee  = Pin(GPIO_PEE,  Pin.IN, Pin.PULL_UP)

pump_out = Pin(GPIO_PUMP_OUT, Pin.OUT)
pump_out.value(0)

# Entprellung
DEBOUNCE_MS = 80

last_ms = {
    "cry": 0,
    "whim": 0,
    "gig": 0,
    "stop": 0,
    "pee": 0,
}

def is_pressed(pin: Pin) -> bool:
    """Active-low button"""
    return pin.value() == 0

def allow(key: str) -> bool:
    now = time.ticks_ms()
    if time.ticks_diff(now, last_ms[key]) > DEBOUNCE_MS:
        last_ms[key] = now
        return True
    return False

# ============================================================
# PIPI-LOGIK (erstmal als Impuls, bühnenfreundlicher als 'solange gedrückt')
# ============================================================
PIPI_PULSE_MS = 900   # Dauer Pumpen-Impuls (später anpassen)
pipi_until = 0

def pipi_trigger():
    global pipi_until
    pipi_until = time.ticks_add(time.ticks_ms(), PIPI_PULSE_MS)

# ============================================================
# MAIN LOOP
# ============================================================
while True:
    # STOP hat Priorität (soll sofort alles beenden)
    if is_pressed(btn_stop) and allow("stop"):
        df_stop()
        pipi_until = 0
        pump_out.value(0)

    # Sounds
    if is_pressed(btn_cry) and allow("cry"):
        df_play_mp3(1)   # /mp3/0001.mp3

    if is_pressed(btn_whim) and allow("whim"):
        df_play_mp3(2)   # /mp3/0002.mp3

    if is_pressed(btn_gig) and allow("gig"):
        df_play_mp3(3)   # /mp3/0003.mp3

    # Pipi-Trigger (Impuls)
    if is_pressed(btn_pee) and allow("pee"):
        pipi_trigger()

    # Pumpen-Ausgang entsprechend Impulszeit
    if time.ticks_diff(pipi_until, time.ticks_ms()) > 0:
        pump_out.value(1)
    else:
        pump_out.value(0)

    time.sleep_ms(10)
