| import gradio as gr |
| 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': '-----', ', ': '--..--', '.': '.-.-.-', '?': '..--..', |
| '/': '-..-.', '-': '-....-', '(': '-.--.', ')': '-.--.-' |
| } |
|
|
| dot_duration = 0.2 |
| dash_duration = dot_duration * 3 |
| space_duration = dot_duration * 7 |
| letter_space_duration = dot_duration * 3 |
|
|
| led_html = """ |
| <div style="width: 50px; height: 50px; border-radius: 50%; background-color: {color};"></div> |
| """ |
|
|
| def morse_to_text(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(morse_code, callback): |
| """Simulates the LED display and updates the Gradio LED component.""" |
| try: |
| for symbol in morse_code: |
| if symbol == '.': |
| callback(led_html.format(color="yellow")) |
| time.sleep(dot_duration) |
| callback(led_html.format(color="gray")) |
| time.sleep(dot_duration) |
| elif symbol == '-': |
| callback(led_html.format(color="yellow")) |
| time.sleep(dash_duration) |
| callback(led_html.format(color="gray")) |
| time.sleep(dot_duration) |
| elif symbol == ' ': |
| time.sleep(letter_space_duration) |
| elif symbol == '/': |
| time.sleep(space_duration) |
| except Exception as e: |
| return f"Error during LED display: {e}" |
| return led_html.format(color="gray") |
|
|
| def decode_morse(morse_code): |
| try: |
| decoded_text = morse_to_text(morse_code.upper()) |
| except ValueError as e: |
| return str(e), led_html.format(color="gray") |
|
|
| |
| def update_led(led_status): |
| return led_status |
|
|
| |
| threading.Thread(target=display_led, args=(morse_code, update_led)).start() |
|
|
| return decoded_text, led_html.format(color="gray") |
|
|
| |
| with gr.Blocks() as iface: |
| morse_input = gr.Textbox(label="Morse Code Input", placeholder="Enter Morse Code Here") |
| decoded_output = gr.Textbox(label="Decoded Text") |
| led_display = gr.HTML(led_html.format(color="gray"), label="LED Output") |
|
|
| morse_input.change(fn=decode_morse, |
| inputs=morse_input, |
| outputs=[decoded_output, led_display]) |
| |
| iface.launch() |
|
|
| |
|
|
| """ |
| import tkinter as tk |
| from tkinter import ttk |
| import time |
| import threading |
| |
| # Morse code dictionary |
| 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") # Set initial window size |
| |
| self.dot_duration = 200 # milliseconds |
| self.dash_duration = self.dot_duration * 3 |
| self.space_duration = self.dot_duration * 7 # Between words |
| self.letter_space_duration = self.dot_duration * 3 # Between letters |
| |
| |
| # Input Frame |
| 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) |
| |
| # Output Frame |
| self.output_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) # Less top padding |
| 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) # Start disabled |
| self.decoded_text.grid(row=1, column=0, columnspan=2, sticky=tk.EW) |
| |
| |
| # LED Light Simulation (Basic) |
| self.led_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) # Less top padding |
| 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) # highlightthickness=0 removes border |
| self.led.grid(row=1, column=0, columnspan=2, pady=5) # pady for spacing |
| self.led_circle = self.led.create_oval(10, 10, 40, 40, fill="gray", outline="") # outline="" removes the default black outline |
| |
| #Status bar at the bottom |
| self.status_bar = ttk.Label(root, text="Ready", relief=tk.SUNKEN, anchor=tk.W) |
| self.status_bar.pack(side=tk.BOTTOM, fill=tk.X) |
| |
| |
| |
| # Configure grid weights for resizing |
| self.input_frame.columnconfigure(0, weight=1) |
| self.input_frame.columnconfigure(1, weight=1) |
| self.input_frame.rowconfigure(1, weight=1) # Morse Text area expands vertically |
| |
| self.output_frame.columnconfigure(0, weight=1) |
| self.output_frame.columnconfigure(1, weight=1) |
| self.output_frame.rowconfigure(1, weight=1) # Decoded text area expands vertically |
| |
| 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() # Get text, remove whitespace, and convert to uppercase |
| 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...") #Update Status bar |
| 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)) #Display error in output text area |
| self.decoded_text.config(state=tk.DISABLED) |
| |
| self.status_bar.config(text=f"Error: {str(e)}") # Show error in status bar |
| |
| except Exception as e: # Catch any other unexpected errors |
| 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): |
| # Basic morse to text conversion (doesn't handle invalid codes well) |
| morse_code = morse_code.replace("/", " / ") # Add space for word separator |
| words = morse_code.split(" / ") |
| text = "" |
| for word in words: |
| letters = word.split() #Splits into individual Morse codes |
| |
| for letter in letters: |
| try: |
| # Reverse lookup from the dictionary (inefficient for large dictionaries, but simple) |
| found = False |
| for key, value in MORSE_CODE_DICT.items(): |
| if value == letter: |
| text += key |
| found = True |
| break # Stop search once a match is found |
| |
| if not found: |
| raise ValueError(f"Invalid Morse code: {letter}") # Custom Error |
| |
| except ValueError as e: |
| raise e # Re-raise the exception to be caught outside |
| text += " " |
| return text.strip() # Remove trailing space |
| |
| |
| |
| |
| 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) # Disable button during processing |
| self.morse_input.config(state=tk.DISABLED) # Disable input field during processing |
| |
| 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) # Intra-character space |
| |
| elif symbol == '-': |
| self.turn_on_led() |
| time.sleep(self.dash_duration / 1000) |
| self.turn_off_led() |
| time.sleep(self.dot_duration / 1000) # Intra-character space |
| |
| |
| elif symbol == ' ': # Space between letters |
| time.sleep(self.letter_space_duration / 1000) # Longer pause between letters |
| elif symbol == '/': |
| time.sleep(self.space_duration/1000) |
| |
| self.root.update() # Update the GUI |
| |
| decoded_text = self.morse_to_text(morse_code) #Decode here, after animation is complete |
| 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.") #Update Status bar |
| |
| except Exception as e: |
| self.status_bar.config(text=f"Error during LED display: {e}") #Status bar |
| print(f"Error during LED display: {e}") |
| |
| finally: # Make sure to re-enable button/text, even if there's an error |
| 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") # Simulate LED turning on |
| self.root.update() |
| |
| def turn_off_led(self): |
| self.led.itemconfig(self.led_circle, fill="gray") # Simulate LED turning off |
| self.root.update() |
| |
| |
| if __name__ == "__main__": |
| root = tk.Tk() |
| app = MorseDecoderApp(root) |
| root.mainloop() |
| |
| """ |