10
10
TODO:
11
11
12
12
Push user to upgrade bootloader as needed
13
+ Bootloader from CLI:
14
+ ambiq_bin2board.exe --bin "artemis_svl.bin" --load-address-blob 0x20000 --magic-num 0xCB --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b 115200 -port "COM3" -r 2 -v
15
+
16
+ ambiq_bin2board.exe --bin "artemis_svl.bin" --load-address-blob 0x20000 --magic-num 0xCB --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b 115200 -port "COM3" -r 2 -v
13
17
14
18
"""
15
19
from typing import Iterator , Tuple
16
20
from serial .tools .list_ports import comports
17
- from PyQt5 .QtCore import QSettings , QProcess
21
+ from PyQt5 .QtCore import QSettings , QProcess , QTimer
18
22
from PyQt5 .QtWidgets import QWidget , QLabel , QComboBox , QGridLayout , \
19
- QPushButton , QApplication , QLineEdit , QFileDialog
20
- from PyQt5 .QtGui import QCloseEvent
21
-
22
- # import artemis_svl
23
+ QPushButton , QApplication , QLineEdit , QFileDialog , QPlainTextEdit
24
+ from PyQt5 .QtGui import QCloseEvent , QTextCursor
23
25
24
26
# Setting constants
25
27
SETTING_PORT_NAME = 'port_name'
26
28
SETTING_FILE_LOCATION = 'message'
27
29
SETTING_BAUD_RATE = '921600'
28
30
29
- progressCount = 1
30
-
31
31
guiVersion = 'v1.0'
32
32
33
33
@@ -69,7 +69,7 @@ def __init__(self, parent: QWidget = None) -> None:
69
69
self .refresh_btn .pressed .connect (self .on_refresh_btn_pressed )
70
70
71
71
# Baudrate Combobox
72
- self .baud_label = QLabel (self .tr ('Baud:' ))
72
+ self .baud_label = QLabel (self .tr ('Baud Rate :' ))
73
73
self .baud_combobox = QComboBox ()
74
74
self .baud_label .setBuddy (self .baud_combobox )
75
75
self .update_baud_rates ()
@@ -78,10 +78,24 @@ def __init__(self, parent: QWidget = None) -> None:
78
78
self .upload_btn = QPushButton (self .tr ('Upload' ))
79
79
self .upload_btn .pressed .connect (self .on_upload_btn_pressed )
80
80
81
+ # Upload Button
82
+ self .updateBootloader_btn = QPushButton (self .tr ('Update Bootloader' ))
83
+ self .updateBootloader_btn .pressed .connect (
84
+ self .on_update_bootloader_btn_pressed )
85
+
81
86
# Status bar
82
87
self .status_label = QLabel (self .tr ('Status:' ))
83
88
self .status = QLabel (self .tr (' ' ))
84
89
90
+ # Messages Bar
91
+ self .messages_label = QLabel (self .tr ('Status / Warnings:' ))
92
+
93
+ # Messages Window
94
+ self .messages = QPlainTextEdit ()
95
+ # Attempting to reduce window size
96
+ #self.messages.setMinimumSize(1, 2)
97
+ #self.messages.resize(1, 2)
98
+
85
99
# Arrange Layout
86
100
layout = QGridLayout ()
87
101
layout .addWidget (self .msg_label , 0 , 0 )
@@ -94,14 +108,30 @@ def __init__(self, parent: QWidget = None) -> None:
94
108
95
109
layout .addWidget (self .baud_label , 2 , 0 )
96
110
layout .addWidget (self .baud_combobox , 2 , 1 )
97
- layout .addWidget (self .upload_btn , 3 , 2 )
98
111
99
- layout .addWidget (self .status_label , 3 , 0 )
100
- layout .addWidget (self .status , 3 , 1 )
112
+ #layout.addWidget(self.status_label, 3, 0)
113
+ #layout.addWidget(self.status, 3, 1)
114
+
115
+ layout .addWidget (self .messages_label , 3 , 0 )
116
+ layout .addWidget (self .messages , 4 , 0 , 4 , 3 )
117
+
118
+ layout .addWidget (self .upload_btn , 15 , 2 )
119
+ layout .addWidget (self .updateBootloader_btn , 15 , 1 )
120
+
101
121
self .setLayout (layout )
102
122
103
123
self ._load_settings ()
104
124
125
+ # Make the text edit window read-only
126
+ self .messages .setReadOnly (True )
127
+ self .messages .clear () # Clear the message window
128
+
129
+ def addMessage (self , msg : str ) -> None :
130
+ self .messages .moveCursor (QTextCursor .End )
131
+ self .messages .ensureCursorVisible ()
132
+ self .messages .appendPlainText (msg )
133
+ self .messages .ensureCursorVisible ()
134
+
105
135
def _load_settings (self ) -> None :
106
136
"""Load settings on startup."""
107
137
settings = QSettings ()
@@ -139,11 +169,26 @@ def show_error_message(self, msg: str) -> None:
139
169
def update_com_ports (self ) -> None :
140
170
"""Update COM Port list in GUI."""
141
171
self .port_combobox .clear ()
172
+
173
+ index = 0
174
+ indexOfCH340 = - 1
142
175
for name , device in gen_serial_ports ():
143
176
self .port_combobox .addItem (name , device )
177
+ if ("CH340" in name ):
178
+ if (indexOfCH340 == - 1 ): # Select the first available
179
+ indexOfCH340 = index
180
+ #print("CH340 found at index " + str(indexOfCH340))
181
+ index = index + 1
182
+
183
+ # If we have no previous settings, and CH340 is in the list, auto-select it
184
+ if indexOfCH340 > - 1 :
185
+ settings = QSettings ()
186
+ port_name = settings .value (SETTING_PORT_NAME )
187
+ if port_name is not None :
188
+ self .port_combobox .setCurrentIndex (indexOfCH340 )
144
189
145
190
def update_baud_rates (self ) -> None :
146
- """Update COM Port list in GUI."""
191
+ """Update baud rate list in GUI."""
147
192
self .baud_combobox .addItem ("921600" , 921600 )
148
193
self .baud_combobox .addItem ("460800" , 460800 )
149
194
self .baud_combobox .addItem ("115200" , 115200 )
@@ -167,6 +212,7 @@ def closeEvent(self, event: QCloseEvent) -> None:
167
212
168
213
def on_refresh_btn_pressed (self ) -> None :
169
214
self .update_com_ports ()
215
+ self .addMessage ("Ports Refreshed" )
170
216
171
217
def on_upload_btn_pressed (self ) -> None :
172
218
"""Check if port is available"""
@@ -176,7 +222,7 @@ def on_upload_btn_pressed(self) -> None:
176
222
if (p .device == self .port ):
177
223
portAvailable = True
178
224
if (portAvailable == False ):
179
- self .status . setText ("Port No Longer Available" )
225
+ self .addMessage ("Port No Longer Available" )
180
226
return
181
227
182
228
"""Check if file exists"""
@@ -188,46 +234,62 @@ def on_upload_btn_pressed(self) -> None:
188
234
fileExists = False
189
235
finally :
190
236
if (fileExists == False ):
191
- self .status . setText ("File Not Found" )
237
+ self .addMessage ("File Not Found" )
192
238
return
193
239
f .close ()
194
240
195
- global progressCount
196
- progressCount = 0
241
+ self .addMessage ("Uploading" )
242
+
243
+ self .process = QProcess ()
244
+ self .process .readyReadStandardError .connect (
245
+ self .onReadyReadStandardError )
246
+ self .process .readyReadStandardOutput .connect (
247
+ self .onReadyReadStandardOutput )
248
+
249
+ commandString = "tools/artemis_svl.exe " + \
250
+ str (self .port ) + " -f\" " + self .fileLocation_lineedit .text () + \
251
+ "\" " + " -b" + str (self .baudRate )
252
+ print (commandString )
253
+ self .process .start (commandString )
254
+
255
+ def on_update_bootloader_btn_pressed (self ) -> None :
256
+ """Check if port is available"""
257
+ portAvailable = False
258
+ ports = comports ()
259
+ for p in ports :
260
+ if (p .device == self .port ):
261
+ portAvailable = True
262
+ if (portAvailable == False ):
263
+ self .addMessage ("Port No Longer Available" )
264
+ return
197
265
198
- self .status . setText ( "Uploading " )
266
+ self .addMessage ( "Updating bootloader " )
199
267
200
268
self .process = QProcess ()
201
269
self .process .readyReadStandardError .connect (
202
270
self .onReadyReadStandardError )
203
271
self .process .readyReadStandardOutput .connect (
204
272
self .onReadyReadStandardOutput )
205
273
206
- self .process .start ("artemis_svl .exe " + str (self .port ) +
207
- " -f \" " + self . fileLocation_lineedit . text () + " \" " + " -b" + str ( self . baudRate ) )
274
+ self .process .start ("tools/ambiq_bin2board .exe --bin tools/artemis_svl.bin --load-address-blob 0x20000 --magic-num 0xCB --version 0x0 --load-address-wired 0xC000 -i 6 --options 0x1 -b 115200 -port " + str (self .port ) +
275
+ " -r 2 -v" )
208
276
209
277
def onReadyReadStandardError (self ):
210
278
error = self .process .readAllStandardError ().data ().decode ()
211
279
# print(error)
212
- self .status . setText (error )
280
+ self .addMessage (error )
213
281
214
282
def onReadyReadStandardOutput (self ):
215
283
"""Parse the output from the process. Update our status as we go."""
216
284
result = self .process .readAllStandardOutput ().data ().decode ()
217
285
# print(result)
286
+ self .addMessage (result )
218
287
if ("complete" in result ):
219
- self .status . setText ("Complete" )
288
+ self .addMessage ("Complete" )
220
289
elif ("failed" in result ):
221
- self .status . setText ("Upload Failed" )
290
+ self .addMessage ("Upload Failed" )
222
291
elif ("open" in result ):
223
- self .status .setText ("Port In Use / Please Close" )
224
- else : # The '#' is displayed 50 times until completion
225
- global progressCount
226
- progressCount = progressCount + result .count ("#" )
227
- # print(progressCount)
228
- for i in range (int (progressCount / 3 )):
229
- current = self .status .text () + "."
230
- self .status .setText (current )
292
+ self .addMessage ("Port In Use / Please Close" )
231
293
232
294
def on_browse_btn_pressed (self ) -> None :
233
295
"""Open dialog to select bin file."""
@@ -246,7 +308,7 @@ def on_browse_btn_pressed(self) -> None:
246
308
import sys
247
309
app = QApplication ([])
248
310
app .setOrganizationName ('SparkFun' )
249
- app .setApplicationName ('Artemis Firmware Uploader' )
311
+ app .setApplicationName ('Artemis Firmware Uploader ' + guiVersion )
250
312
w = RemoteWidget ()
251
313
w .show ()
252
314
sys .exit (app .exec_ ())
0 commit comments