2025年10月29日 星期三

縱向冗餘檢查法(Longitudinal Redundancy Check, LRC) ----Python TKinter

縱向冗餘檢查法(Longitudinal Redundancy Check, LRC)是對傳送資料的每個位元組的前後位置做連續的互斥或(XOR)運算後,以產生一個新的LRC位元組,此新的LRC位元組與資料同時傳送出去。在接收時,將接收資料的前後位置及LRC位元組做互斥或(XOR)運算後,所得的新的LRC位元組應為零,則代表資料是正確的,否則是錯誤的。






LRC 碼產生(資料發送端)

1.輸入資料: 在輸入框中輸入您要傳輸的 16 進制資料,每個位元組用空格隔開 。

   範例輸入: 25 51 3B 52

2.開始模擬: 點擊 「LRC 碼產生 (開始模擬)」 按鈕。

3.逐步運算: 重複點擊 「執行下一步驟 (XOR)」 按鈕 。

  每一步都會將前次 LRC 累加器的二進制值與下一個資料位元組的二進制值進行 XOR 運算 。

4. LRC 碼: 運算完成後,輸出區域會顯示最終 LRC 碼的 16 進制和二進制表示 。


LRC 檢查(資料接收端)

1.輸入資料: 在輸入框中輸入接收到的所有資料(包括原始資料和 LRC 碼本身),用空格隔開 。

   範例輸入 (資料正確): 25 51 3B 52 1D

   範例輸入 (資料錯誤): 23 51 3B 52 1D

2. 開始檢查: 點擊 「LRC 檢查 (開始驗證)」 按鈕。

3. 逐步運算: 重複點擊 「執行下一步驟 (XOR)」 按鈕 。

    程式將連續對所有接收到的位元組進行 XOR 運算 。

4.檢查結果:

   如果最終結果(新的 LRC 位元組)為 00,則表示資料正確 。

   如果最終結果 非零 (例如 06),則表示接收到的資料有錯誤發生 。


import tkinter as tk

from tkinter import ttk, scrolledtext, messagebox


# --- I. LRC 核心計算邏輯 ---


def hex_to_binary(hex_str):

    """將 16 進制字串轉換為 8 位元的二進制字串。"""

    return bin(int(hex_str, 16))[2:].zfill(8)


def binary_to_hex(binary_str):

    """將 8 位元的二進制字串轉換為 16 進制字串。"""

    return hex(int(binary_str, 2))[2:].zfill(2).upper()


def xor_binary_8bit(bin1, bin2):

    """執行兩個 8 位元二進制字串的互斥或 (XOR) 運算。"""

    result = []

    for b1, b2 in zip(bin1, bin2):

        result.append('1' if b1 != b2 else '0')

    return "".join(result)


