from machine import UART, Pin
import st7789
import tft_config
import NotoSans_32 as font
import _thread
import time

def initDisplay():
    # Called whenever the background changes
    global fg, bg, width, w
    height = tft.height()
    width = tft.width()
    w = int(tft.write_len(font, "ESP")/2)
    tft.fill(bg)
    tft.rect(0, 0, width, height, fg)
    tft.vline(int(width/3), 0, 90, fg)
    tft.vline(2*int(width/3), 0, 90, fg)
    tft.hline(0, 90, width, fg)
    tft.write(font, "RP0", int(width/6)-w, 10, fg, bg)
    tft.write(font, "RP1", 3*int(width/6)-w, 10, fg, bg)
    tft.write(font, "ESP", 5*int(width/6)-w, 10, fg, bg)

# RP2040 Threads
def RP0():
    global zero, fg, bg, width, w
    line = ''
    n0 = 0
    h = 30
    x = int(width/6)-w+8
    y = 50
    counter = 0
    pushed = False
    start = time.ticks_ms()
    while True:
        # Watch time flowing
        if time.ticks_diff(time.ticks_ms(), start) > 1000:
            start = time.ticks_ms()
            counter += 1
            count = 'time: '+str(counter)+'s'
            tft.fill_rect(55, 100, 160, 30, bg)
            tft.write(font, count, 55, 100, fg, bg)

        # Display core 0
        tft.fill_rect(x, y, 2*w, h, bg)
        tft.write(font, str(n0), x, y, fg, bg)
        n0 += 1
        if n0 == 100: n0 = 0
                
        # Display ESP32
        start32 = time.ticks_ms()
        while time.ticks_diff(time.ticks_ms(), start32) < 234:
            # Process incoming uart message, if any: change bg color, change led status, display message
            while ESP32.any() > 0:
                buf = ESP32.readline()
                line += buf.decode("utf-8")
            if '#' in line:
                # Change value
                tft.fill_rect(5*int(width/6)-w+8, y, 2*w+2, h, bg)
                tft.write(font, line[:-1], 5*int(width/6)-w+8, y, fg, bg)
                led.value(not led.value())
                line = ''
            elif "=" in line:
                # Change background color
                print(line)
                [r,g,b]=[int(s) for s in line.split() if s.isdigit()]
                bg = st7789.color565(r, g, b)
                initDisplay()
                line = ''
                        
            # Manage button
            state = right_button.value()
            if state == False: # button pushed
                if not pushed:
                    startb = time.ticks_ms()
                pushed = True
            elif pushed:
                pushed = False
                if time.ticks_diff(time.ticks_ms(), startb) > 500: # long push
                    zero = True
                else: # short push
                    n0 = 0

def RP1():
    # Change and display RP1 value
    global zero, width, fg, bg
    time.sleep_ms(50)
    n1 = 0
    h = 30
    x = 3*int(width/6)-w+8
    y = 50
    while True:
        start = time.ticks_ms()
        n1 += 1
        if n1 == 100: n1 = 0
        tft.fill_rect(x, y, 2*w, h, bg)
        tft.write(font, str(n1), x, y, fg, bg)
        while time.ticks_diff(time.ticks_ms(), start) < 1524:
            # Check button to send command to ESP32
            state = left_button.value()
            if state == False:
                ESP32.write('z')
            # Check if long press on right button to zero RP1 count
            if zero:
                n1 = -1
                zero = False

# Init buttons
right_button = Pin (7, Pin.IN, Pin.PULL_UP)
left_button  = Pin (6, Pin.IN, Pin.PULL_UP)

# Init red LED
led = Pin(25, Pin.OUT)
led.off()

# Init display
tft = tft_config.config(1)
tft.init()
bg = st7789.BLUE
fg = st7789.WHITE
initDisplay()

# Init thread core 1
zero = False
_thread.start_new_thread(RP1,())

# Init UART
ESP32 = UART(1, baudrate=38400, tx=Pin(8), rx=Pin(9), cts=Pin(10), rts=Pin(11))


RP0()

