nightfury commited on
Commit
c417206
·
verified ·
1 Parent(s): aa8d45b

Create simulator.py

Browse files
Files changed (1) hide show
  1. simulator.py +201 -0
simulator.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import tkinter as tk
3
+ from tkinter import ttk
4
+ import time
5
+ import threading
6
+
7
+ # Morse code dictionary
8
+ MORSE_CODE_DICT = {
9
+ 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
10
+ 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
11
+ 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
12
+ 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
13
+ 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--',
14
+ '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..',
15
+ '9': '----.', '0': '-----', ', ': '--..--', '.': '.-.-.-', '?': '..--..',
16
+ '/': '-..-.', '-': '-....-', '(': '-.--.', ')': '-.--.-'
17
+ }
18
+
19
+
20
+ class MorseDecoderApp:
21
+ def __init__(self, root):
22
+ self.root = root
23
+ self.root.title("Morse Code Decoder")
24
+ self.root.geometry("600x400") # Set initial window size
25
+
26
+ self.dot_duration = 200 # milliseconds
27
+ self.dash_duration = self.dot_duration * 3
28
+ self.space_duration = self.dot_duration * 7 # Between words
29
+ self.letter_space_duration = self.dot_duration * 3 # Between letters
30
+
31
+
32
+ # Input Frame
33
+ self.input_frame = ttk.Frame(root, padding=(10, 10, 10, 10))
34
+ self.input_frame.pack(fill=tk.BOTH, expand=True)
35
+
36
+ self.input_label = ttk.Label(self.input_frame, text="Morse Code Input:")
37
+ self.input_label.grid(row=0, column=0, sticky=tk.W)
38
+
39
+ self.morse_input = tk.Text(self.input_frame, height=5, width=50)
40
+ self.morse_input.grid(row=1, column=0, columnspan=2, sticky=tk.EW)
41
+
42
+ self.decode_button = ttk.Button(self.input_frame, text="Decode", command=self.decode_morse)
43
+ self.decode_button.grid(row=2, column=0, columnspan=2, pady=5)
44
+
45
+ # Output Frame
46
+ self.output_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) # Less top padding
47
+ self.output_frame.pack(fill=tk.BOTH, expand=True)
48
+
49
+ self.output_label = ttk.Label(self.output_frame, text="Decoded Text:")
50
+ self.output_label.grid(row=0, column=0, sticky=tk.W)
51
+
52
+ self.decoded_text = tk.Text(self.output_frame, height=5, width=50, state=tk.DISABLED) # Start disabled
53
+ self.decoded_text.grid(row=1, column=0, columnspan=2, sticky=tk.EW)
54
+
55
+
56
+ # LED Light Simulation (Basic)
57
+ self.led_frame = ttk.Frame(root, padding=(10, 0, 10, 10)) # Less top padding
58
+ self.led_frame.pack(fill=tk.BOTH, expand=True)
59
+ self.led_label = ttk.Label(self.led_frame, text="LED Output:")
60
+ self.led_label.grid(row=0, column=0, sticky=tk.W)
61
+ self.led = tk.Canvas(self.led_frame, width=50, height=50, bg="white", highlightthickness=0) # highlightthickness=0 removes border
62
+ self.led.grid(row=1, column=0, columnspan=2, pady=5) # pady for spacing
63
+ self.led_circle = self.led.create_oval(10, 10, 40, 40, fill="gray", outline="") # outline="" removes the default black outline
64
+
65
+ #Status bar at the bottom
66
+ self.status_bar = ttk.Label(root, text="Ready", relief=tk.SUNKEN, anchor=tk.W)
67
+ self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
68
+
69
+
70
+
71
+ # Configure grid weights for resizing
72
+ self.input_frame.columnconfigure(0, weight=1)
73
+ self.input_frame.columnconfigure(1, weight=1)
74
+ self.input_frame.rowconfigure(1, weight=1) # Morse Text area expands vertically
75
+
76
+ self.output_frame.columnconfigure(0, weight=1)
77
+ self.output_frame.columnconfigure(1, weight=1)
78
+ self.output_frame.rowconfigure(1, weight=1) # Decoded text area expands vertically
79
+
80
+ self.led_frame.columnconfigure(0, weight=1)
81
+ self.led_frame.columnconfigure(1, weight=1)
82
+
83
+
84
+ def decode_morse(self):
85
+ morse_code = self.morse_input.get("1.0", tk.END).strip().upper() # Get text, remove whitespace, and convert to uppercase
86
+ if not morse_code:
87
+ self.status_bar.config(text="Error: Please enter Morse code.")
88
+ return
89
+
90
+ try:
91
+ decoded_text = self.morse_to_text(morse_code)
92
+ self.status_bar.config(text="Decoding...") #Update Status bar
93
+ self.display_led(morse_code)
94
+
95
+ except ValueError as e:
96
+ self.decoded_text.config(state=tk.NORMAL)
97
+ self.decoded_text.delete("1.0", tk.END)
98
+ self.decoded_text.insert("1.0", str(e)) #Display error in output text area
99
+ self.decoded_text.config(state=tk.DISABLED)
100
+
101
+ self.status_bar.config(text=f"Error: {str(e)}") # Show error in status bar
102
+
103
+ except Exception as e: # Catch any other unexpected errors
104
+ self.decoded_text.config(state=tk.NORMAL)
105
+ self.decoded_text.delete("1.0", tk.END)
106
+ self.decoded_text.insert("1.0", "An unexpected error occurred.")
107
+ self.decoded_text.config(state=tk.DISABLED)
108
+
109
+ self.status_bar.config(text="An unexpected error occurred.")
110
+
111
+
112
+
113
+ def morse_to_text(self, morse_code):
114
+ # Basic morse to text conversion (doesn't handle invalid codes well)
115
+ morse_code = morse_code.replace("/", " / ") # Add space for word separator
116
+ words = morse_code.split(" / ")
117
+ text = ""
118
+ for word in words:
119
+ letters = word.split() #Splits into individual Morse codes
120
+
121
+ for letter in letters:
122
+ try:
123
+ # Reverse lookup from the dictionary (inefficient for large dictionaries, but simple)
124
+ found = False
125
+ for key, value in MORSE_CODE_DICT.items():
126
+ if value == letter:
127
+ text += key
128
+ found = True
129
+ break # Stop search once a match is found
130
+
131
+ if not found:
132
+ raise ValueError(f"Invalid Morse code: {letter}") # Custom Error
133
+
134
+ except ValueError as e:
135
+ raise e # Re-raise the exception to be caught outside
136
+ text += " "
137
+ return text.strip() # Remove trailing space
138
+
139
+
140
+
141
+
142
+ def display_led(self, morse_code):
143
+ """Displays the Morse code using the LED simulation. Runs in a separate thread to avoid freezing the GUI."""
144
+ self.decode_button.config(state=tk.DISABLED) # Disable button during processing
145
+ self.morse_input.config(state=tk.DISABLED) # Disable input field during processing
146
+
147
+ def led_thread():
148
+ try:
149
+ for symbol in morse_code:
150
+ if symbol == '.':
151
+ self.turn_on_led()
152
+ time.sleep(self.dot_duration / 1000)
153
+ self.turn_off_led()
154
+ time.sleep(self.dot_duration / 1000) # Intra-character space
155
+
156
+ elif symbol == '-':
157
+ self.turn_on_led()
158
+ time.sleep(self.dash_duration / 1000)
159
+ self.turn_off_led()
160
+ time.sleep(self.dot_duration / 1000) # Intra-character space
161
+
162
+
163
+ elif symbol == ' ': # Space between letters
164
+ time.sleep(self.letter_space_duration / 1000) # Longer pause between letters
165
+ elif symbol == '/':
166
+ time.sleep(self.space_duration/1000)
167
+
168
+ self.root.update() # Update the GUI
169
+
170
+ decoded_text = self.morse_to_text(morse_code) #Decode here, after animation is complete
171
+ self.decoded_text.config(state=tk.NORMAL)
172
+ self.decoded_text.delete("1.0", tk.END)
173
+ self.decoded_text.insert("1.0", decoded_text)
174
+ self.decoded_text.config(state=tk.DISABLED)
175
+ self.status_bar.config(text="Decoding complete.") #Update Status bar
176
+
177
+ except Exception as e:
178
+ self.status_bar.config(text=f"Error during LED display: {e}") #Status bar
179
+ print(f"Error during LED display: {e}")
180
+
181
+ finally: # Make sure to re-enable button/text, even if there's an error
182
+ self.decode_button.config(state=tk.NORMAL)
183
+ self.morse_input.config(state=tk.NORMAL)
184
+
185
+
186
+ thread = threading.Thread(target=led_thread)
187
+ thread.start()
188
+
189
+ def turn_on_led(self):
190
+ self.led.itemconfig(self.led_circle, fill="yellow") # Simulate LED turning on
191
+ self.root.update()
192
+
193
+ def turn_off_led(self):
194
+ self.led.itemconfig(self.led_circle, fill="gray") # Simulate LED turning off
195
+ self.root.update()
196
+
197
+
198
+ if __name__ == "__main__":
199
+ root = tk.Tk()
200
+ app = MorseDecoderApp(root)
201
+ root.mainloop()