Added the Adafruit Feather nRF52840 to the list of known NRF52 boards and changed the list of known CircuitPython boards to be more explicit with respect to Adafruit boards (i.e. VID 0x239A).
9915
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
1
|
# -*- coding: utf-8 -*- |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
2
|
|
11090
|
3
|
# Copyright (c) 2023 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> |
9915
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
4
|
# |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
5
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
6
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
7
|
Module implementing a dialog to convert a .hex or .bin firmware file to .uf2. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
8
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
9
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
10
|
import json |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
11
|
import os |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
12
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
13
|
from PyQt6.QtCore import QProcess, QRegularExpression, pyqtSlot |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
14
|
from PyQt6.QtGui import QRegularExpressionValidator |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
15
|
from PyQt6.QtWidgets import QDialog |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
16
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
17
|
from eric7 import Preferences |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
18
|
from eric7.EricWidgets.EricPathPicker import EricPathPickerModes |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
19
|
from eric7.SystemUtilities.PythonUtilities import getPythonExecutable |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
20
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
21
|
from .Ui_ConvertToUF2Dialog import Ui_ConvertToUF2Dialog |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
22
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
23
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
24
|
class ConvertToUF2Dialog(QDialog, Ui_ConvertToUF2Dialog): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
25
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
26
|
Class implementing a dialog to convert a .hex or .bin firmware file to .uf2. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
27
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
28
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
29
|
FamiliesFile = os.path.join(os.path.dirname(__file__), "Tools", "uf2families.json") |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
30
|
ConvertScript = os.path.join(os.path.dirname(__file__), "Tools", "uf2conv.py") |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
31
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
32
|
def __init__(self, parent=None): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
33
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
34
|
Constructor |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
35
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
36
|
@param parent reference to the parent widget (defaults to None) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
37
|
@type QWidget (optional) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
38
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
39
|
super().__init__(parent) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
40
|
self.setupUi(self) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
41
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
42
|
self.firmwarePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
43
|
self.firmwarePicker.setFilters( |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
44
|
self.tr("MicroPython Firmware Files (*.hex *.bin);;All Files (*)") |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
45
|
) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
46
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
47
|
self.__validator = QRegularExpressionValidator( |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
48
|
QRegularExpression(r"[0-9a-fA-F]{0,7}") |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
49
|
) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
50
|
self.addressEdit.setValidator(self.__validator) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
51
|
self.addressEdit.setEnabled(False) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
52
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
53
|
self.__populateFamilyComboBox() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
54
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
55
|
self.__process = QProcess(self) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
56
|
self.__process.readyReadStandardOutput.connect(self.__readOutput) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
57
|
self.__process.readyReadStandardError.connect(self.__readError) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
58
|
self.__process.finished.connect(self.__conversionFinished) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
59
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
60
|
self.__updateConvertButton() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
61
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
62
|
def __populateFamilyComboBox(self): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
63
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
64
|
Private method to populate the chip family combo box with values read from |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
65
|
'uf2families.json' file. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
66
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
67
|
with open(ConvertToUF2Dialog.FamiliesFile, "r") as f: |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
68
|
families = json.load(f) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
69
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
70
|
self.familiesComboBox.addItem("", "") |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
71
|
for family in families: |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
72
|
self.familiesComboBox.addItem(family["description"], family["id"]) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
73
|
self.familiesComboBox.model().sort(0) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
74
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
75
|
def __updateConvertButton(self): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
76
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
77
|
Private method to set the enabled status of the 'Convert' button. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
78
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
79
|
self.convertButton.setEnabled( |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
80
|
bool(self.firmwarePicker.text()) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
81
|
and bool(self.familiesComboBox.currentText()) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
82
|
) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
83
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
84
|
@pyqtSlot(str) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
85
|
def on_firmwarePicker_textChanged(self, firmware): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
86
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
87
|
Private slot handling a change of the firmware file name. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
88
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
89
|
@param firmware name of the firmware file |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
90
|
@type str |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
91
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
92
|
self.addressEdit.setEnabled(firmware.lower().endswith(".bin")) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
93
|
self.__updateConvertButton() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
94
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
95
|
@pyqtSlot(str) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
96
|
def on_familiesComboBox_currentTextChanged(self, family): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
97
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
98
|
Private slot handling the selection of a chip family. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
99
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
100
|
@param family name of the selected chip family |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
101
|
@type str |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
102
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
103
|
self.__updateConvertButton() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
104
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
105
|
@pyqtSlot() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
106
|
def on_convertButton_clicked(self): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
107
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
108
|
Private slot activating the conversion process. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
109
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
110
|
self.outputEdit.clear() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
111
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
112
|
inputFile = self.firmwarePicker.text() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
113
|
outputFile = os.path.splitext(inputFile)[0] + ".uf2" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
114
|
args = [ |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
115
|
ConvertToUF2Dialog.ConvertScript, |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
116
|
"--convert", |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
117
|
"--family", |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
118
|
self.familiesComboBox.currentData(), |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
119
|
"--output", |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
120
|
outputFile, |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
121
|
] |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
122
|
if inputFile.lower().endswith(".bin"): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
123
|
address = self.addressEdit.text() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
124
|
if address: |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
125
|
args.extend(["--base", "0x{0}".format(address)]) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
126
|
args.append(inputFile) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
127
|
python = getPythonExecutable() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
128
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
129
|
# output the generated command |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
130
|
self.outputEdit.insertPlainText( |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
131
|
"{0} {1}\n{2}\n\n".format(python, " ".join(args), "=" * 40) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
132
|
) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
133
|
self.outputEdit.ensureCursorVisible() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
134
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
135
|
# start the conversion process |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
136
|
self.convertButton.setEnabled(False) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
137
|
self.__process.start(python, args) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
138
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
139
|
@pyqtSlot() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
140
|
def __readOutput(self): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
141
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
142
|
Private slot to read the standard output channel of the conversion process. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
143
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
144
|
out = str( |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
145
|
self.__process.readAllStandardOutput(), |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
146
|
Preferences.getSystem("IOEncoding"), |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
147
|
"replace", |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
148
|
) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
149
|
self.outputEdit.insertPlainText(out) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
150
|
self.outputEdit.ensureCursorVisible() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
151
|
|
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
152
|
@pyqtSlot() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
153
|
def __readError(self): |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
154
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
155
|
Private slot to read the standard error channel of the conversion process. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
156
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
157
|
out = str( |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
158
|
self.__process.readAllStandardError(), |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
159
|
Preferences.getSystem("IOEncoding"), |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
160
|
"replace", |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
161
|
) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
162
|
self.outputEdit.insertPlainText(self.tr("--- ERROR ---\n")) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
163
|
self.outputEdit.insertPlainText(out) |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
164
|
self.outputEdit.ensureCursorVisible() |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
165
|
|
10069
435cc5875135
Corrected and checked some code style issues (unused function arguments).
Detlev Offenbach <detlev@die-offenbachs.de>
diff
changeset
|
166
|
@pyqtSlot(int, QProcess.ExitStatus) |
10690
fab36645aa7d
Changed the source code and the source code documentation to improve the indication of unused method/function arguments.
Detlev Offenbach <detlev@die-offenbachs.de>
diff
changeset
|
167
|
def __conversionFinished(self, _exitCode, _exitStatus): |
9915
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
168
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
169
|
Private slot handling the end of the conversion process. |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
170
|
|
10690
fab36645aa7d
Changed the source code and the source code documentation to improve the indication of unused method/function arguments.
Detlev Offenbach <detlev@die-offenbachs.de>
diff
changeset
|
171
|
@param _exitCode exit code of the process (unused) |
9915
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
172
|
@type int |
10690
fab36645aa7d
Changed the source code and the source code documentation to improve the indication of unused method/function arguments.
Detlev Offenbach <detlev@die-offenbachs.de>
diff
changeset
|
173
|
@param _exitStatus exit status of the process (unused) |
9915
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
174
|
@type QProcess.ExitStatus |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
175
|
""" |
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
diff
changeset
|
176
|
self.convertButton.setEnabled(True) |