|
|
|
import tkinter as tk |
|
from tkinter import ttk |
|
import time |
|
import threading |
|
|
|
|
|
MORSE_CODE_DICT = { |
|
'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
|
'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
|
'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
|
'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
|
'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', |
|
'4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', |
|
'9': '----.', '0': '-----', ', ': '--..--', '.': '.-.-.-', '?': '..--..', |
|
'/': '-..-.', '-': '-....-', '(': '-.--.', ')': '-.--.-' |
|
} |
|
|
|
|
|
class MorseDecoderApp: |
|
def __init__(self, root): |
|
self.root = root |
|
self.root.title("Morse Code Decoder") |
|
self.root.geometry("600x400") |
|
|
|
self.dot_duration = 200 |
|
self.dash_duration = self.dot_duration * 3 |
|
self.space_duration = self.dot_duration * 7 |
|
self.letter_space_duration = self.dot_duration * 3 |
|
|
|
|
|
|
|
self.input_frame = ttk.Frame(root, padding=(10, 10, 10, 10)) |
|
self.input_frame.pack(fill=tk.BOTH, expand=True) |
|
|
|
self.input_label = ttk.Label(self.input_frame, text="Morse Code Input:") |
|
self.input_label.grid(row=0, column=0, sticky=tk.W) |
|
|
|
self.morse_input = tk.Text(self.input_frame, height=5, width=50) |
|
self.morse_input.grid(row=1, column=0, columnspan=2, sticky=tk.EW) |
|
|
|
self.decode_button = ttk.Button(self.input_frame, text="Decode", command=self.decode_morse) |
|
self.decode_button.grid(row=2, column=0, columnspan=2, pady=5) |
|
|
|
|
|
self.output_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) |
|
self.output_frame.pack(fill=tk.BOTH, expand=True) |
|
|
|
self.output_label = ttk.Label(self.output_frame, text="Decoded Text:") |
|
self.output_label.grid(row=0, column=0, sticky=tk.W) |
|
|
|
self.decoded_text = tk.Text(self.output_frame, height=5, width=50, state=tk.DISABLED) |
|
self.decoded_text.grid(row=1, column=0, columnspan=2, sticky=tk.EW) |
|
|
|
|
|
|
|
self.led_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) |
|
self.led_frame.pack(fill=tk.BOTH, expand=True) |
|
self.led_label = ttk.Label(self.led_frame, text="LED Output:") |
|
self.led_label.grid(row=0, column=0, sticky=tk.W) |
|
self.led = tk.Canvas(self.led_frame, width=50, height=50, bg="white", highlightthickness=0) |
|
self.led.grid(row=1, column=0, columnspan=2, pady=5) |
|
self.led_circle = self.led.create_oval(10, 10, 40, 40, fill="gray", outline="") |
|
|
|
|
|
self.status_bar = ttk.Label(root, text="Ready", relief=tk.SUNKEN, anchor=tk.W) |
|
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X) |
|
|
|
|
|
|
|
|
|
self.input_frame.columnconfigure(0, weight=1) |
|
self.input_frame.columnconfigure(1, weight=1) |
|
self.input_frame.rowconfigure(1, weight=1) |
|
|
|
self.output_frame.columnconfigure(0, weight=1) |
|
self.output_frame.columnconfigure(1, weight=1) |
|
self.output_frame.rowconfigure(1, weight=1) |
|
|
|
self.led_frame.columnconfigure(0, weight=1) |
|
self.led_frame.columnconfigure(1, weight=1) |
|
|
|
|
|
def decode_morse(self): |
|
morse_code = self.morse_input.get("1.0", tk.END).strip().upper() |
|
if not morse_code: |
|
self.status_bar.config(text="Error: Please enter Morse code.") |
|
return |
|
|
|
try: |
|
decoded_text = self.morse_to_text(morse_code) |
|
self.status_bar.config(text="Decoding...") |
|
self.display_led(morse_code) |
|
|
|
except ValueError as e: |
|
self.decoded_text.config(state=tk.NORMAL) |
|
self.decoded_text.delete("1.0", tk.END) |
|
self.decoded_text.insert("1.0", str(e)) |
|
self.decoded_text.config(state=tk.DISABLED) |
|
|
|
self.status_bar.config(text=f"Error: {str(e)}") |
|
|
|
except Exception as e: |
|
self.decoded_text.config(state=tk.NORMAL) |
|
self.decoded_text.delete("1.0", tk.END) |
|
self.decoded_text.insert("1.0", "An unexpected error occurred.") |
|
self.decoded_text.config(state=tk.DISABLED) |
|
|
|
self.status_bar.config(text="An unexpected error occurred.") |
|
|
|
|
|
|
|
def morse_to_text(self, morse_code): |
|
|
|
morse_code = morse_code.replace("/", " / ") |
|
words = morse_code.split(" / ") |
|
text = "" |
|
for word in words: |
|
letters = word.split() |
|
|
|
for letter in letters: |
|
try: |
|
|
|
found = False |
|
for key, value in MORSE_CODE_DICT.items(): |
|
if value == letter: |
|
text += key |
|
found = True |
|
break |
|
|
|
if not found: |
|
raise ValueError(f"Invalid Morse code: {letter}") |
|
|
|
except ValueError as e: |
|
raise e |
|
text += " " |
|
return text.strip() |
|
|
|
|
|
|
|
|
|
def display_led(self, morse_code): |
|
"""Displays the Morse code using the LED simulation. Runs in a separate thread to avoid freezing the GUI.""" |
|
self.decode_button.config(state=tk.DISABLED) |
|
self.morse_input.config(state=tk.DISABLED) |
|
|
|
def led_thread(): |
|
try: |
|
for symbol in morse_code: |
|
if symbol == '.': |
|
self.turn_on_led() |
|
time.sleep(self.dot_duration / 1000) |
|
self.turn_off_led() |
|
time.sleep(self.dot_duration / 1000) |
|
|
|
elif symbol == '-': |
|
self.turn_on_led() |
|
time.sleep(self.dash_duration / 1000) |
|
self.turn_off_led() |
|
time.sleep(self.dot_duration / 1000) |
|
|
|
|
|
elif symbol == ' ': |
|
time.sleep(self.letter_space_duration / 1000) |
|
elif symbol == '/': |
|
time.sleep(self.space_duration/1000) |
|
|
|
self.root.update() |
|
|
|
decoded_text = self.morse_to_text(morse_code) |
|
self.decoded_text.config(state=tk.NORMAL) |
|
self.decoded_text.delete("1.0", tk.END) |
|
self.decoded_text.insert("1.0", decoded_text) |
|
self.decoded_text.config(state=tk.DISABLED) |
|
self.status_bar.config(text="Decoding complete.") |
|
|
|
except Exception as e: |
|
self.status_bar.config(text=f"Error during LED display: {e}") |
|
print(f"Error during LED display: {e}") |
|
|
|
finally: |
|
self.decode_button.config(state=tk.NORMAL) |
|
self.morse_input.config(state=tk.NORMAL) |
|
|
|
|
|
thread = threading.Thread(target=led_thread) |
|
thread.start() |
|
|
|
def turn_on_led(self): |
|
self.led.itemconfig(self.led_circle, fill="yellow") |
|
self.root.update() |
|
|
|
def turn_off_led(self): |
|
self.led.itemconfig(self.led_circle, fill="gray") |
|
self.root.update() |
|
|
|
|
|
if __name__ == "__main__": |
|
root = tk.Tk() |
|
app = MorseDecoderApp(root) |
|
root.mainloop() |