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