2026年1月17日 星期六

1-out-of-4 脈衝位置編碼 (PPM)

1-out-of-4 脈衝位置編碼 (PPM) 

1-out-of-4 脈衝位置編碼 (PPM),主要概念是將一個訊號週期(Symbol)等分成 4 個時段(Slots)。根據資料數值(0, 1, 2, 或 3),脈衝會出現在對應的時段中。



import tkinter as tk

from tkinter import messagebox


class PPMVisualizer:

    def __init__(self, root, bit_stream="110010010111"):

        self.root = root

        self.root.title("1-out-of-4 PPM 互動演示")

        

        self.original_stream = bit_stream

        self.bit_stream = bit_stream

        

        # 初始化狀態

        self.reset_state()


        # --- 介面佈局 ---

        # 標題與進度

        self.label = tk.Label(root, text="", font=("Arial", 12), fg="#333")

        self.label.pack(pady=10)

        self.update_label()


        # 畫布

        self.canvas = tk.Canvas(root, width=850, height=320, bg="#ffffff", 

                                highlightthickness=2, highlightbackground="#cccccc")

        self.canvas.pack(pady=10, padx=20)


        # 按鈕容器

        btn_frame = tk.Frame(root)

        btn_frame.pack(pady=20)


        self.btn_next = tk.Button(btn_frame, text="下一個 Symbol >>", command=self.draw_next_step, 

                                  bg="#4CAF50", fg="white", font=("微軟正黑體", 10, "bold"), width=15)

        self.btn_next.pack(side=tk.LEFT, padx=10)


        self.btn_reset = tk.Button(btn_frame, text="重置開始", command=self.reset_canvas, 

                                   bg="#f44336", fg="white", font=("微軟正黑體", 10, "bold"), width=15)

        self.btn_reset.pack(side=tk.LEFT, padx=10)


    def reset_state(self):

        """初始化或重置內部變數"""

        self.current_index = 0

        self.x_curr = 50

        self.y_base = 200

        self.slot_w = 35

        self.pulse_h = 70

        self.colors = ["#FF5733", "#33FF57", "#3357FF", "#F333FF"]


    def update_label(self):

        processed = self.original_stream[:self.current_index]

        remaining = self.original_stream[self.current_index:]

        self.label.config(text=f"已處理: [{processed}]  剩餘: {remaining}")


    def reset_canvas(self):

        """重置畫布與所有狀態"""

        self.canvas.delete("all") # 清空畫布上所有物件

        self.reset_state()

        self.update_label()

        # 畫一條起始地平線

        self.canvas.create_line(0, self.y_base, 50, self.y_base, width=2)


    def draw_next_step(self):

        if self.current_index >= len(self.original_stream):

            messagebox.showinfo("提示", "訊號已播放完畢,請點擊重置開始。")

            return


        # 1-out-of-4 PPM 每次處理 2 bits

        bits = self.original_stream[self.current_index : self.current_index + 2]

        if len(bits) < 2: bits += "0" # 補位

        

        val = int(bits, 2)

        

        # 繪製灰色背景參考格線

        for s in range(4):

            x_grid = self.x_curr + s * self.slot_w

            self.canvas.create_rectangle(x_grid, self.y_base - 100, x_grid + self.slot_w, self.y_base, 

                                         outline="#f0f0f0")


        # 1. 脈衝前的平線

        self.canvas.create_line(self.x_curr, self.y_base, 

                                self.x_curr + val * self.slot_w, self.y_base, width=2)

        

        # 2. 繪製脈衝 (1-out-of-4)

        px1 = self.x_curr + val * self.slot_w

        px2 = px1 + self.slot_w

        self.canvas.create_rectangle(px1, self.y_base, px2, self.y_base - self.pulse_h, 

                                     fill=self.colors[val], outline="black", width=2)

        

        # 3. 脈衝後的平線

        self.canvas.create_line(px2, self.y_base, 

                                self.x_curr + 4 * self.slot_w, self.y_base, width=2)

        

        # 4. 文字標記

        self.canvas.create_text(self.x_curr + 2 * self.slot_w, self.y_base + 30, 

                                text=f"'{bits}'", font=("Arial", 10, "bold"))

        self.canvas.create_text(self.x_curr + 2 * self.slot_w, self.y_base + 50, 

                                text=f"Slot {val}", font=("Arial", 8), fill="gray")


        # 更新索引與位移

        self.current_index += 2

        self.x_curr += 4 * self.slot_w

        self.update_label()


if __name__ == "__main__":

    main_root = tk.Tk()

    # 測試長字串

    app = PPMVisualizer(main_root, "100011011001")

    main_root.mainloop()


沒有留言:

張貼留言

1-out-of-4 脈衝位置編碼 (PPM)

1-out-of-4 脈衝位置編碼 (PPM)  1-out-of-4 脈衝位置編碼 (PPM) ,主要概念是將一個訊號週期(Symbol)等分成 4 個時段(Slots)。根據資料數值(0, 1, 2, 或 3),脈衝會出現在對應的時段中。 import tkinter as ...