Files
RP2040_UPS_Loader/rp2040_Loader.py
T
2026-04-27 16:43:02 +01:00

166 lines
5.5 KiB
Python

import os
import json
import subprocess
import time
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, messagebox
import serial.tools.list_ports
import sys
from mpremote.main import main as mpremote_main
class RP2040UploaderApp:
def __init__(self, master):
self.master = master
self.folder_path = os.path.join(os.getcwd(), "Resources/RP2040")
self.config_path = os.path.join(self.folder_path, "config.json")
self.label = tk.Label(master, text="Searching for board...")
self.label.pack(pady=10)
self.port, self.board_name = self.find_supported_port()
if self.port:
self.label.config(text=f"{self.board_name} detected on {self.port}")
else:
self.label.config(text="No supported board found.")
# Config entry fields
self.ip_entry = self.create_labeled_entry("IP Address:")
self.subnet_entry = self.create_labeled_entry("Subnet Mask:")
self.gateway_entry = self.create_labeled_entry("Gateway:")
self.load_config()
self.upload_button = ttk.Button(
master,
text="Upload Files",
style="Accent.TButton",
command=self.upload_files,
state=tk.NORMAL if self.port else tk.DISABLED
)
self.upload_button.pack(pady=10)
def create_labeled_entry(self, label_text):
frame = tk.Frame(self.master)
frame.pack(pady=2)
label = tk.Label(frame, text=label_text)
label.pack(side=tk.LEFT)
entry = tk.Entry(frame, width=20)
entry.pack(side=tk.RIGHT)
return entry
def find_supported_port(self):
# List of supported boards (VID, PID, Name)
supported_boards = [
(0x239A, 0x80F2, "RP2040"),
(0x2E8A, 0x0005, "RP2350"),
]
ports = serial.tools.list_ports.comports()
for port in ports:
for vid, pid, name in supported_boards:
if port.vid == vid and port.pid == pid:
return port.device, name
return None, None
def load_config(self):
if os.path.isfile(self.config_path):
try:
with open(self.config_path, "r") as f:
config = json.load(f)
self.ip_entry.insert(0, config.get("ip", ""))
self.subnet_entry.insert(0, config.get("subnet", ""))
self.gateway_entry.insert(0, config.get("gateway", ""))
except Exception as e:
messagebox.showerror("Error", f"Failed to read config.json:\n{e}")
else:
messagebox.showwarning("Missing File", f"No config.json found in {self.folder_path}")
def save_config(self):
config = {
"ip": self.ip_entry.get(),
"subnet": self.subnet_entry.get(),
"gateway": self.gateway_entry.get()
}
try:
with open(self.config_path, "w") as f:
json.dump(config, f, indent=4)
except Exception as e:
messagebox.showerror("Error", f"Failed to save config.json:\n{e}")
def upload_files(self):
if not os.path.isdir(self.folder_path):
messagebox.showerror("Error", f"Folder '{self.folder_path}' not found.")
return
self.save_config()
success = True
for filename in os.listdir(self.folder_path):
full_path = os.path.join(self.folder_path, filename)
if os.path.isfile(full_path):
self.label.config(text=f"Uploading {filename}...")
self.master.update()
# Save original sys.argv and replace it with mpremote-style args
original_argv = sys.argv
sys.argv = ["mpremote", "connect", self.port, "fs", "cp", full_path, f":{filename}"]
try:
mpremote_main()
except SystemExit as e:
success = False
messagebox.showerror("Upload Failed", f"Failed to upload {filename} (mpremote exited with code {e.code}).")
break
finally:
sys.argv = original_argv # Always restore original argv
if success:
# --- Soft reset the board ---
self.label.config(text="Resetting board...")
print("Resetting board...")
self.master.update()
original_argv = sys.argv
sys.argv = ["mpremote", "connect", self.port, "reset"]
try:
mpremote_main()
except SystemExit:
pass
finally:
sys.argv = original_argv
time.sleep(0.4)
self.label.config(text="DONE")
self.master.update()
messagebox.showinfo("Success", "All files uploaded successfully!")
if __name__ == "__main__":
root = tk.Tk()
app = RP2040UploaderApp(root)
root.title("RP Loader V1.2.0")
root.iconbitmap(r'Resources/icon1.ico')
# Set the theme
root.tk.call("source", "Resources/azure.tcl")
root.tk.call("set_theme", "dark")
# Set a minsize for the window, and place it in the middle
root.update()
root.minsize(400, 200)
# Footer label in bottom right
footer_frame = tk.Frame(root)
footer_frame.pack(side=tk.BOTTOM, fill=tk.X)
footer_label = tk.Label(footer_frame, text="Made by Hendo 08/10/2025", anchor="e", justify="right", font=("TkDefaultFont", 7, "bold"))
footer_label.pack(side=tk.RIGHT, padx=10, pady=5)
root.mainloop()