class LRC_Simulator:

    def __init__(self, hex_data_list, mode="GENERATE"):

        # hex_data_list 是一個包含多個 16 進制字串的列表 (例如 ['25', '51', '3B', '52'])

        self.hex_data_list = hex_data_list

        self.mode = mode # GENERATE or CHECK

        

        # 將所有 16 進制數據轉換為二進制

        self.bin_data_list = [hex_to_binary(h) for h in hex_data_list]

        

        self.current_index = 0

        self.max_steps = len(self.bin_data_list)

        

        # 初始 LRC 累加器為第一個數據位元組

        if self.max_steps > 0:

            self.accumulator = self.bin_data_list[0]

            self.current_hex_operand = self.hex_data_list[0]

        else:

            self.accumulator = '00000000'

            self.current_hex_operand = '00'


    def perform_next_step(self):

        """執行一步 LRC (XOR 運算)"""

        

        if self.current_index >= self.max_steps:

            # 計算結束

            final_bin = self.accumulator

            final_hex = binary_to_hex(final_bin)

            

            if self.mode == "GENERATE":

                return "DONE", f"----------------------------------------\n🌟 LRC 碼產生完成!\n🌟 LRC= {final_hex} ({final_bin})\n----------------------------------------"

            else: # CHECK mode

                result_msg = "✅ 資料正確 (餘數為 00)" if final_hex == "00" else f"❌ 資料錯誤 (餘數為 {final_hex})"

                return "DONE", f"----------------------------------------\n🌟 LRC 檢查完成!\n🌟 最終 LRC= {final_hex} ({final_bin})\n{result_msg}\n----------------------------------------"


        

        # 第一步 (i=0) 只是初始化,不執行 XOR 

        if self.current_index == 0 and self.max_steps > 0:

            log_entry = f"初始化: LRC 累加器設定為第一個資料位元組\n"

            log_entry += f"  LRC (Hex): {self.current_hex_operand}\n"

            log_entry += f"  LRC (Bin): {self.accumulator}\n"

            self.current_index += 1

            return "STEP", log_entry

        

        

        # 執行 XOR 步驟 (從第二個數據位元組開始)

        i = self.current_index

        previous_bin = self.accumulator

        previous_hex = binary_to_hex(previous_bin)

        

        current_operand_bin = self.bin_data_list[i]

        self.current_hex_operand = self.hex_data_list[i]

        

        # 執行 XOR 運算

        self.accumulator = xor_binary_8bit(previous_bin, current_operand_bin)

        

        log_entry = f"步驟 {i} (資料位元組 {self.current_hex_operand}H):\n"

        log_entry += f"  前次 LRC (Bin): {previous_bin}\n"

        log_entry += f"  XOR 運算元 (Bin): {current_operand_bin}\n"

        log_entry += f"  XOR 結果 (Bin): {self.accumulator}\n"

        log_entry += f"  XOR 結果 (Hex): {binary_to_hex(self.accumulator)}\n"

        log_entry += "----------------------------------------\n"


        self.current_index += 1

        return "STEP", log_entry


# --- II. Tkinter 介面邏輯 ---


