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()

沒有留言:
張貼留言