diff --git a/SDPPython/prototype5/chip.py b/SDPPython/prototype5/chip.py new file mode 100644 index 0000000..f108118 --- /dev/null +++ b/SDPPython/prototype5/chip.py @@ -0,0 +1,130 @@ +import json +import serial +class IC74Series: + def __init__(self, chip_number, logic_type,n,TruthTable=[],pin_count=14, description=None, pin_config=None): + """ + Initializes a 74 series IC chip. + + :param chip_number: The number associated with the IC (e.g., '7400', '74138'). + :param logic_type: Type of logic gate/function the IC performs (e.g., 'NAND', 'Multiplexer'). + :param pin_count: Number of pins on the chip, defaults to 14 for most 74 series ICs. + :param description: Optional description of the IC's function. + :param pin_config: A dictionary mapping each pin to its type (input, output, VCC, ground). + """ + self.chip_number = chip_number + self.logic_type = logic_type + self.pin_count = pin_count + self.inputn = n + self.TruthTable = TruthTable + self.description = description if description else "No description provided." + self.pin_config = pin_config if pin_config else {} + + def set_pin(self, pin_number, pin_type): + """ + Sets the type of a specific pin (input, output, VCC, or ground). + + :param pin_number: The pin number (1-based index). + :param pin_type: The type of the pin ('input', 'output', 'VCC', 'ground'). + """ + if 1 <= pin_number <= self.pin_count: + self.pin_config[pin_number] = pin_type + else: + raise ValueError(f"Invalid pin number. This IC has {self.pin_count} pins.") + + def get_pin(self, pin_number): + """ + Returns the type of a specific pin. + + :param pin_number: The pin number (1-based index). + :return: The type of the pin ('input', 'output', 'VCC', or 'ground') or 'not configured'. + """ + return self.pin_config.get(pin_number, "not configured") + + def get_details(self): + """ + Returns the details of the IC as a string. + """ + return f"74{self.chip_number} IC - Logic Type: {self.logic_type}, Pins: {self.pin_count}, Description: {self.description}" + + def pin_configuration(self): + """ + Returns a formatted string with the pin configuration. + """ + config_str = f"Pin Configuration for 74{self.chip_number}:\n" + for pin in range(1, self.pin_count + 1): + pin_type = self.get_pin(pin) + config_str += f"Pin {pin}: {pin_type}\n" + return config_str + + def is_standard_pin_count(self): + """ + Checks if the IC has a standard pin count of 14. + """ + return self.pin_count == 14 + + def __str__(self): + return f"74{self.chip_number} ({self.logic_type})" + + def pin_configuration_json(self): + """ + Returns the pin configuration as a JSON string. + """ + config = { + "chip_number": self.chip_number, + "logic_type": self.logic_type, + "pin_count": self.pin_count, + "description": self.description, + "pins": self.pin_config + } + return json.dumps(config) + + def send_pin_configuration(self, uart_port, baudrate=250000): + """ + Sends the pin configuration as a JSON string over UART. + + :param uart_port: The UART port (e.g., 'COM3' on Windows or '/dev/ttyUSB0' on Linux). + :param baudrate: The baudrate for UART communication. + """ + json_data = self.pin_configuration_json() + #print("JSON Data to be sent:", json_data) + #raw_bytes = json_data.encode('utf-8') + #hex_bytes = [f"{byte:02x}" for byte in raw_bytes] # Convert bytes to hex + #print("Raw Bytes (Hex) to be sent:", ' '.join(hex_bytes)) # Print hex bytes as a space-separated string + with serial.Serial(uart_port, baudrate, timeout=10000000) as ser: + ser.write(json_data.encode('utf-8')) + print(f"Sent JSON data over UART: {json_data}") + def set_truth_table(self,outputs): + self.TruthTable=binary_number_list(self.inputn,outputs) + + def print_truth_tale(self): + print(f"Chip: {self.chip_number}") + print(f"Logic type: {self.logic_type}") + print("INPUT BITS|OUTPUT BITS") + for entry in self.TruthTable: + print(f" {entry[0]} {entry[1]}") + +def binary_number_list(bits,outputs): + list = [] + bits = int(bits) + for number in range(0,(2**bits)): + bitslist = separate_bits(number,bits) + list.append([bitslist,outputs[number]]) + return list + +def separate_bits(num, n): + bits = [(num >> i) & 1 for i in range(n)] # Extract each bit + return bits[::-1] # Return in correct order + +def find_input_pins(ic): + n = ic.inputn + + inputpins = [] + temp = [] + for pin in range(1,ic.pin_count+1): + print("PIN NUMBER IS: ", pin, ic.get_pin(pin)) + if(ic.get_pin(pin) == "input"): + temp.append(pin) + if len(temp) == n: + inputpins.append(temp) + temp=[] + return inputpins \ No newline at end of file diff --git a/SDPPython/prototype5/circuits/test.txt b/SDPPython/prototype5/circuits/test.txt new file mode 100644 index 0000000..6b652e7 --- /dev/null +++ b/SDPPython/prototype5/circuits/test.txt @@ -0,0 +1,32 @@ +Chip Number: 00 +Logic Type: NAND +Number of Inputs: 2 +Description: Quad 2-input NAND gate +Pin Count: 14 +1: INPUT +2: INPUT +3: OUTPUT +4: INPUT +5: INPUT +6: OUTPUT +7: GND +8: OUTPUT +9: INPUT +10: INPUT +11: OUTPUT +12: INPUT +13: INPUT +14: VCC +Tests +1: 1 +2: 1 +OUTPUT: 3 +1: 0 +2: 1 +OUTPUT: 3 +1: 1 +2: 0 +OUTPUT: 3 +1: 0 +2: 0 +OUTPUT: 3 \ No newline at end of file diff --git a/SDPPython/prototype5/prototype5.py b/SDPPython/prototype5/prototype5.py new file mode 100644 index 0000000..31e3998 --- /dev/null +++ b/SDPPython/prototype5/prototype5.py @@ -0,0 +1,167 @@ +import tkinter as tk +from tkinter import ttk, filedialog +import os +import serial +import chip +import json + + +# folder path, default is None until user selects one +folder_path = None + +def select_folder(): + global folder_path + folder_path = filedialog.askdirectory(initialdir=".", title="Select Circuit Folder") + if folder_path: + print(f"Selected folder: {folder_path}") + display_label.config(text="Folder selected.", fg="green") + update_folder_display() # update listbox with files from the selected folder + +def get_file_names(folder_path): + try: + return [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))] + except FileNotFoundError: + print("The specified folder was not found.") + return [] + +def update_folder_display(): + file_names = get_file_names(folder_path) + file_listbox.delete(0, tk.END) # clear existing items in the Listbox + + if not file_names: + display_label.config(text="No files found in the folder.", fg="red") + else: + for file in file_names: + file_listbox.insert(tk.END, file) # insert items from selected folder + dropdown['values'] = file_names + +def on_file_select(event): + # update dropdown_var when a file is selected in the listbox + selected_index = file_listbox.curselection() + if selected_index: + selected_file = file_listbox.get(selected_index[0]) + dropdown_var.set(selected_file) + +def read_chip_configuration(file_path): + circuit_data = {} + with open(file_path, 'r') as file: + for line in file: + # Stop reading when reaching "Tests" + if line.strip() == "Tests": + break + if ":" not in line: + continue + key, value = line.strip().split(":") + circuit_data[key.strip()] = value.strip() + return circuit_data + +def read_tests(file_path): + tests = [] + key_values = {} + with open(file_path, 'r') as file: + # Skip lines until "Tests" is found + in_tests_section = False + for line in file: + if line.strip() == "Tests": + in_tests_section = True + continue + if in_tests_section: + if ":" not in line: + continue + key, value = line.strip().split(":") + key_values[key.strip()] = value.strip() + if key.strip() == "OUTPUT": + tests.append(key_values) + key_values = {} + return tests + +def send_selected_file(): + if folder_path is None: + display_label.config(text="Please select a folder.", fg="red") + return + + selected_file = dropdown_var.get() + if not selected_file: + display_label.config(text="Please select a file.", fg="red") + return + + file_path = os.path.join(folder_path, selected_file) + circuit_data = {} + print(0) + try: + # read the chip configuration + circuit_data = read_chip_configuration(file_path) + print(1) + + # read the tests + tests = read_tests(file_path) + print(2) + ic = chip.IC74Series( + chip_number=circuit_data['Chip Number'], + logic_type=circuit_data['Logic Type'], + n=circuit_data['Number of Inputs'], + ) + + print(circuit_data) + print(tests) + + for i in range(1, int(circuit_data['Pin Count']) + 1): + ic.set_pin(i, circuit_data[str(i)]) + + ser = serial.Serial('COM1', 9600) + message = ic.pin_configuration_json() + ser.write((message+"\n").encode('utf-8')) + + response = [] + for test in tests: + ser.write(json.dumps(test).encode('utf-8')) + response.append(ser.readline().decode('utf-8').strip()) + print(response) + display_label.config(text="Circuit test complete. Check console for results.", fg="green") + + except Exception as e: + print(f"An error occurred while reading {selected_file}: {e}") + display_label.config(text="Error testing circuit.", fg="red") + +def print_results(): + print("Results printed to the console or log file.") + +root = tk.Tk() +root.title("Circuit GUI Prototype") +root.geometry("270x350") + +# dropdown for selecting circuit file +dropdown_var = tk.StringVar() +dropdown = ttk.Combobox(root, textvariable=dropdown_var, state="readonly") +dropdown.grid(row=0, column=0, columnspan=3, padx=10, pady=10) + +# label for file list +file_list_label = tk.Label(root, text="Files in Selected Folder:") +file_list_label.grid(row=1, column=0, columnspan=3, padx=10, pady=(5, 0)) + +# frame around Listbox for thicker border +file_listbox_frame = tk.Frame(root, borderwidth=1, relief="solid") +file_listbox_frame.grid(row=2, column=0, columnspan=3, padx=10, pady=(0, 10)) + +# listbox to display files in the selected folder +file_listbox = tk.Listbox(file_listbox_frame, width=40, height=10) +file_listbox.pack() + +# bind the Listbox to an event for selecting a file +file_listbox.bind("<>", on_file_select) + +# buttons in the same row +select_folder_button = tk.Button(root, text="Select Folder", command=select_folder) +select_folder_button.grid(row=3, column=0, padx=5, pady=10) + +send_button = tk.Button(root, text="Test Circuit", command=send_selected_file) +send_button.grid(row=3, column=1, padx=5, pady=10) + +print_results_button = tk.Button(root, text="Print Results", command=print_results) +print_results_button.grid(row=3, column=2, padx=5, pady=10) + +# display label for messages +display_label = tk.Label(root, text="", font=("Arial", 11)) +display_label.grid(row=4, column=0, columnspan=3, padx=10, pady=10) + +root.mainloop()