class LRC_App:

    def __init__(self, master):

        self.master = master

        master.title("LRC 縱向冗餘檢查 - 逐步模擬")


        self.simulator = None

        self.is_running = False


        # --- 設定主框架 ---

        main_frame = ttk.Frame(master, padding="10")

        main_frame.pack(fill='both', expand=True)


        # --- 輸入區 ---

        input_frame = ttk.LabelFrame(main_frame, text="輸入參數 (16 進制)", padding="10")

        input_frame.pack(fill='x', pady=5)


        ttk.Label(input_frame, text="16 進制資料 (Byte 之間用空格分隔):").grid(row=0, column=0, padx=5, pady=5, sticky='w')

        self.data_entry = ttk.Entry(input_frame, width=50)

        self.data_entry.grid(row=0, column=1, padx=5, pady=5, sticky='w')

        self.data_entry.insert(0, "25 51 3B 52") # 範例資料


        # --- 控制按鈕區 ---

        button_frame = ttk.Frame(main_frame)

        button_frame.pack(fill='x', pady=5)


        self.start_gen_button = ttk.Button(button_frame, text="LRC 碼產生 (開始模擬)", command=lambda: self.start_simulation("GENERATE"))

        self.start_gen_button.pack(side='left', padx=5, expand=True)


        self.start_check_button = ttk.Button(button_frame, text="LRC 檢查 (開始驗證)", command=lambda: self.start_simulation("CHECK"))

        self.start_check_button.pack(side='left', padx=5, expand=True)


        self.next_step_button = ttk.Button(button_frame, text="執行下一步驟 (XOR)", command=self.perform_step, state=tk.DISABLED)

        self.next_step_button.pack(side='left', padx=5, expand=True)


        self.reset_button = ttk.Button(button_frame, text="重置", command=self.reset_simulation, state=tk.DISABLED)

        self.reset_button.pack(side='left', padx=5, expand=True)


        # --- 輸出區 (ScrolledText 用於顯示逐步結果) ---

        output_frame = ttk.LabelFrame(main_frame, text="LRC 運算過程輸出 (二進制)", padding="10")

        output_frame.pack(fill='both', expand=True, pady=5)


        self.output_text = scrolledtext.ScrolledText(output_frame, wrap=tk.WORD, width=60, height=20, font=('Consolas', 10))

        self.output_text.pack(fill='both', expand=True)

        self.output_text.insert(tk.END, "請輸入 16 進制資料 (Byte 間用空格分隔),然後點擊「LRC 碼產生」或「LRC 檢查」開始。")


    def validate_hex_input(self, input_str):

        """驗證輸入是否為合法的 16 進制位元組序列 (每 Byte 必須是 2 個字元)。"""

        hex_list = input_str.upper().split()

        if not hex_list:

            return None, "輸入不能為空。"

        

        for h in hex_list:

            if len(h) != 2 or not all(c in '0123456789ABCDEF' for c in h):

                return None, f"'{h}' 格式錯誤。每個 Byte 必須是 2 個 16 進制字元。"

        

        return hex_list, None


    def start_simulation(self, mode):

        """初始化並開始 LRC 模擬"""

        input_data = self.data_entry.get().strip()

        

        hex_data_list, error = self.validate_hex_input(input_data)

        

        if error:

            messagebox.showerror("輸入錯誤", error)

            return


        try:

            # 初始化模擬器

            self.simulator = LRC_Simulator(hex_data_list, mode)

            self.is_running = True

            

            # 更新按鈕狀態

            self.start_gen_button.config(state=tk.DISABLED)

            self.start_check_button.config(state=tk.DISABLED)

            self.next_step_button.config(state=tk.NORMAL)

            self.reset_button.config(state=tk.NORMAL)

            

            # 顯示初始資訊

            self.output_text.delete(1.0, tk.END)

            op_mode = "LRC 碼產生模式" if mode == "GENERATE" else "LRC 檢查模式 (Data + LRC)"

            self.output_text.insert(tk.END, f"--- {op_mode} ---\n")

            self.output_text.insert(tk.END, f"輸入資料 (Hex): {input_data}\n")

            self.output_text.insert(tk.END, f"總共 {len(hex_data_list)} 個位元組需要運算。\n")

            self.output_text.insert(tk.END, "----------------------------------------\n")

            

            # 執行第一步 (初始化)

            self.perform_step()

            

        except Exception as e:

            messagebox.showerror("錯誤", f"初始化錯誤: {e}")

            self.reset_simulation()


    def perform_step(self):

        """執行一步 LRC 計算並更新輸出"""

        if not self.is_running or not self.simulator:

            return


        status, log = self.simulator.perform_next_step()

        self.output_text.insert(tk.END, log)

        self.output_text.see(tk.END) # 滾動到最新輸出


        if status == "DONE":

            self.next_step_button.config(state=tk.DISABLED)

            self.is_running = False

            

            # 顯示完成訊息

            if self.simulator.mode == "GENERATE":

                messagebox.showinfo("模擬結束", "LRC 碼產生完成!")

            else:

                messagebox.showinfo("檢查結束", "LRC 檢查完成!")


    def reset_simulation(self):

        """重置所有狀態"""

        self.simulator = None

        self.is_running = False

        

        # 更新按鈕狀態

        self.start_gen_button.config(state=tk.NORMAL)

        self.start_check_button.config(state=tk.NORMAL)

        self.next_step_button.config(state=tk.DISABLED)

        self.reset_button.config(state=tk.DISABLED)

        

        # 清空輸出

        self.output_text.delete(1.0, tk.END)

        self.output_text.insert(tk.END, "模擬已重置。請輸入 16 進制資料 (Byte 間用空格分隔),然後點擊「LRC 碼產生」或「LRC 檢查」開始。")


if __name__ == "__main__":

    root = tk.Tk()

    app = LRC_App(root)

    root.mainloop()


沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...