import tkinter as tk
from tkinter import ttk
import time

class Dec7447Simulator:
    """
    7447 BCD to Seven-Segment Decoder/Driver 邏輯核心
    """
    def __init__(self):
        # 7447 的輸出為 Active LOW (0 代表點亮，1 代表熄滅)
        # 陣列順序為 [a, b, c, d, e, f, g]
        self.FONT_MAP = {
            0:  [0, 0, 0, 0, 0, 0, 1], # 顯示 0
            1:  [1, 0, 0, 1, 1, 1, 1], # 顯示 1
            2:  [0, 0, 1, 0, 0, 1, 0], # 顯示 2
            3:  [0, 0, 0, 0, 1, 1, 0], # 顯示 3
            4:  [1, 0, 0, 1, 1, 0, 0], # 顯示 4
            5:  [0, 1, 0, 0, 1, 0, 0], # 顯示 5
            6:  [1, 1, 0, 0, 0, 0, 0], # 顯示 6 (無 a 段，經典 7447 字型)
            7:  [0, 0, 0, 1, 1, 1, 1], # 顯示 7
            8:  [0, 0, 0, 0, 0, 0, 0], # 顯示 8
            9:  [0, 0, 0, 1, 1, 0, 0], # 顯示 9 (無 d 段，經典 7447 字型)
            10: [1, 1, 1, 0, 0, 1, 0], # 無效 BCD 10 (7447 特殊符號)
            11: [1, 1, 0, 0, 1, 1, 0], # 無效 BCD 11 (7447 特殊符號)
            12: [1, 0, 1, 1, 0, 0, 0], # 無效 BCD 12 (7447 特殊符號)
            13: [0, 1, 1, 0, 1, 0, 0], # 無效 BCD 13 (7447 特殊符號)
            14: [1, 1, 1, 0, 0, 0, 0], # 無效 BCD 14 (7447 特殊符號)
            15: [1, 1, 1, 1, 1, 1, 1], # 無效 BCD 15 (全熄滅)
        }

    def decode(self, dcba_val, lt_n=1, rbi_n=1, bi_rbo_n=1):
        """
        模擬 7447 解碼邏輯
        """
        # 1. BI (Blanking Input) 為低電位時，強制所有輸出熄滅，忽略其他所有輸入
        if bi_rbo_n == 0:
            return [1, 1, 1, 1, 1, 1, 1], 0, "BI 強制消隱狀態"

        # 2. LT (Lamp Test) 為低電位時（且 BI 為高電位），強制所有段點亮（顯示 8）
        if lt_n == 0:
            return [0, 0, 0, 0, 0, 0, 0], 1, "LT 燈泡測試狀態"

        # 3. 當輸入 BCD 為 0 且 RBI 腳位為低電位時，觸發零消除 (Blanking)
        if dcba_val == 0 and rbi_n == 0:
            return [1, 1, 1, 1, 1, 1, 1], 0, "RBI 零消除啟動 (Blanking)"

        # 4. 正常解碼模式
        segments = self.FONT_MAP.get(dcba_val, [1, 1, 1, 1, 1, 1, 1])
        return segments, 1, "正常解碼模式"

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("7447 數位邏輯與七段顯示器教學展示系統")
        self.geometry("1100x750")
        self.configure(bg="#0f172a") # 深 slate 色背景
        self.resizable(False, False)

        # 晶片邏輯實體
        self.simulator = Dec7447Simulator()

        # 當前硬體狀態變數
        self.val = 0
        self.lt = 1
        self.rbi = 1
        self.bi_rbo = 1
        self.auto_cycle = False
        self.cycle_speed = 1000 # 毫秒

        # 配色定義
        self.COLOR_BG = "#0f172a"
        self.COLOR_CARD = "#1e293b"
        self.COLOR_ACCENT = "#3b82f6"
        self.COLOR_GREEN = "#10b981"
        self.COLOR_RED_ON = "#ef4444"
        self.COLOR_RED_OFF = "#331015"
        self.COLOR_HIGH = "#f43f5e" # 高電位粉紅紅
        self.COLOR_LOW = "#3b82f6"  # 低電位天空藍

        self._create_widgets()
        self._update_all()

    def _create_widgets(self):
        # 標題列
        title_frame = tk.Frame(self, bg=self.COLOR_BG, pady=15)
        title_frame.pack(fill=tk.X)
        lbl_title = tk.Label(title_frame, text="7447 BCD 解碼器與七段顯示器模擬系統", 
                             font=("Microsoft JhengHei", 24, "bold"), fg="#ffffff", bg=self.COLOR_BG)
        lbl_title.pack()
        lbl_sub = tk.Label(title_frame, text="高職電機電子電子群數位邏輯實務教材 | Google AI 核心重製版", 
                            font=("Microsoft JhengHei", 12), fg="#94a3b8", bg=self.COLOR_BG)
        lbl_sub.pack(pady=5)

        # 主顯示區塊 (左右分欄)
        main_frame = tk.Frame(self, bg=self.COLOR_BG)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

        # 左欄：視覺化面板 (Canvas 繪圖)
        left_frame = tk.Frame(main_frame, bg=self.COLOR_BG)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))

        # 1. 七段顯示器 Canvas 元件
        led_card = tk.LabelFrame(left_frame, text="七段顯示器實體模擬 (共陽極 CA)", 
                                 font=("Microsoft JhengHei", 12, "bold"), fg=self.COLOR_GREEN, bg=self.COLOR_CARD, bd=2, relief=tk.FLAT)
        led_card.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        self.led_canvas = tk.Canvas(led_card, bg="#020617", bd=0, highlightthickness=0)
        self.led_canvas.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 2. 7447 晶片引腳動態展示 Canvas
        chip_card = tk.LabelFrame(left_frame, text="7447 晶片實體引腳與邏輯電位監視", 
                                  font=("Microsoft JhengHei", 12, "bold"), fg=self.COLOR_ACCENT, bg=self.COLOR_CARD, bd=2, relief=tk.FLAT)
        chip_card.pack(fill=tk.BOTH, expand=True)
        
        self.chip_canvas = tk.Canvas(chip_card, bg="#020617", bd=0, highlightthickness=0, height=220)
        self.chip_canvas.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 右欄：控制面板 (按鈕與控制項)
        right_frame = tk.Frame(main_frame, bg=self.COLOR_BG, width=420)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, padx=(10, 0))
        right_frame.pack_propagate(False)

        # 1. 快速 BCD 選擇 (0-15 按鈕網格)
        bcd_card = tk.LabelFrame(right_frame, text="快速 BCD 輸入選擇", 
                                 font=("Microsoft JhengHei", 12, "bold"), fg="#ffffff", bg=self.COLOR_CARD, bd=1, relief=tk.FLAT)
        bcd_card.pack(fill=tk.X, pady=(0, 10))

        grid_frame = tk.Frame(bcd_card, bg=self.COLOR_CARD, padx=10, pady=10)
        grid_frame.pack()

        self.bcd_buttons = []
        for i in range(16):
            btn = tk.Button(grid_frame, text=f"{i}", font=("Consolas", 12, "bold"), width=4, height=1,
                            bg="#334155", fg="#f8fafc", activebackground=self.COLOR_ACCENT, activeforeground="#ffffff",
                            relief=tk.FLAT, command=lambda x=i: self._set_bcd_value(x))
            btn.grid(row=i//4, column=i%4, padx=6, pady=6)
            self.bcd_buttons.append(btn)

        # 2. 單 bit 二進制開關
        bit_card = tk.LabelFrame(right_frame, text="二進制輸入微調 (D, C, B, A Switches)", 
                                 font=("Microsoft JhengHei", 12, "bold"), fg="#ffffff", bg=self.COLOR_CARD, bd=1, relief=tk.FLAT)
        bit_card.pack(fill=tk.X, pady=(0, 10))

        bit_inner = tk.Frame(bit_card, bg=self.COLOR_CARD, padx=10, pady=10)
        bit_inner.pack(fill=tk.X)

        self.bit_vars = [tk.IntVar(value=0) for _ in range(4)] # [D, C, B, A]
        bit_labels = ['D (8)', 'C (4)', 'B (2)', 'A (1)']
        self.bit_buttons = []

        for i in range(4):
            btn = tk.Button(bit_inner, text=f"{bit_labels[i]}\nLOW (0)", font=("Microsoft JhengHei", 10, "bold"),
                            bg=self.COLOR_LOW, fg="#ffffff", width=8, height=2, relief=tk.FLAT,
                            command=lambda idx=i: self._toggle_bit(idx))
            btn.pack(side=tk.LEFT, expand=True, padx=5)
            self.bit_buttons.append(btn)

        # 3. 系統控制腳位切換
        ctrl_card = tk.LabelFrame(right_frame, text="7447 系統控制引腳 (Active LOW)", 
                                  font=("Microsoft JhengHei", 12, "bold"), fg="#ffffff", bg=self.COLOR_CARD, bd=1, relief=tk.FLAT)
        ctrl_card.pack(fill=tk.X, pady=(0, 10))

        ctrl_inner = tk.Frame(ctrl_card, bg=self.COLOR_CARD, padx=10, pady=10)
        ctrl_inner.pack(fill=tk.X, expand=True)

        # LT_N Button
        self.btn_lt = tk.Button(ctrl_inner, text="LT (燈泡測試)\nHIGH (1)", font=("Microsoft JhengHei", 9, "bold"),
                                bg=self.COLOR_HIGH, fg="#ffffff", width=12, height=2, relief=tk.FLAT,
                                command=self._toggle_lt)
        self.btn_lt.pack(side=tk.LEFT, expand=True, padx=3)

        # RBI_N Button
        self.btn_rbi = tk.Button(ctrl_inner, text="RBI (前導消隱)\nHIGH (1)", font=("Microsoft JhengHei", 9, "bold"),
                                 bg=self.COLOR_HIGH, fg="#ffffff", width=12, height=2, relief=tk.FLAT,
                                 command=self._toggle_rbi)
        self.btn_rbi.pack(side=tk.LEFT, expand=True, padx=3)

        # BI/RBO_N Button
        self.btn_bi = tk.Button(ctrl_inner, text="BI/RBO (消隱控制)\nHIGH (1)", font=("Microsoft JhengHei", 9, "bold"),
                                bg=self.COLOR_HIGH, fg="#ffffff", width=12, height=2, relief=tk.FLAT,
                                command=self._toggle_bi)
        self.btn_bi.pack(side=tk.LEFT, expand=True, padx=3)

        # 4. 系統自動展示控制與當前資訊
        info_card = tk.LabelFrame(right_frame, text="動態 Demo 與解碼狀態即時監控", 
                                  font=("Microsoft JhengHei", 12, "bold"), fg=self.COLOR_GREEN, bg=self.COLOR_CARD, bd=1, relief=tk.FLAT)
        info_card.pack(fill=tk.BOTH, expand=True)

        info_inner = tk.Frame(info_card, bg=self.COLOR_CARD, padx=15, pady=10)
        info_inner.pack(fill=tk.BOTH, expand=True)

        self.btn_demo = tk.Button(info_inner, text="▶ 啟動 BCD 自動展示", font=("Microsoft JhengHei", 11, "bold"),
                                  bg=self.COLOR_GREEN, fg="#ffffff", height=1, relief=tk.FLAT, command=self._toggle_demo)
        self.btn_demo.pack(fill=tk.X, pady=(0, 10))

        # 狀態監視器文字欄
        self.lbl_status = tk.Label(info_inner, text="解碼模式: 正常模式", font=("Microsoft JhengHei", 12, "bold"),
                                   fg=self.COLOR_GREEN, bg="#020617", height=2, anchor=tk.W, padx=10, justify=tk.LEFT)
        self.lbl_status.pack(fill=tk.X, pady=5)

        self.lbl_bin_info = tk.Label(info_inner, text="二進制數據：D=0, C=0, B=0, A=0", font=("Microsoft JhengHei", 11),
                                     fg="#cbd5e1", bg=self.COLOR_CARD, anchor=tk.W)
        self.lbl_bin_info.pack(fill=tk.X, pady=2)

        self.lbl_out_info = tk.Label(info_inner, text="7447 輸出電平: a=0 b=0 c=0 d=0 e=0 f=0 g=1", font=("Consolas", 10),
                                     fg="#94a3b8", bg=self.COLOR_CARD, anchor=tk.W)
        self.lbl_out_info.pack(fill=tk.X, pady=2)

    def _toggle_bit(self, idx):
        """
        當點擊 D, C, B, A 四個二進制按鈕時觸發
        """
        current_val = self.bit_vars[idx].get()
        new_val = 1 - current_val
        self.bit_vars[idx].set(new_val)
        
        # 重新計算 decimal 數值
        # D=bit_vars[0], C=bit_vars[1], B=bit_vars[2], A=bit_vars[3]
        self.val = (self.bit_vars[0].get() * 8 + 
                    self.bit_vars[1].get() * 4 + 
                    self.bit_vars[2].get() * 2 + 
                    self.bit_vars[3].get() * 1)
        self._update_all()

    def _set_bcd_value(self, target_val):
        """
        當直接點擊 0~15 數值按鈕時觸發
        """
        self.val = target_val
        # 更新二進制狀態
        self.bit_vars[0].set((target_val >> 3) & 1)
        self.bit_vars[1].set((target_val >> 2) & 1)
        self.bit_vars[2].set((target_val >> 1) & 1)
        self.bit_vars[3].set(target_val & 1)
        self._update_all()

    def _toggle_lt(self):
        self.lt = 1 - self.lt
        self._update_all()

    def _toggle_rbi(self):
        self.rbi = 1 - self.rbi
        self._update_all()

    def _toggle_bi(self):
        self.bi_rbo = 1 - self.bi_rbo
        self._update_all()

    def _toggle_demo(self):
        self.auto_cycle = not self.auto_cycle
        if self.auto_cycle:
            self.btn_demo.config(text="■ 停止 BCD 自動展示", bg=self.COLOR_RED_ON)
            self._run_demo()
        else:
            self.btn_demo.config(text="▶ 啟動 BCD 自動展示", bg=self.COLOR_GREEN)

    def _run_demo(self):
        if not self.auto_cycle:
            return
        next_val = (self.val + 1) % 16
        self._set_bcd_value(next_val)
        self.after(self.cycle_speed, self._run_demo)

    def _update_all(self):
        """
        同步所有邏輯並重繪介面
        """
        # 1. 執行解碼運算
        segs, rbo, status_text = self.simulator.decode(self.val, self.lt, self.rbi, self.bi_rbo)

        # 2. 更新控制面板 UI
        # 0~15 按鈕點亮反饋
        for i, btn in enumerate(self.bcd_buttons):
            if i == self.val:
                btn.config(bg=self.COLOR_GREEN, fg="#ffffff")
            else:
                btn.config(bg="#334155", fg="#f8fafc")

        # 二進制 4-bits 控制按鈕顏色
        bit_labels = ['D (8)', 'C (4)', 'B (2)', 'A (1)']
        for i in range(4):
            val_bit = self.bit_vars[i].get()
            if val_bit == 1:
                self.bit_buttons[i].config(text=f"{bit_labels[i]}\nHIGH (1)", bg=self.COLOR_HIGH)
            else:
                self.bit_buttons[i].config(text=f"{bit_labels[i]}\nLOW (0)", bg=self.COLOR_LOW)

        # 系統腳位按鈕狀態
        self.btn_lt.config(text=f"LT (燈泡測試)\n{'HIGH (1)' if self.lt else 'LOW (0)'}", bg=self.COLOR_HIGH if self.lt else self.COLOR_LOW)
        self.btn_rbi.config(text=f"RBI (前導消隱)\n{'HIGH (1)' if self.rbi else 'LOW (0)'}", bg=self.COLOR_HIGH if self.rbi else self.COLOR_LOW)
        self.btn_bi.config(text=f"BI/RBO (消隱)\n{'HIGH (1)' if self.bi_rbo else 'LOW (0)'}", bg=self.COLOR_HIGH if self.bi_rbo else self.COLOR_LOW)

        # 3. 更新底部的純文字監控欄
        self.lbl_status.config(text=f"解碼器運作狀態: {status_text}")
        self.lbl_bin_info.config(text=f"當前輸入：D={self.bit_vars[0].get()}, C={self.bit_vars[1].get()}, B={self.bit_vars[2].get()}, A={self.bit_vars[3].get()} (十進制: {self.val})")
        
        labels_abc = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        out_states = [f"{labels_abc[idx]}={segs[idx]}" for idx in range(7)]
        self.lbl_out_info.config(text=f"7447 輸出狀態 (Active LOW): " + ", ".join(out_states) + f" | RBO狀態={rbo}")

        # 4. 重繪動態 Canvas 元件
        self._draw_led(segs)
        self._draw_chip(segs, rbo)

    def _draw_led(self, segs):
        """
        利用 Canvas 繪製具備斜角與氖紅霓虹發光質感的七段顯示器
        """
        self.led_canvas.delete("all")
        w = self.led_canvas.winfo_width()
        h = self.led_canvas.winfo_height()
        if w < 10: w, h = 450, 220 # 預設大小防呆

        # 基礎定位點 (置中)
        cx, cy = w // 2, h // 2
        
        # 傾斜轉換矩陣：x' = x - (y - cy) * 0.12 (產生美麗的 LED 斜角)
        def transform(x, y):
            slant = 0.12
            return x - (y - cy) * slant, y

        # 七段各段點定義 (相對於中心 cx, cy)
        # a, f, b, g, e, c, d
        segment_polygons = {
            # a (最上橫條)
            'a': [(-50, -85), (50, -85), (40, -71), (-40, -71)],
            # f (左上直條)
            'f': [(-56, -80), (-44, -72), (-44, -10), (-56, -2)],
            # b (右上直條)
            'b': [(44, -72), (56, -80), (56, -2), (44, -10)],
            # g (中間橫條)
            'g': [(-40, -7), (40, -7), (46, 0), (40, 7), (-40, 7), (-46, 0)],
            # e (左下直條)
            'e': [(-56, 2), (-44, 10), (-44, 72), (-56, 80)],
            # c (右下直條)
            'c': [(44, 10), (56, 2), (56, 80), (44, 72)],
            # d (最下橫條)
            'd': [(-40, 71), (40, 71), (50, 85), (-50, 85)]
        }

        seg_keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        for idx, key in enumerate(seg_keys):
            # 7447 輸出是 Active LOW：0 代表點亮，1 代表暗
            is_active = (segs[idx] == 0)
            color_fill = self.COLOR_RED_ON if is_active else self.COLOR_RED_OFF
            color_outline = "#ff8888" if is_active else "#1e1b1c"

            # 轉換所有點至傾斜座標系
            points = []
            for px, py in segment_polygons[key]:
                tx, ty = transform(cx + px, cy + py)
                points.append(tx)
                points.append(ty)

            # 在 Canvas 上畫出 segment 霓虹燈條
            if is_active:
                # 繪製外發光影子層
                shadow_points = []
                for px, py in segment_polygons[key]:
                    tx, ty = transform(cx + px, cy + py)
                    shadow_points.append(tx)
                    shadow_points.append(ty)
                self.led_canvas.create_polygon(shadow_points, fill="#7f1d1d", outline="")
            
            self.led_canvas.create_polygon(points, fill=color_fill, outline=color_outline, width=1.5)

        # 繪製小數點 DP (裝飾用)
        dpx, dpy = transform(cx + 70, cy + 80)
        self.led_canvas.create_oval(dpx-7, dpy-7, dpx+7, dpy+7, fill=self.COLOR_RED_OFF, outline="#1e1b1c")

    def _draw_chip(self, segs, rbo):
        """
        繪製 7447 DIP-16 晶片，並即時用紅藍雙色光點標註各個引腳的實時電位
        """
        self.chip_canvas.delete("all")
        w = self.chip_canvas.winfo_width()
        h = self.chip_canvas.winfo_height()
        if w < 10: w, h = 450, 220

        cx, cy = w // 2, h // 2

        # 晶片外殼繪製 (已將不支援的 stroke="xxx" 修正為 outline="xxx")
        cw, ch = 240, 100
        self.chip_canvas.create_rectangle(cx - cw//2, cy - ch//2, cx + cw//2, cy + ch//2, 
                                          fill="#1e293b", outline="#475569", width=3)
        # 晶片左側半圓缺口
        self.chip_canvas.create_oval(cx - cw//2 - 12, cy - 20, cx - cw//2 + 12, cy + 20, fill="#020617", outline="#475569")
        # 晶片型號標記
        self.chip_canvas.create_text(cx, cy, text="SN7447N", font=("Consolas", 18, "bold"), fill="#f8fafc")
        self.chip_canvas.create_text(cx, cy + 25, text="BCD to 7-SEG DECODER", font=("Consolas", 8), fill="#94a3b8")

        # 16 支引腳對應邏輯狀態設定 (對應引腳編號 1 至 16)
        # BCD 4-bits
        val_d = self.bit_vars[0].get()
        val_c = self.bit_vars[1].get()
        val_b = self.bit_vars[2].get()
        val_a = self.bit_vars[3].get()

        pin_levels = {
            1:  val_c,       # Pin 1: Input B
            2:  val_b,       # Pin 2: Input C
            3:  self.lt,     # Pin 3: Lamp Test (LT)
            4:  self.bi_rbo, # Pin 4: BI/RBO
            5:  self.rbi,    # Pin 5: RBI
            6:  val_d,       # Pin 6: Input D
            7:  val_a,       # Pin 7: Input A
            8:  0,           # Pin 8: GND
            9:  segs[4],     # Pin 9: Output e
            10: segs[3],     # Pin 10: Output d
            11: segs[2],     # Pin 11: Output c
            12: segs[1],     # Pin 12: Output b
            13: segs[0],     # Pin 13: Output a
            14: segs[6],     # Pin 14: Output g
            15: segs[5],     # Pin 15: Output f
            16: 1            # Pin 16: VCC (+5V)
        }

        pin_names = {
            1: "B", 2: "C", 3: "LT", 4: "BI/RBO", 5: "RBI", 6: "D", 7: "A", 8: "GND",
            9: "e", 10: "d", 11: "c", 12: "b", 13: "a", 14: "g", 15: "f", 16: "VCC"
        }

        # 繪製引腳與電位光點 (上半部 16~9 由右至左，下半部 1~8 由左至右)
        # 引腳 X 位置定位
        pin_spacing = 26
        start_x = cx - (7 * pin_spacing) // 2

        # 1. 繪製下半部引腳 (1 至 8)
        for i in range(1, 9):
            px = start_x + (i - 1) * pin_spacing
            py_pin = cy + ch//2
            level = pin_levels[i]
            pin_color = self.COLOR_HIGH if level == 1 else self.COLOR_LOW

            # 畫金屬引腳
            self.chip_canvas.create_line(px, py_pin, px, py_pin + 12, fill="#94a3b8", width=4)
            # 畫電位邏輯光圈
            self.chip_canvas.create_oval(px - 5, py_pin + 15, px + 5, py_pin + 25, fill=pin_color, outline="#ffffff", width=1)
            # 畫引腳編號
            self.chip_canvas.create_text(px, py_pin - 12, text=f"{i}", font=("Consolas", 8), fill="#94a3b8")
            # 畫功能名稱
            self.chip_canvas.create_text(px, py_pin + 35, text=pin_names[i], font=("Consolas", 8, "bold"), fill="#f8fafc")

        # 2. 繪製上半部引腳 (16 至 9，對應引腳在畫面上是從左往右排)
        for i in range(9, 17):
            idx_in_row = 16 - i # Pin 16 在最左邊，Pin 9 在最右邊
            px = start_x + idx_in_row * pin_spacing
            py_pin = cy - ch//2
            level = pin_levels[i]
            pin_color = self.COLOR_HIGH if level == 1 else self.COLOR_LOW

            # 畫金屬引腳
            self.chip_canvas.create_line(px, py_pin, px, py_pin - 12, fill="#94a3b8", width=4)
            # 畫電位邏輯光圈
            self.chip_canvas.create_oval(px - 5, py_pin - 25, px + 5, py_pin - 15, fill=pin_color, outline="#ffffff", width=1)
            # 畫引腳編號
            self.chip_canvas.create_text(px, py_pin + 12, text=f"{i}", font=("Consolas", 8), fill="#94a3b8")
            # 畫功能名稱
            self.chip_canvas.create_text(px, py_pin - 35, text=pin_names[i], font=("Consolas", 8, "bold"), fill="#f8fafc")

if __name__ == "__main__":
    app = App()
    app.mainloop()