55import tkinter as tk
66from tkinter import ttk , messagebox
77
8+ from inputmodule import firmware_update
89from inputmodule .inputmodule import (
910 send_command ,
1011 get_version ,
1112 brightness ,
1213 get_brightness ,
13- bootloader ,
14+ bootloader_jump ,
1415 CommandVals ,
1516 Game ,
1617 GameControlVal
@@ -54,10 +55,12 @@ def run_gui(devices):
5455 tab1 = ttk .Frame (tabControl )
5556 tab_games = ttk .Frame (tabControl )
5657 tab2 = ttk .Frame (tabControl )
58+ tab_fw = ttk .Frame (tabControl )
5759 tab3 = ttk .Frame (tabControl )
5860 tabControl .add (tab1 , text = "Home" )
5961 tabControl .add (tab_games , text = "Games" )
6062 tabControl .add (tab2 , text = "Dynamic Controls" )
63+ tabControl .add (tab_fw , text = "Firmware Update" )
6164 tabControl .add (tab3 , text = "Advanced" )
6265 tabControl .pack (expand = 1 , fill = "both" )
6366
@@ -75,7 +78,7 @@ def run_gui(devices):
7578 checkbox_var = tk .BooleanVar (value = True )
7679 checkbox = ttk .Checkbutton (detected_devices_frame , text = device_info , variable = checkbox_var , style = "TCheckbutton" )
7780 checkbox .pack (anchor = "w" )
78- device_checkboxes [dev .name ] = checkbox_var
81+ device_checkboxes [dev .name ] = ( checkbox_var , checkbox )
7982
8083 # Brightness Slider
8184 brightness_frame = ttk .LabelFrame (tab1 , text = "Brightness" , style = "TLabelframe" )
@@ -160,6 +163,26 @@ def run_gui(devices):
160163 symbols_frame .pack (fill = "x" , padx = 10 , pady = 5 )
161164 ttk .Button (symbols_frame , text = "Send '2 5 degC thunder'" , command = lambda : send_symbols (devices ), style = "TButton" ).pack (side = "left" , padx = 5 , pady = 5 )
162165
166+ # Firmware Update
167+ bootloader_frame = ttk .LabelFrame (tab_fw , text = "Bootloader" , style = "TLabelframe" )
168+ bootloader_frame .pack (fill = "x" , padx = 10 , pady = 5 )
169+ ttk .Button (bootloader_frame , text = "Enter Bootloader" , command = lambda : perform_action (devices , "bootloader" ), style = "TButton" ).pack (side = "left" , padx = 5 , pady = 5 )
170+
171+ bundled_fw_frame = ttk .LabelFrame (tab_fw , text = "Bundled Updates" , style = "TLabelframe" )
172+ bundled_fw_frame .pack (fill = "x" , padx = 10 , pady = 5 )
173+ releases = firmware_update .find_releases (resource_path (), r'(ledmatrix).uf2' )
174+ if not releases :
175+ tk .Label (bundled_fw_frame , text = "Cannot find firmware updates" ).pack (side = "top" , padx = 5 , pady = 5 )
176+ else :
177+ versions = sorted (list (releases .keys ()), reverse = True )
178+
179+ #tk.Label(fw_update_frame, text="Ignore user configured keymap").pack(side="top", padx=5, pady=5)
180+ fw_ver_combo = ttk .Combobox (bundled_fw_frame , values = versions , style = "TCombobox" , state = "readonly" )
181+ fw_ver_combo .pack (side = tk .LEFT , padx = 5 , pady = 5 )
182+ fw_ver_combo .current (0 )
183+ flash_btn = ttk .Button (bundled_fw_frame , text = "Update" , command = lambda : tk_flash_firmware (devices , releases , fw_ver_combo .get (), 'ledmatrix' ), style = "TButton" )
184+ flash_btn .pack (side = "left" , padx = 5 , pady = 5 )
185+
163186 # PWM Frequency Combo Box
164187 pwm_freq_frame = ttk .LabelFrame (tab3 , text = "PWM Frequency" , style = "TLabelframe" )
165188 pwm_freq_frame .pack (fill = "x" , padx = 10 , pady = 5 )
@@ -177,7 +200,6 @@ def run_gui(devices):
177200 device_control_frame = ttk .LabelFrame (tab1 , text = "Device Control" , style = "TLabelframe" )
178201 device_control_frame .pack (fill = "x" , padx = 10 , pady = 5 )
179202 control_buttons = {
180- "Bootloader" : "bootloader" ,
181203 "Sleep" : "sleep" ,
182204 "Wake" : "wake"
183205 }
@@ -194,8 +216,12 @@ def perform_action(devices, action):
194216 if action in action_map :
195217 threading .Thread (target = action_map [action ], args = (devices ,), daemon = True ).start (),
196218
219+ if action == "bootloader" :
220+ disable_devices (devices )
221+ restart_hint ()
222+
197223 action_map = {
198- "bootloader" : bootloader ,
224+ "bootloader" : bootloader_jump ,
199225 "sleep" : lambda dev : send_command (dev , CommandVals .Sleep , [True ]),
200226 "wake" : lambda dev : send_command (dev , CommandVals .Sleep , [False ]),
201227 "start_animation" : lambda dev : animate (dev , True ),
@@ -263,14 +289,47 @@ def set_pwm_freq(devices, freq):
263289 pwm_freq (dev , freq )
264290
265291def get_selected_devices (devices ):
266- return [dev for dev in devices if dev .name in device_checkboxes and device_checkboxes [dev .name ].get ()]
292+ return [dev for dev in devices if dev .name in device_checkboxes and device_checkboxes [dev .name ][ 0 ] .get ()]
267293
268294def resource_path ():
269295 """Get absolute path to resource, works for dev and for PyInstaller"""
270296 try :
271297 # PyInstaller creates a temp folder and stores path in _MEIPASS
272298 base_path = sys ._MEIPASS
273299 except Exception :
274- base_path = os .path .abspath ("../../ " )
300+ base_path = os .path .abspath ("." )
275301
276302 return base_path
303+
304+ def info_popup (msg ):
305+ parent = tk .Tk ()
306+ parent .title ("Info" )
307+ message = tk .Message (parent , text = msg , width = 800 )
308+ message .pack (padx = 20 , pady = 20 )
309+ parent .mainloop ()
310+
311+ def tk_flash_firmware (devices , releases , version , fw_type ):
312+ selected_devices = get_selected_devices (devices )
313+ if len (selected_devices ) != 1 :
314+ info_popup ('To flash select exactly 1 device.' )
315+ return
316+ dev = selected_devices [0 ]
317+ firmware_update .flash_firmware (dev , releases [version ][fw_type ])
318+ # Disable device that we just flashed
319+ disable_devices (devices )
320+ restart_hint ()
321+
322+ def restart_hint ():
323+ parent = tk .Tk ()
324+ parent .title ("Restart Application" )
325+ message = tk .Message (parent , text = "After updating a device,\n restart the application to reload the connections." , width = 800 )
326+ message .pack (padx = 20 , pady = 20 )
327+ parent .mainloop ()
328+
329+ def disable_devices (devices ):
330+ # Disable checkbox of selected devices
331+ for dev in devices :
332+ for name , (checkbox_var , checkbox ) in device_checkboxes .items ():
333+ if name == dev .name :
334+ checkbox_var .set (False )
335+ checkbox .config (state = tk .DISABLED )
0 commit comments